patch zlib check
[platform/upstream/cdrkit.git] / genisoimage / eltorito.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /* @(#)eltorito.c       1.33 05/02/27 joerg */
14 /*
15  * Program eltorito.c - Handle El Torito specific extensions to iso9660.
16  *
17  *
18  *  Written by Michael Fulbright <msf@redhat.com> (1996).
19  *
20  * Copyright 1996 RedHat Software, Incorporated
21  * Copyright (c) 1999-2004 J. Schilling
22  *
23  * This program is free software; you can redistribute it and/or modify
24  * it under the terms of the GNU General Public License as published by
25  * the Free Software Foundation; either version 2, or (at your option)
26  * any later version.
27  *
28  * This program is distributed in the hope that it will be useful,
29  * but WITHOUT ANY WARRANTY; without even the implied warranty of
30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31  * GNU General Public License for more details.
32  *
33  * You should have received a copy of the GNU General Public License
34  * along with this program; if not, write to the Free Software
35  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36  */
37
38 #include <mconfig.h>
39 #include "genisoimage.h"
40 #include <fctldefs.h>
41 #include <utypes.h>
42 #include <intcvt.h>
43 #include "match.h"
44 #include "diskmbr.h"
45 #include "bootinfo.h"
46 #include <schily.h>
47
48 #undef MIN
49 #define MIN(a, b) (((a) < (b))? (a): (b))
50
51 static struct eltorito_validation_entry valid_desc;
52 static struct eltorito_boot_descriptor gboot_desc;
53 static struct disk_master_boot_record disk_mbr;
54 static unsigned int bcat_de_flags;
55
56 void    init_boot_catalog(const char *path);
57 void    insert_boot_cat(void);
58 static  void    get_torito_desc(struct eltorito_boot_descriptor *boot_desc);
59 static  void    fill_boot_desc(struct eltorito_defaultboot_entry *boot_desc_entry,
60                                                                                 struct eltorito_boot_entry_info *boot_entry);
61 void    get_boot_entry(void);
62 void    new_boot_entry(void);
63 static  int     tvd_write(FILE *outfile);
64
65
66 static  char    *bootcat_path;          /* filename of boot catalog */
67 /*
68  * Make sure any existing boot catalog is excluded
69  */
70 void
71 init_boot_catalog(const char *path)
72 {
73 #ifdef  SORTING
74         struct eltorito_boot_entry_info * cbe;
75
76         for (cbe = first_boot_entry;
77             cbe != NULL;
78             cbe = cbe->next) {
79                 char    *p;
80
81                 if (cbe->boot_image == NULL)
82                         comerrno(EX_BAD, "Missing boot image name, use -eltorito-boot option.\n");
83                 p = (char *) e_malloc(strlen(cbe->boot_image) + strlen(path) + 2);
84                 strcpy(p, path);
85                 if (p[strlen(p) - 1] != '/') {
86                         strcat(p, "/");
87                 }
88                 strcat(p, cbe->boot_image);
89                 add_sort_match(p, sort_matches(p, 1));
90                 free(p);
91         }
92 #endif
93         bootcat_path = (char *) e_malloc(strlen(boot_catalog) + strlen(path) + 2);
94         strcpy(bootcat_path, path);
95         if (bootcat_path[strlen(bootcat_path) - 1] != '/') {
96                 strcat(bootcat_path, "/");
97         }
98         strcat(bootcat_path, boot_catalog);
99
100         /*
101          * we are going to create a virtual catalog file
102          * - so make sure any existing is excluded
103          */
104         add_match(bootcat_path);
105
106         /* flag the file as a memory file */
107         bcat_de_flags = MEMORY_FILE;
108
109         /* find out if we want to "hide" this file */
110         if (i_matches(boot_catalog) || i_matches(bootcat_path))
111                 bcat_de_flags |= INHIBIT_ISO9660_ENTRY;
112
113         if (j_matches(boot_catalog) || j_matches(bootcat_path))
114                 bcat_de_flags |= INHIBIT_JOLIET_ENTRY;
115
116 }/* init_boot_catalog(... */
117
118 /*
119  * Create a boot catalog file in memory - genisoimage already uses this type of
120  * file for the TRANS.TBL files. Therefore the boot catalog is set up in
121  * similar way
122  */
123 void
124 insert_boot_cat()
125 {
126         struct directory_entry  *de;
127         struct directory_entry  *s_entry;
128         char                    *p1;
129         char                    *p2;
130         char                    *p3;
131         struct directory        *this_dir;
132         struct directory        *dir;
133         char                    *buffer;
134
135         init_fstatbuf();
136
137         buffer = (char *) e_malloc(SECTOR_SIZE);
138         memset(buffer, 0, SECTOR_SIZE);
139
140         /*
141          * try to find the directory that will contain the boot.cat file
142          * - not very neat, but I can't think of a better way
143          */
144         p1 = strdup(boot_catalog);
145
146         /* get dirname (p1) and basename (p2) of boot.cat */
147         if ((p2 = strrchr(p1, '/')) != NULL) {
148                 *p2 = '\0';
149                 p2++;
150
151                 /* find the dirname directory entry */
152                 de = search_tree_file(root, p1);
153                 if (!de) {
154 #ifdef  USE_LIBSCHILY
155                         comerrno(EX_BAD,
156                         "Uh oh, I cant find the boot catalog directory '%s'!\n",
157                                                                 p1);
158 #else
159                         fprintf(stderr,
160                         "Uh oh, I cant find the boot catalog directory '%s'!\n",
161                                                                 p1);
162                         exit(1);
163 #endif
164                 }
165                 this_dir = 0;
166
167                 /* get the basename (p3) of the directory */
168                 if ((p3 = strrchr(p1, '/')) != NULL)
169                         p3++;
170                 else
171                         p3 = p1;
172
173                 /* find the correct sub-directory entry */
174                 for (dir = de->filedir->subdir; dir; dir = dir->next)
175                         if (!(strcmp(dir->de_name, p3)))
176                                 this_dir = dir;
177
178                 if (this_dir == 0) {
179 #ifdef  USE_LIBSCHILY
180                         comerrno(EX_BAD,
181                         "Uh oh, I cant find the boot catalog directory '%s'!\n",
182                                                                 p3);
183 #else
184                         fprintf(stderr,
185                         "Uh oh, I cant find the boot catalog directory '%s'!\n",
186                                                                 p3);
187                         exit(1);
188 #endif
189                 }
190         } else {
191                 /* boot.cat is in the root directory */
192                 this_dir = root;
193                 p2 = p1;
194         }
195
196         /*
197          * make a directory entry in memory (using the same set up as for table
198          * entries
199          */
200         s_entry = (struct directory_entry *)
201                 e_malloc(sizeof (struct directory_entry));
202         memset(s_entry, 0, sizeof (struct directory_entry));
203         s_entry->next = this_dir->contents;
204         this_dir->contents = s_entry;
205
206 #ifdef SORTING
207         /* inherit any sort weight from parent directory */
208         s_entry->sort = this_dir->sort;
209         s_entry->sort += 2;
210
211         /* see if this entry should have a new weighting */
212         if (do_sort) {
213                 s_entry->sort = sort_matches(bootcat_path, s_entry->sort);
214         }
215 #endif /* SORTING */
216
217         s_entry->isorec.flags[0] = ISO_FILE;
218         s_entry->priority = 32768;
219         iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime);
220         s_entry->inode = TABLE_INODE;
221         s_entry->dev = (dev_t) UNCACHED_DEVICE;
222         set_723(s_entry->isorec.volume_sequence_number,
223                                                 volume_sequence_number);
224         set_733((char *) s_entry->isorec.size, SECTOR_SIZE);
225         s_entry->size = SECTOR_SIZE;
226         s_entry->filedir = this_dir;
227         s_entry->name = strdup(p2);
228         iso9660_file_length(p2, s_entry, 0);
229
230         /* flag file as necessary */
231
232         /*
233          * If the current directory is hidden, then hide this entry
234          */
235         if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY)
236                 bcat_de_flags |= INHIBIT_ISO9660_ENTRY;
237         if (this_dir->dir_flags & INHIBIT_JOLIET_ENTRY)
238                 bcat_de_flags |= INHIBIT_JOLIET_ENTRY;
239
240         s_entry->de_flags = bcat_de_flags;
241
242         if ((use_XA || use_RockRidge) &&
243             !(bcat_de_flags & INHIBIT_ISO9660_ENTRY)) {
244                 fstatbuf.st_mode = 0444 | S_IFREG;
245                 fstatbuf.st_nlink = 1;
246                 generate_xa_rr_attributes("",
247                         p2, s_entry,
248                         &fstatbuf, &fstatbuf, 0);
249         }
250         /*
251          *  memory files are stored at s_entry->table
252          * - but this is also used for each s_entry to generate
253          * TRANS.TBL entries. So if we are generating tables,
254          * store the TRANS.TBL data here for the moment
255          */
256         if (generate_tables && !(bcat_de_flags & INHIBIT_ISO9660_ENTRY)) {
257                 sprintf(buffer, "F\t%s\n", s_entry->name);
258
259                 /* copy the TRANS.TBL entry info and clear the buffer */
260                 s_entry->table = strdup(buffer);
261                 memset(buffer, 0, SECTOR_SIZE);
262
263                 /*
264                  * store the (empty) file data in the
265                  * unused s_entry->whole_name element for the time being
266                  * - this will be transferred to s_entry->table after any
267                  * TRANS.TBL processing later
268                  */
269                 s_entry->whole_name = buffer;
270         } else {
271                 /* store the (empty) file data in the s_entry->table element */
272                 s_entry->table = buffer;
273                 s_entry->whole_name = NULL;
274         }
275 }
276
277 static void
278 get_torito_desc(struct eltorito_boot_descriptor *boot_desc)
279 {
280         int                     checksum;
281         unsigned char           *checksum_ptr;
282         struct directory_entry  *de2;   /* Boot catalog */
283         int                     i;
284         int                     offset;
285         struct eltorito_defaultboot_entry boot_desc_record;
286
287         memset(boot_desc, 0, sizeof (*boot_desc));
288         boot_desc->type[0] = 0;
289         memcpy(boot_desc->id, ISO_STANDARD_ID, sizeof (ISO_STANDARD_ID));
290         boot_desc->version[0] = 1;
291
292         memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof (EL_TORITO_ID));
293
294         /*
295          * search from root of iso fs to find boot catalog
296          * - we already know where the boot catalog is
297          * - we created it above - but lets search for it anyway
298          * - good sanity check!
299          */
300         de2 = search_tree_file(root, boot_catalog);
301         if (!de2 || !(de2->de_flags & MEMORY_FILE)) {
302 #ifdef  USE_LIBSCHILY
303                 comerrno(EX_BAD, "Uh oh, I cant find the boot catalog '%s'!\n",
304                                                         boot_catalog);
305 #else
306                 fprintf(stderr, "Uh oh, I cant find the boot catalog '%s'!\n",
307                                                         boot_catalog);
308                 exit(1);
309 #endif
310         }
311         set_731(boot_desc->bootcat_ptr,
312                 (unsigned int) get_733(de2->isorec.extent));
313
314         /*
315          * we have the boot image, so write boot catalog information
316          * Next we write out the primary descriptor for the disc
317          */
318         memset(&valid_desc, 0, sizeof (valid_desc));
319         valid_desc.headerid[0] = 1;
320         valid_desc.arch[0] = EL_TORITO_ARCH_x86;
321
322         /*
323          * we'll shove start of publisher id into id field,
324          * may get truncated but who really reads this stuff!
325          */
326         if (publisher)
327                 memcpy_max(valid_desc.id, publisher,
328                                                 MIN(23, strlen(publisher)));
329
330         valid_desc.key1[0] = (char) 0x55;
331         valid_desc.key2[0] = (char) 0xAA;
332
333         /* compute the checksum */
334         checksum = 0;
335         checksum_ptr = (unsigned char *) &valid_desc;
336         /* Set checksum to 0 before computing checksum */
337         set_721(valid_desc.cksum, 0);
338         for (i = 0; i < (int)sizeof (valid_desc); i += 2) {
339                 checksum += (unsigned int) checksum_ptr[i];
340                 checksum += ((unsigned int) checksum_ptr[i + 1]) * 256;
341         }
342
343         /* now find out the real checksum */
344         checksum = -checksum;
345         set_721(valid_desc.cksum, (unsigned int) checksum);
346
347         /* now write it to the virtual boot catalog */
348         memcpy(de2->table, &valid_desc, 32);
349
350         for (current_boot_entry = first_boot_entry, offset = sizeof (valid_desc);
351                 current_boot_entry != NULL;
352                 current_boot_entry = current_boot_entry->next,
353                 offset += sizeof (boot_desc_record)) {
354
355                 if (offset >= SECTOR_SIZE) {
356 #ifdef  USE_LIBSCHILY
357                         comerrno(EX_BAD,
358                         "Too many El Torito boot entries\n");
359 #else
360                         fprintf(stderr,
361                         "Too many El Torito boot entries\n");
362                         exit(1);
363 #endif
364                 }
365                 fill_boot_desc(&boot_desc_record, current_boot_entry);
366                 memcpy(de2->table + offset, &boot_desc_record,
367                                         sizeof (boot_desc_record));
368         }
369 }/* get_torito_desc(... */
370
371 static void
372 fill_boot_desc(struct eltorito_defaultboot_entry *boot_desc_entry, 
373                                         struct eltorito_boot_entry_info *boot_entry)
374 {
375         struct directory_entry  *de;    /* Boot file */
376         int                     bootmbr;
377         int                     i;
378         int                     nsectors;
379         int                     geosec;
380
381         if (!boot_desc_entry || !boot_entry)
382                 return;
383
384         /* now adjust boot catalog lets find boot image first */
385         de = search_tree_file(root, boot_entry->boot_image);
386         if (!de) {
387 #ifdef  USE_LIBSCHILY
388                 comerrno(EX_BAD, "Uh oh, I cant find the boot image '%s' !\n",
389                                                         boot_entry->boot_image);
390 #else
391                 fprintf(stderr, "Uh oh, I cant find the boot image '%s' !\n",
392                                                         boot_entry->boot_image);
393                 exit(1);
394 #endif
395         }
396         /* now make the initial/default entry for boot catalog */
397         memset(boot_desc_entry, 0, sizeof (*boot_desc_entry));
398         boot_desc_entry->boot_id[0] = (char) boot_entry->not_bootable ?
399                                 EL_TORITO_NOT_BOOTABLE : EL_TORITO_BOOTABLE;
400
401         /* use default BIOS loadpnt */
402         set_721(boot_desc_entry->loadseg, boot_entry->load_addr);
403
404         /*
405          * figure out size of boot image in 512-byte sectors.
406          * However, round up to the nearest integral CD (2048-byte) sector.
407          * This is only used for no-emulation booting.
408          */
409         nsectors = boot_entry->load_size ? boot_entry->load_size :
410                                 ISO_BLOCKS(de->size) * (SECTOR_SIZE/512);
411
412         if (verbose > 0) {
413                 fprintf(stderr,
414                         "Size of boot image is %d sectors -> ", nsectors);
415         }
416
417         if (boot_entry->hard_disk_boot) {
418                 /* sanity test hard disk boot image */
419                 boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_HD;
420                 if (verbose > 0)
421                         fprintf(stderr, "Emulating a hard disk\n");
422
423                 /* read MBR */
424                 bootmbr = open(de->whole_name, O_RDONLY | O_BINARY);
425                 if (bootmbr == -1) {
426 #ifdef  USE_LIBSCHILY
427                         comerr("Error opening boot image '%s' for read.\n",
428                                                         de->whole_name);
429 #else
430                         fprintf(stderr,
431                                 "Error opening boot image '%s' for read.\n",
432                                                         de->whole_name);
433                         perror("");
434                         exit(1);
435 #endif
436                 }
437                 if (read(bootmbr, &disk_mbr, sizeof (disk_mbr)) !=
438                                                         sizeof (disk_mbr)) {
439 #ifdef  USE_LIBSCHILY
440                         comerr("Error reading MBR from boot image '%s'.\n",
441                                                         de->whole_name);
442 #else
443                         fprintf(stderr,
444                                 "Error reading MBR from boot image '%s'.\n",
445                                                         de->whole_name);
446                         exit(1);
447 #endif
448                 }
449                 close(bootmbr);
450                 if (la_to_u_2_byte(disk_mbr.magic) != MBR_MAGIC) {
451 #ifdef  USE_LIBSCHILY
452                         errmsgno(EX_BAD,
453                         "Warning: boot image '%s' MBR is not a boot sector.\n",
454                                                         de->whole_name);
455 #else
456                         fprintf(stderr,
457                                 "Warning: boot image '%s' MBR is not a boot sector.\n",
458                                                         de->whole_name);
459 #endif
460                 }
461                 /* find partition type */
462                 boot_desc_entry->sys_type[0] = PARTITION_UNUSED;
463                 for (i = 0; i < PARTITION_COUNT; ++i) {
464                         int             s_cyl_sec;
465                         int             e_cyl_sec;
466
467                         s_cyl_sec =
468                         la_to_u_2_byte(disk_mbr.partition[i].s_cyl_sec);
469                         e_cyl_sec =
470                         la_to_u_2_byte(disk_mbr.partition[i].e_cyl_sec);
471
472                         if (disk_mbr.partition[i].type != PARTITION_UNUSED) {
473                                 if (boot_desc_entry->sys_type[0] !=
474                                                         PARTITION_UNUSED) {
475 #ifdef  USE_LIBSCHILY
476                                         comerrno(EX_BAD,
477                                         "Boot image '%s' has multiple partitions.\n",
478                                                         de->whole_name);
479 #else
480                                         fprintf(stderr,
481                                         "Boot image '%s' has multiple partitions.\n",
482                                                         de->whole_name);
483                                         exit(1);
484 #endif
485                                 }
486                                 boot_desc_entry->sys_type[0] =
487                                                 disk_mbr.partition[i].type;
488
489                                 /* a few simple sanity warnings */
490                                 if (!boot_entry->not_bootable &&
491                                     disk_mbr.partition[i].status !=
492                                                         PARTITION_ACTIVE) {
493                                         fprintf(stderr,
494                                         "Warning: partition not marked active.\n");
495                                 }
496                                 if (MBR_CYLINDER(s_cyl_sec) != 0 ||
497                                         disk_mbr.partition[i].s_head != 1 ||
498                                         MBR_SECTOR(s_cyl_sec != 1)) {
499                                         fprintf(stderr,
500                                         "Warning: partition does not start at 0/1/1.\n");
501                                 }
502                                 geosec = (MBR_CYLINDER(e_cyl_sec) + 1) *
503                                         (disk_mbr.partition[i].e_head + 1) *
504                                         MBR_SECTOR(e_cyl_sec);
505                                 if (geosec != nsectors) {
506                                         fprintf(stderr,
507                                         "Warning: image size does not match geometry (%d)\n",
508                                                 geosec);
509                                 }
510 #ifdef DEBUG_TORITO
511                                 fprintf(stderr, "Partition start %u/%u/%u\n",
512                                         MBR_CYLINDER(s_cyl_sec),
513                                         disk_mbr.partition[i].s_head,
514                                         MBR_SECTOR(s_cyl_sec));
515                                 fprintf(stderr, "Partition end %u/%u/%u\n",
516                                         MBR_CYLINDER(e_cyl_sec),
517                                         disk_mbr.partition[i].e_head,
518                                         MBR_SECTOR(e_cyl_sec));
519 #endif
520                         }
521                 }
522                 if (boot_desc_entry->sys_type[0] == PARTITION_UNUSED) {
523 #ifdef  USE_LIBSCHILY
524                         comerrno(EX_BAD,
525                                         "Boot image '%s' has no partitions.\n",
526                                                         de->whole_name);
527 #else
528                         fprintf(stderr,
529                                         "Boot image '%s' has no partitions.\n",
530                                                         de->whole_name);
531                         exit(1);
532 #endif
533                 }
534 #ifdef DEBUG_TORITO
535                 fprintf(stderr, "Partition type %u\n",
536                                                 boot_desc_entry->sys_type[0]);
537 #endif
538         /* load single boot sector, in this case the MBR */
539                 nsectors = 1;
540
541         } else if (boot_entry->no_emul_boot) {
542                 /*
543                  * no emulation is a simple image boot of all the sectors
544                  * in the boot image
545                  */
546                 boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_NOEMUL;
547                 if (verbose > 0)
548                         fprintf(stderr, "No emulation\n");
549
550         } else {
551                 /* choose size of emulated floppy based on boot image size */
552                 if (nsectors == 2880) {
553                         boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_144FLOP;
554                         if (verbose > 0)
555                                 fprintf(stderr, "Emulating a 1440 kB floppy\n");
556
557                 } else if (nsectors == 5760) {
558                         boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_288FLOP;
559                         if (verbose > 0)
560                                 fprintf(stderr, "Emulating a 2880 kB floppy\n");
561
562                 } else if (nsectors == 2400) {
563                         boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_12FLOP;
564                         if (verbose > 0)
565                                 fprintf(stderr, "Emulating a 1200 kB floppy\n");
566
567                 } else {
568 #ifdef  USE_LIBSCHILY
569                         comerrno(EX_BAD,
570                         "Error - boot image '%s' has not an allowable size.\n",
571                                                         de->whole_name);
572 #else
573                         fprintf(stderr,
574                         "Error - boot image '%s' has not an allowable size.\n",
575                                                         de->whole_name);
576                         exit(1);
577 #endif
578                 }
579
580                 /* load single boot sector for floppies */
581                 nsectors = 1;
582         }
583
584         /* fill in boot image details */
585 #ifdef DEBUG_TORITO
586         fprintf(stderr, "Boot %u sectors\n", nsectors);
587         fprintf(stderr, "Extent of boot images is %d\n",
588                                 get_733(de->isorec.extent));
589 #endif
590         set_721(boot_desc_entry->nsect, (unsigned int) nsectors);
591         set_731(boot_desc_entry->bootoff,
592                 (unsigned int) get_733(de->isorec.extent));
593
594
595         /* If the user has asked for it, patch the boot image */
596         if (boot_entry->boot_info_table) {
597                 int             bootimage;
598                 unsigned int    bi_checksum;
599                 unsigned int    total_len;
600                 static char     csum_buffer[SECTOR_SIZE];
601                 int             len;
602                 struct genisoimage_boot_info bi_table;
603                 bootimage = open(de->whole_name, O_RDWR | O_BINARY);
604                 if (bootimage == -1) {
605 #ifdef  USE_LIBSCHILY
606                         comerr(
607                         "Error opening boot image file '%s' for update.\n",
608                                                         de->whole_name);
609 #else
610                         fprintf(stderr,
611                         "Error opening boot image file '%s' for update.\n",
612                                                         de->whole_name);
613                         perror("");
614                         exit(1);
615 #endif
616                 }
617         /* Compute checksum of boot image, sans 64 bytes */
618                 total_len = 0;
619                 bi_checksum = 0;
620                 while ((len = read(bootimage, csum_buffer, SECTOR_SIZE)) > 0) {
621                         if (total_len & 3) {
622 #ifdef  USE_LIBSCHILY
623                                 comerrno(EX_BAD,
624                                 "Odd alignment at non-end-of-file in boot image '%s'.\n",
625                                                         de->whole_name);
626 #else
627                                 fprintf(stderr,
628                                 "Odd alignment at non-end-of-file in boot image '%s'.\n",
629                                                         de->whole_name);
630                                 exit(1);
631 #endif
632                         }
633                         if (total_len < 64)
634                                 memset(csum_buffer, 0, 64 - total_len);
635                         if (len < SECTOR_SIZE)
636                                 memset(csum_buffer + len, 0, SECTOR_SIZE-len);
637                         for (i = 0; i < SECTOR_SIZE; i += 4)
638                                 bi_checksum += get_731(&csum_buffer[i]);
639                         total_len += len;
640                 }
641
642                 if (total_len != de->size) {
643 #ifdef  USE_LIBSCHILY
644                         comerrno(EX_BAD,
645                         "Boot image file '%s' changed underneath us!\n",
646                                                 de->whole_name);
647 #else
648                         fprintf(stderr,
649                         "Boot image file '%s' changed underneath us!\n",
650                                                 de->whole_name);
651                         exit(1);
652 #endif
653                 }
654                 /* End of file, set position to byte 8 */
655                 lseek(bootimage, (off_t)8, SEEK_SET);
656                 memset(&bi_table, 0, sizeof (bi_table));
657                 /* Is it always safe to assume PVD is at session_start+16? */
658                 set_731(bi_table.bi_pvd, session_start + 16);
659                 set_731(bi_table.bi_file, de->starting_block);
660                 set_731(bi_table.bi_length, de->size);
661                 set_731(bi_table.bi_csum, bi_checksum);
662
663                 write(bootimage, &bi_table, sizeof (bi_table)); /* FIXME: check return value */
664                 close(bootimage);
665         }
666 }/* fill_boot_desc(... */
667
668 void
669 get_boot_entry()
670 {
671         if (current_boot_entry)
672                 return;
673
674         current_boot_entry = (struct eltorito_boot_entry_info *)
675                         e_malloc(sizeof (struct eltorito_boot_entry_info));
676         memset(current_boot_entry, 0, sizeof (*current_boot_entry));
677
678         if (!first_boot_entry) {
679                 first_boot_entry = current_boot_entry;
680                 last_boot_entry = current_boot_entry;
681         } else {
682                 last_boot_entry->next = current_boot_entry;
683                 last_boot_entry = current_boot_entry;
684         }
685 }
686
687 void
688 new_boot_entry()
689 {
690         current_boot_entry = NULL;
691 }
692
693 /*
694  * Function to write the EVD for the disc.
695  */
696 static int
697 tvd_write(FILE *outfile)
698 {
699         /* check the boot image is not NULL */
700         if (!boot_image) {
701 #ifdef  USE_LIBSCHILY
702                 comerrno(EX_BAD, "No boot image specified.\n");
703 #else
704                 fprintf(stderr, "No boot image specified.\n");
705                 exit(1);
706 #endif
707         }
708         /* Next we write out the boot volume descriptor for the disc */
709         get_torito_desc(&gboot_desc);
710         jtwrite(&gboot_desc, SECTOR_SIZE, 1, 0, FALSE);
711         xfwrite(&gboot_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
712         last_extent_written++;
713         return (0);
714 }
715
716 struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write, "Eltorito Volume Descriptor"};