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