ReactOS 0.4.15-dev-8135-g1bc6c90
write.c
Go to the documentation of this file.
1/* @(#)write.c 1.146 16/12/13 joerg */
2#include <schily/mconfig.h>
3#ifndef lint
4static UConst char sccsid[] =
5 "@(#)write.c 1.146 16/12/13 joerg";
6#endif
7/*
8 * Program write.c - dump memory structures to file for iso9660 filesystem.
9 *
10 * Written by Eric Youngdale (1993).
11 *
12 * Copyright 1993 Yggdrasil Computing, Incorporated
13 * Copyright (c) 1999-2016 J. Schilling
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2, or (at your option)
18 * any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 */
29
30/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */
31
32/* DUPLICATES_ONCE Alex Kopylov cdrtools@bootcd.ru 19.06.2004 */
33
34#include "mkisofs.h"
35#include <schily/time.h>
36#include <schily/fcntl.h>
37#ifdef SORTING
38#include "match.h"
39#endif /* SORTING */
40#include <schily/errno.h>
41#include <schily/schily.h>
42#include <schily/checkerr.h>
43#ifdef DVD_AUD_VID
44#include "dvd_reader.h"
45#include "dvd_file.h"
46#include "ifo_read.h"
47#endif
48#ifdef APPLE_HYB
49#include <schily/ctype.h>
50#endif
51
52#ifdef VMS
53#include "vms.h"
54#endif
55
56#define SIZEOF_UDF_EXT_ATTRIBUTE_COMMON 50
57
58/* Max number of sectors we will write at one time */
59#define NSECT 32
60
61#define INSERTMACRESFORK 1
62
63/* Counters for statistics */
64
71
73
76
79
80#ifndef APPLE_HFS_HYB
81 char *hfs_error = __("no error");
82#endif
83
84LOCAL int xawrite __PR((void *buffer, int size, int count,
85 FILE *file, int submode, BOOL islast));
86EXPORT void xfwrite __PR((void *buffer, int size, int count,
87 FILE *file, int submode, BOOL islast));
89#if defined(APPLE_HYB) || defined(USE_LARGEFILES)
91 FILE *outfile, off_t off,
92 int isrfile, unsigned rba));
93#else
95 FILE *outfile));
96#endif
97#ifdef UDF
98LOCAL void write_udf_symlink __PR((char *filename, off_t size,
99 FILE *outfile));
100#endif
102#if 0
103LOCAL void dump_filelist __PR((void));
104#endif
105LOCAL int compare_dirs __PR((const void *rr, const void *ll));
107 int rr));
108LOCAL int root_gen __PR((void));
111LOCAL void free_directories __PR((struct directory *dpnt));
113 FILE *outfile));
114LOCAL void build_pathlist __PR((struct directory *node));
115LOCAL int compare_paths __PR((void const *r, void const *l));
117EXPORT void memcpy_max __PR((char *to, char *from, int max));
124LOCAL int graftcp __PR((char *to, char *from, char *ep));
125LOCAL int pathcp __PR((char *to, char *from, char *ep));
128EXPORT int oneblock_size __PR((UInt32_t starting_extent));
129LOCAL int pathtab_size __PR((UInt32_t starting_extent));
130LOCAL int startpad_size __PR((UInt32_t starting_extent));
131LOCAL int interpad_size __PR((UInt32_t starting_extent));
132LOCAL int endpad_size __PR((UInt32_t starting_extent));
133LOCAL int file_gen __PR((void));
134LOCAL int dirtree_dump __PR((void));
135LOCAL int dirtree_fixup __PR((UInt32_t starting_extent));
136LOCAL int dirtree_size __PR((UInt32_t starting_extent));
137LOCAL int ext_size __PR((UInt32_t starting_extent));
143#ifdef APPLE_HYB
144LOCAL int hfs_pad;
145LOCAL int hfs_get_parms __PR((char *key));
146LOCAL void hfs_file_gen __PR((UInt32_t start_extent));
147LOCAL void gen_prepboot __PR((void));
148EXPORT Ulong get_adj_size __PR((int Csize));
149EXPORT int adj_size __PR((int Csize, UInt32_t start_extent, int extra));
150EXPORT void adj_size_other __PR((struct directory *dpnt));
151LOCAL int hfs_hce_write __PR((FILE *outfile));
152EXPORT int insert_padding_file __PR((int size));
153#endif /* APPLE_HYB */
154
155#ifdef SORTING
156LOCAL int compare_sort __PR((const void *rr, const void *ll));
157LOCAL void reassign_link_addresses __PR((struct directory *dpnt));
158LOCAL int sort_file_addresses __PR((void));
159#endif /* SORTING */
160
161/*
162 * Routines to actually write the disc. We write sequentially so that
163 * we could write a tape, or write the disc directly
164 */
165#define FILL_SPACE(X) memset(vol_desc.X, ' ', sizeof (vol_desc.X))
166
167EXPORT void
168xfwrite(buffer, size, count, file, submode, islast)
169 void *buffer;
170 int size;
171 int count;
172 FILE *file;
173 int submode;
174 BOOL islast;
175{
176 /*
177 * This is a hack that could be made better.
178 * XXXIs this the only place?
179 * It is definitely needed on Operating Systems that do not allow to
180 * write files that are > 2GB. If the system is fast enough to be able
181 * to feed 1400 KB/s writing speed of a DVD-R drive, use stdout.
182 * If the system cannot do this reliable, you need to use this hacky
183 * option.
184 */
185 static int idx = 0;
186
187#ifdef XFWRITE_DEBUG
188 if (count != 1 || (size % 2048) != 0)
189 error(_("Count: %d, size: %d\n"), count, size);
190#endif
191 if (count == 0 || size == 0) {
193 _("Implementation botch, write 0 bytes (size %d count %d).\n"),
194 size, count);
195 abort();
196 }
197
198 if (split_output != 0 &&
199 (idx == 0 || ftell(file) >= ((off_t)1024 * 1024 * 1024))) {
200 char nbuf[512];
201 extern char *outfile;
202
203 if (idx == 0)
205 sprintf(nbuf, "%s_%02d", outfile, idx++);
206 file = freopen(nbuf, "wb", file);
207 if (file == NULL) {
208 comerr(_("Cannot open '%s'.\n"), nbuf);
209 }
210 }
211 while (count) {
212 int got;
213
214 seterrno(0);
215 if (osecsize != 0)
216 got = xawrite(buffer, size, count, file, submode, islast);
217 else
218 got = fwrite(buffer, size, count, file);
219
220 if (got <= 0) {
221 comerr(_("cannot fwrite %d*%d\n"), size, count);
222 }
223 /*
224 * This comment is in hope to prevent silly people from
225 * e.g. SuSE (who did not yet learn C but believe that
226 * they need to patch other peoples code) from changing the
227 * next cast into an illegal lhs cast expression.
228 * The cast below is the correct way to handle the problem.
229 * The (void *) cast is to avoid a GCC warning like:
230 * "warning: dereferencing type-punned pointer will break \
231 * strict-aliasing rules"
232 * which is wrong this code. (void *) introduces a compatible
233 * intermediate type in the cast list.
234 */
235 count -= got, *(char **)(void *)&buffer += size * got;
236 }
237}
238
239LOCAL int
240xawrite(buffer, size, count, file, submode, islast)
241 void *buffer;
242 int size;
243 int count;
244 FILE *file;
245 int submode;
246 BOOL islast;
247{
248 register char *p = buffer;
249 register int amt = size * count;
250 register int n;
251 struct xa_subhdr subhdr[2];
252
253 if (osecsize == 2048)
254 return (fwrite(buffer, size, count, file));
255
256 if (amt % 2048)
258 _("Trying to write %d bytes (not a multiple of 2048).\n"),
259 amt);
260
261 subhdr[0].file_number = subhdr[1].file_number = 0;
262 subhdr[0].channel_number = subhdr[1].channel_number = 0;
263 subhdr[0].coding = subhdr[1].coding = 0;
264
265 while (amt > 0) {
266#ifdef LATER
267 if (submode < 0)
268 subhdr[0].sub_mode = subhdr[1].sub_mode = XA_SUBH_DATA;
269 else
270 subhdr[0].sub_mode = subhdr[1].sub_mode = submode;
271#else
272 subhdr[0].sub_mode = subhdr[1].sub_mode = XA_SUBH_DATA;
273#endif
274
275 if ((amt <= 2048) && islast) {
276 subhdr[0].sub_mode = subhdr[1].sub_mode
278 }
279 n = fwrite(subhdr, sizeof (subhdr), 1, file);
280 if (n <= 0)
281 return (n);
282
283 n = fwrite(p, 2048, 1, file);
284 if (n <= 0)
285 return (n);
286
287 p += 2048;
288 amt -= 2048;
289 }
290 return (1);
291}
292
293#ifdef APPLE_HYB
294/*
295 * use the deferred_write struct to store info about the hfs_boot_file
296 */
297LOCAL struct deferred_write mac_boot;
298
299#endif /* APPLE_HYB */
302
307
308/*
309 * We recursively walk through all of the directories and assign extent
310 * numbers to them. We have already assigned extent numbers to everything that
311 * goes in front of them
312 */
313LOCAL int
315 struct directory *node;
316{
317 int dir_size;
318 struct directory *dpnt;
319
320 dpnt = node;
321
322 while (dpnt) {
323 /* skip if it's hidden */
324 if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) {
325 dpnt = dpnt->next;
326 continue;
327 }
328 /*
329 * If we already have an extent for this (i.e. it came from a
330 * multisession disc), then don't reassign a new extent.
331 */
332 dpnt->path_index = next_path_index++;
333 if (dpnt->extent == 0) {
334 dpnt->extent = last_extent;
335 dir_size = ISO_BLOCKS(dpnt->size);
336
337 last_extent += dir_size;
338
339 /*
340 * Leave room for the CE entries for this directory.
341 * Keep them close to the reference directory so that
342 * access will be quick.
343 */
344 if (dpnt->ce_bytes) {
346 }
347 }
348 if (dpnt->subdir) {
350 }
351 dpnt = dpnt->next;
352 }
353 return (0);
354}
355
356#if defined(APPLE_HYB) || defined(USE_LARGEFILES)
357LOCAL void
358write_one_file(filename, size, outfile, off, isrfile, rba)
359 char *filename;
360 off_t size;
361 FILE *outfile;
362 off_t off;
363 int isrfile;
364 unsigned rba;
365#else
366LOCAL void
368 char *filename;
369 off_t size;
370 FILE *outfile;
371#endif /* APPLE_HYB || USE_LARGEFILES */
372{
373 /*
374 * It seems that there are still stone age C-compilers
375 * around.
376 * The Metrowerks C found on BeOS/PPC does not allow
377 * more than 32kB of local vars.
378 * As we do not need to call write_one_file() recursively
379 * we make buffer static.
380 */
381#ifdef __BEOS__
382static char buffer[SECTOR_SIZE * NSECT];
383#else
384 char buffer[SECTOR_SIZE * NSECT];
385#endif
386 FILE *infile;
387 off_t remain;
388 int use;
389 int unroundeduse;
390 int bytestowrite = 0; /* Dummy init. to serve GCC bug */
391 int correctedsize = 0;
392
393
394 if ((infile = fopen(filename, "rb")) == NULL) {
395 if (!errhidden(E_OPEN, filename)) {
397 ;
398 errmsg(_("Cannot open '%s'.\n"), filename);
400 }
401 }
402#if defined(APPLE_HYB) || defined(USE_LARGEFILES)
403 if (infile)
404 fseek(infile, off, SEEK_SET);
405#if defined(INSERTMACRESFORK) && defined(UDF)
406 if (isrfile && use_udf) {
407 memset(buffer, 0, sizeof (buffer));
408 udf_set_extattr_freespace((Uchar *)buffer, size, rba);
411
412 memset(buffer, 0, sizeof (buffer));
413 udf_set_extattr_macresfork((Uchar *)buffer, size, rba);
415 correctedsize = SIZEOF_UDF_EXT_ATTRIBUTE_COMMON;
416 }
417#endif
418#endif /* APPLE_HYB || USE_LARGEFILES */
419 remain = size;
420
421 while (remain > 0) {
422 int amt;
423
424 unroundeduse = use = (remain > SECTOR_SIZE * NSECT - 1 ?
425 NSECT * SECTOR_SIZE : remain);
426 use = ISO_ROUND_UP(use); /* Round up to nearest sector */
427 /* boundary */
428 memset(buffer, 0, use);
429 seterrno(0);
430 if (infile) {
431#ifdef VMS
432 amt = fread(buffer, 1, use, infile);
433#else
434 amt = ffileread(infile, buffer, use);
435#endif
436 } else {
437 amt = use;
438 }
439 if (amt < use && amt != remain) {
440 /*
441 * Note that mkisofs is not star and no 100% archiver.
442 * We only detect file growth if the new size does not
443 * match 'use' at the last read.
444 */
445 if (geterrno() == 0) {
446 if (!errhidden(amt > remain ? E_GROW:E_SHRINK, filename)) {
447 if (!errwarnonly(amt < remain ? E_SHRINK:E_GROW, filename)) {
449 _("Try to use the option -data-change-warn\n"));
451 _("Files should not change while mkisofs is running.\n"));
452 }
454 _("File '%s' did %s.\n"),
455 filename,
456 amt < remain ?
457 _("shrink"):_("grow"));
458 (void) errabort(amt < remain ?
460 filename, TRUE);
461 }
462 } else if (!errhidden(E_READ, filename)) {
464 ;
465 errmsg(_("Cannot read from '%s'\n"), filename);
467 }
468 amt = remain; /* Fake success */
469 if (infile) {
470 fclose(infile); /* Prevent furthe failure */
471 infile = NULL;
472 }
473 }
474#if defined(APPLE_HYB) && defined(INSERTMACRESFORK) && defined(UDF)
475 if (unroundeduse == remain && isrfile && use_udf && correctedsize) {
476 /* adjust the last block to write according to correctedsize */
477 if (use - unroundeduse == correctedsize) {
478 bytestowrite = use;
479 correctedsize = 0;
480 } else if (use - unroundeduse > correctedsize) {
481 bytestowrite = use - correctedsize;
482 correctedsize = 0;
483 } else if (use - unroundeduse < correctedsize) {
484 bytestowrite = unroundeduse;
485 correctedsize -= use - unroundeduse;
486 }
487 } else {
488 bytestowrite = use;
489 }
490#else
491 bytestowrite = use;
492#endif
493
494 xfwrite(buffer, bytestowrite, 1, outfile,
495 XA_SUBH_DATA, remain <= (SECTOR_SIZE * NSECT));
497#if 0
498 if ((last_extent_written % 1000) < use / SECTOR_SIZE) {
500 }
501#else
502 if (verbose > 0 &&
503 (int)(last_extent_written % (gui ? 500 : 5000)) <
504 use / SECTOR_SIZE) {
505 time_t now;
506 time_t the_end;
507 double frac;
508
509 time(&now);
511 the_end = begun + (now - begun) / frac;
512#ifndef NO_FLOATINGPOINT
513 fprintf(stderr, _("%6.2f%% done, estimate finish %s"),
514 frac * 100., ctime(&the_end));
515#else
516 fprintf(stderr, _("%3d.%-02d%% done, estimate finish %s"),
517 (int)(frac * 100.),
518 (int)((frac+.00005) * 10000.)%100,
519 ctime(&the_end));
520#endif
521 fflush(stderr);
522 }
523#endif
524 remain -= use;
525 }
526#ifdef APPLE_HYB
527#if defined(INSERTMACRESFORK) && defined(UDF)
528 if (isrfile && use_udf && correctedsize) {
530 memset(buffer, 0, sizeof (buffer));
531 xfwrite(buffer, SECTOR_SIZE - correctedsize, 1, outfile, XA_SUBH_DATA, 1);
533 }
534 }
535#endif
536#endif
537 if (infile)
538 fclose(infile);
539} /* write_one_file(... */
540
541#ifdef UDF
542LOCAL void
543write_udf_symlink(filename, size, outfile)
544 char *filename;
545 off_t size;
546 FILE *outfile;
547{
548 static char buffer[SECTOR_SIZE * NSECT];
549 off_t remain = sizeof (buffer);
550 int use;
551
552 if (udf_get_symlinkcontents(filename, buffer, &remain) < 0) {
553 comerr(_("Cannot open smylink '%s'\n"), filename);
554 }
555 if (remain != size) {
556 comerrno(EX_BAD, _("Symlink '%s' did %s.\n"),
557 filename,
558 size > remain ?
559 _("shrink"):_("grow"));
560 }
561 use = (remain > SECTOR_SIZE * NSECT - 1 ?
562 NSECT * SECTOR_SIZE : remain);
563 use = ISO_ROUND_UP(use);
564 xfwrite(buffer, use, 1, outfile,
565 XA_SUBH_DATA, remain <= (SECTOR_SIZE * NSECT));
567
568} /* write_udf_symlink(... */
569#endif
570
571LOCAL void
573 FILE *outfile;
574{
575 struct deferred_write *dwpnt,
576 *dwnext;
577 unsigned rba = 0;
578
579 dwpnt = dw_head;
580 while (dwpnt) {
581/*#define DEBUG*/
582#ifdef DEBUG
584 _("The file name is %s and pad is %d, size is %lld and extent is %d\n"),
585 dwpnt->name, dwpnt->pad,
586 (Llong)dwpnt->size, dwpnt->extent);
587#endif
588 if (dwpnt->table) {
589 xfwrite(dwpnt->table, ISO_ROUND_UP(dwpnt->size), 1,
590 outfile,
593 table_size += dwpnt->size;
594/* fprintf(stderr, _("Size %lld "), (Llong)dwpnt->size); */
595 free(dwpnt->table);
596 dwpnt->table = NULL;
597 } else {
598
599#ifdef VMS
600 vms_write_one_file(dwpnt->name, dwpnt->size, outfile);
601#else
602#ifdef UDF
603 if ((dwpnt->dw_flags & IS_SYMLINK) && use_udf && create_udfsymlinks) {
604 write_udf_symlink(dwpnt->name, dwpnt->size, outfile);
605 } else {
606#endif /* UDF */
607#ifdef APPLE_HYB
608#if defined(INSERTMACRESFORK) && defined(UDF)
609 if (file_is_resource(dwpnt->name, dwpnt->hfstype) && (dwpnt->size > 0) && use_udf) {
610 rba = dwpnt->extent;
611 } else {
612 rba = 0;
613 }
614#endif /* INSERTMACRESFORK && UDF */
615 write_one_file(dwpnt->name, dwpnt->size, outfile, dwpnt->off,
616 file_is_resource(dwpnt->name, dwpnt->hfstype) && (dwpnt->size > 0), rba);
617#else
618#ifdef USE_LARGEFILES
619 write_one_file(dwpnt->name, dwpnt->size, outfile, dwpnt->off, 0, 0);
620#else
621 write_one_file(dwpnt->name, dwpnt->size, outfile);
622#endif
623#endif /* APPLE_HYB */
624#ifdef UDF
625 }
626#endif
627#endif /* VMS */
628 free(dwpnt->name);
629 dwpnt->name = NULL;
630 }
631
632
633#ifndef DVD_AUD_VID
634#define dvd_aud_vid_flag 0
635#endif
636
637#ifndef APPLE_HYB
638#define apple_hyb 0
639#endif
640
641#if defined(APPLE_HYB) || defined(DVD_AUD_VID)
642
643 if ((apple_hyb && !donotwrite_macpart) || (dvd_aud_vid_flag & DVD_SPEC_VIDEO)) {
644 /*
645 * we may have to pad out ISO files to work with HFS
646 * clump sizes
647 */
648 char blk[SECTOR_SIZE];
649 Uint i;
650
651 for (i = 0; i < dwpnt->pad; i++)
653
654 last_extent_written += dwpnt->pad;
655 }
656#endif /* APPLE_HYB || DVD_AUD_VID */
657
658
659 dwnext = dwpnt;
660 dwpnt = dwpnt->next;
661 free(dwnext);
662 dwnext = NULL;
663 }
664} /* write_files(... */
665
666#if 0
667LOCAL void
668dump_filelist()
669{
670 struct deferred_write *dwpnt;
671
672 dwpnt = dw_head;
673 while (dwpnt) {
674 fprintf(stderr, _("File %s\n"), dwpnt->name);
675 dwpnt = dwpnt->next;
676 }
677 fprintf(stderr, "\n");
678}
679
680#endif
681
682LOCAL int
684 const void *rr;
685 const void *ll;
686{
687 char *rpnt,
688 *lpnt;
689 struct directory_entry **r,
690 **l;
691
692 r = (struct directory_entry **)rr;
693 l = (struct directory_entry **)ll;
694 rpnt = (*r)->isorec.name;
695 lpnt = (*l)->isorec.name;
696
697#ifdef APPLE_HYB
698 /*
699 * resource fork MUST (not sure if this is true for HFS volumes) be
700 * before the data fork - so force it here
701 */
702 if ((*r)->assoc && (*r)->assoc == (*l))
703 return (1);
704 if ((*l)->assoc && (*l)->assoc == (*r))
705 return (-1);
706#endif /* APPLE_HYB */
707
708 /*
709 * If the names are the same, multiple extent sections of the same file
710 * are sorted by part number. If the part numbers do not differ, this
711 * is an error.
712 */
713 if (strcmp(rpnt, lpnt) == 0) {
714#ifdef USE_LARGEFILES
715 if ((*r)->mxpart < (*l)->mxpart)
716 return (-1);
717 else if ((*r)->mxpart > (*l)->mxpart)
718 return (1);
719#endif
721 _("Error: '%s' and '%s' have the same ISO9660 name '%s'.\n"),
722 (*r)->whole_name, (*l)->whole_name,
723 rpnt);
724 sort_goof++;
725 }
726 /* Check we don't have the same RR name */
727 if (use_RockRidge && !is_rr_dir) {
728 /*
729 * entries *can* have the same RR name in the "rr_moved"
730 * directory so skip checks if we're in reloc_dir
731 */
732 if (strcmp((*r)->name, (*l)->name) == 0) {
734 _("Error: '%s' and '%s' have the same Rock Ridge name '%s'.\n"),
735 (*r)->whole_name, (*l)->whole_name,
736 (*r)->name);
737 sort_goof++;
738 }
739 }
740 /*
741 * Put the '.' and '..' entries on the head of the sorted list. For
742 * normal ASCII, this always happens to be the case, but out of band
743 * characters cause this not to be the case sometimes.
744 * FIXME(eric) - these tests seem redundant, in that the name is never
745 * assigned these values. It will instead be \000 or \001, and thus
746 * should always be sorted correctly. I need to figure out why I
747 * thought I needed this in the first place.
748 */
749#if 0
750 if (strcmp(rpnt, ".") == 0)
751 return (-1);
752 if (strcmp(lpnt, ".") == 0)
753 return (1);
754
755 if (strcmp(rpnt, "..") == 0)
756 return (-1);
757 if (strcmp(lpnt, "..") == 0)
758 return (1);
759#else
760 /*
761 * The code above is wrong (as explained in Eric's comment), leading to
762 * incorrect sort order iff the -L option ("allow leading dots") is in
763 * effect and a directory contains entries that start with a dot.
764 * (TF, Tue Dec 29 13:49:24 CET 1998)
765 */
766 if ((*r)->isorec.name_len[0] == 1 && *rpnt == 0)
767 return (-1); /* '.' */
768 if ((*l)->isorec.name_len[0] == 1 && *lpnt == 0)
769 return (1);
770
771 if ((*r)->isorec.name_len[0] == 1 && *rpnt == 1)
772 return (-1); /* '..' */
773 if ((*l)->isorec.name_len[0] == 1 && *lpnt == 1)
774 return (1);
775#endif
776
777 while (*rpnt && *lpnt) {
778 if (*rpnt == ';' && *lpnt != ';')
779 return (-1);
780 if (*rpnt != ';' && *lpnt == ';')
781 return (1);
782
783 if (*rpnt == ';' && *lpnt == ';')
784 return (0);
785
786 if (*rpnt == '.' && *lpnt != '.')
787 return (-1);
788 if (*rpnt != '.' && *lpnt == '.')
789 return (1);
790
791 if ((unsigned char) *rpnt < (unsigned char) *lpnt)
792 return (-1);
793 if ((unsigned char) *rpnt > (unsigned char) *lpnt)
794 return (1);
795 rpnt++;
796 lpnt++;
797 }
798 if (*rpnt)
799 return (1);
800 if (*lpnt)
801 return (-1);
802 return (0);
803}
804
805/*
806 * Function: sort_directory
807 *
808 * Purpose: Sort the directory in the appropriate ISO9660
809 * order.
810 *
811 * Notes: Returns 0 if OK, returns > 0 if an error occurred.
812 */
813EXPORT int
814sort_directory(sort_dir, rr)
815 struct directory_entry **sort_dir;
816 int rr;
817{
818 int dcount = 0;
819 int xcount = 0;
820 int j;
821 int i,
822 len;
823 struct directory_entry *s_entry;
824 struct directory_entry **sortlist;
825
826 /* need to keep a count of how many entries are hidden */
827 s_entry = *sort_dir;
828 while (s_entry) {
829 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
830 xcount++;
831 dcount++;
832 s_entry = s_entry->next;
833 }
834
835 if (dcount == 0) {
836 return (0);
837 }
838 /* OK, now we know how many there are. Build a vector for sorting. */
839 sortlist = (struct directory_entry **)
840 e_malloc(sizeof (struct directory_entry *) * dcount);
841
842 j = dcount - xcount;
843 dcount = 0;
844 s_entry = *sort_dir;
845 while (s_entry) {
846 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
847 /* put any hidden entries at the end of the vector */
848 sortlist[j++] = s_entry;
849 } else {
850 sortlist[dcount] = s_entry;
851 dcount++;
852 }
853 len = s_entry->isorec.name_len[0];
854 s_entry->isorec.name[len] = 0;
855 s_entry = s_entry->next;
856 }
857
858 /* Each directory is required to contain at least . and .. */
859 if (dcount < 2) {
861 _("Directory size too small (. or .. may be missing)\n"));
862 sort_goof = 1;
863
864 } else {
865 /* only sort the non-hidden entries */
866 sort_goof = 0;
867 is_rr_dir = rr;
868#ifdef PROTOTYPES
869 qsort(sortlist, dcount, sizeof (struct directory_entry *),
870 (int (*) (const void *, const void *)) compare_dirs);
871#else
872 qsort(sortlist, dcount, sizeof (struct directory_entry *),
874#endif
875
876 /*
877 * Now reassemble the linked list in the proper sorted order
878 * We still need the hidden entries, as they may be used in
879 * the Joliet tree.
880 */
881 for (i = 0; i < dcount + xcount - 1; i++) {
882 sortlist[i]->next = sortlist[i + 1];
883 }
884
885 sortlist[dcount + xcount - 1]->next = NULL;
886 *sort_dir = sortlist[0];
887 }
888
889 free(sortlist);
890 sortlist = NULL;
891 return (sort_goof);
892}
893
894LOCAL int
896{
898
899 root_record.length[0] = 1 +
901 root_record.ext_attr_length[0] = 0;
902 set_733((char *)root_record.extent, root->extent);
903 set_733((char *)root_record.size, ISO_ROUND_UP(root->size));
904 iso9660_date(root_record.date, root_statbuf.st_mtime);
905 root_record.flags[0] = ISO_DIRECTORY;
906 root_record.file_unit_size[0] = 0;
907 root_record.interleave[0] = 0;
908 set_723(root_record.volume_sequence_number, volume_sequence_number);
909 root_record.name_len[0] = 1;
910 return (0);
911}
912
913#ifdef SORTING
914/*
915 * sorts deferred_write entries based on the sort weight
916 */
917LOCAL int
918compare_sort(rr, ll)
919 const void *rr;
920 const void *ll;
921{
922 struct deferred_write **r;
923 struct deferred_write **l;
924 int r_sort;
925 int l_sort;
926
927 r = (struct deferred_write **)rr;
928 l = (struct deferred_write **)ll;
929 r_sort = (*r)->s_entry->sort;
930 l_sort = (*l)->s_entry->sort;
931
932 if (r_sort != l_sort)
933 return (r_sort < l_sort ? 1 : -1);
934 else
935 return ((*r)->extent - (*l)->extent);
936}
937
938/*
939 * reassign start extents to files that are "hard links" to
940 * files that may have been sorted
941 */
942LOCAL void
943reassign_link_addresses(dpnt)
944 struct directory *dpnt;
945{
946 struct directory_entry *s_entry;
947 struct file_hash *s_hash;
948
949 while (dpnt) {
950 s_entry = dpnt->contents;
951 for (s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) {
952 /* link files have already been given the weight NOT_SORTED */
953 if (s_entry->sort != NOT_SORTED)
954 continue;
955
956 /* update the start extent */
957 s_hash = find_hash(s_entry);
958 if (s_hash) {
959 set_733((char *)s_entry->isorec.extent, s_hash->starting_block);
960 s_entry->starting_block = s_hash->starting_block;
961 }
962 }
963 if (dpnt->subdir) {
964 reassign_link_addresses(dpnt->subdir);
965 }
966
967 dpnt = dpnt->next;
968 }
969}
970
971/*
972 * sort files in order of the given sort weight
973 */
974LOCAL int
975sort_file_addresses()
976{
977 struct deferred_write *dwpnt;
978 struct deferred_write **sortlist;
979 struct directory_entry *s_entry;
980 UInt32_t start_extent;
981 int num = 0;
982 int i;
983
984 /* need to store start extents for linked files */
985 flush_hash();
986
987 /* find out how many files we have */
988 dwpnt = dw_head;
989 while (dwpnt) {
990 num++;
991 dwpnt = dwpnt->next;
992 }
993
994 /* return if we have none */
995 if (num == 0) {
996 return (1);
997 }
998
999 /* save the start extent of the first file */
1000 start_extent = dw_head->extent;
1001
1002 /* set up vector to store entries */
1003 sortlist = (struct deferred_write **)
1004 e_malloc(sizeof (struct deferred_write *) * num);
1005
1006 for (i = 0, dwpnt = dw_head; i < num; i++, dwpnt = dwpnt->next)
1007 sortlist[i] = dwpnt;
1008
1009 /* sort the list */
1010#ifdef PROTOTYPES
1011 qsort(sortlist, num, sizeof (struct deferred_write *),
1012 (int (*)(const void *, const void *))compare_sort);
1013#else
1014 qsort(sortlist, num, sizeof (struct deferred_write *), compare_sort);
1015#endif
1016
1017 /* reconstruct the linked list */
1018 for (i = 0; i < num-1; i++) {
1019 sortlist[i]->next = sortlist[i+1];
1020 }
1021
1022 sortlist[num-1]->next = NULL;
1023 dw_head = sortlist[0];
1024
1025 free(sortlist);
1026
1027 /* set the new start extents for the sorted list */
1028 for (i = 0, dwpnt = dw_head; i < num; i++, dwpnt = dwpnt->next) {
1029 s_entry = dwpnt->s_entry;
1030 dwpnt->extent = s_entry->starting_block = start_extent;
1031
1032 if (s_entry->de_flags & MULTI_EXTENT) {
1033 struct directory_entry *s_e;
1034 UInt32_t ext = start_extent;
1035
1036 /*
1037 * For unknown reason, we sometimes get mxroot as
1038 * part of the chain and sometime it's missing.
1039 * Be careful to distinct between the mxroot entry and
1040 * others to select both corectly in a conservative way.
1041 */
1042 s_entry->mxroot->starting_block = start_extent;
1043 set_733((char *)s_entry->mxroot->isorec.extent,
1044 start_extent);
1045 start_extent += ISO_BLOCKS(s_entry->mxroot->size);
1046
1047 for (s_e = s_entry;
1048 s_e && s_e->mxroot == s_entry->mxroot;
1049 s_e = s_e->next) {
1050 if (s_e == s_entry->mxroot)
1051 continue;
1052
1053 set_733((char *)s_e->isorec.extent, ext);
1054 s_entry->starting_block = ext;
1055 ext += ISO_BLOCKS(s_e->size);
1056 }
1057 } else {
1058 set_733((char *)s_entry->isorec.extent, start_extent);
1059 start_extent += ISO_BLOCKS(s_entry->size);
1060 }
1061#ifdef DVD_AUD_VID
1062 /*
1063 * Shouldn't this be done for every type of sort? Otherwise
1064 * we will loose every pad info we add if we sort the files
1065 */
1066 if (dvd_aud_vid_flag & DVD_SPEC_VIDEO) {
1067 start_extent += dwpnt->pad;
1068 }
1069#endif /* DVD_AUD_VID */
1070
1071 /* cache start extents for any linked files */
1072 add_hash(s_entry);
1073 }
1074
1075 return (0);
1076}
1077#endif /* SORTING */
1078
1079
1080
1081LOCAL BOOL
1083 struct directory *dpnt;
1084 BOOL isnest;
1085{
1086 struct directory *finddir;
1087 struct directory_entry *s_entry;
1088 struct file_hash *s_hash;
1089 struct deferred_write *dwpnt;
1090 char whole_path[PATH_MAX];
1091#ifdef DVD_AUD_VID
1092 char dvd_path[PATH_MAX];
1093 title_set_info_t *title_set_info = NULL;
1094 char *p;
1095#endif
1096 BOOL ret = FALSE;
1097
1098 while (dpnt) {
1099#ifdef DVD_AUD_VID
1100 if ((dvd_aud_vid_flag & DVD_SPEC_VIDEO) && root == dpnt->parent &&
1101 ((p = strstr(dpnt->whole_name, "VIDEO_TS")) != 0)&&
1102 strcmp(p, "VIDEO_TS") == 0) {
1103 int maxlen = strlen(dpnt->whole_name)-8+1;
1104
1105 if (maxlen > sizeof (dvd_path))
1106 maxlen = sizeof (dvd_path);
1107 strlcpy(dvd_path, dpnt->whole_name, maxlen);
1108#ifdef DEBUG
1109 fprintf(stderr, _("Found 'VIDEO_TS', the path is %s \n"), dvd_path);
1110#endif
1111 title_set_info = DVDGetFileSet(dvd_path);
1112 if (title_set_info == 0) {
1113 /*
1114 * Do not switch off -dvd-video but let is fail later.
1115 */
1116/* dvd_aud_vid_flag &= ~DVD_SPEC_VIDEO;*/
1117 errmsgno(EX_BAD, _("Unable to parse DVD-Video structures.\n"));
1118 } else {
1119 ret = TRUE;
1120 }
1121 }
1122#endif /* DVD_AUD_VID */
1123
1124 for (s_entry = dpnt->contents; s_entry;
1125 s_entry = s_entry->next) {
1126 /*
1127 * If we already have an extent for this entry, then
1128 * don't assign a new one. It must have come from a
1129 * previous session on the disc. Note that we don't
1130 * end up scheduling the thing for writing either.
1131 */
1132 if (get_733(s_entry->isorec.extent) != 0) {
1133 continue;
1134 }
1135 /*
1136 * This saves some space if there are symlinks present.
1137 * If this is a multi-extent file, we get mxpart == 1
1138 * from find_hash().
1139 */
1140 s_hash = find_hash(s_entry);
1141 if (s_hash) {
1142 if (verbose > 2) {
1143 fprintf(stderr, _("Cache hit for '%s%s%s'\n"),
1144 s_entry->filedir->de_name,
1146 s_entry->name);
1147 }
1148 s_entry->starting_block = s_hash->starting_block;
1149 set_733((char *)s_entry->isorec.extent,
1150 s_hash->starting_block);
1151 set_733((char *)s_entry->isorec.size,
1152 s_hash->size);
1153#ifdef USE_LARGEFILES
1154 if (s_entry->de_flags & MULTI_EXTENT) {
1155 struct directory_entry *s_e;
1156 unsigned int ext = s_hash->starting_block;
1157
1158 /*
1159 * Skip the multi extent root entry.
1160 */
1161 if (s_entry->mxpart == 0)
1162 continue;
1163 /*
1164 * The directory is sorted, so we should
1165 * see s_entry->mxpart == 1 first.
1166 */
1167 if (s_entry->mxpart != 1) {
1169 _("Panic: Multi extent parts for %s not sorted.\n"),
1170 s_entry->whole_name);
1171 }
1172 s_entry->mxroot->starting_block = ext;
1173 for (s_e = s_entry;
1174 s_e && s_e->mxroot == s_entry->mxroot;
1175 s_e = s_e->next) {
1176 set_733((char *)s_e->isorec.extent,
1177 ext);
1178 ext += ISO_BLOCKS(s_e->size);
1179 }
1180 }
1181#endif
1182
1183#ifdef SORTING
1184 /* check for non-directory files */
1185 if (do_sort && ((s_entry->isorec.flags[0] & ISO_DIRECTORY) == 0)) {
1186 /* make sure the real file has the highest weighting */
1187 s_hash->de->sort = MAX(s_entry->sort, s_hash->de->sort);
1188 /* flag this as a potential non-sorted file */
1189 s_entry->sort = NOT_SORTED;
1190 }
1191#endif /* SORTING */
1192 continue;
1193 }
1194 /*
1195 * If this is for a directory that is not a . or
1196 * a .. entry, then look up the information for the
1197 * entry. We have already assigned extents for
1198 * directories, so we just need to fill in the blanks
1199 * here.
1200 */
1201 if (strcmp(s_entry->name, ".") != 0 &&
1202 strcmp(s_entry->name, "..") != 0 &&
1203 s_entry->isorec.flags[0] & ISO_DIRECTORY) {
1204 finddir = dpnt->subdir;
1205 while (finddir && finddir->self != s_entry) {
1206 finddir = finddir->next;
1207 }
1208 if (!finddir) {
1209#ifdef DVD_AUD_VID
1210 if (title_set_info != 0) {
1211 DVDFreeFileSet(title_set_info);
1212 }
1213#endif
1215 _("Fatal goof - could not find dir entry for '%s'\n"),
1216 s_entry->name);
1217 }
1218 set_733((char *)s_entry->isorec.extent,
1219 finddir->extent);
1220 s_entry->starting_block = finddir->extent;
1221 s_entry->size = ISO_ROUND_UP(finddir->size);
1222 total_dir_size += s_entry->size;
1223 add_hash(s_entry);
1224 set_733((char *)s_entry->isorec.size,
1225 ISO_ROUND_UP(finddir->size));
1226 continue;
1227 }
1228 /*
1229 * If this is . or .., then look up the relevant info
1230 * from the tables.
1231 */
1232 if (strcmp(s_entry->name, ".") == 0) {
1233 set_733((char *)s_entry->isorec.extent,
1234 dpnt->extent);
1235
1236 /*
1237 * Set these so that the hash table has the
1238 * correct information
1239 */
1240 s_entry->starting_block = dpnt->extent;
1241 s_entry->size = ISO_ROUND_UP(dpnt->size);
1242
1243 add_hash(s_entry);
1244 s_entry->starting_block = dpnt->extent;
1245 set_733((char *)s_entry->isorec.size,
1246 ISO_ROUND_UP(dpnt->size));
1247 continue;
1248 }
1249 if (strcmp(s_entry->name, "..") == 0) {
1250 if (dpnt == root) {
1251 total_dir_size += root->size;
1252 }
1253 set_733((char *)s_entry->isorec.extent,
1254 dpnt->parent->extent);
1255
1256 /*
1257 * Set these so that the hash table has the
1258 * correct information
1259 */
1260 s_entry->starting_block = dpnt->parent->extent;
1261 s_entry->size =
1262 ISO_ROUND_UP(dpnt->parent->size);
1263
1264 add_hash(s_entry);
1265 s_entry->starting_block = dpnt->parent->extent;
1266 set_733((char *)s_entry->isorec.size,
1267 ISO_ROUND_UP(dpnt->parent->size));
1268 continue;
1269 }
1270 /*
1271 * Some ordinary non-directory file. Just schedule
1272 * the file to be written. This is all quite
1273 * straightforward, just make a list and assign
1274 * extents as we go. Once we get through writing all
1275 * of the directories, we should be ready write out
1276 * these files
1277 */
1278 if (s_entry->size) {
1279 dwpnt = (struct deferred_write *)
1280 e_malloc(sizeof (struct deferred_write));
1281 /* save this directory entry for later use */
1282 dwpnt->s_entry = s_entry;
1283 /* set the initial padding to zero */
1284 dwpnt->pad = 0;
1285 dwpnt->dw_flags = 0;
1286#ifdef DVD_AUD_VID
1287 if ((dvd_aud_vid_flag & DVD_SPEC_VIDEO) && (title_set_info != 0)) {
1288 int pad;
1289
1290 pad = DVDGetFilePad(title_set_info, s_entry->name);
1291 if (pad < 0) {
1293 _("Implementation botch. Video pad for file %s is %d\n"),
1294 s_entry->name, pad),
1296 _("Either the *.IFO file is bad or you found a mkisofs bug.\n"));
1297 }
1298 dwpnt->pad = pad;
1299 if (verbose > 0 && pad != 0) {
1301 _("The pad was %d for file %s\n"),
1302 dwpnt->pad, s_entry->name);
1303 }
1304 }
1305#endif /* DVD_AUD_VID */
1306#ifdef APPLE_HYB
1307 /*
1308 * maybe an offset to start of the real
1309 * file/fork
1310 */
1311 dwpnt->off = s_entry->hfs_off;
1312 dwpnt->hfstype = s_entry->hfs_type;
1313#else
1314 dwpnt->off = (off_t)0;
1315#endif /* APPLE_HYB */
1316 if (s_entry->inode == TABLE_INODE) {
1317 dwpnt->table = s_entry->table;
1318 dwpnt->name = NULL;
1319 sprintf(whole_path, "%s%s%s",
1320 s_entry->filedir->whole_name,
1322 } else {
1323 dwpnt->table = NULL;
1324 strlcpy(whole_path,
1325 s_entry->whole_name,
1326 sizeof (whole_path));
1327 dwpnt->name = e_strdup(whole_path);
1328 }
1329 dwpnt->next = NULL;
1330 dwpnt->size = s_entry->size;
1331 dwpnt->extent = last_extent;
1332 set_733((char *)s_entry->isorec.extent,
1333 last_extent);
1334 s_entry->starting_block = last_extent;
1335#ifdef USE_LARGEFILES
1336 /*
1337 * Update the entries for multi-section files
1338 * as we now know the starting extent numbers.
1339 */
1340 if (s_entry->de_flags & MULTI_EXTENT) {
1341 struct directory_entry *s_e;
1342 unsigned int ext = last_extent;
1343
1344 /*
1345 * Skip the multi extent root entry.
1346 */
1347 if (s_entry->mxpart == 0) {
1348 if (dwpnt->name)
1349 free(dwpnt->name);
1350 free(dwpnt);
1351 continue;
1352 }
1353 /*
1354 * The directory is sorted, so we should
1355 * see s_entry->mxpart == 1 first.
1356 */
1357 if (s_entry->mxpart != 1) {
1359 _("Panic: Multi extent parts for %s not sorted.\n"),
1360 s_entry->whole_name);
1361 }
1362 dwpnt->size = s_entry->mxroot->size;
1363 s_entry->mxroot->starting_block = ext;
1364 /*
1365 * Set the mxroot (mxpart == 0) to allow
1366 * the UDF code to fetch the starting
1367 * extent number.
1368 */
1369 set_733((char *)s_entry->mxroot->isorec.extent, ext);
1370 for (s_e = s_entry;
1371 s_e && s_e->mxroot == s_entry->mxroot;
1372 s_e = s_e->next) {
1373 if (s_e->mxpart == 0)
1374 continue;
1375 set_733((char *)s_e->isorec.extent,
1376 ext);
1377 ext += ISO_BLOCKS(s_e->size);
1378 }
1379 add_hash(s_entry);
1380 }
1381#endif
1382 if (dw_tail) {
1383 dw_tail->next = dwpnt;
1384 dw_tail = dwpnt;
1385 } else {
1386 dw_head = dwpnt;
1387 dw_tail = dwpnt;
1388 }
1389 add_hash(s_entry);
1390 /*
1391 * The cache holds the full size of the file
1392 */
1393 last_extent += ISO_BLOCKS(dwpnt->size);
1394 dwpnt->dw_flags = s_entry->de_flags;
1395#ifdef APPLE_HYB
1396#if defined(INSERTMACRESFORK) && defined(UDF)
1397 if (file_is_resource(dwpnt->name, dwpnt->s_entry->hfs_type) && (dwpnt->size > 0) && use_udf) {
1398 last_extent++;
1399 if (ISO_ROUND_UP(dwpnt->size) <
1401 last_extent++;
1402 }
1403 }
1404#endif
1405#endif /* APPLE_HYB */
1406#ifdef DVD_AUD_VID
1407 /* Shouldn't we always add the pad info? */
1408 if (dvd_aud_vid_flag & DVD_SPEC_VIDEO) {
1409 last_extent += dwpnt->pad;
1410 }
1411#endif /* DVD_AUD_VID */
1412 if (verbose > 2) {
1413 fprintf(stderr, "%u %d %s\n",
1414 s_entry->starting_block,
1415 last_extent - 1, whole_path);
1416 }
1417#ifdef DBG_ISO
1418 if (ISO_BLOCKS(s_entry->size) > 500) {
1420 _("Warning: large file '%s'\n"),
1421 whole_path);
1423 _("Starting block is %d\n"),
1424 s_entry->starting_block);
1426 _("Reported file size is %lld\n"),
1427 (Llong)s_entry->size);
1428
1429 }
1430#endif
1431#ifdef NOT_NEEDED /* Never use this code if you like to create a DVD */
1432
1433 if (last_extent > (800000000 >> 11)) {
1434 /* More than 800Mb? Punt */
1436 _("Extent overflow processing file '%s'\n"),
1437 whole_path);
1439 _("Starting block is %d\n"),
1440 s_entry->starting_block);
1442 _("Reported file size is %lld\n"),
1443 (Llong)s_entry->size);
1444 exit(1);
1445 }
1446#endif
1447 continue;
1448 }
1449 /*
1450 * This is for zero-length files. If we leave the
1451 * extent 0, then we get screwed, because many readers
1452 * simply drop files that have an extent of zero.
1453 * Thus we leave the size 0, and just assign the
1454 * extent number.
1455 */
1456 set_733((char *)s_entry->isorec.extent, last_extent);
1457 }
1458 if (dpnt->subdir) {
1459 if (assign_file_addresses(dpnt->subdir, TRUE))
1460 ret = TRUE;
1461 }
1462 dpnt = dpnt->next;
1463 }
1464#ifdef DVD_AUD_VID
1465 if (title_set_info != NULL) {
1466 DVDFreeFileSet(title_set_info);
1467 }
1468 if ((dvd_aud_vid_flag & DVD_SPEC_VIDEO)&& !ret && !isnest) {
1470 _("Could not find correct 'VIDEO_TS' directory.\n"));
1471 }
1472#endif /* DVD_AUD_VID */
1473 return (ret);
1474} /* assign_file_addresses(... */
1475
1476LOCAL void
1478 struct directory *dpnt;
1479{
1480 struct directory_entry *s_entry;
1481 struct directory_entry *s_entry_d;
1482
1483 s_entry = dpnt->contents;
1484 while (s_entry) {
1485 s_entry_d = s_entry;
1486 s_entry = s_entry->next;
1487
1488 if (s_entry_d->rr_attributes) {
1489 free(s_entry_d->rr_attributes);
1490 s_entry_d->rr_attributes = NULL;
1491 }
1492 if (s_entry_d->name != NULL) {
1493 free(s_entry_d->name);
1494 s_entry_d->name = NULL;
1495 }
1496 if (s_entry_d->whole_name != NULL) {
1497 free(s_entry_d->whole_name);
1498 s_entry_d->whole_name = NULL;
1499 }
1500#ifdef APPLE_HYB
1501 if (apple_both && s_entry_d->hfs_ent && !s_entry_d->assoc &&
1502 (s_entry_d->isorec.flags[0] & ISO_MULTIEXTENT) == 0) {
1503 free(s_entry_d->hfs_ent);
1504 }
1505#endif /* APPLE_HYB */
1506
1507#ifdef DUPLICATES_ONCE
1508 if (s_entry_d->digest_fast) {
1509
1510 if (s_entry_d->digest_full &&
1511 (s_entry_d->digest_full != s_entry_d->digest_fast))
1512 free(s_entry_d->digest_full);
1513
1514 free(s_entry_d->digest_fast);
1515
1516 s_entry_d->digest_fast = NULL;
1517 s_entry_d->digest_full = NULL;
1518 }
1519#endif
1520 free(s_entry_d);
1521 s_entry_d = NULL;
1522 }
1523 dpnt->contents = NULL;
1524} /* free_one_directory(... */
1525
1526LOCAL void
1528 struct directory *dpnt;
1529{
1530 while (dpnt) {
1531 free_one_directory(dpnt);
1532 if (dpnt->subdir)
1533 free_directories(dpnt->subdir);
1534 dpnt = dpnt->next;
1535 }
1536}
1537
1538EXPORT void
1540 struct directory *dpnt;
1541 FILE *outfile;
1542{
1543 unsigned int ce_address = 0;
1544 char *ce_buffer;
1545 unsigned int ce_index = 0;
1546 unsigned int ce_size;
1547 unsigned int dir_index;
1548 char *directory_buffer;
1549 int new_reclen;
1550 struct directory_entry *s_entry;
1551 struct directory_entry *s_entry_d;
1552 unsigned int total_size;
1553
1554 total_size = ISO_ROUND_UP(dpnt->size);
1555 directory_buffer = (char *)e_malloc(total_size);
1556 memset(directory_buffer, 0, total_size);
1557 dir_index = 0;
1558
1559 ce_size = ISO_ROUND_UP(dpnt->ce_bytes);
1560 ce_buffer = NULL;
1561
1562 if (ce_size > 0) {
1563 ce_buffer = (char *)e_malloc(ce_size);
1564 memset(ce_buffer, 0, ce_size);
1565
1566 ce_index = 0;
1567
1568 /* Absolute sector address of CE entries for this directory */
1569 ce_address = last_extent_written + (total_size >> 11);
1570 }
1571 s_entry = dpnt->contents;
1572 while (s_entry) {
1573 /* skip if it's hidden */
1574 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
1575 s_entry = s_entry->next;
1576 continue;
1577 }
1578 /*
1579 * We do not allow directory entries to cross sector
1580 * boundaries. Simply pad, and then start the next entry at
1581 * the next sector
1582 */
1583 new_reclen = s_entry->isorec.length[0];
1584 if ((dir_index & (SECTOR_SIZE - 1)) + new_reclen >=
1585 SECTOR_SIZE) {
1586 dir_index = ISO_ROUND_UP(dir_index);
1587 }
1588 memcpy(directory_buffer + dir_index, &s_entry->isorec,
1589 offsetof(struct iso_directory_record, name[0]) +
1590 s_entry->isorec.name_len[0]);
1591 dir_index += offsetof(struct iso_directory_record, name[0]) +
1592 s_entry->isorec.name_len[0];
1593
1594 /* Add the Rock Ridge attributes, if present */
1595 if (s_entry->rr_attr_size) {
1596 if (dir_index & 1) {
1597 directory_buffer[dir_index++] = 0;
1598 }
1599 /*
1600 * If the RR attributes were too long, then write the
1601 * CE records, as required.
1602 */
1603 if (s_entry->rr_attr_size != s_entry->total_rr_attr_size) {
1604 struct iso_xa_dir_record *xadp;
1605 unsigned char *pnt;
1606 int len,
1607 nbytes;
1608
1609 /*
1610 * Go through the entire record, first skip
1611 * the XA record and then fix up the
1612 * CE entries so that the extent and offset
1613 * are correct
1614 */
1615 pnt = s_entry->rr_attributes;
1616 len = s_entry->total_rr_attr_size;
1617
1618 if (len >= 14) {
1619 xadp = (struct iso_xa_dir_record *)pnt;
1620
1621 if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' &&
1622 xadp->reserved[0] == '\0') {
1623 len -= 14;
1624 pnt += 14;
1625 }
1626 }
1627
1628 while (len > 3) {
1629#ifdef DEBUG
1630 if (ce_size <= 0) {
1632 _("Warning: ce_index(%d) && ce_address(%d) not initialized\n"),
1633 ce_index, ce_address);
1634 }
1635#endif
1636
1637 if (pnt[0] == 'C' && pnt[1] == 'E') {
1638 nbytes = get_733((char *)pnt + 20);
1639
1640 if ((ce_index & (SECTOR_SIZE - 1)) + nbytes >=
1641 SECTOR_SIZE) {
1642 ce_index = ISO_ROUND_UP(ce_index);
1643 }
1644 set_733((char *)pnt + 4,
1645 ce_address + (ce_index >> 11));
1646 set_733((char *)pnt + 12,
1647 ce_index & (SECTOR_SIZE - 1));
1648
1649
1650
1651 /*
1652 * Now store the block in the
1653 * ce buffer
1654 */
1655 memcpy(ce_buffer + ce_index,
1656 pnt + pnt[2], nbytes);
1657 ce_index += nbytes;
1658 if (ce_index & 1) {
1659 ce_index++;
1660 }
1661 }
1662 len -= pnt[2];
1663 pnt += pnt[2];
1664 }
1665
1666 }
1668 memcpy(directory_buffer + dir_index,
1669 s_entry->rr_attributes,
1670 s_entry->rr_attr_size);
1671 dir_index += s_entry->rr_attr_size;
1672 }
1673 if (dir_index & 1) {
1674 directory_buffer[dir_index++] = 0;
1675 }
1676 s_entry_d = s_entry;
1677 s_entry = s_entry->next;
1678
1679 /*
1680 * Joliet doesn't use the Rock Ridge attributes, so we free
1681 * it here.
1682 */
1683 if (s_entry_d->rr_attributes) {
1684 free(s_entry_d->rr_attributes);
1685 s_entry_d->rr_attributes = NULL;
1686 }
1687 }
1688
1689 if (dpnt->size != dir_index) {
1691 _("Unexpected directory length %lld expected: %d '%s'\n"),
1692 (Llong)dpnt->size,
1693 dir_index, dpnt->de_name);
1694 }
1695 xfwrite(directory_buffer, total_size, 1, outfile, 0, FALSE);
1696 last_extent_written += total_size >> 11;
1697 free(directory_buffer);
1698 directory_buffer = NULL;
1699
1700 if (ce_size > 0) {
1701 if (ce_index != dpnt->ce_bytes) {
1703 _("Continuation entry record length mismatch %d expected: %d.\n"),
1704 ce_index, dpnt->ce_bytes);
1705 }
1706 xfwrite(ce_buffer, ce_size, 1, outfile, 0, FALSE);
1707 last_extent_written += ce_size >> 11;
1708 free(ce_buffer);
1709 ce_buffer = NULL;
1710 }
1711} /* generate_one_directory(... */
1712
1713LOCAL void
1715 struct directory *node;
1716{
1717 struct directory *dpnt;
1718
1719 dpnt = node;
1720
1721 while (dpnt) {
1722 /* skip if it's hidden */
1723 if ((dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0)
1724 pathlist[dpnt->path_index] = dpnt;
1725
1726 if (dpnt->subdir)
1727 build_pathlist(dpnt->subdir);
1728 dpnt = dpnt->next;
1729 }
1730} /* build_pathlist(... */
1731
1732LOCAL int
1734 void const *r;
1735 void const *l;
1736{
1737 struct directory const *ll = *(struct directory * const *) l;
1738 struct directory const *rr = *(struct directory * const *) r;
1739
1740 if (rr->parent->path_index < ll->parent->path_index) {
1741 return (-1);
1742 }
1743 if (rr->parent->path_index > ll->parent->path_index) {
1744 return (1);
1745 }
1746 return (strcmp(rr->self->isorec.name, ll->self->isorec.name));
1747
1748} /* compare_paths(... */
1749
1750LOCAL int
1752{
1753 struct directory_entry *de = NULL;
1754 struct directory *dpnt;
1755 int fix;
1756 int i;
1757 int j;
1758 int namelen;
1759 char *npnt;
1760 char *npnt1;
1761 int tablesize;
1762
1763 /* First allocate memory for the tables and initialize the memory */
1764 tablesize = path_blocks << 11;
1765 path_table_m = (char *)e_malloc(tablesize);
1766 path_table_l = (char *)e_malloc(tablesize);
1767 memset(path_table_l, 0, tablesize);
1768 memset(path_table_m, 0, tablesize);
1769
1770 /*
1771 * Now start filling in the path tables. Start with root directory
1772 */
1773
1774 path_table_index = 0;
1775 pathlist = (struct directory **)e_malloc(sizeof (struct directory *)
1777 memset(pathlist, 0, sizeof (struct directory *) * next_path_index);
1779
1780 do {
1781 fix = 0;
1782#ifdef PROTOTYPES
1784 sizeof (struct directory *),
1785 (int (*) (const void *, const void *)) compare_paths);
1786#else
1788 sizeof (struct directory *),
1790#endif
1791
1792 for (j = 1; j < next_path_index; j++) {
1793 if (pathlist[j]->path_index != j) {
1794 pathlist[j]->path_index = j;
1795 fix++;
1796 }
1797 }
1798 } while (fix);
1799
1800 for (j = 1; j < next_path_index; j++) {
1801 dpnt = pathlist[j];
1802 if (!dpnt) {
1803 comerrno(EX_BAD, _("Entry %d not in path tables\n"), j);
1804 }
1805 npnt = dpnt->de_name;
1806
1807 /* So the root comes out OK */
1808 if ((*npnt == 0) || (dpnt == root)) {
1809 npnt = ".";
1810 }
1811 npnt1 = strrchr(npnt, PATH_SEPARATOR);
1812 if (npnt1) {
1813 npnt = npnt1 + 1;
1814 }
1815 de = dpnt->self;
1816 if (!de) {
1818 _("Fatal ISO9660 goof - directory has amnesia\n"));
1819 }
1820 namelen = de->isorec.name_len[0];
1821
1824 path_table_index += 2;
1825
1828 path_table_index += 4;
1829
1831 dpnt->parent->path_index);
1833 dpnt->parent->path_index);
1834
1835 if (dpnt->parent->path_index > 0xffff) {
1836 static int warned = 0;
1837
1838 if (!warned) {
1839 warned++;
1841 _("Unable to generate sane path tables - too many directories (%u)\n"),
1842 dpnt->parent->path_index);
1843 if (!nolimitpathtables)
1845 _("Try to use the option -no-limit-pathtables\n"));
1846 }
1847 if (!nolimitpathtables)
1848 exit(EX_BAD);
1849 /*
1850 * Let it point to the root directory instead.
1851 */
1854 }
1855
1856 path_table_index += 2;
1857
1858 for (i = 0; i < namelen; i++) {
1862 }
1863 if (path_table_index & 1) {
1864 path_table_index++; /* For odd lengths we pad */
1865 }
1866 }
1867
1868 free(pathlist);
1869 pathlist = NULL;
1872 _("Path table lengths do not match %d expected: %d\n"),
1875 }
1876 return (0);
1877} /* generate_path_tables(... */
1878
1879EXPORT void
1881 char *to;
1882 char *from;
1883 int max;
1884{
1885 int n = strlen(from);
1886
1887 if (n > max) {
1888 n = max;
1889 }
1890 memcpy(to, from, n);
1891
1892} /* memcpy_max(... */
1893
1894EXPORT void
1896 struct output_fragment *frag;
1897{
1898 struct output_fragment *nfrag;
1899
1900 nfrag = e_malloc(sizeof (*frag));
1901 movebytes(frag, nfrag, sizeof (*frag));
1902 nfrag->of_start_extent = 0;
1903
1904 if (out_tail == NULL) {
1905 out_list = out_tail = nfrag;
1906 } else {
1907 out_tail->of_next = nfrag;
1908 out_tail = nfrag;
1909 }
1910}
1911
1912LOCAL int
1914 FILE *outfile;
1915{
1916 Uint should_write;
1917
1918#ifdef APPLE_HYB
1919 char buffer[SECTOR_SIZE];
1920
1921 memset(buffer, 0, sizeof (buffer));
1922
1923 if (apple_hyb && !donotwrite_macpart) {
1924
1925 int i;
1926
1927 /*
1928 * write out padding to round up to HFS allocation block
1929 */
1930 for (i = 0; i < hfs_pad; i++)
1931 xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
1932
1933 last_extent_written += hfs_pad;
1934 }
1935#endif /* APPLE_HYB */
1936
1937 /*
1938 * OK, all done with that crap. Now write out the directories. This is
1939 * where the fur starts to fly, because we need to keep track of each
1940 * file as we find it and keep track of where we put it.
1941 */
1942 should_write = last_extent - session_start;
1943
1944 if (verbose > 2) {
1945#ifdef DBG_ISO
1947 _("Total directory extents being written = %u\n"),
1948 last_extent);
1949#endif
1950
1951#ifdef APPLE_HYB
1954 _("Total extents scheduled to be written (inc HFS) = %u\n"),
1956 else
1957#endif /* APPLE_HYB */
1958
1960 _("Total extents scheduled to be written = %u\n"),
1962 }
1963 /* Now write all of the files that we need. */
1965
1966#ifdef APPLE_HYB
1967 /* write out extents/catalog/dt file */
1968 if (apple_hyb && !donotwrite_macpart) {
1969
1970 xfwrite(hce->hfs_ce, HFS_BLOCKSZ, hce->hfs_tot_size, outfile, 0, FALSE);
1971
1972 /* round up to a whole CD block */
1973 if (HFS_ROUND_UP(hce->hfs_tot_size) -
1974 hce->hfs_tot_size * HFS_BLOCKSZ) {
1976 HFS_ROUND_UP(hce->hfs_tot_size) -
1977 hce->hfs_tot_size * HFS_BLOCKSZ, 1, outfile, 0, FALSE);
1978 }
1979 last_extent_written += ISO_ROUND_UP(hce->hfs_tot_size *
1980 HFS_BLOCKSZ) / SECTOR_SIZE;
1981
1982 /* write out HFS boot block */
1983 if (mac_boot.name)
1984 write_one_file(mac_boot.name, mac_boot.size, outfile,
1985 mac_boot.off, 0, 0);
1986 }
1987#endif /* APPLE_HYB */
1988
1989 /* The rest is just fluff. */
1990 if (verbose == 0) {
1991 return (0);
1992 }
1993#ifdef APPLE_HYB
1994 if (apple_hyb && !donotwrite_macpart) {
1996 _("Total extents actually written (inc HFS) = %u\n"),
1998 fprintf(stderr, _("(Size of ISO volume = %d, HFS extra = %d)\n"),
1999 last_extent_written - session_start - hfs_extra,
2000 hfs_extra);
2001 } else
2002#else
2003 fprintf(stderr, _("Total extents actually written = %d\n"),
2005#endif /* APPLE_HYB */
2006
2007 /* Hard links throw us off here */
2008 if (should_write != (last_extent - session_start)) {
2010 _("Number of extents written not what was predicted. Please fix.\n"));
2011 fprintf(stderr, _("Predicted = %d, written = %d\n"),
2012 should_write, last_extent);
2013 }
2014 fprintf(stderr, _("Total translation table size: %d\n"), table_size);
2015 fprintf(stderr, _("Total rockridge attributes bytes: %d\n"),
2017 fprintf(stderr, _("Total directory bytes: %d\n"), total_dir_size);
2018 fprintf(stderr, _("Path table size(bytes): %d\n"), path_table_size);
2019
2020#ifdef DEBUG
2022 "next extent, last_extent, last_extent_written %d %d %d\n",
2024#endif
2025
2026 return (0);
2027
2028} /* iso_write(... */
2029
2030/*
2031 * Function to write the PVD for the disc.
2032 */
2033LOCAL int
2035 FILE *outfile;
2036{
2037 char iso_time[17];
2038 int should_write;
2039 int i;
2040 int s;
2041 Uchar *cp;
2043
2044
2045 iso9660_ldate(iso_time, tv_begun.tv_sec, tv_begun.tv_usec * 1000, -100);
2046
2047 /* Next we write out the primary descriptor for the disc */
2048 memset(&vol_desc, 0, sizeof (vol_desc));
2049 vol_desc.type[0] = ISO_VD_PRIMARY;
2051 vol_desc.version[0] = 1;
2052
2053 memset(vol_desc.system_id, ' ', sizeof (vol_desc.system_id));
2055
2056 memset(vol_desc.volume_id, ' ', sizeof (vol_desc.volume_id));
2058
2059 should_write = last_extent - session_start;
2060 set_733((char *)vol_desc.volume_space_size, should_write);
2061 set_723(vol_desc.volume_set_size, volume_set_size);
2062 set_723(vol_desc.volume_sequence_number, volume_sequence_number);
2063 set_723(vol_desc.logical_block_size, SECTOR_SIZE);
2064
2065 /*
2066 * The path tables are used by DOS based machines to cache directory
2067 * locations
2068 */
2069 set_733((char *)vol_desc.path_table_size, path_table_size);
2070 set_731(vol_desc.type_l_path_table, path_table[0]);
2071 set_731(vol_desc.opt_type_l_path_table, path_table[1]);
2072 set_732(vol_desc.type_m_path_table, path_table[2]);
2073 set_732(vol_desc.opt_type_m_path_table, path_table[3]);
2074
2075 /* Now we copy the actual root directory record */
2076 memcpy(vol_desc.root_directory_record, &root_record,
2077 offsetof(struct iso_directory_record, name[0]) + 1);
2078
2079 /*
2080 * The rest is just fluff. It looks nice to fill in many of these
2081 * fields, though.
2082 */
2083 FILL_SPACE(volume_set_id);
2084 if (volset_id)
2085 memcpy_max(vol_desc.volume_set_id, volset_id, strlen(volset_id));
2086
2087 FILL_SPACE(publisher_id);
2088 if (publisher)
2089 memcpy_max(vol_desc.publisher_id, publisher, strlen(publisher));
2090
2091 FILL_SPACE(preparer_id);
2092 if (preparer)
2093 memcpy_max(vol_desc.preparer_id, preparer, strlen(preparer));
2094
2095 FILL_SPACE(application_id);
2096 if (appid)
2097 memcpy_max(vol_desc.application_id, appid, strlen(appid));
2098
2099 FILL_SPACE(copyright_file_id);
2100 if (copyright)
2101 memcpy_max(vol_desc.copyright_file_id, copyright,
2102 strlen(copyright));
2103
2104 FILL_SPACE(abstract_file_id);
2105 if (abstract)
2106 memcpy_max(vol_desc.abstract_file_id, abstract,
2107 strlen(abstract));
2108
2109 FILL_SPACE(bibliographic_file_id);
2110 if (biblio)
2111 memcpy_max(vol_desc.bibliographic_file_id, biblio,
2112 strlen(biblio));
2113
2114 FILL_SPACE(creation_date);
2116 FILL_SPACE(expiration_date);
2117 FILL_SPACE(effective_date);
2118 vol_desc.file_structure_version[0] = 1;
2119 FILL_SPACE(application_data);
2120
2121 iso9660_ldate(vol_desc.modification_date,
2125
2126 memcpy(vol_desc.creation_date, iso_time, 17);
2127 memcpy(vol_desc.expiration_date, "0000000000000000", 17);
2128 memcpy(vol_desc.effective_date, iso_time, 17);
2129
2130 if (use_XA) {
2131 char *xap = &((char *)&vol_desc)[1024];
2132
2133 memcpy(&xap[0], "CD-XA001", 8); /* XA Sign. */
2134 memcpy(&xap[8], "\0\0", 2); /* XA flags */
2135 memcpy(&xap[10], "\0\0\0\0\0\0\0\0", 8); /* Start dir */
2136 memcpy(&xap[18], "\0\0\0\0\0\0\0\0", 8); /* Reserved */
2137 }
2138
2139 /*
2140 * Compute a checksum to be used as a fingerprint in case we
2141 * include correct inode/link-count information in the current image.
2142 */
2143 for (i = 0, s = 0, cp = (Uchar *)&vol_desc; i < SECTOR_SIZE; i++) {
2144 s += cp[i] & 0xFF;
2145 }
2146 vol_desc_sum = s;
2147
2148 /* if not a bootable cd do it the old way */
2151 return (0);
2152}
2153
2154/*
2155 * Function to write the Extended PVD for the disc.
2156 */
2157LOCAL int
2159 FILE *outfile;
2160{
2162 vol_desc.version[0] = 2;
2163 vol_desc.file_structure_version[0] = 2;
2164
2165 /* if not a bootable cd do it the old way */
2168 return (0);
2169}
2170
2171/*
2172 * Function to write the EVD for the disc.
2173 */
2174LOCAL int
2176 FILE *outfile;
2177{
2178 struct iso_primary_descriptor evol_desc;
2179
2180 /*
2181 * Now write the end volume descriptor. Much simpler than the other
2182 * one
2183 */
2184 memset(&evol_desc, 0, sizeof (evol_desc));
2185 evol_desc.type[0] = (unsigned char) ISO_VD_END;
2186 strncpy(evol_desc.id, ISO_STANDARD_ID, sizeof (evol_desc.id));
2187 evol_desc.version[0] = 1;
2188 xfwrite(&evol_desc, SECTOR_SIZE, 1, outfile, 0, TRUE);
2190 return (0);
2191}
2192
2193/*
2194 * Function to write the version information for the disc.
2195 * Warning: Do not disable or change this function. The data created by this
2196 * function is used to tell the filesystem driver in the OS kernel that this
2197 * mkisofs version includes correct inode information.
2198 */
2199LOCAL int
2201 FILE *outfile;
2202{
2203 char vers[SECTOR_SIZE+1];
2204 int X_ac;
2205 char **X_av;
2206 char *cp;
2207 int i;
2208 int idx = 4;
2209 int len;
2210 extern char version_string[];
2211 extern int path_ind;
2212
2213 /* Now write the version descriptor. */
2214 memset(vers, 0, sizeof (vers));
2215 strcpy(vers, "MKI "); /* strcpy() OK here */
2216
2217 cp = vers;
2218 X_ac = saved_ac();
2219 X_av = saved_av();
2220 strlcpy(&cp[idx], ctime(&begun), 26);
2221 idx += 25;
2224 for (i = 1; i < X_ac; i++) {
2225 len = strlen(X_av[i]);
2226 if ((idx + len + 2) >= SECTOR_SIZE)
2227 break;
2228 cp[idx++] = ' ';
2229 /*
2230 * Do not give away secret information when not in debug mode.
2231 */
2232 if (debug)
2233 strlcpy(&cp[idx], X_av[i], SECTOR_SIZE - idx);
2234 else if (i >= path_ind)
2235 len = graftcp(&cp[idx], X_av[i], &vers[SECTOR_SIZE-1]);
2236 else if (X_av[i][0] == '/')
2237 len = pathcp(&cp[idx], X_av[i], &vers[SECTOR_SIZE-1]);
2238 else
2239 strlcpy(&cp[idx], X_av[i], SECTOR_SIZE - idx);
2240 idx += len;
2241 }
2242
2243 cp[SECTOR_SIZE - 1] = '\0';
2244 len = 0;
2245 if (correct_inodes) {
2246 /*
2247 * Only add this fingerprint in case we include correct
2248 * inode/link-count information in the current image.
2249 */
2250 len = vol_desc_sum;
2251 }
2252 cp = &vers[SECTOR_SIZE - 1];
2253 *(Uchar *)cp = len % 256;
2254 len /= 256;
2255 *(Uchar *)--cp = len % 256;
2256 len /= 256;
2257 *(Uchar *)--cp = len % 256;
2258
2259 xfwrite(vers, SECTOR_SIZE, 1, outfile, 0, TRUE);
2261 return (0);
2262}
2263
2264/*
2265 * Avoid to write unwanted information into the version info string.
2266 */
2267LOCAL int
2269 char *to;
2270 char *from;
2271 char *ep;
2272{
2273 int len = strlen(from);
2274 char *node = NULL;
2275
2276 if (use_graft_ptrs)
2277 node = findgequal(from);
2278
2279 if (node == NULL) {
2280 len = 0;
2281 node = from;
2282 } else {
2283 len = node - from;
2284 *node = '\0';
2285 strncpy(to, from, ep - to);
2286 *node++ = '=';
2287 to += len++;
2288 *to++ = '=';
2289 }
2290 return (len + pathcp(to, node, ep));
2291}
2292
2293LOCAL int
2294pathcp(to, from, ep)
2295 char *to;
2296 char *from;
2297 char *ep;
2298{
2299 int len = strlen(from);
2300 char *p;
2301
2302 p = strrchr(from, '/');
2303 if (p == NULL) {
2304 strncpy(to, from, ep - to);
2305 } else {
2306 if (p[1] == '\0') {
2307 --p;
2308 while (p > from && *p != '/')
2309 --p;
2310 }
2311 len = 0;
2312 if (*p == '/') {
2313 strncpy(to, "...", ep - to);
2314 to += 3;
2315 len = 3;
2316 }
2317 if (to < ep) {
2318 strncpy(to, p, ep - to);
2319 len += strlen(to);
2320 }
2321 }
2322 return (len);
2323}
2324
2325
2326/*
2327 * Function to write the path table for the disc.
2328 */
2329LOCAL int
2331 FILE *outfile;
2332{
2333 /* Next we write the path tables */
2341 return (0);
2342}
2343
2344LOCAL int
2346 FILE *outfile;
2347{
2350 return (0);
2351}
2352
2353/*
2354 * Functions to describe padding block at the start of the disc.
2355 */
2356EXPORT int
2357oneblock_size(starting_extent)
2358 UInt32_t starting_extent;
2359{
2360 last_extent++;
2361 return (0);
2362}
2363
2364/*
2365 * Functions to describe path table size.
2366 */
2367LOCAL int
2368pathtab_size(starting_extent)
2369 UInt32_t starting_extent;
2370{
2371 path_table[0] = starting_extent;
2372
2373 path_table[1] = 0;
2375 path_table[3] = 0;
2376 last_extent += 2 * path_blocks;
2377 return (0);
2378}
2379
2380/*
2381 * Functions to describe padding blocks before PVD.
2382 */
2383LOCAL int
2384startpad_size(starting_extent)
2385 UInt32_t starting_extent;
2386{
2388 return (0);
2389}
2390
2391/*
2392 * Functions to describe padding blocks between sections.
2393 */
2394LOCAL int
2395interpad_size(starting_extent)
2396 UInt32_t starting_extent;
2397{
2398 int emod = 0;
2399
2400#ifdef needed
2401 starting_extent += 16; /* First add 16 pad blocks */
2402#endif
2403 if ((emod = starting_extent % 16) != 0) {
2404 starting_extent += 16 - emod; /* Now pad to mod 16 # */
2405 }
2406 last_extent = starting_extent;
2407 return (0);
2408}
2409
2410/*
2411 * Functions to describe padding blocks at end of disk.
2412 */
2413LOCAL int
2414endpad_size(starting_extent)
2415 UInt32_t starting_extent;
2416{
2417 starting_extent += 150; /* 150 pad blocks (post gap) */
2418 last_extent = starting_extent;
2419 return (0);
2420}
2421
2422LOCAL int
2424{
2425#ifdef APPLE_HYB
2426 UInt32_t start_extent = last_extent; /* orig ISO files start */
2427
2428#endif /* APPLE_HYB */
2429
2431#ifdef DVD_AUD_VID
2432 if (dvd_aud_vid_flag & DVD_SPEC_VIDEO) {
2433 comerrno(EX_BAD, _("Unable to make a DVD-Video image.\n"));
2434 }
2435#else
2436 ;
2437 /* EMPTY */
2438#endif
2439 }
2440
2441
2442#ifdef SORTING
2443 if (do_sort) {
2444 if (sort_file_addresses() == 0)
2445 reassign_link_addresses(root);
2446 }
2447#endif /* SORTING */
2448
2449#ifdef APPLE_HYB
2450 /*
2451 * put this here for the time being - may when I've worked out how to
2452 * use Eric's new system for creating/writing parts of the image it
2453 * may move to it's own routine
2454 */
2456 hfs_file_gen(start_extent);
2457#ifdef PREP_BOOT
2458 else if (use_prep_boot || use_chrp_boot)
2459 gen_prepboot();
2460#endif /* PREP_BOOT */
2461#endif /* APPLE_HYB */
2462
2463 /*
2464 * Do inode/hard link related stuff for non-directory type files.
2465 */
2466 do_inode(root);
2467 return (0);
2468}
2469
2470LOCAL int
2472{
2473 if (verbose > 2) {
2474 dump_tree(root);
2475 }
2476 return (0);
2477}
2478
2479LOCAL int
2480dirtree_fixup(starting_extent)
2481 UInt32_t starting_extent;
2482{
2483 if (use_RockRidge && reloc_dir)
2485
2486 /*
2487 * Set the link count for directories to 2 + number of sub-directories.
2488 */
2489 if (use_RockRidge)
2491 return (0);
2492}
2493
2494LOCAL int
2495dirtree_size(starting_extent)
2496 UInt32_t starting_extent;
2497{
2499 return (0);
2500}
2501
2502LOCAL int
2503ext_size(starting_extent)
2504 UInt32_t starting_extent;
2505{
2506 extern int extension_record_size;
2507 struct directory_entry *s_entry;
2508
2509 extension_record_extent = starting_extent;
2510 s_entry = root->contents;
2511 set_733((char *)s_entry->rr_attributes + s_entry->rr_attr_size - 24,
2513 set_733((char *)s_entry->rr_attributes + s_entry->rr_attr_size - 8,
2515 last_extent++;
2516 return (0);
2517}
2518
2519LOCAL int
2521 FILE *outfile;
2522{
2524 return (0);
2525}
2526
2527LOCAL int
2529 FILE *outfile;
2530{
2532 return (0);
2533}
2534
2535LOCAL int
2537 FILE *outfile;
2538{
2539 char buffer[SECTOR_SIZE];
2540 int i;
2541 int npad;
2542
2543 memset(buffer, 0, sizeof (buffer));
2544
2545 npad = session_start + 16 - last_extent_written;
2546
2547 for (i = 0; i < npad; i++) {
2548 xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
2549 }
2550
2551 last_extent_written += npad;
2552 return (0);
2553}
2554
2555LOCAL int
2557 FILE *outfile;
2558{
2559 char buffer[SECTOR_SIZE];
2560 int i;
2561 int npad = 0;
2562
2563 memset(buffer, 0, sizeof (buffer));
2564
2565#ifdef needed
2566 npad = 16;
2567#endif
2568 if ((i = last_extent_written % 16) != 0)
2569 npad += 16 - i;
2570
2571 for (i = 0; i < npad; i++) {
2572 xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
2573 }
2574
2575 last_extent_written += npad;
2576 return (0);
2577}
2578
2579LOCAL int
2581 FILE *outfile;
2582{
2583 char buffer[SECTOR_SIZE];
2584 int i;
2585
2586 memset(buffer, 0, sizeof (buffer));
2587
2588 for (i = 0; i < 150; i++) {
2589 xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
2590 }
2591
2592 last_extent_written += 150;
2593 return (0);
2594}
2595
2596#ifdef APPLE_HYB
2597
2598/*
2599 * hfs_get_parms: get HFS parameters from the command line
2600 */
2601
2602LOCAL int
2603hfs_get_parms(key)
2604 char *key;
2605{
2606 int ret = 0;
2607 char *p;
2608
2609 if (hfs_parms == NULL)
2610 return (ret);
2611
2612 if ((p = strstr(hfs_parms, key)) != NULL) {
2613 p += strlen(key) + 1;
2614 sscanf(p, "%d", &ret);
2615 }
2616
2617 return (ret);
2618}
2619
2620/*
2621 * hfs_file_gen: set up "fake" HFS volume using the ISO9660 tree
2622 */
2623LOCAL void
2624hfs_file_gen(start_extent)
2625 UInt32_t start_extent;
2626{
2627 int Csize; /* clump size for HFS vol */
2628 int loop;
2629 UInt32_t last_extent_save = last_extent;
2630 char *p;
2631
2632 /* allocate memory for the libhfs/mkisofs extra info */
2633 hce = (hce_mem *) e_malloc(sizeof (hce_mem));
2634
2635 hce->error = (char *)e_malloc(1024);
2636
2637 /* mark as unallocated for use later */
2638 hce->hfs_ce = hce->hfs_hdr = hce->hfs_map = 0;
2639
2640 /* reserve space for the label partition - if it is needed */
2641#ifdef PREP_BOOT
2642 /* a PReP bootable partition needs the map.. */
2643 if (gen_pt || use_prep_boot || use_chrp_boot)
2644#else
2645 if (gen_pt)
2646#endif /* PREP_BOOT */
2647 hce->hfs_map_size = HFS_MAP_SIZE;
2648 else
2649 hce->hfs_map_size = 0;
2650
2651 /* set the HFS parameter string to upper case */
2652 if (hfs_parms) {
2653 for (p = hfs_parms; *p; p++)
2654 *p = toupper((*p & 0xFF));
2655 }
2656
2657 /* set the initial factor to increase Catalog file size */
2658 if ((hce->ctc_size = hfs_get_parms("CTC")) == 0)
2659 hce->ctc_size = CTC;
2660
2661 /* set the max size of the Catalog file */
2662 if ((hce->max_XTCsize = hfs_get_parms("MAX_XTCSIZE")) == 0)
2663 hce->max_XTCsize = MAX_XTCSIZE;
2664
2665 /* set the number of time to try to make an HFS volume */
2666 if ((loop = hfs_get_parms("CTC_LOOP")) == 0)
2667 loop = CTC_LOOP;
2668
2669 /*
2670 * "create" the HFS volume (just the header, catalog/extents files) if
2671 * there's a problem with the Catalog file being too small, we keep on
2672 * increasing the size (up to CTC_LOOP) times and try again.
2673 * Unfortunately I don't know enough about the inner workings of HFS,
2674 * so I can't workout the size of the Catalog file in advance (and I
2675 * don't want to "grow" as is is normally allowed to), therefore, this
2676 * approach is a bit over the top as it involves throwing away the
2677 * "volume" we have created and trying again ...
2678 */
2679 do {
2680 hce->error[0] = '\0';
2681
2682 /* attempt to create the Mac volume */
2683#ifdef APPLE_HFS_HYB
2684 Csize = make_mac_volume(root, start_extent);
2685#else
2686 Csize = -1;
2687#endif
2688
2689 /* if we have a problem ... */
2690 if (Csize < 0) {
2691 /*
2692 * we've made too many attempts, or got some other
2693 * error
2694 */
2695 if (loop == 0 || errno != HCE_ERROR) {
2696 /* HCE_ERROR is not a valid errno value */
2697 if (errno == HCE_ERROR)
2698 errno = 0;
2699
2700 /* exit with the error */
2701 if (*hce->error)
2702 fprintf(stderr, "%s\n", hce->error);
2703 perr(hfs_error);
2704 } else {
2705 /* increase Catalog file size factor */
2706 hce->ctc_size *= CTC;
2707
2708 /*
2709 * reset the initial "last_extent" and try
2710 * again
2711 */
2712 last_extent = last_extent_save;
2713 }
2714 } else {
2715 /* everything OK - just carry on ... */
2716 loop = 0;
2717 }
2718 }
2719 while (loop--);
2720
2721 hfs_extra = HFS_ROUND_UP(hce->hfs_tot_size) / SECTOR_SIZE;
2722
2723 last_extent += hfs_extra;
2724
2725 /* generate the Mac label and HFS partition maps */
2726 mac_boot.name = hfs_boot_file;
2727
2728 /*
2729 * only generate the partition tables etc. if we are making a bootable
2730 * CD - or if the -part option is given
2731 */
2732 if (gen_pt) {
2733 if (gen_mac_label(&mac_boot)) {
2734 if (*hce->error)
2735 fprintf(stderr, "%s\n", hce->error);
2736 perr(hfs_error);
2737 }
2738 }
2739 /* set Autostart filename if required */
2740 if (autoname) {
2741 if (autostart())
2742 perr("Autostart filename must less than 12 characters");
2743 }
2744 /* finished with any HFS type errors */
2745 free(hce->error);
2746 hce->error = 0;
2747
2748 /*
2749 * the ISO files need to start on a multiple of the HFS allocation
2750 * blocks, so find out how much padding we need
2751 */
2752
2753 /*
2754 * take in accout alignment of files wrt HFS volume start - remove any
2755 * previous session as well
2756 */
2757 start_extent -= session_start;
2758 hfs_pad = ROUND_UP(start_extent*SECTOR_SIZE +
2759 (hce->hfs_hdr_size + hce->hfs_map_size) * HFS_BLOCKSZ,
2760 Csize) / SECTOR_SIZE;
2761
2762 hfs_pad -= (start_extent + (hce->hfs_hdr_size + hce->hfs_map_size) /
2763 HFS_BLK_CONV);
2764
2765#ifdef PREP_BOOT
2766 gen_prepboot_label(hce->hfs_map);
2767#endif /* PREP_BOOT */
2768
2769}
2770
2771#ifdef PREP_BOOT
2772LOCAL void
2773gen_prepboot()
2774{
2775 /*
2776 * we need to allocate the hce struct since hce->hfs_map is used to
2777 * generate the fdisk partition map required for PReP booting
2778 */
2779 hce = (hce_mem *) e_malloc(sizeof (hce_mem));
2780
2781 /* mark as unallocated for use later */
2782 hce->hfs_ce = hce->hfs_hdr = hce->hfs_map = 0;
2783
2784 /* reserve space for the label partition - if it is needed */
2785 hce->hfs_map_size = HFS_MAP_SIZE;
2786
2787 hce->hfs_map = (unsigned char *) e_malloc(hce->hfs_map_size * HFS_BLOCKSZ);
2788 gen_prepboot_label(hce->hfs_map);
2789}
2790
2791#endif /* PREP_BOOT */
2792
2793/*
2794 * get_adj_size: get the ajusted size of the volume with the HFS
2795 * allocation block size for each file
2796 */
2798get_adj_size(Csize)
2799 int Csize;
2800{
2801 struct deferred_write *dw;
2802 Ulong size = 0;
2803 int count = 0;
2804
2805 /* loop through all the files finding the new total size */
2806 for (dw = dw_head; dw; dw = dw->next) {
2807 size += (ROUND_UP(dw->size, Csize)/HFS_BLOCKSZ);
2808 count++;
2809 }
2810
2811 /*
2812 * crude attempt to prevent overflows - HFS can only cope with a
2813 * maximum of about 65536 forks (actually less) - this will trap cases
2814 * when we have far too many files
2815 */
2816
2817 if (count >= 65536)
2818 return (-1);
2819 else
2820 return (size);
2821}
2822
2823/*
2824 * adj_size: adjust the ISO record entries for all files
2825 * based on the HFS allocation block size
2826 */
2827EXPORT int
2828adj_size(Csize, start_extent, extra)
2829 int Csize;
2830 UInt32_t start_extent;
2831 int extra;
2832{
2833 struct deferred_write *dw;
2834 struct directory_entry *s_entry;
2835 int size;
2836
2837 /* get the adjusted start_extent (with padding) */
2838 /* take in accout alignment of files wrt HFS volume start */
2839
2840 start_extent -= session_start;
2841
2842 start_extent = ROUND_UP(start_extent*SECTOR_SIZE + extra*HFS_BLOCKSZ,
2843 Csize) / SECTOR_SIZE;
2844
2845 start_extent -= (extra / HFS_BLK_CONV);
2846
2847 start_extent += session_start;
2848
2849 /* initialise file hash */
2850 flush_hash();
2851
2852 /*
2853 * loop through all files changing their starting blocks and finding
2854 * any padding needed to written out latter
2855 */
2856 for (dw = dw_head; dw; dw = dw->next) {
2857 s_entry = dw->s_entry;
2858 s_entry->starting_block = dw->extent = start_extent;
2859 set_733((char *)s_entry->isorec.extent, start_extent);
2860 size = ROUND_UP(dw->size, Csize) / SECTOR_SIZE;
2861 dw->pad = size - ISO_ROUND_UP(dw->size) / SECTOR_SIZE;
2862
2863 /*
2864 * cache non-HFS files - as there may be multiple links to
2865 * these files (HFS files can't have multiple links). We will
2866 * need to change the starting extent of the other links later
2867 */
2868 if (!s_entry->hfs_ent)
2869 add_hash(s_entry);
2870
2871 start_extent += size;
2872 }
2873
2874 return (start_extent);
2875}
2876
2877/*
2878 * adj_size_other: adjust any non-HFS files that may be linked
2879 * to an existing file (i.e. not have a deferred_write
2880 * entry of it's own
2881 */
2882EXPORT void
2883adj_size_other(dpnt)
2884 struct directory *dpnt;
2885{
2886 struct directory_entry *s_entry;
2887 struct file_hash *s_hash;
2888
2889 while (dpnt) {
2890 s_entry = dpnt->contents;
2891 for (s_entry = dpnt->contents; s_entry;
2892 s_entry = s_entry->next) {
2893 /*
2894 * if it's an HFS file or a directory - then ignore
2895 * (we're after non-HFS files)
2896 */
2897 if (s_entry->hfs_ent ||
2898 (s_entry->isorec.flags[0] & ISO_DIRECTORY))
2899 continue;
2900
2901 /*
2902 * find any cached entry and assign new starting
2903 * extent
2904 */
2905 s_hash = find_hash(s_entry);
2906 if (s_hash) {
2907 set_733((char *)s_entry->isorec.extent,
2908 s_hash->starting_block);
2909 /* not vital - but tidy */
2910 s_entry->starting_block =
2911 s_hash->starting_block;
2912 }
2913 }
2914 if (dpnt->subdir) {
2915 adj_size_other(dpnt->subdir);
2916 }
2917 dpnt = dpnt->next;
2918 }
2919
2920 /* clear file hash */
2921 flush_hash();
2922}
2923
2924/*
2925 * hfs_hce_write: write out the HFS header stuff
2926 */
2927LOCAL int
2928hfs_hce_write(outfile)
2929 FILE *outfile;
2930{
2931 char buffer[SECTOR_SIZE];
2932 int n = 0;
2933 int r; /* HFS hdr output */
2934 int tot_size = hce->hfs_map_size + hce->hfs_hdr_size;
2935
2936 memset(buffer, 0, sizeof (buffer));
2937
2938 /*
2939 * hack time ... if the tot_size is greater than 32Kb then
2940 * it won't fit in the first 16 blank SECTORS (64 512 byte
2941 * blocks, as most of this is padding, we just truncate this
2942 * data to 64x4xHFS_BLOCKSZ ... hope this is OK ...
2943 */
2944
2945 if (tot_size > 64) tot_size = 64;
2946
2947 /* get size in CD blocks == 4xHFS_BLOCKSZ == 2048 */
2948 n = tot_size / HFS_BLK_CONV;
2949 r = tot_size % HFS_BLK_CONV;
2950
2951 /* write out HFS volume header info */
2952 xfwrite(hce->hfs_map, HFS_BLOCKSZ, tot_size, outfile, 0, FALSE);
2953
2954 /* fill up to a complete CD block */
2955 if (r) {
2956 xfwrite(buffer, HFS_BLOCKSZ, HFS_BLK_CONV - r, outfile, 0, FALSE);
2957 n++;
2958 }
2960 return (0);
2961}
2962
2963/*
2964 * insert_padding_file : insert a dumy file to make volume at least
2965 * 800k
2966 *
2967 * XXX If we ever need to write more then 2 GB, make size off_t
2968 */
2969EXPORT int
2970insert_padding_file(size)
2971 int size;
2972{
2973 struct deferred_write *dwpnt;
2974
2975 /* get the size in bytes */
2976 size *= HFS_BLOCKSZ;
2977
2978 dwpnt = (struct deferred_write *)
2979 e_malloc(sizeof (struct deferred_write));
2980 dwpnt->s_entry = 0;
2981 /* set the padding to zero */
2982 dwpnt->pad = 0;
2983 /* set offset to zero */
2984 dwpnt->off = (off_t)0;
2985 dwpnt->dw_flags = 0;
2986#ifdef APPLE_HYB
2987 dwpnt->hfstype = TYPE_NONE;
2988#endif
2989
2990 /*
2991 * don't need to wory about the s_entry stuff as it won't be touched#
2992 * at this point onwards
2993 */
2994
2995 /* insert the entry in the list */
2996 if (dw_tail) {
2997 dw_tail->next = dwpnt;
2998 dw_tail = dwpnt;
2999 } else {
3000 dw_head = dwpnt;
3001 dw_tail = dwpnt;
3002 }
3003
3004 /* aloocate memory as a "Table" file */
3005 dwpnt->table = e_malloc(size);
3006 dwpnt->name = NULL;
3007
3008 dwpnt->next = NULL;
3009 dwpnt->size = size;
3010 dwpnt->extent = last_extent;
3012
3013 /* retune the size in HFS blocks */
3014 return (ISO_ROUND_UP(size) / HFS_BLOCKSZ);
3015}
3016
3017struct output_fragment hfs_desc = {NULL, NULL, NULL, hfs_hce_write, "HFS volume header"};
3018
3019#endif /* APPLE_HYB */
3020
3022struct output_fragment voldesc_desc = {NULL, oneblock_size, root_gen, pvd_write, "Primary Volume Descriptor"};
3023struct output_fragment xvoldesc_desc = {NULL, oneblock_size, NULL, xpvd_write, "Enhanced Volume Descriptor"};
3024struct output_fragment end_vol = {NULL, oneblock_size, NULL, evd_write, "End Volume Descriptor" };
3029struct output_fragment extension_desc = {NULL, ext_size, NULL, exten_write, "Extension record" };
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int toupper(int c)
Definition: utclib.c:881
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#define MAX(x, y)
Definition: rdesktop.h:175
#define PATH_MAX
Definition: types.h:280
char copyright[]
Definition: main.c:27
size_t strlcpy(char *d, const char *s, size_t bufsize)
Definition: compat.c:3
void add_hash(struct hash_table *table, unsigned char *name, int len, unsigned char *pointer)
Definition: hash.c:82
#define SECTOR_SIZE
Definition: fs.h:22
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t _In_ uint64_t _In_ bool file_write
Definition: btrfs_drv.h:1366
w ll
Definition: byte_order.h:167
r l[0]
Definition: byte_order.h:168
#define UConst
Definition: ccomdefs.h:72
EXPORT BOOL errwarnonly(int etype, const char *fname)
Definition: checkerr.c:282
EXPORT BOOL errabort(int etype, const char *fname, BOOL doexit)
Definition: checkerr.c:300
EXPORT BOOL errhidden(int etype, const char *fname)
Definition: checkerr.c:264
#define E_SHRINK
Definition: checkerr.h:52
#define E_OPEN
Definition: checkerr.h:48
#define E_READ
Definition: checkerr.h:49
#define E_GROW
Definition: checkerr.h:51
EXPORT void comerrno(int err, char *msg, va_alist)
Definition: comerr.c:137
EXPORT int errmsgno(int err, char *msg, va_alist)
Definition: comerr.c:219
EXPORT void comerr(char *msg, va_alist)
Definition: comerr.c:84
EXPORT int errmsg(char *msg, va_alist)
Definition: comerr.c:192
@ TYPE_NONE
Definition: createspec.c:69
#define free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
#define frac(x)
Definition: texture.c:364
static const WCHAR *const ext[]
Definition: module.c:53
unsigned char
Definition: typeof.h:29
#define off_t
Definition: dosfsck.h:5
__kernel_time_t time_t
Definition: linux.h:252
__kernel_off_t off_t
Definition: linux.h:201
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
EXPORT ssize_t ffileread(FILE *f, void *buf, size_t len)
Definition: ffileread.c:20
unsigned int BOOL
Definition: ntddk_ex.h:94
time_t now
Definition: finger.c:65
EXPORT int geterrno()
Definition: geterrno.c:34
GLdouble s
Definition: gl.h:2039
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint buffer
Definition: glext.h:5915
GLint namelen
Definition: glext.h:7232
GLfloat GLfloat p
Definition: glext.h:8902
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define _(X)
Definition: i386-dis.c:35
#define abort()
Definition: i386-dis.c:34
@ extra
Definition: id3.c:95
_Check_return_ _CRTIMP FILE *__cdecl freopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode, _Inout_ FILE *_File)
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
_Check_return_opt_ _CRTIMP int __cdecl fflush(_Inout_opt_ FILE *_File)
_Check_return_opt_ _CRTIMP size_t __cdecl fread(_Out_writes_bytes_(_ElementSize *_Count) void *_DstBuf, _In_ size_t _ElementSize, _In_ size_t _Count, _Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
_Check_return_opt_ _CRTIMP int __cdecl fseek(_Inout_ FILE *_File, _In_ long _Offset, _In_ int _Origin)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP long __cdecl ftell(_Inout_ FILE *_File)
_Check_return_opt_ _CRTIMP size_t __cdecl fwrite(_In_reads_bytes_(_Size *_Count) const void *_Str, _In_ size_t _Size, _In_ size_t _Count, _Inout_ FILE *_File)
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
REFIID LPVOID DWORD_PTR dw
Definition: atlbase.h:40
EXPORT void do_inode(struct directory *dpnt)
Definition: inode.c:55
EXPORT void do_dir_nlink(struct directory *dpnt)
Definition: inode.c:85
const char * filename
Definition: ioapi.h:137
#define ISO_VD_SUPPLEMENTARY
Definition: iso9660.h:44
#define ISO_DIRECTORY
Definition: iso9660.h:265
#define ISO_STANDARD_ID
Definition: iso9660.h:47
#define XA_SUBH_EOR
Definition: iso9660.h:367
#define XA_SUBH_DATA
Definition: iso9660.h:370
#define ISO_VD_END
Definition: iso9660.h:45
#define ISO_VD_PRIMARY
Definition: iso9660.h:43
#define ISO_MULTIEXTENT
Definition: iso9660.h:271
#define XA_SUBH_EOF
Definition: iso9660.h:374
EXPORT void set_723(void *vp, UInt32_t i)
Definition: isonum.c:76
EXPORT void set_731(void *vp, UInt32_t i)
Definition: isonum.c:91
EXPORT void set_722(void *vp, UInt32_t i)
Definition: isonum.c:61
EXPORT void set_721(void *vp, UInt32_t i)
Definition: isonum.c:46
EXPORT void set_732(void *vp, UInt32_t i)
Definition: isonum.c:108
EXPORT UInt32_t get_733(void *vp)
Definition: isonum.c:219
EXPORT void set_733(void *vp, UInt32_t i)
Definition: isonum.c:125
#define SEEK_SET
Definition: jmemansi.c:26
#define LOCAL(type)
Definition: jmorecfg.h:289
#define debug(msg)
Definition: key_call.c:71
#define unlink
Definition: syshdrs.h:54
#define blk
Definition: linetest.c:70
POINT cp
Definition: magnifier.c:59
__u8 volume_id[4]
Definition: mkdosfs.c:3
__u16 ctime
Definition: mkdosfs.c:4
__u16 time
Definition: mkdosfs.c:8
__u8 system_id[8]
Definition: mkdosfs.c:1
#define error(str)
Definition: mkdosfs.c:1605
EXPORT char * findgequal(char *s)
Definition: mkisofs.c:3642
int osecsize
Definition: mkisofs.c:112
EXPORT int iso9660_date(char *result, time_t crtime)
Definition: mkisofs.c:1868
char *abstract char * volset_id
Definition: mkisofs.c:165
int volume_sequence_number
Definition: mkisofs.c:173
char * extension_record
Definition: mkisofs.c:90
char * path_table_m
Definition: mkisofs.c:1632
int volume_set_size
Definition: mkisofs.c:172
int path_ind
Definition: mkisofs.c:69
BOOL correct_inodes
Definition: mkisofs.c:324
struct iso_directory_record root_record
Definition: mkisofs.c:87
UInt32_t session_start
Definition: mkisofs.c:77
char * biblio
Definition: mkisofs.c:163
UInt32_t next_extent
Definition: mkisofs.c:75
ldate modification_date
Definition: mkisofs.c:197
char version_string[]
Definition: mkisofs.c:71
char * path_table_l
Definition: mkisofs.c:1631
unsigned int path_table_size
Definition: mkisofs.c:78
int use_RockRidge
Definition: mkisofs.c:110
int gui
Definition: mkisofs.c:130
char * trans_tbl
Definition: mkisofs.c:259
EXPORT void * e_malloc(size_t size)
Definition: mkisofs.c:3921
char * appid
Definition: mkisofs.c:161
unsigned int path_blocks
Definition: mkisofs.c:80
int use_graft_ptrs
Definition: mkisofs.c:230
int extension_record_size
Definition: mkisofs.c:92
char * preparer
Definition: mkisofs.c:159
UInt32_t extension_record_extent
Definition: mkisofs.c:91
EXPORT int iso9660_ldate(char *result, time_t crtime, int nsec, int gmtoff)
Definition: mkisofs.c:1907
int nolimitpathtables
Definition: mkisofs.c:245
EXPORT char * e_strdup(char *s) const
Definition: mkisofs.c:3941
unsigned int path_table[4]
Definition: mkisofs.c:79
char * publisher
Definition: mkisofs.c:160
int use_XA
Definition: mkisofs.c:111
UInt32_t last_extent
Definition: mkisofs.c:76
int split_output
Definition: mkisofs.c:156
int donotwrite_macpart
Definition: mkisofs.c:298
#define TABLE_INODE
Definition: mkisofs.h:763
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
struct stat root_statbuf
Definition: tree.c:110
int create_udfsymlinks
struct directory * reloc_dir
Definition: tree.c:111
#define IS_SYMLINK
Definition: mkisofs.h:807
#define ISO_BLOCKS(X)
Definition: mkisofs.h:743
#define MULTI_EXTENT
Definition: mkisofs.h:808
#define ISO_ROUND_UP(X)
Definition: mkisofs.h:742
char * abstract
#define INHIBIT_ISO9660_ENTRY
Definition: mkisofs.h:802
#define SPATH_SEPARATOR
Definition: mkisofs.h:787
#define sprintf(buf, format,...)
Definition: sprintf.c:55
EXPORT char * movebytes(void *fromv, void *tov, ssize_t cnt) const
Definition: movebytes.c:30
#define __(s)
Definition: nlsdefs.h:101
#define __PR(a)
Definition: prototyp.h:106
static FILE * infile
Definition: rdjpgcom.c:65
#define verbose
Definition: rosglue.h:36
EXPORT int saved_ac()
Definition: saveargs.c:96
EXPORT char ** saved_av()
Definition: saveargs.c:105
#define offsetof(TYPE, MEMBER)
#define errno
Definition: errno.h:18
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
#define exit(n)
Definition: config.h:202
#define memset(x, y, z)
Definition: compat.h:39
EXPORT void flush_hash()
Definition: hash.c:240
EXPORT struct file_hash * find_hash(struct directory_entry *spnt)
Definition: hash.c:192
EXPORT void finish_cl_pl_entries()
Definition: tree.c:1036
EXPORT void init_fstatbuf()
Definition: tree.c:2974
EXPORT void dump_tree(struct directory *node)
Definition: tree.c:2863
EXPORT void generate_iso9660_directories(struct directory *node, FILE *outfile)
Definition: tree.c:2458
EXPORT void memcpy_max(char *to, char *from, int max)
Definition: write.c:1880
LOCAL int vers_write(FILE *outfile)
Definition: write.c:2200
LOCAL struct directory ** pathlist
Definition: write.c:68
LOCAL int evd_write(FILE *outfile)
Definition: write.c:2175
LOCAL struct deferred_write * dw_tail
Definition: write.c:301
LOCAL int compare_dirs(void *rr, const void *ll) const
Definition: write.c:683
LOCAL void write_one_file(char *filename, off_t size, FILE *outfile)
Definition: write.c:367
struct output_fragment end_vol
Definition: write.c:3024
LOCAL int endpad_write(FILE *outfile)
Definition: write.c:2580
LOCAL int table_size
Definition: write.c:65
LOCAL int compare_paths(void const *r, void const *l)
Definition: write.c:1733
struct output_fragment * out_list
Definition: write.c:75
LOCAL int xpvd_write(FILE *outfile)
Definition: write.c:2158
struct output_fragment interpad_desc
Definition: write.c:3031
LOCAL int dirtree_write(FILE *outfile)
Definition: write.c:2520
EXPORT void outputlist_insert(struct output_fragment *frag)
Definition: write.c:1895
LOCAL int sort_goof
Definition: write.c:70
LOCAL int graftcp(char *to, char *from, char *ep)
Definition: write.c:2268
LOCAL int endpad_size(UInt32_t starting_extent)
Definition: write.c:2414
struct output_fragment files_desc
Definition: write.c:3030
LOCAL int xawrite(void *buffer, int size, int count, FILE *file, int submode, BOOL islast)
Definition: write.c:240
LOCAL void build_pathlist(struct directory *node)
Definition: write.c:1714
EXPORT void generate_one_directory(struct directory *dpnt, FILE *outfile)
Definition: write.c:1539
LOCAL int next_path_index
Definition: write.c:69
LOCAL struct deferred_write * dw_head
Definition: write.c:300
LOCAL int ext_size(UInt32_t starting_extent)
Definition: write.c:2503
struct output_fragment startpad_desc
Definition: write.c:3021
char * hfs_error
Definition: write.c:81
struct output_fragment voldesc_desc
Definition: write.c:3022
struct output_fragment endpad_desc
Definition: write.c:3032
struct output_fragment extension_desc
Definition: write.c:3029
LOCAL int assign_directory_addresses(struct directory *node)
Definition: write.c:314
#define SIZEOF_UDF_EXT_ATTRIBUTE_COMMON
Definition: write.c:56
static UConst char sccsid[]
Definition: write.c:4
LOCAL int pathtab_size(UInt32_t starting_extent)
Definition: write.c:2368
LOCAL int pathcp(char *to, char *from, char *ep)
Definition: write.c:2294
EXPORT struct iso_primary_descriptor vol_desc
Definition: write.c:77
LOCAL int startpad_write(FILE *outfile)
Definition: write.c:2536
#define FILL_SPACE(X)
Definition: write.c:165
LOCAL void write_files(FILE *outfile)
Definition: write.c:572
LOCAL int interpad_size(UInt32_t starting_extent)
Definition: write.c:2395
LOCAL Uint path_table_index
Definition: write.c:304
struct output_fragment * out_tail
Definition: write.c:74
UInt32_t last_extent_written
Definition: write.c:303
LOCAL int vol_desc_sum
Definition: write.c:78
LOCAL int dirtree_size(UInt32_t starting_extent)
Definition: write.c:2495
EXPORT int sort_directory(struct directory_entry **sort_dir, int rr)
Definition: write.c:814
LOCAL int pathtab_write(FILE *outfile)
Definition: write.c:2330
#define apple_hyb
LOCAL int interpad_write(FILE *outfile)
Definition: write.c:2556
LOCAL int total_dir_size
Definition: write.c:66
#define dvd_aud_vid_flag
EXPORT time_t begun
Definition: write.c:305
#define NSECT
Definition: write.c:59
LOCAL int file_gen()
Definition: write.c:2423
LOCAL int dirtree_dump()
Definition: write.c:2471
LOCAL int startpad_size(UInt32_t starting_extent)
Definition: write.c:2384
LOCAL int root_gen()
Definition: write.c:895
LOCAL void free_one_directory(struct directory *dpnt)
Definition: write.c:1477
struct output_fragment xvoldesc_desc
Definition: write.c:3023
struct output_fragment pathtable_desc
Definition: write.c:3026
LOCAL int is_rr_dir
Definition: write.c:72
EXPORT void xfwrite(void *buffer, int size, int count, FILE *file, int submode, BOOL islast)
Definition: write.c:168
LOCAL int rockridge_size
Definition: write.c:67
struct output_fragment dirtree_desc
Definition: write.c:3027
LOCAL BOOL assign_file_addresses(struct directory *dpnt, BOOL isnest)
Definition: write.c:1082
struct output_fragment version_desc
Definition: write.c:3025
EXPORT struct timeval tv_begun
Definition: write.c:306
LOCAL int dirtree_cleanup(FILE *outfile)
Definition: write.c:2528
LOCAL int exten_write(FILE *outfile)
Definition: write.c:2345
LOCAL int generate_path_tables()
Definition: write.c:1751
struct output_fragment dirtree_clean
Definition: write.c:3028
EXPORT int oneblock_size(UInt32_t starting_extent)
Definition: write.c:2357
LOCAL void free_directories(struct directory *dpnt)
Definition: write.c:1527
LOCAL int dirtree_fixup(UInt32_t starting_extent)
Definition: write.c:2480
LOCAL int pvd_write(FILE *outfile)
Definition: write.c:2034
void __cdecl qsort(_Inout_updates_bytes_(_NumOfElements *_SizeOfElements) void *_Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ int(__cdecl *_PtFuncCompare)(const void *, const void *))
EXPORT int seterrno(int err)
Definition: seterrno.c:34
CardRegion * from
Definition: spigame.cpp:19
#define EX_BAD
Definition: standard.h:62
unsigned int pad
Definition: mkisofs.h:303
unsigned int dw_flags
Definition: mkisofs.h:305
struct directory_entry * s_entry
Definition: mkisofs.h:302
off_t size
Definition: mkisofs.h:300
struct deferred_write * next
Definition: mkisofs.h:297
unsigned int extent
Definition: mkisofs.h:299
char * name
Definition: mkisofs.h:301
char * table
Definition: mkisofs.h:298
char * name
Definition: compiler.c:66
Definition: mkisofs.h:107
char * whole_name
Definition: mkisofs.h:118
struct directory_entry * mxroot
Definition: mkisofs.h:121
unsigned int starting_block
Definition: mkisofs.h:111
unsigned int rr_attr_size
Definition: mkisofs.h:135
unsigned char * rr_attributes
Definition: mkisofs.h:134
off_t size
Definition: mkisofs.h:112
int mxpart
Definition: mkisofs.h:113
struct directory_entry * next
Definition: mkisofs.h:108
char * name
Definition: mkisofs.h:116
unsigned int de_flags
Definition: mkisofs.h:122
struct iso_directory_record isorec
Definition: mkisofs.h:110
unsigned int total_rr_attr_size
Definition: mkisofs.h:136
struct directory * parent
Definition: mkisofs.h:269
char * de_name
Definition: mkisofs.h:275
unsigned short dir_flags
Definition: mkisofs.h:285
char * whole_name
Definition: mkisofs.h:273
unsigned int ce_bytes
Definition: mkisofs.h:276
unsigned int extent
Definition: mkisofs.h:280
unsigned int size
Definition: mkisofs.h:279
struct directory * subdir
Definition: mkisofs.h:268
struct directory * next
Definition: mkisofs.h:267
struct directory_entry * self
Definition: mkisofs.h:272
struct directory_entry * contents
Definition: mkisofs.h:270
unsigned int path_index
Definition: mkisofs.h:283
unsigned int starting_block
Definition: mkisofs.h:161
off_t size
Definition: mkisofs.h:162
Definition: fci.c:127
char type[ISODCL(1, 1)]
Definition: iso9660.h:65
char id[ISODCL(2, 6)]
Definition: iso9660.h:66
char version[ISODCL(7, 7)]
Definition: iso9660.h:67
char reserved[ISODCL(10, 14)]
Definition: iso9660.h:330
char signature[ISODCL(7, 8)]
Definition: iso9660.h:328
Definition: copy.c:22
Definition: mkisofs.h:331
int l_gmtoff
Definition: mkisofs.h:334
time_t l_sec
Definition: mkisofs.h:332
int l_usec
Definition: mkisofs.h:333
Definition: name.c:39
unsigned int of_start_extent
Definition: mkisofs.h:196
Uchar file_number
Definition: iso9660.h:358
Uchar coding
Definition: iso9660.h:361
Uchar channel_number
Definition: iso9660.h:359
Uchar sub_mode
Definition: iso9660.h:360
#define max(a, b)
Definition: svc.c:63
long Llong
Definition: stdint.h:152
Definition: dlist.c:348
unsigned int Uint
Definition: utypes.h:43
unsigned char Uchar
Definition: utypes.h:45
unsigned long Ulong
Definition: utypes.h:42
int ret
static FILE * outfile
Definition: wrjpgcom.c:81
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
#define PATH_SEPARATOR
Definition: xmllint.c:205
#define const
Definition: zconf.h:233