13 /* Possible commands to run. Or them together... */
14 #define CMD_LIST 0x0001
15 #define CMD_BUILD_IMAGE 0x0002
17 typedef unsigned long long UINT64;
18 typedef unsigned long UINT32;
20 #define BUF_SIZE 65536
22 /* Different types used in the extent_type below */
25 #define JTET_FILE_MATCH 2
26 #define JTET_NOMATCH 3
28 #define JTE_ID_STRING "JTE"
29 #define JTE_HEADER_STRING "MKJ IMAGE START"
30 #define JTE_FOOTER_STRING "*MKJ IMAGE END*"
31 #define JTE_VER_MAJOR 0x0001
32 #define JTE_VER_MINOR 0x0000
36 unsigned char id[4]; /* "JTE" plus NULL terminator */
37 unsigned char extent_type; /* The type of this extent in the jigdo template file */
38 unsigned char extent_length[8]; /* The length in bytes of this extent, including all
39 the metadata. 64-bit, big endian */
40 unsigned char start_sector[4]; /* The start sector of this extent within the output image;
41 32-bit BE. Header and footer use 0xFFFFFFFF */
46 unsigned char header_string[16]; /* Recognition string. Should contain "MKJ IMAGE START",
47 including NULL terminator */
48 unsigned char version[4]; /* Version number, encoded MMmm */
49 unsigned char sector_size[4]; /* Sector size used in this image.
50 _Always_ expected to be 2KB. Stored as 32-bit BE */
51 unsigned char pad[16];
55 unsigned char footer_string[16]; /* Recognition string. Should contain "*MKJ IMAGE END*",
56 including NULL terminator */
57 unsigned char image_size[8]; /* Size of image, in bytes. 64-bit BE. */
58 unsigned char md5[16]; /* MD5SUM of the entire image */
62 unsigned char file_length[8]; /* The actual length of the file stored in this extent.
63 Will be <= extent_length; also 64-bit BE */
64 unsigned char filename_length[4]; /* The length of the following filename entry */
65 unsigned char md5[16]; /* MD5SUM of the _file_ data in this lump, without padding */
66 unsigned char pad[12];
70 unsigned char unmatched_length[8]; /* The length of the data in this extent. Will be ==
71 extent_length - sizeof(struct jt_extent_data) ; also 64-bit BE */
72 unsigned char md5[16]; /* MD5SUM of this lump of unmatched data */
73 unsigned char pad[16];
80 UINT32 sector_size = 0;
84 static char *print_md5(unsigned char *buf)
86 static char outbuf[33];
88 bzero(outbuf, sizeof(outbuf));
89 sprintf(outbuf, "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
90 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
91 buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
95 static int my_sendfile(int src_fd, int dst_fd, off_t length)
100 off_t bytes_written = 0;
103 while (bytes < length)
105 size = length - bytes;
109 bytes_read = read(src_fd, buf, size);
110 if (size != bytes_read)
112 printf("my_sendfile: FAILED to read %llu bytes from input file; error %d\n", size, errno);
115 bytes_written = write(dst_fd, buf, bytes_read);
116 if (bytes_read != bytes_written)
118 printf("my_sendfile: FAILED to write %llu bytes to output file; error %d\n", bytes_read, errno);
124 /* Now pad if necessary */
125 if (length % sector_size)
127 bzero (buf, BUF_SIZE);
128 off_t pad_size = sector_size - (length % sector_size);
130 bytes = write(dst_fd, buf, pad_size);
133 printf("my_sendfile: FAILED to pad with %llu bytes; error %d\n", pad_size, errno);
141 UINT64 handle_jtet_header(UINT64 extent_length,
142 UINT32 start_sector, unsigned char *buf)
144 struct jt_extent_data *extent = (struct jt_extent_data *)buf;
146 sector_size = extent->data.header.sector_size[0] << 24;
147 sector_size |= extent->data.header.sector_size[1] << 16;
148 sector_size |= extent->data.header.sector_size[2] << 8;
149 sector_size |= extent->data.header.sector_size[3];
153 printf(" Header string: %s\n", extent->data.header.header_string);
154 printf(" JTE version: %d.%d\n",
155 (extent->data.header.version[0] << 8) | extent->data.header.version[1],
156 (extent->data.header.version[2] << 8) | extent->data.header.version[3]);
157 printf(" Sector size: %ld bytes\n", sector_size);
159 return extent_length;
162 UINT64 handle_jtet_footer(UINT64 extent_length,
163 UINT32 start_sector, unsigned char *buf)
165 struct jt_extent_data *extent = (struct jt_extent_data *)buf;
166 UINT64 image_size = (UINT64)extent->data.footer.image_size[0] << 56;
167 image_size |= (UINT64)extent->data.footer.image_size[1] << 48;
168 image_size |= (UINT64)extent->data.footer.image_size[2] << 40;
169 image_size |= (UINT64)extent->data.footer.image_size[3] << 32;
170 image_size |= (UINT64)extent->data.footer.image_size[4] << 24;
171 image_size |= (UINT64)extent->data.footer.image_size[5] << 16;
172 image_size |= (UINT64)extent->data.footer.image_size[6] << 8;
173 image_size |= (UINT64)extent->data.footer.image_size[7];
177 printf(" Footer string: %s\n", extent->data.footer.footer_string);
178 printf(" ISO image size: %llu\n", image_size);
179 printf(" ISO image MD5sum: %s\n", print_md5(extent->data.footer.md5));
184 UINT64 handle_jtet_file_match(UINT64 extent_length,
185 UINT32 start_sector, unsigned char *buf)
189 struct jt_extent_data *extent = (struct jt_extent_data *)buf;
190 char *filename = &buf[57];
192 int filename_length = 0;
194 length |= (UINT64)extent->data.file_match.file_length[0] << 56;
195 length |= (UINT64)extent->data.file_match.file_length[1] << 48;
196 length |= (UINT64)extent->data.file_match.file_length[2] << 40;
197 length |= (UINT64)extent->data.file_match.file_length[3] << 32;
198 length |= (UINT64)extent->data.file_match.file_length[4] << 24;
199 length |= (UINT64)extent->data.file_match.file_length[5] << 16;
200 length |= (UINT64)extent->data.file_match.file_length[6] << 8;
201 length |= (UINT64)extent->data.file_match.file_length[7];
203 filename_length |= extent->data.file_match.filename_length[0] << 24;
204 filename_length |= extent->data.file_match.filename_length[1] << 16;
205 filename_length |= extent->data.file_match.filename_length[2] << 8;
206 filename_length |= extent->data.file_match.filename_length[3];
210 printf(" File length: %llu\n", length);
211 printf(" Filename len: %d\n", filename_length);
212 printf(" Filename: %s\n", filename);
213 printf(" File MD5sum: %s\n", print_md5(extent->data.file_match.md5));
216 if (cmd & CMD_BUILD_IMAGE)
218 chunk_fd = open(filename, O_RDONLY|O_LARGEFILE);
221 printf("FAILED to open filename %s, error %d. Aborting\n", filename, errno);
227 printf("Writing %7llu bytes of %s to output file\n", length, filename);
228 error = my_sendfile(chunk_fd, out_fd, length);
232 printf("FAILED to copy contents of %s into output file; error %d. Aborting\n", filename, error);
238 return extent_length;
241 UINT64 handle_jtet_no_match(UINT64 extent_length,
242 UINT32 start_sector, unsigned char *buf)
246 struct jt_extent_data *extent = (struct jt_extent_data *)buf;
248 length |= (UINT64)extent->data.nomatch.unmatched_length[0] << 56;
249 length |= (UINT64)extent->data.nomatch.unmatched_length[1] << 48;
250 length |= (UINT64)extent->data.nomatch.unmatched_length[2] << 40;
251 length |= (UINT64)extent->data.nomatch.unmatched_length[3] << 32;
252 length |= (UINT64)extent->data.nomatch.unmatched_length[4] << 24;
253 length |= (UINT64)extent->data.nomatch.unmatched_length[5] << 16;
254 length |= (UINT64)extent->data.nomatch.unmatched_length[6] << 8;
255 length |= (UINT64)extent->data.nomatch.unmatched_length[7];
259 printf(" Unmatched data, length %llu\n", length);
260 printf(" Chunk MD5sum: %s\n", print_md5(extent->data.nomatch.md5));
263 if (cmd & CMD_BUILD_IMAGE)
265 /* Seek past the header of this block */
266 lseek(jte_fd, sizeof(struct jt_extent_data), SEEK_CUR);
268 printf("Writing %7llu bytes of unmatched image data to output file\n", length);
269 error = my_sendfile(jte_fd, out_fd, length);
272 printf("FAILED to copy unmatched data chunk into output file; error %d. Aborting\n", error);
277 return extent_length;
280 UINT64 parse_jte_block(UINT64 offset, unsigned char *buf, size_t buf_size)
283 UINT64 extent_length = 0;
284 UINT32 start_sector = 0;
285 struct jt_extent_data *extent = (struct jt_extent_data *)buf;
287 if (strncmp(extent->id, JTE_ID_STRING, 4))
289 printf("Error! Didn't find expected JTE block at offset %lld\n", offset);
293 printf("\nJTE block found at offset %lld\n", offset);
295 extent_type = extent->extent_type;
297 extent_length |= (UINT64)extent->extent_length[0] << 56;
298 extent_length |= (UINT64)extent->extent_length[1] << 48;
299 extent_length |= (UINT64)extent->extent_length[2] << 40;
300 extent_length |= (UINT64)extent->extent_length[3] << 32;
301 extent_length |= (UINT64)extent->extent_length[4] << 24;
302 extent_length |= (UINT64)extent->extent_length[5] << 16;
303 extent_length |= (UINT64)extent->extent_length[6] << 8;
304 extent_length |= (UINT64)extent->extent_length[7];
306 start_sector |= extent->start_sector[0] << 24;
307 start_sector |= extent->start_sector[1] << 16;
308 start_sector |= extent->start_sector[2] << 8;
309 start_sector |= extent->start_sector[3];
312 printf(" extent type %d, length %llu, start_sector %ld (out offset %llu)\n",
313 extent_type, extent_length, start_sector, (off_t)start_sector * sector_size);
318 return handle_jtet_header(extent_length, start_sector, buf);
320 return handle_jtet_footer(extent_length, start_sector, buf);
321 case JTET_FILE_MATCH:
322 return handle_jtet_file_match(extent_length, start_sector, buf);
324 return handle_jtet_no_match(extent_length, start_sector, buf);
326 printf("Awooga! Invalid extent type!\n");
331 int main(int argc, char **argv)
333 char *filename = NULL;
334 char *outfile = NULL;
335 unsigned char *buf = NULL;
341 for (i = 1; i < argc; i++)
343 if (!strcmp(argv[i], "-l"))
345 else if (!strcmp(argv[i], "-b"))
346 cmd |= CMD_BUILD_IMAGE;
347 else if (!strcmp(argv[i], "-v"))
349 else if (!strcmp(argv[i], "-o") && i < argc - 1)
351 else if (!strcmp(argv[i], "-f") && i < argc - 1)
352 filename = argv[++i];
358 if (NULL == filename)
360 printf("No filename specified! Try again...\n");
364 if ( (cmd & CMD_BUILD_IMAGE) && !outfile)
366 printf("No output filename given; aborting...\n");
370 jte_fd = open(filename, O_RDONLY|O_LARGEFILE);
373 printf("Failed to open input file %s, error %d!. Try again...\n", filename, errno);
379 out_fd = open(outfile, O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, 0644);
382 printf("Failed to open output file %s, error %d!\n", outfile, errno);
387 buf = malloc(BUF_SIZE);
390 printf("Failed to malloc %d bytes. Abort!\n", BUF_SIZE);
396 UINT64 start_offset = -1;
397 lseek(jte_fd, offset, SEEK_SET);
398 bytes = read(jte_fd, buf, BUF_SIZE);
401 printf("Failed to read! error %d\n", errno);
405 lseek(jte_fd, offset, SEEK_SET);
406 start_offset = parse_jte_block(offset, buf, bytes);
408 break; /* We're finished! */
409 offset += start_offset;