2 * This file has been modified for the cdrkit suite.
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).
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.
13 /* @(#)write.c 1.88 06/02/01 joerg */
14 /* Parts from @(#)write.c 1.106 07/02/17 joerg */
16 * Program write.c - dump memory structures to file for iso9660 filesystem.
18 * Written by Eric Youngdale (1993).
20 * Copyright 1993 Yggdrasil Computing, Incorporated
21 * Copyright (c) 1999-2003 J. Schilling
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)
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.
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.
38 /* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */
41 #include "genisoimage.h"
50 #include "dvd_reader.h"
62 /* Max number of sectors we will write at one time */
65 /* Counters for statistics */
67 static int table_size = 0;
68 static int total_dir_size = 0;
69 static int rockridge_size = 0;
70 static struct directory **pathlist;
71 static int next_path_index = 1;
74 static int is_rr_dir = 0;
76 struct output_fragment *out_tail;
77 struct output_fragment *out_list;
79 struct iso_primary_descriptor vol_desc;
81 void set_721(char *pnt, unsigned int i);
82 void set_722(char *pnt, unsigned int i);
83 void set_723(char *pnt, unsigned int i);
84 void set_731(char *pnt, unsigned int i);
85 void set_732(char *pnt, unsigned int i);
86 void set_733(char *pnt, unsigned int i);
90 static int xawrite(void *buffer, int size, int count, FILE *file,
91 int submode, BOOL islast);
92 void xfwrite(void *buffer, int size, int count, FILE *file, int submode,
94 static int assign_directory_addresses(struct directory *node);
96 static void write_one_file(char *filename, off_t size, FILE *outfile,
99 static void write_one_file(char *filename, off_t size, FILE *outfile);
101 static void write_files(FILE *outfile);
103 static void dump_filelist __PR((void));
105 static int compare_dirs(const void *rr, const void *ll);
106 int sort_directory(struct directory_entry **sort_dir, int rr);
107 static int root_gen(void);
108 static BOOL assign_file_addresses(struct directory *dpnt, BOOL isnest);
109 static void free_one_directory(struct directory *dpnt);
110 static void free_directories(struct directory *dpnt);
111 void generate_one_directory(struct directory *dpnt, FILE *outfile);
112 static void build_pathlist(struct directory *node);
113 static int compare_paths(void const *r, void const *l);
114 static int generate_path_tables(void);
115 void memcpy_max(char *to, char *from, int max);
116 void outputlist_insert(struct output_fragment *frag);
117 static int file_write(FILE *outfile);
118 static int pvd_write(FILE *outfile);
119 static int xpvd_write(FILE *outfile);
120 static int evd_write(FILE *outfile);
121 static int vers_write(FILE *outfile);
122 static int graftcp(char *to, char *from, char *ep);
123 static int pathcp(char *to, char *from, char *ep);
124 static int pathtab_write(FILE *outfile);
125 static int exten_write(FILE *outfile);
126 int oneblock_size(int starting_extent);
127 static int pathtab_size(int starting_extent);
128 static int startpad_size(int starting_extent);
129 static int interpad_size(int starting_extent);
130 static int endpad_size(int starting_extent);
131 static int file_gen(void);
132 static int dirtree_dump(void);
133 static int dirtree_fixup(int starting_extent);
134 static int dirtree_size(int starting_extent);
135 static int ext_size(int starting_extent);
136 static int dirtree_write(FILE *outfile);
137 static int dirtree_cleanup(FILE *outfile);
138 static int startpad_write(FILE *outfile);
139 static int interpad_write(FILE *outfile);
140 static int endpad_write(FILE *outfile);
143 static int hfs_get_parms(char *key);
144 static void hfs_file_gen(int start_extent);
145 static void gen_prepboot(void);
146 Ulong get_adj_size(int Csize);
147 int adj_size(int Csize, int start_extent, int extra);
148 void adj_size_other(struct directory *dpnt);
149 static int hfs_hce_write(FILE * outfile);
150 int insert_padding_file(int size);
151 #endif /* APPLE_HYB */
154 static int compare_sort(const void * rr, const void * ll);
155 static void reassign_link_addresses(struct directory * dpnt);
156 static int sort_file_addresses(void);
160 * Routines to actually write the disc. We write sequentially so that
161 * we could write a tape, or write the disc directly
163 #define FILL_SPACE(X) memset(vol_desc.X, ' ', sizeof (vol_desc.X))
166 set_721(char *pnt, unsigned int i)
169 pnt[1] = (i >> 8) & 0xff;
173 set_722(char *pnt, unsigned int i)
175 pnt[0] = (i >> 8) & 0xff;
180 set_723(char *pnt, unsigned int i)
182 pnt[3] = pnt[0] = i & 0xff;
183 pnt[2] = pnt[1] = (i >> 8) & 0xff;
187 set_731(char *pnt, unsigned int i)
190 pnt[1] = (i >> 8) & 0xff;
191 pnt[2] = (i >> 16) & 0xff;
192 pnt[3] = (i >> 24) & 0xff;
196 set_732(char *pnt, unsigned int i)
199 pnt[2] = (i >> 8) & 0xff;
200 pnt[1] = (i >> 16) & 0xff;
201 pnt[0] = (i >> 24) & 0xff;
205 set_733(char *pnt, unsigned int i)
207 pnt[7] = pnt[0] = i & 0xff;
208 pnt[6] = pnt[1] = (i >> 8) & 0xff;
209 pnt[5] = pnt[2] = (i >> 16) & 0xff;
210 pnt[4] = pnt[3] = (i >> 24) & 0xff;
216 return ((p[0] & 0xff)
217 | ((p[1] & 0xff) << 8)
218 | ((p[2] & 0xff) << 16)
219 | ((p[3] & 0xff) << 24));
225 return ((p[3] & 0xff)
226 | ((p[2] & 0xff) << 8)
227 | ((p[1] & 0xff) << 16)
228 | ((p[0] & 0xff) << 24));
234 return ((p[0] & 0xff)
235 | ((p[1] & 0xff) << 8)
236 | ((p[2] & 0xff) << 16)
237 | ((p[3] & 0xff) << 24));
241 xfwrite(void *buffer, int size, int count, FILE *file, int submode, BOOL islast)
244 * This is a hack that could be made better.
245 * XXXIs this the only place?
246 * It is definitely needed on Operating Systems that do not allow to
247 * write files that are > 2GB. If the system is fast enough to be able
248 * to feed 1400 KB/s writing speed of a DVD-R drive, use stdout.
249 * If the system cannot do this reliable, you need to use this hacky
255 if (count != 1 || (size % 2048) != 0)
256 fprintf(stderr, "Count: %d, size: %d\n", count, size);
259 if (split_output != 0 &&
260 (idx == 0 || ftell(file) >= ((off_t)1024 * 1024 * 1024))) {
262 extern char *outfile;
266 sprintf(nbuf, "%s_%02d", outfile, idx++);
267 file = freopen(nbuf, "wb", file);
270 comerr("Cannot open '%s'.\n", nbuf);
272 fprintf(stderr, "Cannot open '%s'.\n", nbuf);
282 got = xawrite(buffer, size, count, file, submode, islast);
284 got = fwrite(buffer, size, count, file);
288 comerr("cannot fwrite %d*%d\n", size, count);
290 fprintf(stderr, "cannot fwrite %d*%d\n", size, count);
295 * This comment is in hope to prevent silly people from
296 * e.g. SuSE (who did not yet learn C but believe that
297 * they need to patch other peoples code) from changing the
298 * next cast into an illegal lhs cast expression.
299 * The cast below is the correct way to handle the problem.
300 * The (void *) cast is to avoid a GCC warning like:
301 * "warning: dereferencing type-punned pointer will break \
302 * strict-aliasing rules"
303 * which is wrong this code. (void *) introduces a compatible
304 * intermediate type in the cast list.
307 buffer = (void *)(((char *)buffer) + size * got);
312 xawrite(void *buffer, int size, int count, FILE *file, int submode, BOOL islast)
314 register char *p = buffer;
315 register int amt = size * count;
317 struct xa_subhdr subhdr[2];
319 if (osecsize == 2048)
320 return (fwrite(buffer, size, count, file));
324 "Trying to write %d bytes (not a multiple of 2048).\n",
327 subhdr[0].file_number = subhdr[1].file_number = 0;
328 subhdr[0].channel_number = subhdr[1].channel_number = 0;
329 subhdr[0].coding = subhdr[1].coding = 0;
334 subhdr[0].sub_mode = subhdr[1].sub_mode = XA_SUBH_DATA;
336 subhdr[0].sub_mode = subhdr[1].sub_mode = submode;
338 subhdr[0].sub_mode = subhdr[1].sub_mode = XA_SUBH_DATA;
341 if ((amt <= 2048) && islast) {
342 subhdr[0].sub_mode = subhdr[1].sub_mode
343 |= (XA_SUBH_EOR|XA_SUBH_EOF);
345 n = fwrite(&subhdr, sizeof (subhdr), 1, file);
349 n = fwrite(p, 2048, 1, file);
361 * use the deferred_write struct to store info about the hfs_boot_file
363 static struct deferred_write mac_boot;
365 #endif /* APPLE_HYB */
366 static struct deferred_write *dw_head = NULL,
369 unsigned int last_extent_written = 0;
370 static Uint path_table_index;
374 * We recursively walk through all of the directories and assign extent
375 * numbers to them. We have already assigned extent numbers to everything that
376 * goes in front of them
379 assign_directory_addresses(struct directory *node)
382 struct directory *dpnt;
387 /* skip if it's hidden */
388 if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) {
393 * If we already have an extent for this (i.e. it came from a
394 * multisession disc), then don't reassign a new extent.
396 dpnt->path_index = next_path_index++;
397 if (dpnt->extent == 0) {
398 dpnt->extent = last_extent;
399 dir_size = ISO_BLOCKS(dpnt->size);
401 last_extent += dir_size;
404 * Leave room for the CE entries for this directory.
405 * Keep them close to the reference directory so that
406 * access will be quick.
408 if (dpnt->ce_bytes) {
409 last_extent += ISO_BLOCKS(dpnt->ce_bytes);
413 assign_directory_addresses(dpnt->subdir);
422 write_one_file(char *filename, off_t size, FILE *outfile, off_t off)
425 write_one_file(char *filename, off_t size, FILE *outfile)
426 #endif /* APPLE_HYB */
429 * It seems that there are still stone age C-compilers
431 * The Metrowerks C found on BeOS/PPC does not allow
432 * more than 32kB of local vars.
433 * As we do not need to call write_one_file() recursively
434 * we make buffer static.
436 static char buffer[SECTOR_SIZE * NSECT];
442 unsigned char md5[16];
443 int include_in_jigdo = list_file_in_jigdo(filename, size, &mirror_name, md5);
445 if ((infile = fopen(filename, "rb")) == NULL) {
447 comerr("cannot open '%s'\n", filename);
449 #ifndef HAVE_STRERROR
450 fprintf(stderr, "cannot open '%s': (%d)\n",
453 fprintf(stderr, "cannot open '%s': %s\n",
454 filename, strerror(errno));
460 fseek(infile, off, SEEK_SET);
461 #endif /* APPLE_HYB */
464 if (include_in_jigdo)
465 write_jt_match_record(filename, mirror_name, SECTOR_SIZE, size, md5);
470 use = (remain > SECTOR_SIZE * NSECT - 1 ?
471 NSECT * SECTOR_SIZE : remain);
472 use = ISO_ROUND_UP(use); /* Round up to nearest sector */
474 memset(buffer, 0, use);
476 amt = fread(buffer, 1, use, infile);
477 if (amt < use && amt < remain) {
479 * Note that genisoimage is not star and no 100% archiver.
480 * We only detect file growth if the new size does not
481 * match 'use' at the last read.
483 if (geterrno() == 0) {
486 "File '%s' did shrink.\n"
487 "Files must not be changed while genisoimage runs!\n",
491 "File '%s' did shrink.\n"
492 "Files must not be changed while genisoimage runs!\n",
498 comerr("Cannot read from '%s'\n", filename);
500 fprintf(stderr, "Cannot read from '%s'\n", filename);
504 if (!include_in_jigdo)
505 jtwrite(buffer, use, 1,
506 XA_SUBH_DATA, remain <= (SECTOR_SIZE * NSECT));
507 xfwrite(buffer, use, 1, outfile,
508 XA_SUBH_DATA, remain <= (SECTOR_SIZE * NSECT));
509 last_extent_written += use / SECTOR_SIZE;
511 if ((last_extent_written % 1000) < use / SECTOR_SIZE) {
512 fprintf(stderr, "%d..", last_extent_written);
516 (int)(last_extent_written % (gui ? 500 : 5000)) <
523 frac = last_extent_written / (1.0 * last_extent);
524 the_end = begun + (now - begun) / frac;
525 #ifndef NO_FLOATINGPOINT
526 fprintf(stderr, "%6.2f%% done, estimate finish %s",
527 frac * 100., ctime(&the_end));
529 fprintf(stderr, "%3d.%-02d%% done, estimate finish %s",
531 (int)((frac+.00005) * 10000.)%100,
540 }/* write_one_file(... */
543 write_files(FILE *outfile)
545 struct deferred_write *dwpnt,
553 "The file name is %s and pad is %d, size is %lld and extent is %d\n",
554 dwpnt->name, dwpnt->pad,
555 (Llong)dwpnt->size, dwpnt->extent);
558 jtwrite(dwpnt->table, ISO_ROUND_UP(dwpnt->size), 1, XA_SUBH_DATA, TRUE);
559 xfwrite(dwpnt->table, ISO_ROUND_UP(dwpnt->size), 1,
562 last_extent_written += ISO_BLOCKS(dwpnt->size);
563 table_size += dwpnt->size;
564 /* fprintf(stderr, "Size %lld ", (Llong)dwpnt->size); */
570 vms_write_one_file(dwpnt->name, dwpnt->size, outfile);
573 write_one_file(dwpnt->name, dwpnt->size, outfile,
576 write_one_file(dwpnt->name, dwpnt->size, outfile);
577 #endif /* APPLE_HYB */
592 #if defined(APPLE_HYB) || defined(DVD_VIDEO)
594 if (apple_hyb || dvd_video) {
596 * we may have to pad out ISO files to work with HFS
599 char blk[SECTOR_SIZE];
602 for (i = 0; i < dwpnt->pad; i++) {
603 jtwrite(blk, SECTOR_SIZE, 1, 0, FALSE);
604 xfwrite(blk, SECTOR_SIZE, 1, outfile, 0, FALSE);
605 last_extent_written++;
608 #endif /* APPLE_HYB || DVD_VIDEO */
616 }/* write_files(... */
622 struct deferred_write *dwpnt;
626 fprintf(stderr, "File %s\n", dwpnt->name);
629 fprintf(stderr, "\n");
635 compare_dirs(const void *rr, const void *ll)
639 struct directory_entry **r,
642 r = (struct directory_entry **) rr;
643 l = (struct directory_entry **) ll;
644 rpnt = (*r)->isorec.name;
645 lpnt = (*l)->isorec.name;
649 * resource fork MUST (not sure if this is true for HFS volumes) be
650 * before the data fork - so force it here
652 if ((*r)->assoc && (*r)->assoc == (*l))
654 if ((*l)->assoc && (*l)->assoc == (*r))
656 #endif /* APPLE_HYB */
658 /* If the entries are the same, this is an error. */
659 if (strcmp(rpnt, lpnt) == 0) {
662 "Error: '%s' and '%s' have the same ISO9660 name '%s'.\n",
663 (*r)->whole_name, (*l)->whole_name,
667 "Error: '%s' and '%s' have the same ISO9660 name '%s'.\n",
668 (*r)->whole_name, (*l)->whole_name,
673 /* Check we don't have the same RR name */
674 if (use_RockRidge && !is_rr_dir) {
676 * entries *can* have the same RR name in the "rr_moved"
677 * directory so skip checks if we're in reloc_dir
679 if (!(strcmp((*r)->name, (*l)->name))) {
682 "Error: '%s' and '%s' have the same Rock Ridge name '%s'.\n",
683 (*r)->whole_name, (*l)->whole_name,
687 "Error: '%s' and '%s' have the same Rock Ridge name '%s'.\n",
688 (*r)->whole_name, (*l)->whole_name,
695 * Put the '.' and '..' entries on the head of the sorted list. For
696 * normal ASCII, this always happens to be the case, but out of band
697 * characters cause this not to be the case sometimes.
698 * FIXME(eric) - these tests seem redundant, in that the name is never
699 * assigned these values. It will instead be \000 or \001, and thus
700 * should always be sorted correctly. I need to figure out why I
701 * thought I needed this in the first place.
704 if (strcmp(rpnt, ".") == 0)
706 if (strcmp(lpnt, ".") == 0)
709 if (strcmp(rpnt, "..") == 0)
711 if (strcmp(lpnt, "..") == 0)
715 * The code above is wrong (as explained in Eric's comment), leading to
716 * incorrect sort order iff the -L option ("allow leading dots") is in
717 * effect and a directory contains entries that start with a dot.
718 * (TF, Tue Dec 29 13:49:24 CET 1998)
720 if ((*r)->isorec.name_len[0] == 1 && *rpnt == 0)
721 return (-1); /* '.' */
722 if ((*l)->isorec.name_len[0] == 1 && *lpnt == 0)
725 if ((*r)->isorec.name_len[0] == 1 && *rpnt == 1)
726 return (-1); /* '..' */
727 if ((*l)->isorec.name_len[0] == 1 && *lpnt == 1)
731 while (*rpnt && *lpnt) {
732 if (*rpnt == ';' && *lpnt != ';')
734 if (*rpnt != ';' && *lpnt == ';')
737 if (*rpnt == ';' && *lpnt == ';')
740 if (*rpnt == '.' && *lpnt != '.')
742 if (*rpnt != '.' && *lpnt == '.')
745 if ((unsigned char) *rpnt < (unsigned char) *lpnt)
747 if ((unsigned char) *rpnt > (unsigned char) *lpnt)
760 * Function: sort_directory
762 * Purpose: Sort the directory in the appropriate ISO9660
765 * Notes: Returns 0 if OK, returns > 0 if an error occurred.
768 sort_directory(struct directory_entry **sort_dir, int rr)
775 struct directory_entry *s_entry;
776 struct directory_entry **sortlist;
778 /* need to keep a count of how many entries are hidden */
781 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
784 s_entry = s_entry->next;
790 /* OK, now we know how many there are. Build a vector for sorting. */
791 sortlist = (struct directory_entry **)
792 e_malloc(sizeof (struct directory_entry *) * dcount);
798 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
799 /* put any hidden entries at the end of the vector */
800 sortlist[j--] = s_entry;
802 sortlist[dcount] = s_entry;
805 len = s_entry->isorec.name_len[0];
806 s_entry->isorec.name[len] = 0;
807 s_entry = s_entry->next;
810 /* Each directory is required to contain at least . and .. */
814 "Directory size too small (. or .. missing ??%s)\n",
815 "?"); /* Try to avoid a GCC trigraph warning */
818 "Directory size too small (. or .. missing ??%s)\n",
819 "?"); /* Try to avoid a GCC trigraph warning */
824 /* only sort the non-hidden entries */
828 qsort(sortlist, dcount, sizeof (struct directory_entry *),
829 (int (*) (const void *, const void *)) compare_dirs);
831 qsort(sortlist, dcount, sizeof (struct directory_entry *),
836 * Now reassemble the linked list in the proper sorted order
837 * We still need the hidden entries, as they may be used in
840 for (i = 0; i < dcount + xcount - 1; i++) {
841 sortlist[i]->next = sortlist[i + 1];
844 sortlist[dcount + xcount - 1]->next = NULL;
845 *sort_dir = sortlist[0];
858 root_record.length[0] = 1 +
859 offsetof(struct iso_directory_record, name[0]);
860 root_record.ext_attr_length[0] = 0;
861 set_733((char *) root_record.extent, root->extent);
862 set_733((char *) root_record.size, ISO_ROUND_UP(root->size));
863 iso9660_date(root_record.date, root_statbuf.st_mtime);
864 root_record.flags[0] = ISO_DIRECTORY;
865 root_record.file_unit_size[0] = 0;
866 root_record.interleave[0] = 0;
867 set_723(root_record.volume_sequence_number, volume_sequence_number);
868 root_record.name_len[0] = 1;
874 * sorts deferred_write entries based on the sort weight
877 compare_sort(const void *rr, const void *ll)
879 struct deferred_write **r;
880 struct deferred_write **l;
884 r = (struct deferred_write **) rr;
885 l = (struct deferred_write **) ll;
886 r_sort = (*r)->s_entry->sort;
887 l_sort = (*l)->s_entry->sort;
889 if (r_sort != l_sort)
890 return (r_sort < l_sort ? 1 : -1);
892 return ((*r)->extent - (*l)->extent);
896 * reassign start extents to files that are "hard links" to
897 * files that may have been sorted
900 reassign_link_addresses(struct directory *dpnt)
902 struct directory_entry *s_entry;
903 struct file_hash *s_hash;
906 s_entry = dpnt->contents;
907 for (s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) {
908 /* link files have already been given the weight NOT_SORTED */
909 if (s_entry->sort == NOT_SORTED)
911 /* update the start extent */
912 s_hash = find_hash(s_entry->dev, s_entry->inode);
914 set_733((char *) s_entry->isorec.extent,
915 s_hash->starting_block);
916 s_entry->starting_block = s_hash->starting_block;
920 if (verbose > 2 && s_entry->size != 0) {
921 fprintf(stderr, "%8u %8u ",
922 s_entry->starting_block,
923 (unsigned int)(s_entry->starting_block + ISO_BLOCKS(s_entry->size) - 1));
925 if (s_entry->inode != TABLE_INODE) {
926 fprintf(stderr, "%s\n", s_entry->whole_name);
928 fprintf(stderr, "%s%s%s\n",
929 s_entry->filedir->whole_name,
930 SPATH_SEPARATOR, trans_tbl);
935 reassign_link_addresses(dpnt->subdir);
943 * sort files in order of the given sort weight
946 sort_file_addresses()
948 struct deferred_write *dwpnt;
949 struct deferred_write **sortlist;
950 struct directory_entry *s_entry;
955 /* need to store start extents for linked files */
958 /* find out how many files we have */
965 /* return if we have none */
970 /* save the start extent of the first file */
971 start_extent = dw_head->extent;
973 /* set up vector to store entries */
974 sortlist = (struct deferred_write **)
975 e_malloc(sizeof (struct deferred_write *) * num);
977 for (i = 0, dwpnt = dw_head; i < num; i++, dwpnt = dwpnt->next)
982 qsort(sortlist, num, sizeof (struct deferred_write *),
983 (int (*)(const void *, const void *))compare_sort);
985 qsort(sortlist, num, sizeof (struct deferred_write *), compare_sort);
988 /* reconstruct the linked list */
989 for (i = 0; i < num-1; i++) {
990 sortlist[i]->next = sortlist[i+1];
993 sortlist[num-1]->next = NULL;
994 dw_head = sortlist[0];
998 /* set the new start extents for the sorted list */
999 for (i = 0, dwpnt = dw_head; i < num; i++, dwpnt = dwpnt->next) {
1000 s_entry = dwpnt->s_entry;
1001 dwpnt->extent = s_entry->starting_block = start_extent;
1002 set_733((char *) s_entry->isorec.extent, start_extent);
1004 start_extent += ISO_BLOCKS(s_entry->size);
1007 * Shouldn't this be done for every type of sort? Otherwise
1008 * we will loose every pad info we add if we sort the files
1011 start_extent += dwpnt->pad;
1013 #endif /* DVD_VIDEO */
1015 /* cache start extents for any linked files */
1021 #endif /* SORTING */
1026 assign_file_addresses(struct directory *dpnt, BOOL isnest)
1028 struct directory *finddir;
1029 struct directory_entry *s_entry;
1030 struct file_hash *s_hash;
1031 struct deferred_write *dwpnt;
1032 char whole_path[PATH_MAX];
1034 char dvd_path[PATH_MAX];
1035 title_set_info_t * title_set_info = NULL;
1042 if (dvd_video && root == dpnt->parent &&
1043 ((p = strstr(dpnt->whole_name, "VIDEO_TS")) != 0)&&
1044 strcmp(p, "VIDEO_TS") == 0) {
1046 int maxlen = strlen(dpnt->whole_name)-8;
1047 if (maxlen > (sizeof (dvd_path)-1))
1048 maxlen = sizeof (dvd_path)-1;
1049 strncpy(dvd_path, dpnt->whole_name, maxlen);
1050 dvd_path[maxlen] = '\0';
1053 fprintf(stderr, "Found 'VIDEO_TS', the path is %s \n", dvd_path);
1055 title_set_info = DVDGetFileSet(dvd_path);
1056 if (title_set_info == 0) {
1058 * Do not switch off -dvd-video but let is fail later.
1061 errmsgno(EX_BAD, "Unable to parse DVD-Video structures.\n");
1066 #endif /* DVD_VIDEO */
1068 s_entry = dpnt->contents;
1069 for (s_entry = dpnt->contents; s_entry;
1070 s_entry = s_entry->next) {
1072 * If we already have an extent for this entry, then
1073 * don't assign a new one. It must have come from a
1074 * previous session on the disc. Note that we don't
1075 * end up scheduling the thing for writing either.
1077 if (get_733(s_entry->isorec.extent) != 0) {
1081 * This saves some space if there are symlinks present
1083 s_hash = find_hash(s_entry->dev, s_entry->inode);
1086 fprintf(stderr, "Cache hit for '%s%s%s'\n", s_entry->filedir->de_name,
1090 set_733((char *) s_entry->isorec.extent,
1091 s_hash->starting_block);
1092 set_733((char *) s_entry->isorec.size,
1095 /* check for non-directory files */
1096 if (do_sort && ((s_entry->isorec.flags[0] & ISO_DIRECTORY) == 0)) {
1097 /* make sure the real file has the highest weighting */
1098 s_hash->de->sort = MAX(s_entry->sort, s_hash->de->sort);
1099 /* flag this as a potential non-sorted file */
1100 s_entry->sort = NOT_SORTED;
1102 #endif /* SORTING */
1106 * If this is for a directory that is not a . or
1107 * a .. entry, then look up the information for the
1108 * entry. We have already assigned extents for
1109 * directories, so we just need to fill in the blanks
1112 if (strcmp(s_entry->name, ".") != 0 &&
1113 strcmp(s_entry->name, "..") != 0 &&
1114 s_entry->isorec.flags[0] & ISO_DIRECTORY) {
1115 finddir = dpnt->subdir;
1117 if (finddir->self == s_entry)
1119 finddir = finddir->next;
1122 if (title_set_info != 0) {
1123 DVDFreeFileSet(title_set_info);
1127 "Fatal goof - could not find dir entry for '%s'\n",
1131 set_733((char *) s_entry->isorec.extent,
1133 s_entry->starting_block = finddir->extent;
1134 s_entry->size = ISO_ROUND_UP(finddir->size);
1135 total_dir_size += s_entry->size;
1137 set_733((char *) s_entry->isorec.size,
1138 ISO_ROUND_UP(finddir->size));
1142 * If this is . or .., then look up the relevant info
1145 if (strcmp(s_entry->name, ".") == 0) {
1146 set_733((char *) s_entry->isorec.extent,
1150 * Set these so that the hash table has the
1151 * correct information
1153 s_entry->starting_block = dpnt->extent;
1154 s_entry->size = ISO_ROUND_UP(dpnt->size);
1157 s_entry->starting_block = dpnt->extent;
1158 set_733((char *) s_entry->isorec.size,
1159 ISO_ROUND_UP(dpnt->size));
1162 if (strcmp(s_entry->name, "..") == 0) {
1164 total_dir_size += root->size;
1166 set_733((char *) s_entry->isorec.extent,
1167 dpnt->parent->extent);
1170 * Set these so that the hash table has the
1171 * correct information
1173 s_entry->starting_block = dpnt->parent->extent;
1175 ISO_ROUND_UP(dpnt->parent->size);
1178 s_entry->starting_block = dpnt->parent->extent;
1179 set_733((char *) s_entry->isorec.size,
1180 ISO_ROUND_UP(dpnt->parent->size));
1184 * Some ordinary non-directory file. Just schedule
1185 * the file to be written. This is all quite
1186 * straightforward, just make a list and assign
1187 * extents as we go. Once we get through writing all
1188 * of the directories, we should be ready write out
1191 if (s_entry->size) {
1192 dwpnt = (struct deferred_write *)
1193 e_malloc(sizeof (struct deferred_write));
1194 /* save this directory entry for later use */
1195 dwpnt->s_entry = s_entry;
1196 /* set the initial padding to zero */
1199 if (dvd_video && (title_set_info != 0)) {
1202 pad = DVDGetFilePad(title_set_info, s_entry->name);
1205 "Implementation botch. Video pad for file %s is %d\n",
1206 s_entry->name, pad),
1208 "Either the *.IFO file is bad or you found a genisoimage bug.\n");
1211 if (verbose > 0 && pad != 0) {
1213 "The pad was %d for file %s\n", dwpnt->pad, s_entry->name);
1216 #endif /* DVD_VIDEO */
1219 * maybe an offset to start of the real
1222 dwpnt->off = s_entry->hfs_off;
1224 dwpnt->off = (off_t)0;
1225 #endif /* APPLE_HYB */
1227 dw_tail->next = dwpnt;
1233 if (s_entry->inode == TABLE_INODE) {
1234 dwpnt->table = s_entry->table;
1236 sprintf(whole_path, "%s%s%s",
1237 s_entry->filedir->whole_name,
1238 SPATH_SEPARATOR, trans_tbl);
1240 dwpnt->table = NULL;
1241 strcpy(whole_path, s_entry->whole_name);
1242 dwpnt->name = strdup(whole_path);
1245 dwpnt->size = s_entry->size;
1246 dwpnt->extent = last_extent;
1247 set_733((char *) s_entry->isorec.extent,
1249 s_entry->starting_block = last_extent;
1251 last_extent += ISO_BLOCKS(s_entry->size);
1253 /* Shouldn't we always add the pad info? */
1255 last_extent += dwpnt->pad;
1257 #endif /* DVD_VIDEO */
1258 if (verbose > 2 && !do_sort) {
1259 fprintf(stderr, "%8d %8u %s\n",
1260 s_entry->starting_block,
1261 last_extent - 1, whole_path);
1264 if (ISO_BLOCKS(s_entry->size) > 500) {
1266 "Warning: large file '%s'\n",
1269 "Starting block is %d\n",
1270 s_entry->starting_block);
1272 "Reported file size is %lld\n",
1273 (Llong)s_entry->size);
1277 #ifdef NOT_NEEDED /* Never use this code if you like to create a DVD */
1279 if (last_extent > (800000000 >> 11)) {
1280 /* More than 800Mb? Punt */
1282 "Extent overflow processing file '%s'\n",
1285 "Starting block is %d\n",
1286 s_entry->starting_block);
1288 "Reported file size is %lld\n",
1289 (Llong)s_entry->size);
1296 * This is for zero-length files. If we leave the
1297 * extent 0, then we get screwed, because many readers
1298 * simply drop files that have an extent of zero.
1299 * Thus we leave the size 0, and just assign the
1302 set_733((char *) s_entry->isorec.extent, last_extent);
1305 if (assign_file_addresses(dpnt->subdir, TRUE))
1311 if (title_set_info != NULL) {
1312 DVDFreeFileSet(title_set_info);
1314 if (dvd_video && !ret && !isnest) {
1316 "Could not find correct 'VIDEO_TS' directory.\n");
1318 #endif /* DVD_VIDEO */
1320 } /* assign_file_addresses(... */
1323 free_one_directory(struct directory *dpnt)
1325 struct directory_entry *s_entry;
1326 struct directory_entry *s_entry_d;
1328 s_entry = dpnt->contents;
1330 s_entry_d = s_entry;
1331 s_entry = s_entry->next;
1333 if (s_entry_d->rr_attributes) {
1334 free(s_entry_d->rr_attributes);
1335 s_entry_d->rr_attributes = NULL;
1337 if (s_entry_d->name != NULL) {
1338 free(s_entry_d->name);
1339 s_entry_d->name = NULL;
1341 if (s_entry_d->whole_name != NULL) {
1342 free(s_entry_d->whole_name);
1343 s_entry_d->whole_name = NULL;
1346 if (apple_both && s_entry_d->hfs_ent && !s_entry_d->assoc)
1347 free(s_entry_d->hfs_ent);
1348 #endif /* APPLE_HYB */
1353 dpnt->contents = NULL;
1354 }/* free_one_directory(... */
1357 free_directories(struct directory *dpnt)
1360 free_one_directory(dpnt);
1362 free_directories(dpnt->subdir);
1368 generate_one_directory(struct directory *dpnt, FILE *outfile)
1370 unsigned int ce_address = 0;
1372 unsigned int ce_index = 0;
1373 unsigned int ce_size;
1374 unsigned int dir_index;
1375 char *directory_buffer;
1377 struct directory_entry *s_entry;
1378 struct directory_entry *s_entry_d;
1379 unsigned int total_size;
1381 total_size = ISO_ROUND_UP(dpnt->size);
1382 directory_buffer = (char *) e_malloc(total_size);
1383 memset(directory_buffer, 0, total_size);
1386 ce_size = ISO_ROUND_UP(dpnt->ce_bytes);
1390 ce_buffer = (char *) e_malloc(ce_size);
1391 memset(ce_buffer, 0, ce_size);
1395 /* Absolute byte address of CE entries for this directory */
1396 ce_address = last_extent_written + (total_size >> 11);
1397 ce_address = ce_address << 11;
1399 s_entry = dpnt->contents;
1401 /* skip if it's hidden */
1402 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
1403 s_entry = s_entry->next;
1407 * We do not allow directory entries to cross sector
1408 * boundaries. Simply pad, and then start the next entry at
1411 new_reclen = s_entry->isorec.length[0];
1412 if ((dir_index & (SECTOR_SIZE - 1)) + new_reclen >=
1414 dir_index = ISO_ROUND_UP(dir_index);
1416 memcpy(directory_buffer + dir_index, &s_entry->isorec,
1417 offsetof(struct iso_directory_record, name[0]) +
1418 s_entry->isorec.name_len[0]);
1419 dir_index += offsetof(struct iso_directory_record, name[0]) +
1420 s_entry->isorec.name_len[0];
1422 /* Add the Rock Ridge attributes, if present */
1423 if (s_entry->rr_attr_size) {
1424 if (dir_index & 1) {
1425 directory_buffer[dir_index++] = 0;
1428 * If the RR attributes were too long, then write the
1429 * CE records, as required.
1431 if (s_entry->rr_attr_size != s_entry->total_rr_attr_size) {
1432 struct iso_xa_dir_record *xadp;
1438 * Go through the entire record, first skip
1439 * the XA record and then fix up the
1440 * CE entries so that the extent and offset
1443 pnt = s_entry->rr_attributes;
1444 len = s_entry->total_rr_attr_size;
1447 xadp = (struct iso_xa_dir_record *)pnt;
1449 if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' &&
1450 xadp->reserved[0] == '\0') {
1460 "Warning: ce_index(%d) && ce_address(%d) not initialized\n",
1461 ce_index, ce_address);
1465 if (pnt[0] == 'C' && pnt[1] == 'E') {
1466 nbytes = get_733((char *) pnt + 20);
1468 if ((ce_index & (SECTOR_SIZE - 1)) + nbytes >=
1470 ce_index = ISO_ROUND_UP(ce_index);
1472 set_733((char *) pnt + 4,
1473 (ce_address + ce_index) >> 11);
1474 set_733((char *) pnt + 12,
1475 (ce_address + ce_index) & (SECTOR_SIZE - 1));
1479 * Now store the block in the
1482 memcpy(ce_buffer + ce_index,
1483 pnt + pnt[2], nbytes);
1494 rockridge_size += s_entry->total_rr_attr_size;
1495 memcpy(directory_buffer + dir_index,
1496 s_entry->rr_attributes,
1497 s_entry->rr_attr_size);
1498 dir_index += s_entry->rr_attr_size;
1500 if (dir_index & 1) {
1501 directory_buffer[dir_index++] = 0;
1503 s_entry_d = s_entry;
1504 s_entry = s_entry->next;
1507 * Joliet doesn't use the Rock Ridge attributes, so we free
1510 if (s_entry_d->rr_attributes) {
1511 free(s_entry_d->rr_attributes);
1512 s_entry_d->rr_attributes = NULL;
1516 if (dpnt->size != dir_index) {
1517 #ifdef USE_LIBSCHILY
1519 "Unexpected directory length %lld expected: %d '%s'\n",
1521 dir_index, dpnt->de_name);
1524 "Unexpected directory length %lld expected: %d '%s'\n",
1526 dir_index, dpnt->de_name);
1529 jtwrite(directory_buffer, total_size, 1, 0, FALSE);
1530 xfwrite(directory_buffer, total_size, 1, outfile, 0, FALSE);
1531 last_extent_written += total_size >> 11;
1532 free(directory_buffer);
1533 directory_buffer = NULL;
1536 if (ce_index != dpnt->ce_bytes) {
1537 #ifdef USE_LIBSCHILY
1539 "Continuation entry record length mismatch %d expected: %d.\n",
1540 ce_index, dpnt->ce_bytes);
1543 "Continuation entry record length mismatch %d expected: %d.\n",
1544 ce_index, dpnt->ce_bytes);
1547 jtwrite(ce_buffer, ce_size, 1, 0, FALSE);
1548 xfwrite(ce_buffer, ce_size, 1, outfile, 0, FALSE);
1549 last_extent_written += ce_size >> 11;
1553 }/* generate_one_directory(... */
1556 build_pathlist(struct directory *node)
1558 struct directory *dpnt;
1563 /* skip if it's hidden */
1564 if ((dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0)
1565 pathlist[dpnt->path_index] = dpnt;
1568 build_pathlist(dpnt->subdir);
1571 }/* build_pathlist(... */
1574 compare_paths(void const *r, void const *l)
1576 struct directory const *ll = *(struct directory * const *) l;
1577 struct directory const *rr = *(struct directory * const *) r;
1579 if (rr->parent->path_index < ll->parent->path_index) {
1582 if (rr->parent->path_index > ll->parent->path_index) {
1585 return (strcmp(rr->self->isorec.name, ll->self->isorec.name));
1587 }/* compare_paths(... */
1590 generate_path_tables()
1592 struct directory_entry *de = NULL;
1593 struct directory *dpnt;
1602 /* First allocate memory for the tables and initialize the memory */
1603 tablesize = path_blocks << 11;
1604 path_table_m = (char *) e_malloc(tablesize);
1605 path_table_l = (char *) e_malloc(tablesize);
1606 memset(path_table_l, 0, tablesize);
1607 memset(path_table_m, 0, tablesize);
1610 * Now start filling in the path tables. Start with root directory
1613 path_table_index = 0;
1614 pathlist = (struct directory **) e_malloc(sizeof (struct directory *)
1616 memset(pathlist, 0, sizeof (struct directory *) * next_path_index);
1617 build_pathlist(root);
1622 qsort(&pathlist[1], next_path_index - 1,
1623 sizeof (struct directory *),
1624 (int (*) (const void *, const void *)) compare_paths);
1626 qsort(&pathlist[1], next_path_index - 1,
1627 sizeof (struct directory *),
1631 for (j = 1; j < next_path_index; j++) {
1632 if (pathlist[j]->path_index != j) {
1633 pathlist[j]->path_index = j;
1639 for (j = 1; j < next_path_index; j++) {
1642 #ifdef USE_LIBSCHILY
1643 comerrno(EX_BAD, "Entry %d not in path tables\n", j);
1645 fprintf(stderr, "Entry %d not in path tables\n", j);
1649 npnt = dpnt->de_name;
1651 /* So the root comes out OK */
1652 if ((*npnt == 0) || (dpnt == root)) {
1655 npnt1 = strrchr(npnt, PATH_SEPARATOR);
1661 #ifdef USE_LIBSCHILY
1663 "Fatal ISO9660 goof - directory has amnesia\n");
1666 "Fatal ISO9660 goof - directory has amnesia\n");
1670 namelen = de->isorec.name_len[0];
1672 path_table_l[path_table_index] = namelen;
1673 path_table_m[path_table_index] = namelen;
1674 path_table_index += 2;
1676 set_731(path_table_l + path_table_index, dpnt->extent);
1677 set_732(path_table_m + path_table_index, dpnt->extent);
1678 path_table_index += 4;
1680 if (dpnt->parent->path_index > 0xffff) {
1681 #ifdef USE_LIBSCHILY
1683 "Unable to generate sane path tables - too many directories (%d)\n",
1684 dpnt->parent->path_index);
1687 "Unable to generate sane path tables - too many directories (%d)\n",
1688 dpnt->parent->path_index);
1693 set_721(path_table_l + path_table_index,
1694 dpnt->parent->path_index);
1695 set_722(path_table_m + path_table_index,
1696 dpnt->parent->path_index);
1697 path_table_index += 2;
1699 for (i = 0; i < namelen; i++) {
1700 path_table_l[path_table_index] = de->isorec.name[i];
1701 path_table_m[path_table_index] = de->isorec.name[i];
1704 if (path_table_index & 1) {
1705 path_table_index++; /* For odd lengths we pad */
1711 if (path_table_index != path_table_size) {
1712 #ifdef USE_LIBSCHILY
1714 "Path table lengths do not match %d expected: %d\n",
1719 "Path table lengths do not match %d expected: %d\n",
1725 }/* generate_path_tables(... */
1728 memcpy_max(char *to, char *from, int max)
1730 int n = strlen(from);
1735 memcpy(to, from, n);
1737 }/* memcpy_max(... */
1740 outputlist_insert(struct output_fragment *frag)
1742 struct output_fragment *nfrag;
1744 nfrag = e_malloc(sizeof (*frag));
1745 movebytes(frag, nfrag, sizeof (*frag));
1746 nfrag->of_start_extent = 0;
1748 if (out_tail == NULL) {
1749 out_list = out_tail = nfrag;
1751 out_tail->of_next = nfrag;
1757 file_write(FILE *outfile)
1762 char buffer[SECTOR_SIZE];
1764 memset(buffer, 0, sizeof (buffer));
1771 * write out padding to round up to HFS allocation block
1773 for (i = 0; i < hfs_pad; i++) {
1774 jtwrite(buffer, sizeof (buffer), 1, 0, FALSE);
1775 xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
1776 last_extent_written++;
1779 #endif /* APPLE_HYB */
1782 * OK, all done with that crap. Now write out the directories. This is
1783 * where the fur starts to fly, because we need to keep track of each
1784 * file as we find it and keep track of where we put it.
1786 should_write = last_extent - session_start;
1791 "Total directory extents being written = %d\n",
1798 "Total extents scheduled to be written (inc HFS) = %d\n",
1799 last_extent - session_start);
1801 #endif /* APPLE_HYB */
1804 "Total extents scheduled to be written = %u\n",
1805 last_extent - session_start);
1807 /* Now write all of the files that we need. */
1808 write_files(outfile);
1811 /* write out extents/catalog/dt file */
1814 jtwrite(hce->hfs_ce, HFS_BLOCKSZ, hce->hfs_tot_size, 0, FALSE);
1815 xfwrite(hce->hfs_ce, HFS_BLOCKSZ, hce->hfs_tot_size, outfile, 0, FALSE);
1817 /* round up to a whole CD block */
1818 if (HFS_ROUND_UP(hce->hfs_tot_size) -
1819 hce->hfs_tot_size * HFS_BLOCKSZ) {
1821 HFS_ROUND_UP(hce->hfs_tot_size) -
1822 hce->hfs_tot_size * HFS_BLOCKSZ, 1, 0, FALSE);
1824 HFS_ROUND_UP(hce->hfs_tot_size) -
1825 hce->hfs_tot_size * HFS_BLOCKSZ, 1, outfile, 0, FALSE);
1827 last_extent_written += ISO_ROUND_UP(hce->hfs_tot_size *
1828 HFS_BLOCKSZ) / SECTOR_SIZE;
1830 /* write out HFS boot block */
1832 write_one_file(mac_boot.name, mac_boot.size, outfile,
1835 #endif /* APPLE_HYB */
1837 /* The rest is just fluff. */
1844 "Total extents actually written (inc HFS) = %d\n",
1845 last_extent_written - session_start);
1846 fprintf(stderr, "(Size of ISO volume = %d, HFS extra = %d)\n",
1847 last_extent_written - session_start - hfs_extra,
1851 fprintf(stderr, "Total extents actually written = %d\n",
1852 last_extent_written - session_start);
1853 #endif /* APPLE_HYB */
1855 /* Hard links throw us off here */
1856 if (should_write != (last_extent - session_start)) {
1858 "Number of extents written not what was predicted. Please fix.\n");
1859 fprintf(stderr, "Predicted = %d, written = %d\n",
1860 should_write, last_extent);
1862 fprintf(stderr, "Total translation table size: %d\n", table_size);
1863 fprintf(stderr, "Total rockridge attributes bytes: %d\n",
1865 fprintf(stderr, "Total directory bytes: %d\n", total_dir_size);
1866 fprintf(stderr, "Path table size(bytes): %d\n", path_table_size);
1870 "next extent, last_extent, last_extent_written %d %d %d\n",
1871 next_extent, last_extent, last_extent_written);
1876 }/* iso_write(... */
1879 * Function to write the PVD for the disc.
1882 pvd_write(FILE *outfile)
1892 local = *localtime(&begun);
1893 gmt = *gmtime(&begun);
1896 * There was a comment here about breaking in the year 2000.
1897 * That's not true, in 2000 tm_year == 100, so 1900+tm_year == 2000.
1899 sprintf(iso_time, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00",
1900 1900 + local.tm_year,
1901 local.tm_mon + 1, local.tm_mday,
1902 local.tm_hour, local.tm_min, local.tm_sec);
1904 local.tm_min -= gmt.tm_min;
1905 local.tm_hour -= gmt.tm_hour;
1906 local.tm_yday -= gmt.tm_yday;
1907 if (local.tm_yday < -2) /* Hit new-year limit */
1908 local.tm_yday = 1; /* Local is GMT + 1 day */
1909 iso_time[16] = (local.tm_min + 60 *
1910 (local.tm_hour + 24 * local.tm_yday)) / 15;
1912 /* Next we write out the primary descriptor for the disc */
1913 memset(&vol_desc, 0, sizeof (vol_desc));
1914 vol_desc.type[0] = ISO_VD_PRIMARY;
1915 memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof (ISO_STANDARD_ID));
1916 vol_desc.version[0] = 1;
1918 memset(vol_desc.system_id, ' ', sizeof (vol_desc.system_id));
1919 memcpy_max(vol_desc.system_id, system_id, strlen(system_id));
1921 memset(vol_desc.volume_id, ' ', sizeof (vol_desc.volume_id));
1922 memcpy_max(vol_desc.volume_id, volume_id, strlen(volume_id));
1924 should_write = last_extent - session_start;
1925 set_733((char *) vol_desc.volume_space_size, should_write);
1926 set_723(vol_desc.volume_set_size, volume_set_size);
1927 set_723(vol_desc.volume_sequence_number, volume_sequence_number);
1928 set_723(vol_desc.logical_block_size, SECTOR_SIZE);
1931 * The path tables are used by DOS based machines to cache directory
1934 set_733((char *) vol_desc.path_table_size, path_table_size);
1935 set_731(vol_desc.type_l_path_table, path_table[0]);
1936 set_731(vol_desc.opt_type_l_path_table, path_table[1]);
1937 set_732(vol_desc.type_m_path_table, path_table[2]);
1938 set_732(vol_desc.opt_type_m_path_table, path_table[3]);
1940 /* Now we copy the actual root directory record */
1941 memcpy(vol_desc.root_directory_record, &root_record,
1942 offsetof(struct iso_directory_record, name[0]) + 1);
1945 * The rest is just fluff. It looks nice to fill in many of these
1948 FILL_SPACE(volume_set_id);
1950 memcpy_max(vol_desc.volume_set_id, volset_id, strlen(volset_id));
1952 FILL_SPACE(publisher_id);
1954 memcpy_max(vol_desc.publisher_id, publisher, strlen(publisher));
1956 FILL_SPACE(preparer_id);
1958 memcpy_max(vol_desc.preparer_id, preparer, strlen(preparer));
1960 FILL_SPACE(application_id);
1962 memcpy_max(vol_desc.application_id, appid, strlen(appid));
1964 FILL_SPACE(copyright_file_id);
1966 memcpy_max(vol_desc.copyright_file_id, copyright,
1969 FILL_SPACE(abstract_file_id);
1971 memcpy_max(vol_desc.abstract_file_id, abstract,
1974 FILL_SPACE(bibliographic_file_id);
1976 memcpy_max(vol_desc.bibliographic_file_id, biblio,
1979 FILL_SPACE(creation_date);
1980 FILL_SPACE(modification_date);
1981 FILL_SPACE(expiration_date);
1982 FILL_SPACE(effective_date);
1983 vol_desc.file_structure_version[0] = 1;
1984 FILL_SPACE(application_data);
1986 memcpy(vol_desc.creation_date, iso_time, 17);
1987 memcpy(vol_desc.modification_date, iso_time, 17);
1988 memcpy(vol_desc.expiration_date, "0000000000000000", 17);
1989 memcpy(vol_desc.effective_date, iso_time, 17);
1992 char *xap = &((char *)&vol_desc)[1024];
1994 memcpy(&xap[0], "CD-XA001", 8); /* XA Sign. */
1995 memcpy(&xap[8], "\0\0", 2); /* XA flags */
1996 memcpy(&xap[10], "\0\0\0\0\0\0\0\0", 8); /* Start dir */
1997 memcpy(&xap[18], "\0\0\0\0\0\0\0\0", 8); /* Reserved */
2000 /* if not a bootable cd do it the old way */
2001 jtwrite(&vol_desc, SECTOR_SIZE, 1, 0, FALSE);
2002 xfwrite(&vol_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
2003 last_extent_written++;
2008 * Function to write the Extended PVD for the disc.
2011 xpvd_write(FILE *outfile)
2013 vol_desc.type[0] = ISO_VD_SUPPLEMENTARY;
2014 vol_desc.version[0] = 2;
2015 vol_desc.file_structure_version[0] = 2;
2017 /* if not a bootable cd do it the old way */
2018 jtwrite(&vol_desc, SECTOR_SIZE, 1, 0, FALSE);
2019 xfwrite(&vol_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
2020 last_extent_written++;
2025 * Function to write the EVD for the disc.
2028 evd_write(FILE *outfile)
2030 struct iso_primary_descriptor evol_desc;
2033 * Now write the end volume descriptor. Much simpler than the other
2036 memset(&evol_desc, 0, sizeof (evol_desc));
2037 evol_desc.type[0] = (unsigned char) ISO_VD_END;
2038 memcpy(evol_desc.id, ISO_STANDARD_ID, sizeof (ISO_STANDARD_ID));
2039 evol_desc.version[0] = 1;
2040 jtwrite(&evol_desc, SECTOR_SIZE, 1, 0, TRUE);
2041 xfwrite(&evol_desc, SECTOR_SIZE, 1, outfile, 0, TRUE);
2042 last_extent_written += 1;
2047 * Function to write the version information for the disc.
2050 vers_write(FILE *outfile)
2052 char vers[SECTOR_SIZE+1];
2059 extern char version_string[];
2060 extern int path_ind;
2062 /* Now write the version descriptor. */
2063 memset(vers, 0, sizeof (vers));
2064 strcpy(vers, "MKI ");
2069 strcpy(&cp[idx], ctime(&begun));
2071 strcpy(&cp[idx], version_string);
2072 idx += strlen(version_string);
2073 for (i = 1; i < X_ac; i++) {
2074 len = strlen(X_av[i]);
2075 if ((idx + len + 2) >= SECTOR_SIZE)
2079 * Do not give away secret information when not in debug mode.
2082 strcpy(&cp[idx], X_av[i]);
2083 else if (i >= path_ind)
2084 len = graftcp(&cp[idx], X_av[i], &vers[SECTOR_SIZE-1]);
2085 else if (X_av[i][0] == '/')
2086 len = pathcp(&cp[idx], X_av[i], &vers[SECTOR_SIZE-1]);
2088 strcpy(&cp[idx], X_av[i]);
2092 cp[SECTOR_SIZE - 1] = '\0';
2093 /* Per default: keep privacy. Blackout the version and arguments. */
2094 if(getenv("ISODEBUG")) {
2095 jtwrite(vers, SECTOR_SIZE, 1, 0, TRUE);
2096 xfwrite(vers, SECTOR_SIZE, 1, outfile, 0, TRUE);
2098 jtwrite(calloc(SECTOR_SIZE, 1), SECTOR_SIZE, 1, 0, TRUE);
2099 xfwrite(calloc(SECTOR_SIZE, 1), SECTOR_SIZE, 1, outfile, 0, TRUE);
2101 last_extent_written += 1;
2106 * Avoid to write unwanted information into the version info string.
2109 graftcp(char *to, char *from, char *ep)
2111 int len = strlen(from);
2115 node = findgequal(from);
2123 strncpy(to, from, ep - to);
2128 return (len + pathcp(to, node, ep));
2132 pathcp(char *to, char *from, char *ep)
2134 int len = strlen(from);
2137 p = strrchr(from, '/');
2139 strncpy(to, from, ep - to);
2143 while (p > from && *p != '/')
2148 strncpy(to, "...", ep - to);
2153 strncpy(to, p, ep - to);
2162 * Function to write the path table for the disc.
2165 pathtab_write(FILE *outfile)
2167 /* Next we write the path tables */
2168 jtwrite(path_table_l, path_blocks << 11, 1, 0, FALSE);
2169 xfwrite(path_table_l, path_blocks << 11, 1, outfile, 0, FALSE);
2170 last_extent_written += path_blocks;
2171 jtwrite(path_table_m, path_blocks << 11, 1, 0, FALSE);
2172 xfwrite(path_table_m, path_blocks << 11, 1, outfile, 0, FALSE);
2173 last_extent_written += path_blocks;
2176 path_table_l = NULL;
2177 path_table_m = NULL;
2182 exten_write(FILE *outfile)
2184 jtwrite(extension_record, SECTOR_SIZE, 1, 0, FALSE);
2185 xfwrite(extension_record, SECTOR_SIZE, 1, outfile, 0, FALSE);
2186 last_extent_written++;
2191 * Functions to describe padding block at the start of the disc.
2194 oneblock_size(int starting_extent)
2201 * Functions to describe path table size.
2204 pathtab_size(int starting_extent)
2206 path_table[0] = starting_extent;
2209 path_table[2] = path_table[0] + path_blocks;
2211 last_extent += 2 * path_blocks;
2216 * Functions to describe padding blocks before PVD.
2219 startpad_size(int starting_extent)
2221 last_extent = session_start + 16;
2226 * Functions to describe padding blocks between sections.
2229 interpad_size(int starting_extent)
2234 starting_extent += 16; /* First add 16 pad blocks */
2236 if ((emod = starting_extent % 16) != 0) {
2237 starting_extent += 16 - emod; /* Now pad to mod 16 # */
2239 last_extent = starting_extent;
2244 * Functions to describe padding blocks at end of disk.
2247 endpad_size(int starting_extent)
2249 starting_extent += 150; /* 150 pad blocks (post gap) */
2250 last_extent = starting_extent;
2258 int start_extent = last_extent; /* orig ISO files start */
2260 #endif /* APPLE_HYB */
2262 if (!assign_file_addresses(root, FALSE)) {
2265 comerrno(EX_BAD, "Unable to make a DVD-Video image.\n"
2266 "Possible reasons:\n"
2267 " - VIDEO_TS subdirectory was not found on specified location\n"
2268 " - VIDEO_TS has invalid contents\n"
2279 if (sort_file_addresses() == 0)
2280 reassign_link_addresses(root);
2282 #endif /* SORTING */
2286 * put this here for the time being - may when I've worked out how to
2287 * use Eric's new system for creating/writing parts of the image it
2288 * may move to it's own routine
2291 hfs_file_gen(start_extent);
2293 else if (use_prep_boot || use_chrp_boot)
2295 #endif /* PREP_BOOT */
2296 #endif /* APPLE_HYB */
2311 dirtree_fixup(int starting_extent)
2313 if (use_RockRidge && reloc_dir)
2314 finish_cl_pl_entries();
2317 update_nlink_field(root);
2322 dirtree_size(int starting_extent)
2324 assign_directory_addresses(root);
2329 ext_size(int starting_extent)
2331 extern int extension_record_size;
2332 struct directory_entry *s_entry;
2334 extension_record_extent = starting_extent;
2335 s_entry = root->contents;
2336 set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 24,
2337 extension_record_extent);
2338 set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 8,
2339 extension_record_size);
2345 dirtree_write(FILE *outfile)
2347 generate_iso9660_directories(root, outfile);
2352 dirtree_cleanup(FILE *outfile)
2354 free_directories(root);
2359 startpad_write(FILE *outfile)
2361 char buffer[SECTOR_SIZE];
2365 memset(buffer, 0, sizeof (buffer));
2367 npad = session_start + 16 - last_extent_written;
2369 for (i = 0; i < npad; i++) {
2370 jtwrite(buffer, sizeof (buffer), 1, 0, FALSE);
2371 xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
2372 last_extent_written++;
2379 interpad_write(FILE *outfile)
2381 char buffer[SECTOR_SIZE];
2385 memset(buffer, 0, sizeof (buffer));
2390 if ((i = last_extent_written % 16) != 0)
2393 for (i = 0; i < npad; i++) {
2394 jtwrite(buffer, sizeof (buffer), 1, 0, FALSE);
2395 xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
2396 last_extent_written++;
2403 endpad_write(FILE *outfile)
2405 char buffer[SECTOR_SIZE];
2408 memset(buffer, 0, sizeof (buffer));
2410 for (i = 0; i < 150; i++) {
2411 jtwrite(buffer, sizeof (buffer), 1, 0, FALSE);
2412 xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
2413 last_extent_written++;
2422 * hfs_get_parms: get HFS parameters from the command line
2426 hfs_get_parms(char *key)
2431 if (hfs_parms == NULL)
2434 if ((p = strstr(hfs_parms, key)) != NULL) {
2435 p += strlen(key) + 1;
2436 sscanf(p, "%d", &ret);
2443 * hfs_file_gen: set up "fake" HFS volume using the ISO9660 tree
2446 hfs_file_gen(int start_extent)
2448 int Csize; /* clump size for HFS vol */
2450 int last_extent_save = last_extent;
2453 /* allocate memory for the libhfs/genisoimage extra info */
2454 hce = (hce_mem *) e_malloc(sizeof (hce_mem));
2456 hce->error = (char *) e_malloc(1024);
2458 /* mark as unallocated for use later */
2459 hce->hfs_ce = hce->hfs_hdr = hce->hfs_map = 0;
2461 /* reserve space for the label partition - if it is needed */
2463 /* a PReP bootable partition needs the map.. */
2464 if (gen_pt || use_prep_boot || use_chrp_boot)
2467 #endif /* PREP_BOOT */
2468 hce->hfs_map_size = HFS_MAP_SIZE;
2470 hce->hfs_map_size = 0;
2472 /* set the HFS parameter string to upper case */
2474 for (p = hfs_parms; *p; p++)
2478 /* set the initial factor to increase Catalog file size */
2479 if ((hce->ctc_size = hfs_get_parms("CTC")) == 0)
2480 hce->ctc_size = CTC;
2482 /* set the max size of the Catalog file */
2483 if ((hce->max_XTCsize = hfs_get_parms("MAX_XTCSIZE")) == 0)
2484 hce->max_XTCsize = MAX_XTCSIZE;
2486 /* set the number of time to try to make an HFS volume */
2487 if ((loop = hfs_get_parms("CTC_LOOP")) == 0)
2491 * "create" the HFS volume (just the header, catalog/extents files) if
2492 * there's a problem with the Catalog file being too small, we keep on
2493 * increasing the size (up to CTC_LOOP) times and try again.
2494 * Unfortunately I don't know enough about the inner workings of HFS,
2495 * so I can't workout the size of the Catalog file in advance (and I
2496 * don't want to "grow" as is is normally allowed to), therefore, this
2497 * approach is a bit over the top as it involves throwing away the
2498 * "volume" we have created and trying again ...
2501 hce->error[0] = '\0';
2503 /* attempt to create the Mac volume */
2504 Csize = make_mac_volume(root, start_extent);
2506 /* if we have a problem ... */
2509 * we've made too many attempts, or got some other
2512 if (loop == 0 || errno != HCE_ERROR) {
2513 /* HCE_ERROR is not a valid errno value */
2514 if (errno == HCE_ERROR)
2517 /* exit with the error */
2519 fprintf(stderr, "%s\n", hce->error);
2522 /* increase Catalog file size factor */
2523 hce->ctc_size *= CTC;
2526 * reset the initial "last_extent" and try
2529 last_extent = last_extent_save;
2532 /* everything OK - just carry on ... */
2538 hfs_extra = HFS_ROUND_UP(hce->hfs_tot_size) / SECTOR_SIZE;
2540 last_extent += hfs_extra;
2542 /* generate the Mac label and HFS partition maps */
2543 mac_boot.name = hfs_boot_file;
2546 * only generate the partition tables etc. if we are making a bootable
2547 * CD - or if the -part option is given
2550 if (gen_mac_label(&mac_boot)) {
2552 fprintf(stderr, "%s\n", hce->error);
2556 /* set Autostart filename if required */
2559 perr("Autostart filename must less than 12 characters");
2561 /* finished with any HFS type errors */
2566 * the ISO files need to start on a multiple of the HFS allocation
2567 * blocks, so find out how much padding we need
2571 * take in accout alignment of files wrt HFS volume start - remove any
2572 * previous session as well
2574 start_extent -= session_start;
2575 hfs_pad = ROUND_UP(start_extent*SECTOR_SIZE +
2576 (hce->hfs_hdr_size + hce->hfs_map_size) * HFS_BLOCKSZ,
2577 Csize) / SECTOR_SIZE;
2579 hfs_pad -= (start_extent + (hce->hfs_hdr_size + hce->hfs_map_size) /
2583 gen_prepboot_label(hce->hfs_map);
2584 #endif /* PREP_BOOT */
2593 * we need to allocate the hce struct since hce->hfs_map is used to
2594 * generate the fdisk partition map required for PReP booting
2596 hce = (hce_mem *) e_malloc(sizeof (hce_mem));
2598 /* mark as unallocated for use later */
2599 hce->hfs_ce = hce->hfs_hdr = hce->hfs_map = 0;
2601 /* reserve space for the label partition - if it is needed */
2602 hce->hfs_map_size = HFS_MAP_SIZE;
2604 hce->hfs_map = (unsigned char *) e_malloc(hce->hfs_map_size * HFS_BLOCKSZ);
2605 gen_prepboot_label(hce->hfs_map);
2608 #endif /* PREP_BOOT */
2611 * get_adj_size: get the ajusted size of the volume with the HFS
2612 * allocation block size for each file
2615 get_adj_size(int Csize)
2617 struct deferred_write *dw;
2621 /* loop through all the files finding the new total size */
2622 for (dw = dw_head; dw; dw = dw->next) {
2623 size += (ROUND_UP(dw->size, Csize)/HFS_BLOCKSZ);
2628 * crude attempt to prevent overflows - HFS can only cope with a
2629 * maximum of about 65536 forks (actually less) - this will trap cases
2630 * when we have far too many files
2640 * adj_size: adjust the ISO record entries for all files
2641 * based on the HFS allocation block size
2644 adj_size(int Csize, int start_extent, int extra)
2646 struct deferred_write *dw;
2647 struct directory_entry *s_entry;
2650 /* get the adjusted start_extent (with padding) */
2651 /* take in accout alignment of files wrt HFS volume start */
2653 start_extent -= session_start;
2655 start_extent = ROUND_UP(start_extent*SECTOR_SIZE + extra*HFS_BLOCKSZ,
2656 Csize) / SECTOR_SIZE;
2658 start_extent -= (extra / HFS_BLK_CONV);
2660 start_extent += session_start;
2662 /* initialise file hash */
2666 * loop through all files changing their starting blocks and finding
2667 * any padding needed to written out latter
2669 for (dw = dw_head; dw; dw = dw->next) {
2670 s_entry = dw->s_entry;
2671 s_entry->starting_block = dw->extent = start_extent;
2672 set_733((char *) s_entry->isorec.extent, start_extent);
2673 size = ROUND_UP(dw->size, Csize) / SECTOR_SIZE;
2674 dw->pad = size - ISO_ROUND_UP(dw->size) / SECTOR_SIZE;
2677 * cache non-HFS files - as there may be multiple links to
2678 * these files (HFS files can't have multiple links). We will
2679 * need to change the starting extent of the other links later
2681 if (!s_entry->hfs_ent)
2684 start_extent += size;
2687 return (start_extent);
2691 * adj_size_other: adjust any non-HFS files that may be linked
2692 * to an existing file (i.e. not have a deferred_write
2696 adj_size_other(struct directory *dpnt)
2698 struct directory_entry *s_entry;
2699 struct file_hash *s_hash;
2702 s_entry = dpnt->contents;
2703 for (s_entry = dpnt->contents; s_entry;
2704 s_entry = s_entry->next) {
2706 * if it's an HFS file or a directory - then ignore
2707 * (we're after non-HFS files)
2709 if (s_entry->hfs_ent ||
2710 (s_entry->isorec.flags[0] & ISO_DIRECTORY))
2714 * find any cached entry and assign new starting
2717 s_hash = find_hash(s_entry->dev, s_entry->inode);
2719 set_733((char *) s_entry->isorec.extent,
2720 s_hash->starting_block);
2721 /* not vital - but tidy */
2722 s_entry->starting_block =
2723 s_hash->starting_block;
2727 adj_size_other(dpnt->subdir);
2732 /* clear file hash */
2737 * hfs_hce_write: write out the HFS header stuff
2740 hfs_hce_write(FILE *outfile)
2742 char buffer[SECTOR_SIZE];
2744 int r; /* HFS hdr output */
2745 int tot_size = hce->hfs_map_size + hce->hfs_hdr_size;
2747 memset(buffer, 0, sizeof (buffer));
2750 * hack time ... if the tot_size is greater than 32Kb then
2751 * it won't fit in the first 16 blank SECTORS (64 512 byte
2752 * blocks, as most of this is padding, we just truncate this
2753 * data to 64x4xHFS_BLOCKSZ ... hope this is OK ...
2756 if (tot_size > 64) tot_size = 64;
2758 /* get size in CD blocks == 4xHFS_BLOCKSZ == 2048 */
2759 n = tot_size / HFS_BLK_CONV;
2760 r = tot_size % HFS_BLK_CONV;
2762 /* write out HFS volume header info */
2763 jtwrite(hce->hfs_map, HFS_BLOCKSZ, tot_size, 0, FALSE);
2764 xfwrite(hce->hfs_map, HFS_BLOCKSZ, tot_size, outfile, 0, FALSE);
2766 /* fill up to a complete CD block */
2768 jtwrite(buffer, HFS_BLOCKSZ, HFS_BLK_CONV - r, 0, FALSE);
2769 xfwrite(buffer, HFS_BLOCKSZ, HFS_BLK_CONV - r, outfile, 0, FALSE);
2772 last_extent_written += n;
2777 * insert_padding_file : insert a dumy file to make volume at least
2780 * XXX If we ever need to write more then 2 GB, make size off_t
2783 insert_padding_file(int size)
2785 struct deferred_write *dwpnt;
2787 /* get the size in bytes */
2788 size *= HFS_BLOCKSZ;
2790 dwpnt = (struct deferred_write *)
2791 e_malloc(sizeof (struct deferred_write));
2793 /* set the padding to zero */
2795 /* set offset to zero */
2796 dwpnt->off = (off_t)0;
2799 * don't need to wory about the s_entry stuff as it won't be touched#
2800 * at this point onwards
2803 /* insert the entry in the list */
2805 dw_tail->next = dwpnt;
2812 /* aloocate memory as a "Table" file */
2813 dwpnt->table = e_malloc(size);
2818 dwpnt->extent = last_extent;
2819 last_extent += ISO_BLOCKS(size);
2821 /* retune the size in HFS blocks */
2822 return (ISO_ROUND_UP(size) / HFS_BLOCKSZ);
2825 struct output_fragment hfs_desc = {NULL, NULL, NULL, hfs_hce_write, "HFS volume header"};
2827 #endif /* APPLE_HYB */
2829 struct output_fragment startpad_desc = {NULL, startpad_size, NULL, startpad_write, "Initial Padblock"};
2830 struct output_fragment voldesc_desc = {NULL, oneblock_size, root_gen, pvd_write, "Primary Volume Descriptor"};
2831 struct output_fragment xvoldesc_desc = {NULL, oneblock_size, NULL, xpvd_write, "Enhanced Volume Descriptor"};
2832 struct output_fragment end_vol = {NULL, oneblock_size, NULL, evd_write, "End Volume Descriptor" };
2833 struct output_fragment version_desc = {NULL, oneblock_size, NULL, vers_write, "Version block" };
2834 struct output_fragment pathtable_desc = {NULL, pathtab_size, generate_path_tables, pathtab_write, "Path table"};
2835 struct output_fragment dirtree_desc = {NULL, dirtree_size, NULL, dirtree_write, "Directory tree" };
2836 struct output_fragment dirtree_clean = {NULL, dirtree_fixup, dirtree_dump, dirtree_cleanup, "Directory tree cleanup" };
2837 struct output_fragment extension_desc = {NULL, ext_size, NULL, exten_write, "Extension record" };
2838 struct output_fragment files_desc = {NULL, NULL, file_gen, file_write, "The File(s)"};
2839 struct output_fragment interpad_desc = {NULL, interpad_size, NULL, interpad_write, "Intermediate Padblock"};
2840 struct output_fragment endpad_desc = {NULL, endpad_size, NULL, endpad_write, "Ending Padblock"};