e13a2b9c8077eef56dbf95a4945c9d83c3cd3d2e
[jigit.git] / jigdump.c
1 #include <errno.h>
2 #include <math.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <zlib.h>
6 #include <stdio.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #include <sys/mman.h>
12 #include "md5.h"
13
14 typedef unsigned long long UINT64;
15 typedef long long INT64;
16 typedef unsigned long      UINT32;
17
18 #define BUF_SIZE 65536
19
20 typedef enum state_
21 {
22     STARTING,
23     IN_DATA,
24     IN_DESC,
25     DUMP_DESC,
26     DONE,
27     ERROR
28 } e_state;
29
30 INT64 find_string(unsigned char *buf, size_t buf_size, char *search)
31 {
32     size_t length = strlen(search);
33     INT64 result;
34     
35     for (result = 0; result < (buf_size - length); result++)
36     {
37         if (!memcmp(&buf[result], search, length))
38             return result;
39     }
40     return -1;
41 }
42
43 INT64 parse_data_block(INT64 offset, unsigned char *buf, size_t buf_size)
44 {
45     /* Parse the contents of this data block... */
46     UINT64 dataLen = 0;
47     UINT64 dataUnc = 0;
48     
49     printf("\nDATA block found at offset %lld\n", offset);
50     dataLen = (UINT64)buf[4];
51     dataLen |= (UINT64)buf[5] << 8;
52     dataLen |= (UINT64)buf[6] << 16;
53     dataLen |= (UINT64)buf[7] << 24;
54     dataLen |= (UINT64)buf[8] << 32;
55     dataLen |= (UINT64)buf[9] << 40;
56     printf("  compressed block size %llu bytes\n", dataLen);
57
58     dataUnc = (UINT64)buf[10];
59     dataUnc |= (UINT64)buf[11] << 8;
60     dataUnc |= (UINT64)buf[12] << 16;
61     dataUnc |= (UINT64)buf[13] << 24;
62     dataUnc |= (UINT64)buf[14] << 32;
63     dataUnc |= (UINT64)buf[15] << 40;
64     printf("  uncompressed block size %llu bytes\n", dataUnc);
65
66     return dataLen;
67 }
68
69 INT64 parse_desc_block(INT64 offset, unsigned char *buf, size_t buf_size)
70 {
71     /* Parse the contents of this data block... */
72     UINT64 descLen = 0;
73     
74     printf("\nDESC block found at offset %lld\n", offset);
75     descLen = (UINT64)buf[4];
76     descLen |= (UINT64)buf[5] << 8;
77     descLen |= (UINT64)buf[6] << 16;
78     descLen |= (UINT64)buf[7] << 24;
79     descLen |= (UINT64)buf[8] << 32;
80     descLen |= (UINT64)buf[9] << 40;
81     printf("  DESC block size is %llu bytes\n", descLen);
82     
83     return 10;
84 }
85
86 INT64 parse_desc_data(INT64 offset, unsigned char *buf, size_t buf_size)
87 {
88     int type = buf[0];
89     printf("  DESC entry: block type %d\n", type);
90     
91     switch (type)
92     {
93         case 2:
94         {
95             UINT64 skipLen = 0;
96             skipLen = (UINT64)buf[1];
97             skipLen |= (UINT64)buf[2] << 8;
98             skipLen |= (UINT64)buf[3] << 16;
99             skipLen |= (UINT64)buf[4] << 24;
100             skipLen |= (UINT64)buf[5] << 32;
101             skipLen |= (UINT64)buf[6] << 40;
102             printf("    Unmatched data, %llu bytes\n", skipLen);
103             return 7;
104         }
105         case 5:
106         {
107             UINT64 imglen = 0;
108             UINT32 blocklen = 0;
109             int i = 0;
110
111             imglen = (UINT64)buf[1];
112             imglen |= (UINT64)buf[2] << 8;
113             imglen |= (UINT64)buf[3] << 16;
114             imglen |= (UINT64)buf[4] << 24;
115             imglen |= (UINT64)buf[5] << 32;
116             imglen |= (UINT64)buf[6] << 40;
117
118             blocklen = (UINT32)buf[23];
119             blocklen |= (UINT32)buf[24] << 8;
120             blocklen |= (UINT32)buf[25] << 16;
121             blocklen |= (UINT32)buf[26] << 24;
122
123             printf("    Original image length %llu bytes\n", imglen);
124             printf("    Image MD5: ");
125             for (i = 7; i < 23; i++)
126                 printf("%2.2x", buf[i]);
127             printf(" (%s)\n", base64_dump(&buf[7], 16));
128             printf("    Rsync block length %lu bytes\n", blocklen);
129             return 0; /* i.e. we're finished! */
130         }
131         case 6:
132         {
133             UINT64 fileLen = 0;
134             int i = 0;
135
136             fileLen = (UINT64)buf[1];
137             fileLen |= (UINT64)buf[2] << 8;
138             fileLen |= (UINT64)buf[3] << 16;
139             fileLen |= (UINT64)buf[4] << 24;
140             fileLen |= (UINT64)buf[5] << 32;
141             fileLen |= (UINT64)buf[6] << 40;
142             
143             printf("    File, length %llu bytes\n", fileLen);
144             printf("    file rsyncsum: ");
145             for (i = 7; i < 15; i++)
146                 printf("%2.2x", buf[i]);
147             printf(" (%s)\n", base64_dump(&buf[7], 8));
148             printf("    file md5: ");
149             for (i = 15; i < 31; i++)
150                 printf("%2.2x", buf[i]);
151             printf(" (%s)\n", base64_dump(&buf[15], 16));
152             return 31;
153         }
154         default:
155             break;
156     }
157
158     return 0;
159 }
160
161 int main(int argc, char **argv)
162 {
163     char *filename = NULL;
164     int fd = -1;
165     unsigned char *buf = NULL;
166     INT64 offset = 0;
167     INT64 bytes = 0;
168     e_state state = STARTING;
169     
170     if (argc != 2)
171     {
172         printf("No filename specified! Try again...\n");
173         return EINVAL;
174     }
175     
176     filename = argv[1];
177     
178     fd = open(filename, O_RDONLY);
179     if (-1 == fd)
180     {
181         printf("Failed to open file %s, error %d!. Try again...\n", filename, errno);
182         return errno;
183     }
184
185     buf = malloc(BUF_SIZE);
186     if (!buf)
187     {
188         printf("Failed to malloc %d bytes. Abort!\n", BUF_SIZE);
189         return ENOMEM;
190     }
191
192     /* Find the beginning of the data - read the first chunk, including the header */
193     while (STARTING == state)
194     {
195         INT64 start_offset = -1;
196
197         bytes = read(fd, buf, BUF_SIZE);
198         if (0 >= bytes)
199         {
200             state = DONE;
201             break;
202         }
203         start_offset = find_string(buf, bytes, "DATA");
204         if (start_offset >= 0)
205         {
206             offset += start_offset;
207             state = IN_DATA;
208             break;
209         }
210         offset += bytes;
211     }
212
213     while (DONE != state && ERROR != state)
214     {
215         INT64 start_offset = -1;
216         lseek(fd, offset, SEEK_SET);
217         bytes = read(fd, buf, BUF_SIZE);
218         if (0 >= bytes)
219         {
220             state = ERROR;
221             break;
222         }
223         if (IN_DATA == state)
224         {
225             if (!find_string(buf, bytes, "DATA"))
226                 state = IN_DATA;
227             if (!find_string(buf, bytes, "DESC"))
228                 state = IN_DESC;
229         }
230         switch (state)
231         {
232             case IN_DATA:
233                 start_offset = parse_data_block(offset, buf, bytes);
234                 offset += start_offset;
235                 break;
236             case IN_DESC:
237                 start_offset = parse_desc_block(offset, buf, bytes);
238                 offset += start_offset;
239                 state = DUMP_DESC;
240                 break;
241             case DUMP_DESC:
242                 start_offset = parse_desc_data(offset, buf, bytes);
243                 offset += start_offset;
244                 if (0 == start_offset)
245                     state = DONE;
246                 break;
247             default:
248                 break;
249         }
250     }        
251     
252     close(fd);
253
254     return 0;
255 }