Bug Summary

File:src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/write.c
Warning:line 1781, column 6
Value stored to 's_entry' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name write.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/obj -resource-dir /usr/local/lib/clang/13.0.0 -D SYSTEM_ID_DEFAULT="OpenBSD" -D APPLE_HYB -D VANILLA_AUTOCONF -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/include -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/libhfs_iso -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/libfile -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/write.c
1/*
2 * Program write.c - dump memory structures to file for iso9660 filesystem.
3
4 Written by Eric Youngdale (1993).
5
6 Copyright 1993 Yggdrasil Computing, Incorporated
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 16/3/1999 */
23#include <string.h>
24#include <stdlib.h>
25#include <err.h>
26#include "config.h"
27#include "mkisofs.h"
28#include "iso9660.h"
29#include "volume.h"
30#include "write.h"
31#include "apple_proto.h"
32#include "mac_label_proto.h"
33#include <time.h>
34#include <errno(*__errno()).h>
35
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <fcntl.h>
39
40#ifdef HAVE_UNISTD_H1
41#include <unistd.h>
42#endif
43
44#ifdef __SVR4
45extern char * strdup(const char *);
46#endif
47
48#ifdef VMS
49extern char * strdup(const char *);
50#endif
51
52
53/* Max number of sectors we will write at one time */
54#define NSECT16 16
55
56/* Counters for statistics */
57
58static int table_size = 0;
59static int total_dir_size = 0;
60static int rockridge_size = 0;
61static struct directory ** pathlist;
62static int next_path_index = 1;
63static int sort_goof;
64
65struct output_fragment * out_tail;
66struct output_fragment * out_list;
67
68struct iso_primary_descriptor vol_desc;
69
70#ifdef APPLE_HYB1
71static int hfs_pad;
72#endif /* APPLE_HYB */
73
74static int root_gen __PR((void))(void);
75static int generate_path_tables __PR((void))(void);
76static int file_gen __PR((void))(void);
77static int dirtree_dump __PR((void))(void);
78
79/* Routines to actually write the disc. We write sequentially so that
80 we could write a tape, or write the disc directly */
81
82
83#define FILL_SPACE(X)memset(vol_desc.X, ' ', sizeof(vol_desc.X)) memset(vol_desc.X, ' ', sizeof(vol_desc.X))
84
85void FDECL2(set_721, char *, pnt, unsigned int, i)set_721(char * pnt, unsigned int i)
86{
87 pnt[0] = i & 0xff;
88 pnt[1] = (i >> 8) & 0xff;
89}
90
91void FDECL2(set_722, char *, pnt, unsigned int, i)set_722(char * pnt, unsigned int i)
92{
93 pnt[0] = (i >> 8) & 0xff;
94 pnt[1] = i & 0xff;
95}
96
97void FDECL2(set_723, char *, pnt, unsigned int, i)set_723(char * pnt, unsigned int i)
98{
99 pnt[3] = pnt[0] = i & 0xff;
100 pnt[2] = pnt[1] = (i >> 8) & 0xff;
101}
102
103void FDECL2(set_731, char *, pnt, unsigned int, i)set_731(char * pnt, unsigned int i)
104{
105 pnt[0] = i & 0xff;
106 pnt[1] = (i >> 8) & 0xff;
107 pnt[2] = (i >> 16) & 0xff;
108 pnt[3] = (i >> 24) & 0xff;
109}
110
111void FDECL2(set_732, char *, pnt, unsigned int, i)set_732(char * pnt, unsigned int i)
112{
113 pnt[3] = i & 0xff;
114 pnt[2] = (i >> 8) & 0xff;
115 pnt[1] = (i >> 16) & 0xff;
116 pnt[0] = (i >> 24) & 0xff;
117}
118
119int FDECL1(get_733, char *, p)get_733(char * p)
120{
121 return ((p[0] & 0xff)
122 | ((p[1] & 0xff) << 8)
123 | ((p[2] & 0xff) << 16)
124 | ((p[3] & 0xff) << 24));
125}
126
127void FDECL2(set_733, char *, pnt, unsigned int, i)set_733(char * pnt, unsigned int i)
128{
129 pnt[7] = pnt[0] = i & 0xff;
130 pnt[6] = pnt[1] = (i >> 8) & 0xff;
131 pnt[5] = pnt[2] = (i >> 16) & 0xff;
132 pnt[4] = pnt[3] = (i >> 24) & 0xff;
133}
134
135void FDECL4(xfwrite, void *, buffer, int, count, int, size, FILE *, file)xfwrite(void * buffer, int count, int size, FILE * file)
136{
137 /*
138 * This is a hack that could be made better. XXXIs this the only place?
139 * It is definitely needed on Operating Systems that do not
140 * allow to write files that are > 2GB.
141 * If the system is fast enough to be able to feed 1400 KB/s
142 * writing speed of a DVD-R drive, use stdout.
143 * If the system cannot do this reliable, you need to use this
144 * hacky option.
145 */
146 static int idx = 0;
147 if (split_output != 0 &&
148 (idx == 0 || ftell(file) >= (1024 * 1024 * 1024) )) {
149 char nbuf[512];
150 extern char *outfile;
151
152 if (idx == 0)
153 unlink(outfile);
154 snprintf(nbuf, sizeof nbuf, "%s_%02d", outfile, idx++);
155 file = freopen(nbuf, "wb", file);
156 if (file == NULL((void *)0)) {
157 fprintf(stderr(&__sF[2]), "Cannot open '%s'.\n", nbuf);
158 exit(1);
159 }
160
161 }
162 while(count)
163 {
164 int got = fwrite(buffer,size,count,file);
165
166 if(got<=0)
167 {
168 fprintf(stderr(&__sF[2]),"cannot fwrite %d*%d\n",size,count);
169 exit(1);
170 }
171 count-=got,*(char**)&buffer+=size*got;
172 }
173}
174
175#ifdef APPLE_HYB1
176/* use the deferred_write struct to store info about the hfs_boot_file */
177static struct deferred_write mac_boot;
178#endif /* APPLE_HYB */
179static struct deferred_write * dw_head = NULL((void *)0), * dw_tail = NULL((void *)0);
180
181unsigned int last_extent_written =0;
182static int path_table_index;
183static time_t begun;
184
185/* We recursively walk through all of the directories and assign extent
186 numbers to them. We have already assigned extent numbers to everything that
187 goes in front of them */
188
189static int FDECL1(assign_directory_addresses, struct directory *, node)assign_directory_addresses(struct directory * node)
190{
191 int dir_size;
192 struct directory * dpnt;
193
194 dpnt = node;
195
196 while (dpnt)
197 {
198 /* skip if it's hidden */
199 if(dpnt->dir_flags & INHIBIT_ISO9660_ENTRY0x40) {
200 dpnt = dpnt->next;
201 continue;
202 }
203
204 /*
205 * If we already have an extent for this (i.e. it came from
206 * a multisession disc), then don't reassign a new extent.
207 */
208 dpnt->path_index = next_path_index++;
209 if( dpnt->extent == 0 )
210 {
211 dpnt->extent = last_extent;
212 dir_size = (dpnt->size + (SECTOR_SIZE(2048) - 1)) >> 11;
213
214 last_extent += dir_size;
215
216 /*
217 * Leave room for the CE entries for this directory. Keep them
218 * close to the reference directory so that access will be
219 * quick.
220 */
221 if(dpnt->ce_bytes)
222 {
223 last_extent += ROUND_UP(dpnt->ce_bytes)((dpnt->ce_bytes + ((2048) - 1)) & ~((2048) - 1)) >> 11;
224 }
225 }
226
227 if(dpnt->subdir)
228 {
229 assign_directory_addresses(dpnt->subdir);
230 }
231
232 dpnt = dpnt->next;
233 }
234 return 0;
235}
236
237#ifdef APPLE_HYB1
238static void FDECL4(write_one_file, char *, filename,write_one_file(char * filename, unsigned int size, FILE * outfile
, unsigned int off)
239 unsigned int, size, FILE *, outfile, unsigned int, off)write_one_file(char * filename, unsigned int size, FILE * outfile
, unsigned int off)
240#else
241static void FDECL3(write_one_file, char *, filename,write_one_file(char * filename, unsigned int size, FILE * outfile
)
242 unsigned int, size, FILE *, outfile)write_one_file(char * filename, unsigned int size, FILE * outfile
)
243#endif /* APPLE_HYB */
244{
245 char buffer[SECTOR_SIZE(2048) * NSECT16];
246 FILE * infile;
247 int remain;
248 int use;
249
250
251 if ((infile = fopen(filename, "rb")) == NULL((void *)0))
252 {
253#if defined(sun) || defined(_AUX_SOURCE)
254 fprintf(stderr(&__sF[2]), "cannot open %s: (%d)\n", filename, errno(*__errno()));
255#else
256 fprintf(stderr(&__sF[2]), "cannot open %s: %s\n", filename, strerror(errno(*__errno())));
257#endif
258 exit(1);
259 }
260#ifdef APPLE_HYB1
261 fseek(infile, off, SEEK_SET0);
262#endif /* APPLE_HYB */
263 remain = size;
264
265 while(remain > 0)
266 {
267 use = (remain > SECTOR_SIZE(2048) * NSECT16 - 1 ? NSECT16*SECTOR_SIZE(2048) : remain);
268 use = ROUND_UP(use)((use + ((2048) - 1)) & ~((2048) - 1)); /* Round up to nearest sector boundary */
269 memset(buffer, 0, use);
270 if (fread(buffer, 1, use, infile) == 0)
271 {
272 fprintf(stderr(&__sF[2]),"cannot read from %s\n",filename);
273 exit(1);
274 }
275 xfwrite(buffer, 1, use, outfile);
276 last_extent_written += use/SECTOR_SIZE(2048);
277#if 0
278 if((last_extent_written % 1000) < use/SECTOR_SIZE(2048))
279 {
280 fprintf(stderr(&__sF[2]),"%d..", last_extent_written);
281 }
282#else
283 if((last_extent_written % 5000) < use/SECTOR_SIZE(2048)
284 && verbose > 3)
285 {
286 time_t now;
287 time_t the_end;
288 double frac;
289
290 time(&now);
291 frac = last_extent_written / (double)last_extent;
292 the_end = begun + (now - begun) / frac;
293 fprintf(stderr(&__sF[2]), "%6.2f%% done, estimate finish %s",
294 frac * 100., ctime(&the_end));
295 }
296#endif
297 remain -= use;
298 }
299 fclose(infile);
300} /* write_one_file(... */
301
302static void FDECL1(write_files, FILE *, outfile)write_files(FILE * outfile)
303{
304 struct deferred_write * dwpnt, *dwnext;
305 dwpnt = dw_head;
306 while(dwpnt)
307 {
308 if(dwpnt->table)
309 {
310 xfwrite(dwpnt->table, 1, ROUND_UP(dwpnt->size)((dwpnt->size + ((2048) - 1)) & ~((2048) - 1)), outfile);
311 last_extent_written += ROUND_UP(dwpnt->size)((dwpnt->size + ((2048) - 1)) & ~((2048) - 1)) / SECTOR_SIZE(2048);
312 table_size += dwpnt->size;
313/* fprintf(stderr,"Size %d ", dwpnt->size); */
314 free(dwpnt->table);
315 }
316 else
317 {
318
319#ifdef VMS
320 vms_write_one_file(dwpnt->name, dwpnt->size, outfile);
321#else
322#ifdef APPLE_HYB1
323 write_one_file(dwpnt->name, dwpnt->size, outfile, dwpnt->off);
324#else
325 write_one_file(dwpnt->name, dwpnt->size, outfile);
326#endif /* APPLE_HYB */
327#endif
328 free(dwpnt->name);
329 }
330
331#ifdef APPLE_HYB1
332 if (apple_hyb)
333 {
334 /* we may have to pad out ISO files to work with
335 HFS clump sizes */
336 char blk[SECTOR_SIZE(2048)];
337 int i;
338
339 for(i=0;i<dwpnt->pad;i++)
340 xfwrite(blk, 1, SECTOR_SIZE(2048), outfile);
341
342 last_extent_written += dwpnt->pad;
343 }
344#endif /* APPLE_HYB */
345
346 dwnext = dwpnt;
347 dwpnt = dwpnt->next;
348 free(dwnext);
349 }
350} /* write_files(... */
351
352#if 0
353static void dump_filelist()
354{
355 struct deferred_write * dwpnt;
356 dwpnt = dw_head;
357 while(dwpnt)
358 {
359 fprintf(stderr(&__sF[2]), "File %s\n",dwpnt->name);
360 dwpnt = dwpnt->next;
361 }
362 fprintf(stderr(&__sF[2]),"\n");
363}
364#endif
365
366static int FDECL2(compare_dirs, const void *, rr, const void *, ll)compare_dirs(const void * rr, const void * ll)
367{
368 char * rpnt, *lpnt;
369 struct directory_entry ** r, **l;
370
371 r = (struct directory_entry **) rr;
372 l = (struct directory_entry **) ll;
373 rpnt = (*r)->isorec.name;
374 lpnt = (*l)->isorec.name;
375
376#ifdef APPLE_HYB1
377 /* resource fork MUST (not sure if this is true for HFS volumes) be
378 before the data fork - so force it here */
379 if ((*r)->assoc && (*r)->assoc == (*l))
380 return 1;
381 if ((*l)->assoc && (*l)->assoc == (*r))
382 return -1;
383#endif /* APPLE_HYB */
384
385 /*
386 * If the entries are the same, this is an error.
387 */
388 if( strcmp(rpnt, lpnt) == 0 )
389 {
390 sort_goof++;
391 }
392
393 /*
394 * Put the '.' and '..' entries on the head of the sorted list.
395 * For normal ASCII, this always happens to be the case, but out of
396 * band characters cause this not to be the case sometimes.
397 *
398 * FIXME(eric) - these tests seem redundant, in taht the name is
399 * never assigned these values. It will instead be \000 or \001,
400 * and thus should always be sorted correctly. I need to figure
401 * out why I thought I needed this in the first place.
402 */
403#if 0
404 if( strcmp(rpnt, ".") == 0 ) return -1;
405 if( strcmp(lpnt, ".") == 0 ) return 1;
406
407 if( strcmp(rpnt, "..") == 0 ) return -1;
408 if( strcmp(lpnt, "..") == 0 ) return 1;
409#else
410 /*
411 * The code above is wrong (as explained in Eric's comment), leading to incorrect
412 * sort order iff the -L option ("allow leading dots") is in effect and a directory
413 * contains entries that start with a dot.
414 *
415 * (TF, Tue Dec 29 13:49:24 CET 1998)
416 */
417 if((*r)->isorec.name_len[0] == 1 && *rpnt == 0) return -1; /* '.' */
418 if((*l)->isorec.name_len[0] == 1 && *lpnt == 0) return 1;
419
420 if((*r)->isorec.name_len[0] == 1 && *rpnt == 1) return -1; /* '..' */
421 if((*l)->isorec.name_len[0] == 1 && *lpnt == 1) return 1;
422#endif
423
424 while(*rpnt && *lpnt)
425 {
426 if(*rpnt == ';' && *lpnt != ';') return -1;
427 if(*rpnt != ';' && *lpnt == ';') return 1;
428
429 if(*rpnt == ';' && *lpnt == ';') return 0;
430
431 if(*rpnt == '.' && *lpnt != '.') return -1;
432 if(*rpnt != '.' && *lpnt == '.') return 1;
433
434 if((unsigned char)*rpnt < (unsigned char)*lpnt) return -1;
435 if((unsigned char)*rpnt > (unsigned char)*lpnt) return 1;
436 rpnt++; lpnt++;
437 }
438 if(*rpnt) return 1;
439 if(*lpnt) return -1;
440 return 0;
441}
442
443/*
444 * Function: sort_directory
445 *
446 * Purpose: Sort the directory in the appropriate ISO9660
447 * order.
448 *
449 * Notes: Returns 0 if OK, returns > 0 if an error occurred.
450 */
451int FDECL1(sort_directory, struct directory_entry **, sort_dir)sort_directory(struct directory_entry ** sort_dir)
452{
453 int dcount = 0;
454 int xcount = 0;
455 int j;
456 int i, len;
457 struct directory_entry * s_entry;
458 struct directory_entry ** sortlist;
459
460 /* need to keep a count of how many entries are hidden */
461 s_entry = *sort_dir;
462 while(s_entry)
463 {
464 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY0x40)
465 xcount++;
466 dcount++;
467 s_entry = s_entry->next;
468 }
469
470 if( dcount == 0 )
471 {
472 return 0;
473 }
474
475 /*
476 * OK, now we know how many there are. Build a vector for sorting.
477 */
478 sortlist = (struct directory_entry **)
479 e_malloc(sizeof(struct directory_entry *) * dcount);
480
481 j = dcount - 1;
482 dcount = 0;
483 s_entry = *sort_dir;
484 while(s_entry)
485 {
486 if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY0x40)
487 {
488 /* put any hidden entries at the end of the vector */
489 sortlist[j--] = s_entry;
490 }
491 else
492 {
493 sortlist[dcount] = s_entry;
494 dcount++;
495 }
496 len = s_entry->isorec.name_len[0];
497 s_entry->isorec.name[len] = 0;
498 s_entry = s_entry->next;
499 }
500
501 /*
502 * Each directory is required to contain at least . and ..
503 */
504 if( dcount < 2 )
505 {
506 sort_goof = 1;
507
508 }
509 else
510 {
511 /* only sort the non-hidden entries */
512 sort_goof = 0;
513#ifdef __STDC__1
514 qsort(sortlist, dcount, sizeof(struct directory_entry *),
515 (int (*)(const void *, const void *))compare_dirs);
516#else
517 qsort(sortlist, dcount, sizeof(struct directory_entry *),
518 compare_dirs);
519#endif
520
521 /*
522 * Now reassemble the linked list in the proper sorted order
523 * We still need the hidden entries, as they may be used in the
524 * Joliet tree.
525 */
526 for(i=0; i<dcount+xcount-1; i++)
527 {
528 sortlist[i]->next = sortlist[i+1];
529 }
530
531 sortlist[dcount+xcount-1]->next = NULL((void *)0);
532 *sort_dir = sortlist[0];
533 }
534
535 free(sortlist);
536 return sort_goof;
537}
538
539static int root_gen()
540{
541 init_fstatbuf();
542
543 root_record.length[0] = 1 + sizeof(struct iso_directory_record)
544 - sizeof(root_record.name);
545 root_record.ext_attr_length[0] = 0;
546 set_733((char *) root_record.extent, root->extent);
547 set_733((char *) root_record.size, ROUND_UP(root->size)((root->size + ((2048) - 1)) & ~((2048) - 1)));
548 iso9660_date(root_record.date, root_statbuf.st_mtimest_mtim.tv_sec);
549 root_record.flags[0] = 2;
550 root_record.file_unit_size[0] = 0;
551 root_record.interleave[0] = 0;
552 set_723(root_record.volume_sequence_number, volume_sequence_number);
553 root_record.name_len[0] = 1;
554 return 0;
555}
556
557static void FDECL1(assign_file_addresses, struct directory *, dpnt)assign_file_addresses(struct directory * dpnt)
558{
559 struct directory * finddir;
560 struct directory_entry * s_entry;
561 struct file_hash *s_hash;
562 struct deferred_write * dwpnt;
563 char whole_path[1024];
564
565 while (dpnt)
566 {
567 s_entry = dpnt->contents;
568 for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next)
569 {
570 /*
571 * If we already have an extent for this entry,
572 * then don't assign a new one. It must have come
573 * from a previous session on the disc. Note that
574 * we don't end up scheduling the thing for writing
575 * either.
576 */
577 if( isonum_733((unsigned char *) s_entry->isorec.extent) != 0 )
578 {
579 continue;
580 }
581
582 /*
583 * This saves some space if there are symlinks present
584 */
585 s_hash = find_hash(s_entry->dev, s_entry->inode);
586 if(s_hash)
587 {
588 if(verbose > 2)
589 {
590 fprintf(stderr(&__sF[2]), "Cache hit for %s%s%s\n",s_entry->filedir->de_name,
591 SPATH_SEPARATOR"/", s_entry->name);
592 }
593 set_733((char *) s_entry->isorec.extent, s_hash->starting_block);
594 set_733((char *) s_entry->isorec.size, s_hash->size);
595 continue;
596 }
597
598 /*
599 * If this is for a directory that is not a . or a .. entry,
600 * then look up the information for the entry. We have already
601 * assigned extents for directories, so we just need to
602 * fill in the blanks here.
603 */
604 if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..") &&
605 s_entry->isorec.flags[0] == 2)
606 {
607 finddir = dpnt->subdir;
608 while(1==1)
609 {
610 if(finddir->self == s_entry) break;
611 finddir = finddir->next;
612 if(!finddir)
613 {
614 fprintf(stderr(&__sF[2]),"Fatal goof\n"); exit(1);
615 }
616 }
617 set_733((char *) s_entry->isorec.extent, finddir->extent);
618 s_entry->starting_block = finddir->extent;
619 s_entry->size = ROUND_UP(finddir->size)((finddir->size + ((2048) - 1)) & ~((2048) - 1));
620 total_dir_size += s_entry->size;
621 add_hash(s_entry);
622 set_733((char *) s_entry->isorec.size, ROUND_UP(finddir->size)((finddir->size + ((2048) - 1)) & ~((2048) - 1)));
623 continue;
624 }
625
626
627 /*
628 * If this is . or .., then look up the relevant info from the
629 * tables.
630 */
631 if(strcmp(s_entry->name,".") == 0)
632 {
633 set_733((char *) s_entry->isorec.extent, dpnt->extent);
634
635 /*
636 * Set these so that the hash table has the
637 * correct information
638 */
639 s_entry->starting_block = dpnt->extent;
640 s_entry->size = ROUND_UP(dpnt->size)((dpnt->size + ((2048) - 1)) & ~((2048) - 1));
641
642 add_hash(s_entry);
643 s_entry->starting_block = dpnt->extent;
644 set_733((char *) s_entry->isorec.size, ROUND_UP(dpnt->size)((dpnt->size + ((2048) - 1)) & ~((2048) - 1)));
645 continue;
646 }
647
648 if(strcmp(s_entry->name,"..") == 0)
649 {
650 if(dpnt == root)
651 {
652 total_dir_size += root->size;
653 }
654 set_733((char *) s_entry->isorec.extent, dpnt->parent->extent);
655
656 /*
657 * Set these so that the hash table has the
658 * correct information
659 */
660 s_entry->starting_block = dpnt->parent->extent;
661 s_entry->size = ROUND_UP(dpnt->parent->size)((dpnt->parent->size + ((2048) - 1)) & ~((2048) - 1
))
;
662
663 add_hash(s_entry);
664 s_entry->starting_block = dpnt->parent->extent;
665 set_733((char *) s_entry->isorec.size, ROUND_UP(dpnt->parent->size)((dpnt->parent->size + ((2048) - 1)) & ~((2048) - 1
))
);
666 continue;
667 }
668
669 /*
670 * Some ordinary non-directory file. Just schedule the
671 * file to be written. This is all quite
672 * straightforward, just make a list and assign extents
673 * as we go. Once we get through writing all of the
674 * directories, we should be ready write out these
675 * files
676 */
677 if(s_entry->size)
678 {
679 dwpnt = (struct deferred_write *)
680 e_malloc(sizeof(struct deferred_write));
681#ifdef APPLE_HYB1
682 /* save this directory entry for later use */
683 dwpnt->s_entry = s_entry;
684 /* set the initial padding to zero */
685 dwpnt->pad = 0;
686 /* maybe an offset to start of the real file/fork */
687 dwpnt->off = s_entry->hfs_off;
688#endif /* APPLE_HYB */
689 if(dw_tail)
690 {
691 dw_tail->next = dwpnt;
692 dw_tail = dwpnt;
693 }
694 else
695 {
696 dw_head = dwpnt;
697 dw_tail = dwpnt;
698 }
699 if(s_entry->inode == TABLE_INODE(sizeof(ino_t) >= 8 ? 0x7ffffffffffffffeLL : 0x7ffffffe))
700 {
701 dwpnt->table = s_entry->table;
702 dwpnt->name = NULL((void *)0);
703#ifdef APPLE_HYB1
704 snprintf(whole_path, sizeof whole_path, "%s%s%s",
705 s_entry->filedir->whole_name, SPATH_SEPARATOR"/",
706 trans_tbl);
707#else
708 snprintf(whole_path, sizeof whole_path,
709 "%s%sTRANS.TBL",
710 s_entry->filedir->whole_name, SPATH_SEPARATOR"/");
711#endif /* APPLE_HYB */
712 }
713 else
714 {
715 dwpnt->table = NULL((void *)0);
716 strcpy(whole_path, s_entry->whole_name);
717 dwpnt->name = strdup(whole_path);
718 }
719 dwpnt->next = NULL((void *)0);
720 dwpnt->size = s_entry->size;
721 dwpnt->extent = last_extent;
722 set_733((char *) s_entry->isorec.extent, last_extent);
723 s_entry->starting_block = last_extent;
724 add_hash(s_entry);
725 last_extent += ROUND_UP(s_entry->size)((s_entry->size + ((2048) - 1)) & ~((2048) - 1)) >> 11;
726 if(verbose > 2)
727 {
728 fprintf(stderr(&__sF[2]),"%d %d %s\n", s_entry->starting_block,
729 last_extent-1, whole_path);
730 }
731#ifdef DBG_ISO
732 if((ROUND_UP(s_entry->size)((s_entry->size + ((2048) - 1)) & ~((2048) - 1)) >> 11) > 500)
733 {
734 fprintf(stderr(&__sF[2]),"Warning: large file %s\n", whole_path);
735 fprintf(stderr(&__sF[2]),"Starting block is %d\n", s_entry->starting_block);
736 fprintf(stderr(&__sF[2]),"Reported file size is %d extents\n", s_entry->size);
737
738 }
739#endif
740#ifdef NOT_NEEDED /* Never use this code if you like to create a DVD */
741
742 if(last_extent > (800000000 >> 11))
743 {
744 /*
745 * More than 800Mb? Punt
746 */
747 fprintf(stderr(&__sF[2]),"Extent overflow processing file %s\n", whole_path);
748 fprintf(stderr(&__sF[2]),"Starting block is %d\n", s_entry->starting_block);
749 fprintf(stderr(&__sF[2]),"Reported file size is %d extents\n", s_entry->size);
750 exit(1);
751 }
752#endif
753 continue;
754 }
755
756 /*
757 * This is for zero-length files. If we leave the extent 0,
758 * then we get screwed, because many readers simply drop files
759 * that have an extent of zero. Thus we leave the size 0,
760 * and just assign the extent number.
761 */
762 set_733((char *) s_entry->isorec.extent, last_extent);
763 }
764 if(dpnt->subdir)
765 {
766 assign_file_addresses(dpnt->subdir);
767 }
768 dpnt = dpnt->next;
769 }
770} /* assign_file_addresses(... */
771
772static void FDECL1(free_one_directory, struct directory *, dpnt)free_one_directory(struct directory * dpnt)
773{
774 struct directory_entry * s_entry;
775 struct directory_entry * s_entry_d;
776
777 s_entry = dpnt->contents;
778 while(s_entry)
779 {
780 s_entry_d = s_entry;
781 s_entry = s_entry->next;
782
783 if( s_entry_d->name != NULL((void *)0) )
784 {
785 free (s_entry_d->name);
786 }
787 if( s_entry_d->whole_name != NULL((void *)0) )
788 {
789 free (s_entry_d->whole_name);
790 }
791#ifdef APPLE_HYB1
792 if (apple_both && s_entry_d->hfs_ent && !s_entry_d->assoc)
793 free(s_entry_d->hfs_ent);
794#endif /* APPLE_HYB */
795
796 free (s_entry_d);
797 }
798 dpnt->contents = NULL((void *)0);
799} /* free_one_directory(... */
800
801static void FDECL1(free_directories, struct directory *, dpnt)free_directories(struct directory * dpnt)
802{
803 while (dpnt)
804 {
805 free_one_directory(dpnt);
806 if(dpnt->subdir) free_directories(dpnt->subdir);
807 dpnt = dpnt->next;
808 }
809}
810
811void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile)generate_one_directory(struct directory * dpnt, FILE * outfile
)
812{
813 unsigned int ce_address = 0;
814 char * ce_buffer;
815 unsigned int ce_index = 0;
816 unsigned int ce_size;
817 unsigned int dir_index;
818 char * directory_buffer;
819 int new_reclen;
820 struct directory_entry * s_entry;
821 struct directory_entry * s_entry_d;
822 unsigned int total_size;
823
824 total_size = (dpnt->size + (SECTOR_SIZE(2048) - 1)) & ~(SECTOR_SIZE(2048) - 1);
825 directory_buffer = (char *) e_malloc(total_size);
826 memset(directory_buffer, 0, total_size);
827 dir_index = 0;
828
829 ce_size = (dpnt->ce_bytes + (SECTOR_SIZE(2048) - 1)) & ~(SECTOR_SIZE(2048) - 1);
830 ce_buffer = NULL((void *)0);
831
832 if(ce_size)
833 {
834 ce_buffer = (char *) e_malloc(ce_size);
835 memset(ce_buffer, 0, ce_size);
836
837 ce_index = 0;
838
839 /*
840 * Absolute byte address of CE entries for this directory
841 */
842 ce_address = last_extent_written + (total_size >> 11);
843 ce_address = ce_address << 11;
844 }
845
846 s_entry = dpnt->contents;
847 while(s_entry)
848 {
849 /* skip if it's hidden */
850 if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY0x40) {
851 s_entry = s_entry->next;
852 continue;
853 }
854
855 /*
856 * We do not allow directory entries to cross sector boundaries.
857 * Simply pad, and then start the next entry at the next sector
858 */
859 new_reclen = s_entry->isorec.length[0];
860 if( (dir_index & (SECTOR_SIZE(2048) - 1)) + new_reclen >= SECTOR_SIZE(2048) )
861 {
862 dir_index = (dir_index + (SECTOR_SIZE(2048) - 1)) &
863 ~(SECTOR_SIZE(2048) - 1);
864 }
865
866 memcpy(directory_buffer + dir_index, &s_entry->isorec,
867 sizeof(struct iso_directory_record) -
868 sizeof(s_entry->isorec.name) + s_entry->isorec.name_len[0]);
869 dir_index += sizeof(struct iso_directory_record) -
870 sizeof (s_entry->isorec.name)+ s_entry->isorec.name_len[0];
871
872 /*
873 * Add the Rock Ridge attributes, if present
874 */
875 if(s_entry->rr_attr_size)
876 {
877 if(dir_index & 1)
878 {
879 directory_buffer[dir_index++] = 0;
880 }
881
882 /*
883 * If the RR attributes were too long, then write the
884 * CE records, as required.
885 */
886 if(s_entry->rr_attr_size != s_entry->total_rr_attr_size)
887 {
888 unsigned char * pnt;
889 int len, nbytes;
890
891 /*
892 * Go through the entire record and fix up the CE entries
893 * so that the extent and offset are correct
894 */
895
896 pnt = s_entry->rr_attributes;
897 len = s_entry->total_rr_attr_size;
898 while(len > 3)
899 {
900#ifdef DEBUG
901 if (!ce_size)
902 {
903 fprintf(stderr(&__sF[2]),"Warning: ce_index(%d) && ce_address(%d) not initialized\n",
904 ce_index, ce_address);
905 }
906#endif
907
908 if(pnt[0] == 'C' && pnt[1] == 'E')
909 {
910 nbytes = get_733( (char *) pnt+20);
911
912 if((ce_index & (SECTOR_SIZE(2048) - 1)) + nbytes >=
913 SECTOR_SIZE(2048))
914 {
915 ce_index = ROUND_UP(ce_index)((ce_index + ((2048) - 1)) & ~((2048) - 1));
916 }
917
918 set_733( (char *) pnt+4,
919 (ce_address + ce_index) >> 11);
920 set_733( (char *) pnt+12,
921 (ce_address + ce_index) & (SECTOR_SIZE(2048) - 1));
922
923
924 /*
925 * Now store the block in the ce buffer
926 */
927 memcpy(ce_buffer + ce_index,
928 pnt + pnt[2], nbytes);
929 ce_index += nbytes;
930 if(ce_index & 1)
931 {
932 ce_index++;
933 }
934 }
935 len -= pnt[2];
936 pnt += pnt[2];
937 }
938
939 }
940
941 rockridge_size += s_entry->total_rr_attr_size;
942 memcpy(directory_buffer + dir_index, s_entry->rr_attributes,
943 s_entry->rr_attr_size);
944 dir_index += s_entry->rr_attr_size;
945 }
946 if(dir_index & 1)
947 {
948 directory_buffer[dir_index++] = 0;
949 }
950
951 s_entry_d = s_entry;
952 s_entry = s_entry->next;
953
954 /*
955 * Joliet doesn't use the Rock Ridge attributes, so we free it here.
956 */
957 if (s_entry_d->rr_attributes)
958 {
959 free(s_entry_d->rr_attributes);
960 s_entry_d->rr_attributes = NULL((void *)0);
961 }
962 }
963
964 if(dpnt->size != dir_index)
965 {
966 fprintf(stderr(&__sF[2]),"Unexpected directory length %d %d %s\n",dpnt->size,
967 dir_index, dpnt->de_name);
968 }
969
970 xfwrite(directory_buffer, 1, total_size, outfile);
971 last_extent_written += total_size >> 11;
972 free(directory_buffer);
973
974 if(ce_size)
975 {
976 if(ce_index != dpnt->ce_bytes)
977 {
978 fprintf(stderr(&__sF[2]),"Continuation entry record length mismatch (%d %d).\n",
979 ce_index, dpnt->ce_bytes);
980 }
981 xfwrite(ce_buffer, 1, ce_size, outfile);
982 last_extent_written += ce_size >> 11;
983 free(ce_buffer);
984 }
985
986} /* generate_one_directory(... */
987
988static
989void FDECL1(build_pathlist, struct directory *, node)build_pathlist(struct directory * node)
990{
991 struct directory * dpnt;
992
993 dpnt = node;
994
995 while (dpnt)
996 {
997 /* skip if it's hidden */
998 if( (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY0x40) == 0 )
999 pathlist[dpnt->path_index] = dpnt;
1000
1001 if(dpnt->subdir) build_pathlist(dpnt->subdir);
1002 dpnt = dpnt->next;
1003 }
1004} /* build_pathlist(... */
1005
1006static int FDECL2(compare_paths, void const *, r, void const *, l)compare_paths(void const * r, void const * l)
1007{
1008 struct directory const *ll = *(struct directory * const *)l;
1009 struct directory const *rr = *(struct directory * const *)r;
1010
1011 if (rr->parent->path_index < ll->parent->path_index)
1012 {
1013 return -1;
1014 }
1015
1016 if (rr->parent->path_index > ll->parent->path_index)
1017 {
1018 return 1;
1019 }
1020
1021 return strcmp(rr->self->isorec.name, ll->self->isorec.name);
1022
1023} /* compare_paths(... */
1024
1025static int generate_path_tables()
1026{
1027 struct directory_entry * de;
1028 struct directory * dpnt;
1029 int fix;
1030 int i;
1031 int j;
1032 int namelen;
1033 char * npnt;
1034 char * npnt1;
1035 int tablesize;
1036
1037 /*
1038 * First allocate memory for the tables and initialize the memory
1039 */
1040 tablesize = path_blocks << 11;
1041 path_table_m = (char *) e_malloc(tablesize);
1042 path_table_l = (char *) e_malloc(tablesize);
1043 memset(path_table_l, 0, tablesize);
1044 memset(path_table_m, 0, tablesize);
1045
1046 /*
1047 * Now start filling in the path tables. Start with root directory
1048 */
1049 if( next_path_index > 0xffff )
1050 {
1051 fprintf(stderr(&__sF[2]), "Unable to generate sane path tables - too many directories (%d)\n",
1052 next_path_index);
1053 exit(1);
1054 }
1055
1056 path_table_index = 0;
1057 pathlist = (struct directory **) e_malloc(sizeof(struct directory *)
1058 * next_path_index);
1059 memset(pathlist, 0, sizeof(struct directory *) * next_path_index);
1060 build_pathlist(root);
1061
1062 do
1063 {
1064 fix = 0;
1065#ifdef __STDC__1
1066 qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *),
1067 (int (*)(const void *, const void *))compare_paths);
1068#else
1069 qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *),
1070 compare_paths);
1071#endif
1072
1073 for(j=1; j<next_path_index; j++)
1074 {
1075 if(pathlist[j]->path_index != j)
1076 {
1077 pathlist[j]->path_index = j;
1078 fix++;
1079 }
1080 }
1081 } while(fix);
1082
1083 for(j=1; j<next_path_index; j++)
1084 {
1085 dpnt = pathlist[j];
1086 if(!dpnt)
1087 {
1088 fprintf(stderr(&__sF[2]),"Entry %d not in path tables\n", j);
1089 exit(1);
1090 }
1091 npnt = dpnt->de_name;
1092
1093 /*
1094 * So the root comes out OK
1095 */
1096 if( (*npnt == 0) || (dpnt == root) )
1097 {
1098 npnt = ".";
1099 }
1100 npnt1 = strrchr(npnt, PATH_SEPARATOR'/');
1101 if(npnt1)
1102 {
1103 npnt = npnt1 + 1;
1104 }
1105
1106 de = dpnt->self;
1107 if(!de)
1108 {
1109 fprintf(stderr(&__sF[2]),"Fatal goof\n");
1110 exit(1);
1111 }
1112
1113
1114 namelen = de->isorec.name_len[0];
1115
1116 path_table_l[path_table_index] = namelen;
1117 path_table_m[path_table_index] = namelen;
1118 path_table_index += 2;
1119
1120 set_731(path_table_l + path_table_index, dpnt->extent);
1121 set_732(path_table_m + path_table_index, dpnt->extent);
1122 path_table_index += 4;
1123
1124 set_721(path_table_l + path_table_index,
1125 dpnt->parent->path_index);
1126 set_722(path_table_m + path_table_index,
1127 dpnt->parent->path_index);
1128 path_table_index += 2;
1129
1130 for(i =0; i<namelen; i++)
1131 {
1132 path_table_l[path_table_index] = de->isorec.name[i];
1133 path_table_m[path_table_index] = de->isorec.name[i];
1134 path_table_index++;
1135 }
1136 if(path_table_index & 1)
1137 {
1138 path_table_index++; /* For odd lengths we pad */
1139 }
1140 }
1141
1142 free(pathlist);
1143 if(path_table_index != path_table_size)
1144 {
1145 fprintf(stderr(&__sF[2]),"Path table lengths do not match %d %d\n",
1146 path_table_index,
1147 path_table_size);
1148 }
1149 return 0;
1150} /* generate_path_tables(... */
1151
1152void
1153FDECL3(memcpy_max, char *, to, char *, from, int, max)memcpy_max(char * to, char * from, int max)
1154{
1155 int n = strlen(from);
1156 if (n > max)
1157 {
1158 n = max;
1159 }
1160 memcpy(to, from, n);
1161
1162} /* memcpy_max(... */
1163
1164void FDECL1(outputlist_insert, struct output_fragment *, frag)outputlist_insert(struct output_fragment * frag)
1165{
1166 if( out_tail == NULL((void *)0) )
1167 {
1168 out_list = out_tail = frag;
1169 }
1170 else
1171 {
1172 out_tail->of_next = frag;
1173 out_tail = frag;
1174 }
1175}
1176
1177static int FDECL1(file_write, FILE *, outfile)file_write(FILE * outfile)
1178{
1179 int should_write;
1180#ifdef APPLE_HYB1
1181 char buffer[2048];
1182
1183 memset(buffer, 0, sizeof(buffer));
1184
1185 if (apple_hyb) {
1186
1187 int i;
1188
1189 /* write out padding to round up to HFS allocation block */
1190 for(i=0;i<hfs_pad;i++)
1191 xfwrite(buffer, 1, sizeof(buffer), outfile);
1192
1193 last_extent_written += hfs_pad;
1194 }
1195#endif /* APPLE_HYB */
1196
1197 /*
1198 * OK, all done with that crap. Now write out the directories.
1199 * This is where the fur starts to fly, because we need to keep track of
1200 * each file as we find it and keep track of where we put it.
1201 */
1202
1203 should_write = last_extent - session_start;
1204
1205 if( print_size > 0 )
1206 {
1207#ifdef APPLE_HYB1
1208 if (apple_hyb)
1209 fprintf(stderr(&__sF[2]),"Total extents scheduled to be written (inc HFS) = %d\n",
1210 last_extent - session_start);
1211 else
1212#endif
1213 fprintf(stderr(&__sF[2]),"Total extents scheduled to be written = %d\n",
1214 last_extent - session_start);
1215 exit(0);
1216 }
1217 if( verbose > 2 )
1218 {
1219#ifdef DBG_ISO
1220 fprintf(stderr(&__sF[2]),"Total directory extents being written = %d\n", last_extent);
1221#endif
1222
1223#ifdef APPLE_HYB1
1224 if (apple_hyb)
1225 fprintf(stderr(&__sF[2]),"Total extents scheduled to be written (inc HFS) = %d\n",
1226 last_extent - session_start);
1227 else
1228#endif
1229 fprintf(stderr(&__sF[2]),"Total extents scheduled to be written = %d\n",
1230 last_extent - session_start);
1231 }
1232
1233 /*
1234 * Now write all of the files that we need.
1235 */
1236 write_files(outfile);
1237
1238#ifdef APPLE_HYB1
1239 /* write out extents/catalog/dt file */
1240 if (apple_hyb) {
1241
1242 xfwrite(hce->hfs_ce, hce->hfs_tot_size, HFS_BLOCKSZ512, outfile);
1243
1244 /* round up to a whole CD block */
1245 if (H_ROUND_UP(hce->hfs_tot_size)((((hce->hfs_tot_size)*512) + ((2048) - 1)) & ~((2048)
- 1))
- hce->hfs_tot_size*HFS_BLOCKSZ512)
1246 xfwrite(buffer, 1, H_ROUND_UP(hce->hfs_tot_size)((((hce->hfs_tot_size)*512) + ((2048) - 1)) & ~((2048)
- 1))
- hce->hfs_tot_size*HFS_BLOCKSZ512, outfile);
1247
1248 last_extent_written += ROUND_UP(hce->hfs_tot_size*HFS_BLOCKSZ)((hce->hfs_tot_size*512 + ((2048) - 1)) & ~((2048) - 1
))
/SECTOR_SIZE(2048);
1249
1250 /* write out HFS boot block */
1251 if (mac_boot.name)
1252 write_one_file(mac_boot.name, mac_boot.size, outfile, mac_boot.off);
1253 }
1254#endif /* APPLE_HYB */
1255
1256 /*
1257 * The rest is just fluff.
1258 */
1259 if( verbose == 0 )
1260 {
1261 return 0;
1262 }
1263
1264#ifdef APPLE_HYB1
1265 if (apple_hyb) {
1266 fprintf(stderr(&__sF[2]), "Total extents actually written (inc HFS) = %d\n",
1267 last_extent_written - session_start);
1268 fprintf(stderr(&__sF[2]), "(Size of ISO volume = %d, HFS extra = %d)\n",
1269 last_extent_written - session_start - hfs_extra, hfs_extra);
1270 }
1271 else
1272#else
1273 fprintf(stderr(&__sF[2]),"Total extents actually written = %d\n",
1274 last_extent_written - session_start);
1275#endif /* APPLE_HYB */
1276 /*
1277 * Hard links throw us off here
1278 */
1279 if(should_write != last_extent - session_start)
1280 {
1281 fprintf(stderr(&__sF[2]),"Number of extents written not what was predicted. Please fix.\n");
1282 fprintf(stderr(&__sF[2]),"Predicted = %d, written = %d\n", should_write, last_extent);
1283 }
1284
1285 fprintf(stderr(&__sF[2]),"Total translation table size: %d\n", table_size);
1286 fprintf(stderr(&__sF[2]),"Total rockridge attributes bytes: %d\n", rockridge_size);
1287 fprintf(stderr(&__sF[2]),"Total directory bytes: %d\n", total_dir_size);
1288 fprintf(stderr(&__sF[2]),"Path table size(bytes): %d\n", path_table_size);
1289
1290#ifdef DEBUG
1291 fprintf(stderr(&__sF[2]), "next extent, last_extent, last_extent_written %d %d %d\n",
1292 next_extent, last_extent, last_extent_written);
1293#endif
1294
1295 return 0;
1296
1297} /* iso_write(... */
1298
1299/*
1300 * Function to write the PVD for the disc.
1301 */
1302static int FDECL1(pvd_write, FILE *, outfile)pvd_write(FILE * outfile)
1303{
1304 char iso_time[17];
1305 int should_write;
1306 struct tm local;
1307 struct tm gmt;
1308
1309
1310 time(&begun);
1311
1312 local = *localtime(&begun);
1313 gmt = *gmtime(&begun);
1314
1315 /*
1316 * This will break in the year 2000, I supose, but there is no good way
1317 * to get the top two digits of the year.
1318 */
1319 snprintf(iso_time, sizeof iso_time, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00",
1320 1900 + local.tm_year,
1321 local.tm_mon+1, local.tm_mday,
1322 local.tm_hour, local.tm_min, local.tm_sec);
1323
1324 local.tm_min -= gmt.tm_min;
1325 local.tm_hour -= gmt.tm_hour;
1326 local.tm_yday -= gmt.tm_yday;
1327 iso_time[16] = (local.tm_min + 60*(local.tm_hour + 24*local.tm_yday)) / 15;
1328
1329 /*
1330 * Next we write out the primary descriptor for the disc
1331 */
1332 memset(&vol_desc, 0, sizeof(vol_desc));
1333 vol_desc.type[0] = ISO_VD_PRIMARY1;
1334 memcpy(vol_desc.id, ISO_STANDARD_ID"CD001", sizeof(ISO_STANDARD_ID"CD001") - 1);
1335 vol_desc.version[0] = 1;
1336
1337 memset(vol_desc.system_id, ' ', sizeof(vol_desc.system_id));
1338 memcpy_max(vol_desc.system_id, system_id, strlen(system_id));
1339
1340 memset(vol_desc.volume_id, ' ', sizeof(vol_desc.volume_id));
1341 memcpy_max(vol_desc.volume_id, volume_id, strlen(volume_id));
1342
1343 should_write = last_extent - session_start;
1344 set_733((char *) vol_desc.volume_space_size, should_write);
1345 set_723(vol_desc.volume_set_size, volume_set_size);
1346 set_723(vol_desc.volume_sequence_number, volume_sequence_number);
1347 set_723(vol_desc.logical_block_size, 2048);
1348
1349 /*
1350 * The path tables are used by DOS based machines to cache directory
1351 * locations
1352 */
1353
1354 set_733((char *) vol_desc.path_table_size, path_table_size);
1355 set_731(vol_desc.type_l_path_table, path_table[0]);
1356 set_731(vol_desc.opt_type_l_path_table, path_table[1]);
1357 set_732(vol_desc.type_m_path_table, path_table[2]);
1358 set_732(vol_desc.opt_type_m_path_table, path_table[3]);
1359
1360 /*
1361 * Now we copy the actual root directory record
1362 */
1363 memcpy(vol_desc.root_directory_record, &root_record,
1364 sizeof(vol_desc.root_directory_record));
1365
1366 /*
1367 * The rest is just fluff. It looks nice to fill in many of these fields,
1368 * though.
1369 */
1370 FILL_SPACE(volume_set_id)memset(vol_desc.volume_set_id, ' ', sizeof(vol_desc.volume_set_id
))
;
1371 if(volset_id) memcpy_max(vol_desc.volume_set_id, volset_id, strlen(volset_id));
1372
1373 FILL_SPACE(publisher_id)memset(vol_desc.publisher_id, ' ', sizeof(vol_desc.publisher_id
))
;
1374 if(publisher) memcpy_max(vol_desc.publisher_id, publisher, strlen(publisher));
1375
1376 FILL_SPACE(preparer_id)memset(vol_desc.preparer_id, ' ', sizeof(vol_desc.preparer_id
))
;
1377 if(preparer) memcpy_max(vol_desc.preparer_id, preparer, strlen(preparer));
1378
1379 FILL_SPACE(application_id)memset(vol_desc.application_id, ' ', sizeof(vol_desc.application_id
))
;
1380 if(appid) memcpy_max(vol_desc.application_id, appid, strlen(appid));
1381
1382 FILL_SPACE(copyright_file_id)memset(vol_desc.copyright_file_id, ' ', sizeof(vol_desc.copyright_file_id
))
;
1383 if(copyright) memcpy_max(vol_desc.copyright_file_id, copyright,
1384 strlen(copyright));
1385
1386 FILL_SPACE(abstract_file_id)memset(vol_desc.abstract_file_id, ' ', sizeof(vol_desc.abstract_file_id
))
;
1387 if(abstract) memcpy_max(vol_desc.abstract_file_id, abstract,
1388 strlen(abstract));
1389
1390 FILL_SPACE(bibliographic_file_id)memset(vol_desc.bibliographic_file_id, ' ', sizeof(vol_desc.bibliographic_file_id
))
;
1391 if(biblio) memcpy_max(vol_desc.bibliographic_file_id, biblio,
1392 strlen(biblio));
1393
1394 FILL_SPACE(creation_date)memset(vol_desc.creation_date, ' ', sizeof(vol_desc.creation_date
))
;
1395 FILL_SPACE(modification_date)memset(vol_desc.modification_date, ' ', sizeof(vol_desc.modification_date
))
;
1396 FILL_SPACE(expiration_date)memset(vol_desc.expiration_date, ' ', sizeof(vol_desc.expiration_date
))
;
1397 FILL_SPACE(effective_date)memset(vol_desc.effective_date, ' ', sizeof(vol_desc.effective_date
))
;
1398 vol_desc.file_structure_version[0] = 1;
1399 FILL_SPACE(application_data)memset(vol_desc.application_data, ' ', sizeof(vol_desc.application_data
))
;
1400
1401 memcpy(vol_desc.creation_date, iso_time, 17);
1402 memcpy(vol_desc.modification_date, iso_time, 17);
1403 memcpy(vol_desc.expiration_date, "0000000000000000", 17);
1404 memcpy(vol_desc.effective_date, iso_time, 17);
1405
1406 /*
1407 * if not a bootable cd do it the old way
1408 */
1409 xfwrite(&vol_desc, 1, 2048, outfile);
1410 last_extent_written++;
1411 return 0;
1412}
1413
1414/*
1415 * Function to write the EVD for the disc.
1416 */
1417static int FDECL1(evd_write, FILE *, outfile)evd_write(FILE * outfile)
1418{
1419 struct iso_primary_descriptor evol_desc;
1420
1421 /*
1422 * Now write the end volume descriptor. Much simpler than the other one
1423 */
1424 memset(&evol_desc, 0, sizeof(evol_desc));
1425 evol_desc.type[0] = ISO_VD_END255;
1426 memcpy(evol_desc.id, ISO_STANDARD_ID"CD001", sizeof(ISO_STANDARD_ID"CD001") - 1);
1427 evol_desc.version[0] = 1;
1428 xfwrite(&evol_desc, 1, 2048, outfile);
1429 last_extent_written += 1;
1430 return 0;
1431}
1432
1433/*
1434 * Function to write the EVD for the disc.
1435 */
1436static int FDECL1(pathtab_write, FILE *, outfile)pathtab_write(FILE * outfile)
1437{
1438 /*
1439 * Next we write the path tables
1440 */
1441 xfwrite(path_table_l, 1, path_blocks << 11, outfile);
1442 xfwrite(path_table_m, 1, path_blocks << 11, outfile);
1443 last_extent_written += 2*path_blocks;
1444 free(path_table_l);
1445 free(path_table_m);
1446 path_table_l = NULL((void *)0);
1447 path_table_m = NULL((void *)0);
1448 return 0;
1449}
1450
1451static int FDECL1(exten_write, FILE *, outfile)exten_write(FILE * outfile)
1452{
1453 xfwrite(extension_record, 1, SECTOR_SIZE(2048), outfile);
1454 last_extent_written++;
1455 return 0;
1456}
1457
1458/*
1459 * Functions to describe padding block at the start of the disc.
1460 */
1461int FDECL1(oneblock_size, int, starting_extent)oneblock_size(int starting_extent)
1462{
1463 last_extent++;
1464 return 0;
1465}
1466
1467/*
1468 * Functions to describe padding block at the start of the disc.
1469 */
1470static int FDECL1(pathtab_size, int, starting_extent)pathtab_size(int starting_extent)
1471{
1472 path_table[0] = starting_extent;
1473
1474 path_table[1] = 0;
1475 path_table[2] = path_table[0] + path_blocks;
1476 path_table[3] = 0;
1477 last_extent += 2*path_blocks;
1478 return 0;
1479}
1480
1481static int FDECL1(padblock_size, int, starting_extent)padblock_size(int starting_extent)
1482{
1483 last_extent += 16;
1484 return 0;
1485}
1486
1487static int file_gen()
1488{
1489#ifdef APPLE_HYB1
1490 int start_extent = last_extent; /* orig ISO files start */
1491#endif /* APPLE_HYB */
1492 assign_file_addresses(root);
1493#ifdef APPLE_HYB1
1494 /* put this here for the time being - may when I've worked out how
1495 to use Eric's new system for creating/writing parts of the image
1496 it may move to it's own routine */
1497
1498 if (apple_hyb)
1499 {
1500 int Csize; /* clump size for HFS vol */
1501 int loop = CTC_LOOP4;
1502 int last_extent_save = last_extent;
1503
1504 /* allocate memory for the libhfs/mkisofs extra info */
1505 hce = (hce_mem *)e_malloc(sizeof(hce_mem));
1506
1507 hce->error = (char *)e_malloc(ERROR_SIZE1024);
1508
1509 /* mark as unallocated for use later */
1510 hce->hfs_ce = hce->hfs_hdr = hce->hfs_map = 0;
1511
1512 /* reserve space for the label partition - if it is needed */
1513 if (gen_pt)
1514 hce->hfs_map_size = HFS_MAP_SIZE16;
1515 else
1516 hce->hfs_map_size = 0;
1517
1518 /* set the intial factor to increase Catalog file size */
1519 hce->ctc_size = CTC2;
1520
1521 /* "create" the HFS volume (just the header, catalog/extents files)
1522 if there's a problem with the Catalog file being too small,
1523 we keep on increasing the size (up to CTC_LOOP) times and try again.
1524 Unfortunately I don't know enough about the inner workings of
1525 HFS, so I can't workout the size of the Catalog file in
1526 advance (and I don't want to "grow" as is is normally allowed to),
1527 therefore, this approach is a bit over the top as it involves
1528 throwing away the "volume" we have created and trying again ... */
1529 do
1530 {
1531 hce->error[0] = '\0';
1532
1533 /* attempt to create the Mac volume */
1534 Csize = make_mac_volume(root, start_extent);
1535
1536 /* if we have a problem ... */
1537 if (Csize < 0)
1538 {
1539 /* we've made too many attempts, or got some other error */
1540 if (loop == 0 || errno(*__errno()) != HCE_ERROR-9999)
1541 {
1542 /* HCE_ERROR is not a valid errno value */
1543 if (errno(*__errno()) == HCE_ERROR-9999)
1544 errno(*__errno()) = 0;
1545
1546 /* exit with the error */
1547 if (*hce->error)
1548 fprintf(stderr(&__sF[2]), "%s\n", hce->error);
1549 err(1, "%s", hfs_error);
1550 }
1551 else
1552 {
1553 /* increase Catalog file size factor */
1554 hce->ctc_size *= CTC2;
1555
1556 /* reset the initial "last_extent" and try again */
1557 last_extent = last_extent_save;
1558 }
1559 }
1560 else
1561 /* everything OK - just carry on ... */
1562 loop = 0;
1563 }
1564 while (loop--);
1565
1566 hfs_extra = H_ROUND_UP(hce->hfs_tot_size)((((hce->hfs_tot_size)*512) + ((2048) - 1)) & ~((2048)
- 1))
/SECTOR_SIZE(2048);
1567
1568 last_extent += hfs_extra;
1569
1570 /* generate the Mac label and HFS partition maps */
1571 mac_boot.name = hfs_boot_file;
1572
1573 /* only generate the partition tables etc. if we are making a bootable
1574 CD - or if the -part option is given */
1575 if (gen_pt) {
1576 if (gen_mac_label(&mac_boot)) {
1577 if (*hce->error)
1578 fprintf(stderr(&__sF[2]), "%s\n", hce->error);
1579 err(1, "%s", hfs_error);
1580 }
1581 }
1582
1583 /* set Autostart filename if required */
1584 if (autoname) {
1585 if(autostart())
1586 errx(1, "Autostart filename must less than 12 characters");
1587 }
1588
1589 /* finished with any HFS type errors */
1590 free(hce->error);
1591 hce->error = 0;
1592
1593 /* the ISO files need to start on a multiple of the HFS allocation
1594 blocks, so find out how much padding we need */
1595
1596 /* take in accout alignment of files wrt HFS volume start */
1597 hfs_pad = V_ROUND_UP(start_extent*SECTOR_SIZE + (hce->hfs_hdr_size + hce->hfs_map_size)*HFS_BLOCKSZ, Csize)(((start_extent*(2048) + (hce->hfs_hdr_size + hce->hfs_map_size
)*512 + (Csize - 1)) / Csize) * Csize)
/SECTOR_SIZE(2048);
1598
1599 hfs_pad -= (start_extent + (hce->hfs_hdr_size + hce->hfs_map_size)/BLK_CONV((2048)/512));
1600 }
1601#endif /* APPLE_HYB */
1602 return 0;
1603}
1604
1605static int dirtree_dump()
1606{
1607 if (verbose > 2)
1608 {
1609 dump_tree(root);
1610 }
1611 return 0;
1612}
1613
1614static int FDECL1(dirtree_fixup, int, starting_extent)dirtree_fixup(int starting_extent)
1615{
1616 if (use_RockRidge && reloc_dir)
1617 finish_cl_pl_entries();
1618
1619 if (use_RockRidge )
1620 update_nlink_field(root);
1621 return 0;
1622}
1623
1624static int FDECL1(dirtree_size, int, starting_extent)dirtree_size(int starting_extent)
1625{
1626 assign_directory_addresses(root);
1627 return 0;
1628}
1629
1630static int FDECL1(ext_size, int, starting_extent)ext_size(int starting_extent)
1631{
1632 extern int extension_record_size;
1633 struct directory_entry * s_entry;
1634 extension_record_extent = starting_extent;
1635 s_entry = root->contents;
1636 set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 24,
1637 extension_record_extent);
1638 set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 8,
1639 extension_record_size);
1640 last_extent++;
1641 return 0;
1642}
1643
1644static int FDECL1(dirtree_write, FILE *, outfile)dirtree_write(FILE * outfile)
1645{
1646 generate_iso9660_directories(root, outfile);
1647 return 0;
1648}
1649
1650static int FDECL1(dirtree_cleanup, FILE *, outfile)dirtree_cleanup(FILE * outfile)
1651{
1652 free_directories(root);
1653 return 0;
1654}
1655
1656static int FDECL1(padblock_write, FILE *, outfile)padblock_write(FILE * outfile)
1657{
1658 char buffer[2048];
1659 int i;
1660#ifdef APPLE_HYB1
1661 int n = 0;
1662#endif /* APPLE_HYB */
1663
1664 memset(buffer, 0, sizeof(buffer));
1665
1666#ifdef APPLE_HYB1
1667 if (apple_hyb)
1668 {
1669 int r; /* HFS hdr output */
1670 int tot_size = hce->hfs_map_size + hce->hfs_hdr_size;
1671
1672 /* get size in CD blocks == 4xHFS_BLOCKSZ == 2048 */
1673 n = tot_size/BLK_CONV((2048)/512);
1674 r = tot_size%BLK_CONV((2048)/512);
1675
1676 /* write out HFS volume header info */
1677 xfwrite(hce->hfs_map, tot_size, HFS_BLOCKSZ512, outfile);
1678
1679 /* write out any partial CD block */
1680 if (r)
1681 {
1682 xfwrite(buffer, BLK_CONV((2048)/512)-r, HFS_BLOCKSZ512, outfile);
1683 n++;
1684 }
1685 }
1686
1687 /* write out the remainder of the ISO header */
1688 for(i=n; i<16; i++)
1689#else
1690 for(i=0; i<16; i++)
1691#endif /* APPLE_HYB */
1692 {
1693 xfwrite(buffer, 1, sizeof(buffer), outfile);
1694 }
1695
1696 last_extent_written += 16;
1697 return 0;
1698}
1699
1700#ifdef APPLE_HYB1
1701
1702/*
1703** get_adj_size: get the ajusted size of the volume with the HFS
1704** allocation block size for each file
1705*/
1706int FDECL1(get_adj_size, int, Csize)get_adj_size(int Csize)
1707{
1708 struct deferred_write *dw;
1709 int size = 0;
1710 int count = 0;
1711
1712 /* loop through all the files finding the new total size */
1713 for(dw = dw_head; dw; dw = dw->next)
1714 {
1715 size += V_ROUND_UP(dw->size, Csize)(((dw->size + (Csize - 1)) / Csize) * Csize);
1716 count++;
1717 }
1718
1719 /* crude attempt to prevent overflows - HFS can only cope with a
1720 maximum of about 65536 forks (actually less) - this will trap
1721 cases when we have far too many files */
1722 if (count >= 65536)
1723 return (-1);
1724 else
1725 return(size);
1726}
1727/*
1728** adj_size: adjust the ISO record entries for all files
1729** based on the HFS allocation block size
1730*/
1731int FDECL3(adj_size, int, Csize, int, start_extent, int, extra)adj_size(int Csize, int start_extent, int extra)
1732{
1733 struct deferred_write *dw;
1734 struct directory_entry *s_entry;
1735 int size;
1736
1737 /* get the adjusted start_extent (with padding) */
1738 /* take in accout alignment of files wrt HFS volume start */
1739
1740 start_extent = V_ROUND_UP(start_extent*SECTOR_SIZE + extra *HFS_BLOCKSZ, Csize)(((start_extent*(2048) + extra *512 + (Csize - 1)) / Csize) *
Csize)
/SECTOR_SIZE(2048);
1741
1742 start_extent -= (extra/BLK_CONV((2048)/512));
1743
1744 /* initialise file hash */
1745 flush_hash();
1746
1747 /* loop through all files changing their starting blocks and
1748 finding any padding needed to written out latter */
1749 for(dw = dw_head; dw; dw = dw->next)
1750 {
1751 s_entry = dw->s_entry;
1752 s_entry->starting_block = dw->extent = start_extent;
1753 set_733((char *) s_entry->isorec.extent, start_extent);
1754 size = V_ROUND_UP(dw->size, Csize)(((dw->size + (Csize - 1)) / Csize) * Csize)/SECTOR_SIZE(2048);
1755 dw->pad = size - ROUND_UP(dw->size)((dw->size + ((2048) - 1)) & ~((2048) - 1))/SECTOR_SIZE(2048);
1756
1757 /* cache non-HFS files - as there may be multiple links to
1758 these files (HFS files can't have multiple links). We will
1759 need to change the starting extent of the other links later */
1760 if (!s_entry->hfs_ent)
1761 add_hash(s_entry);
1762
1763 start_extent += size;
1764 }
1765
1766 return(start_extent);
1767}
1768
1769/*
1770** adj_size_other: adjust any non-HFS files that may be linked
1771** to an existing file (i.e. not have a deferred_write
1772** entry of it's own
1773*/
1774void FDECL1(adj_size_other, struct directory *, dpnt)adj_size_other(struct directory * dpnt)
1775{
1776 struct directory_entry * s_entry;
1777 struct file_hash *s_hash;
1778
1779 while (dpnt)
1780 {
1781 s_entry = dpnt->contents;
Value stored to 's_entry' is never read
1782 for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next)
1783 {
1784 /* if it's an HFS file or a directory - then ignore
1785 (we're after non-HFS files) */
1786 if (s_entry->hfs_ent || (s_entry->isorec.flags[0] & 2))
1787 continue;
1788
1789 /* find any cached entry and assign new starting extent */
1790 s_hash = find_hash(s_entry->dev, s_entry->inode);
1791 if(s_hash)
1792 {
1793 set_733((char *) s_entry->isorec.extent, s_hash->starting_block);
1794 /* not vital - but tidy */
1795 s_entry->starting_block = s_hash->starting_block;
1796 }
1797
1798 }
1799 if(dpnt->subdir)
1800 {
1801 adj_size_other(dpnt->subdir);
1802 }
1803 dpnt = dpnt->next;
1804 }
1805
1806 /* clear file hash */
1807 flush_hash();
1808}
1809
1810#endif /* APPLE_HYB */
1811
1812struct output_fragment padblock_desc = {NULL((void *)0), padblock_size, NULL((void *)0), padblock_write};
1813struct output_fragment voldesc_desc = {NULL((void *)0), oneblock_size, root_gen, pvd_write};
1814struct output_fragment end_vol = {NULL((void *)0), oneblock_size, NULL((void *)0), evd_write};
1815struct output_fragment pathtable_desc = {NULL((void *)0), pathtab_size, generate_path_tables, pathtab_write};
1816struct output_fragment dirtree_desc = {NULL((void *)0), dirtree_size, NULL((void *)0), dirtree_write};
1817struct output_fragment dirtree_clean = {NULL((void *)0), dirtree_fixup, dirtree_dump, dirtree_cleanup};
1818struct output_fragment extension_desc = {NULL((void *)0), ext_size, NULL((void *)0), exten_write};
1819struct output_fragment files_desc = {NULL((void *)0), NULL((void *)0), file_gen, file_write};