[MKISOFS]
[reactos.git] / reactos / sdk / tools / mkisofs / schilytools / mkisofs / joliet.c
1 /* @(#)joliet.c 1.68 15/12/30 joerg */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)joliet.c 1.68 15/12/30 joerg";
6 #endif
7 /*
8 * File joliet.c - handle Win95/WinNT long file/unicode extensions for iso9660.
9 *
10 * Copyright 1997 Eric Youngdale.
11 * APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 22/2/2000
12 * Copyright (c) 1999-2015 J. Schilling
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29 /*
30 * Joliet extensions for ISO9660. These are spottily documented by
31 * Microsoft. In their infinite stupidity, they completely ignored
32 * the possibility of using an SUSP record with the long filename
33 * in it, and instead wrote out a duplicate directory tree with the
34 * long filenames in it.
35 *
36 * I am not sure why they did this. One reason is that they get the path
37 * tables with the long filenames in them.
38 *
39 * There are two basic principles to Joliet, and the non-Unicode variant
40 * known as Romeo. Long filenames seem to be the main one, and the second
41 * is that the character set and a few other things is substantially relaxed.
42 *
43 * The SVD is identical to the PVD, except:
44 *
45 * Id is 2, not 1 (indicates SVD).
46 * escape_sequences contains UCS-2 indicator (levels 1, 2 or 3).
47 * The root directory record points to a different extent (with different
48 * size).
49 * There are different path tables for the two sets of directory trees.
50 *
51 * The Unicode level is coded in the SVD as follows:
52 *
53 * Standard Level ASCII escape code
54 * UCS-2 Level-1 %/@
55 * UCS-2 Level-2 %/C
56 * UCS-2 Level-3 %/E
57 *
58 * The following fields are recorded in Unicode:
59 * system_id
60 * volume_id
61 * volume_set_id
62 * publisher_id
63 * preparer_id
64 * application_id
65 * copyright_file_id
66 * abstract_file_id
67 * bibliographic_file_id
68 *
69 * Unicode strings are always encoded in big-endian format.
70 *
71 * In a directory record, everything is the same as with iso9660, except
72 * that the name is recorded in unicode. The name length is specified in
73 * total bytes, not in number of unicode characters.
74 *
75 * The character set used for the names is different with UCS - the
76 * restrictions are that the following are not allowed:
77 *
78 * Characters (00)(00) through (00)(1f) (control chars)
79 * (00)(2a) '*'
80 * (00)(2f) '/'
81 * (00)(3a) ':'
82 * (00)(3b) ';'
83 * (00)(3f) '?'
84 * (00)(5c) '\'
85 */
86 #include "mkisofs.h"
87 #include <schily/time.h>
88 #include <schily/utypes.h>
89 #include <schily/intcvt.h>
90 #include <schily/schily.h>
91 #include <schily/errno.h>
92
93 LOCAL Uint jpath_table_index;
94 LOCAL struct directory **jpathlist;
95 LOCAL int next_jpath_index = 1;
96 LOCAL int jsort_goof;
97 LOCAL int jsort_glen;
98
99 LOCAL char ucs_codes[] = {
100 '\0', /* UCS-level 0 is illegal */
101 '@', /* UCS-level 1 */
102 'C', /* UCS-level 2 */
103 'E', /* UCS-level 3 */
104 };
105
106 #ifdef UDF
107 EXPORT void convert_to_unicode __PR((unsigned char *buffer,
108 int size, char *source,
109 siconvt_t *inls));
110 EXPORT int joliet_strlen __PR((const char *string, size_t maxlen,
111 siconvt_t *inls));
112 #else
113 LOCAL void convert_to_unicode __PR((unsigned char *buffer,
114 int size, char *source,
115 siconvt_t *inls));
116 LOCAL int joliet_strlen __PR((const char *string, size_t maxlen,
117 siconvt_t *inls));
118 #endif
119 LOCAL void get_joliet_vol_desc __PR((struct iso_primary_descriptor *jvol_desc));
120 LOCAL void assign_joliet_directory_addresses __PR((struct directory *node));
121 LOCAL void build_jpathlist __PR((struct directory *node));
122 LOCAL int joliet_compare_paths __PR((void const *r, void const *l));
123 LOCAL int generate_joliet_path_tables __PR((void));
124 LOCAL void generate_one_joliet_directory __PR((struct directory *dpnt,
125 FILE *outfile));
126 LOCAL int joliet_sort_n_finish __PR((struct directory *this_dir));
127
128 LOCAL int joliet_compare_dirs __PR((const void *rr, const void *ll));
129
130 LOCAL int joliet_sort_directory __PR((struct directory_entry **sort_dir));
131 EXPORT int joliet_sort_tree __PR((struct directory *node));
132 LOCAL void generate_joliet_directories __PR((struct directory *node,
133 FILE *outfile));
134 LOCAL int jpathtab_write __PR((FILE *outfile));
135 LOCAL int jdirtree_size __PR((UInt32_t starting_extent));
136 LOCAL int jroot_gen __PR((void));
137 LOCAL int jdirtree_write __PR((FILE *outfile));
138 LOCAL int jvd_write __PR((FILE *outfile));
139 LOCAL int jpathtab_size __PR((UInt32_t starting_extent));
140
141 /*
142 * conv_charset: convert to/from charsets via Unicode.
143 *
144 * Any unknown character is set to '_'
145 *
146 */
147 EXPORT void
148 conv_charset(to, tosizep, from, fromsizep, inls, onls)
149 unsigned char *to;
150 size_t *tosizep;
151 unsigned char *from;
152 size_t *fromsizep;
153 siconvt_t *inls;
154 siconvt_t *onls;
155 {
156 UInt16_t unichar;
157 size_t fromsize = *fromsizep;
158 size_t tosize = *tosizep;
159 Uchar ob[2]; /* 2 octets (16 Bit) UCS-2 */
160
161 if (fromsize == 0 || tosize == 0)
162 return;
163
164 /*
165 * If we have a null mapping, just return the input character
166 */
167 if (inls->sic_name == onls->sic_name) {
168 *to = *from;
169 (*fromsizep)--;
170 (*tosizep)--;
171 return;
172 }
173 #ifdef USE_ICONV
174 #ifdef HAVE_ICONV_CONST
175 #define __IC_CONST const
176 #else
177 #define __IC_CONST
178 #endif
179 if (use_iconv(inls)) {
180 char *obuf = (char *)ob;
181 size_t osize = 2; /* UCS-2 character size */
182
183 if (iconv(inls->sic_cd2uni, (__IC_CONST char **)&from,
184 fromsizep,
185 &obuf, &osize) == -1) {
186 int err = geterrno();
187
188 if ((err == EINVAL || err == EILSEQ) &&
189 *fromsizep == fromsize) {
190 ob[0] = 0; ob[1] = '_';
191 (*fromsizep)--;
192 }
193 }
194 unichar = ob[0] * 256 + ob[1]; /* Compute 16 Bit UCS-2 char */
195 } else
196 #endif
197 {
198 unsigned char c = *from;
199
200 unichar = sic_c2uni(inls, c); /* Get the UNICODE char */
201 (*fromsizep)--;
202
203 if (unichar == 0)
204 unichar = '_';
205
206 ob[0] = unichar >> 8 & 0xFF; /* Compute 2 octet variant */
207 ob[1] = unichar & 0xFF;
208 }
209
210 #ifdef USE_ICONV
211 if (use_iconv(onls)) {
212 char *ibuf = (char *)ob;
213 size_t isize = 2; /* UCS-2 character size */
214
215 if (iconv(onls->sic_uni2cd, (__IC_CONST char **)&ibuf, &isize,
216 (char **)&to, tosizep) == -1) {
217 int err = geterrno();
218
219 if ((err == EINVAL || err == EILSEQ) &&
220 *tosizep == tosize) {
221 *to = '_';
222 (*tosizep)--;
223 }
224 }
225 } else
226 #endif
227 {
228 *to = sic_uni2c(onls, unichar); /* Get the backconverted char */
229 (*tosizep)--;
230 }
231 }
232
233
234 /*
235 * Function: convert_to_unicode
236 *
237 * Purpose: Perform a unicode conversion on a text string
238 * using the supplied input character set.
239 *
240 * Notes:
241 */
242 #ifdef UDF
243 EXPORT void
244 #else
245 LOCAL void
246 #endif
247 convert_to_unicode(buffer, size, source, inls)
248 unsigned char *buffer;
249 int size;
250 char *source;
251 siconvt_t *inls;
252 {
253 unsigned char *tmpbuf;
254 int i;
255 int j;
256 UInt16_t unichar;
257 unsigned char uc;
258 int jsize = size;
259
260 /*
261 * If we get a NULL pointer for the source, it means we have an
262 * inplace copy, and we need to make a temporary working copy first.
263 */
264 if (source == NULL) {
265 tmpbuf = (Uchar *) e_malloc(size);
266 memcpy(tmpbuf, buffer, size);
267 } else {
268 tmpbuf = (Uchar *) source;
269 }
270
271 /*
272 * Now start copying characters. If the size was specified to be 0,
273 * then assume the input was 0 terminated.
274 */
275 j = 0;
276 for (i = 0; (i + 1) < size; i += 2, j++) { /* Size may be odd! */
277 /*
278 * Let all valid unicode characters pass
279 * through (according to charset). Others are set to '_' .
280 */
281 if (j < jsize)
282 uc = tmpbuf[j]; /* temporary copy */
283 else
284 uc = '\0';
285 if (uc == '\0') {
286 jsize = j;
287 unichar = 0;
288 } else { /* must be converted */
289 #ifdef USE_ICONV
290 if (use_iconv(inls)) {
291 Uchar ob[2];
292 __IC_CONST char *inbuf = (char *)&tmpbuf[j];
293 size_t isize = 3;
294 char *obuf = (char *)ob;
295 size_t osize = 2;
296
297 /*
298 * iconv() from glibc ignores osize and thus
299 * may try to access more than a single multi
300 * byte character from the input and read from
301 * non-existent memory.
302 */
303 if (iconv(inls->sic_cd2uni, &inbuf, &isize,
304 &obuf, &osize) == -1) {
305 int err = geterrno();
306
307 if ((err == EINVAL || err == EILSEQ) &&
308 isize == 3) {
309 ob[0] = ob[1] = 0;
310 isize--;
311 }
312 }
313 unichar = ob[0] * 256 + ob[1];
314 j += 2 - isize;
315 } else
316 #endif
317 unichar = sic_c2uni(inls, uc); /* Get the UNICODE */
318
319 /*
320 * This code is currently also used for UDF formatting.
321 * Do not enforce silly Microsoft limitations in case
322 * that we only create UDF extensions.
323 */
324 if (!use_Joliet)
325 goto all_chars;
326
327 if (unichar <= 0x1f || unichar == 0x7f)
328 unichar = '\0'; /* control char */
329
330 switch (unichar) { /* test special characters */
331
332 case '*':
333 case '/':
334 case ':':
335 case ';':
336 case '?':
337 case '\\':
338 case '\0': /* illegal char mark */
339 /*
340 * Even Joliet has some standards as to what is
341 * allowed in a pathname. Pretty tame in
342 * comparison to what DOS restricts you to.
343 */
344 unichar = '_';
345 }
346 all_chars:
347 ;
348 }
349 buffer[i] = unichar >> 8 & 0xFF; /* final UNICODE */
350 buffer[i + 1] = unichar & 0xFF; /* conversion */
351 }
352
353 if (size & 1) { /* beautification */
354 buffer[size - 1] = 0;
355 }
356 if (source == NULL) {
357 free(tmpbuf);
358 }
359 }
360
361 /*
362 * Function: joliet_strlen
363 *
364 * Purpose: Return length in bytes of string after conversion to unicode.
365 *
366 * Notes: This is provided mainly as a convenience so that when more
367 * intelligent Unicode conversion for either Multibyte or 8-bit
368 * codes is available that we can easily adapt.
369 */
370 #ifdef UDF
371 EXPORT int
372 #else
373 LOCAL int
374 #endif
375 joliet_strlen(string, maxlen, inls)
376 const char *string;
377 size_t maxlen;
378 siconvt_t *inls;
379 {
380 int rtn = 0;
381
382 #ifdef USE_ICONV
383 if (use_iconv(inls)) {
384 int j = 0;
385
386 while (string[j] != '\0') {
387 Uchar ob[2];
388 __IC_CONST char *inbuf = (char *)&string[j];
389 size_t isize = 3;
390 char *obuf = (char *)ob;
391 size_t osize = 2;
392
393 /*
394 * iconv() from glibc ignores osize and thus
395 * may try to access more than a single multi
396 * byte character from the input and read from
397 * non-existent memory.
398 */
399 if (iconv(inls->sic_cd2uni, &inbuf, &isize,
400 &obuf, &osize) == -1) {
401 int err = geterrno();
402
403 if ((err == EINVAL || err == EILSEQ) &&
404 isize == 3) {
405 ob[0] = ob[1] = 0;
406 isize--;
407 }
408 }
409 j += 3 - isize;
410 rtn += 2;
411 }
412 } else
413 #endif
414 rtn = strlen(string) << 1;
415
416 /*
417 * We do clamp the maximum length of a Joliet or UDF string to be the
418 * maximum path size.
419 */
420 if (rtn > 2*maxlen) {
421 rtn = 2*maxlen;
422 }
423 return (rtn);
424 }
425
426 /*
427 * Function: get_joliet_vol_desc
428 *
429 * Purpose: generate a Joliet compatible volume desc.
430 *
431 * Notes: Assume that we have the non-joliet vol desc
432 * already present in the buffer. Just modifiy the
433 * appropriate fields.
434 */
435 LOCAL void
436 get_joliet_vol_desc(jvol_desc)
437 struct iso_primary_descriptor *jvol_desc;
438 {
439 jvol_desc->type[0] = ISO_VD_SUPPLEMENTARY;
440 jvol_desc->version[0] = 1;
441 jvol_desc->file_structure_version[0] = 1;
442 /*
443 * For now, always do Unicode level 3.
444 * I don't really know what 1 and 2 are - perhaps a more limited
445 * Unicode set.
446 * FIXME(eric) - how does Romeo fit in here?
447 */
448 sprintf(jvol_desc->escape_sequences, "%%/%c", ucs_codes[ucs_level]);
449
450 /* Until we have Unicode path tables, leave these unset. */
451 set_733((char *)jvol_desc->path_table_size, jpath_table_size);
452 set_731(jvol_desc->type_l_path_table, jpath_table[0]);
453 set_731(jvol_desc->opt_type_l_path_table, jpath_table[1]);
454 set_732(jvol_desc->type_m_path_table, jpath_table[2]);
455 set_732(jvol_desc->opt_type_m_path_table, jpath_table[3]);
456
457 /* Set this one up. */
458 memcpy(jvol_desc->root_directory_record, &jroot_record,
459 offsetof(struct iso_directory_record, name[0]) + 1);
460
461 /*
462 * Finally, we have a bunch of strings to convert to Unicode.
463 * FIXME(eric) - I don't know how to do this in general,
464 * so we will just be really lazy and do a char -> short conversion.
465 * We probably will want to filter any characters >= 0x80.
466 */
467 convert_to_unicode((Uchar *)jvol_desc->system_id,
468 sizeof (jvol_desc->system_id), NULL, in_nls);
469 convert_to_unicode((Uchar *)jvol_desc->volume_id,
470 sizeof (jvol_desc->volume_id), NULL, in_nls);
471 convert_to_unicode((Uchar *)jvol_desc->volume_set_id,
472 sizeof (jvol_desc->volume_set_id), NULL, in_nls);
473 convert_to_unicode((Uchar *)jvol_desc->publisher_id,
474 sizeof (jvol_desc->publisher_id), NULL, in_nls);
475 convert_to_unicode((Uchar *)jvol_desc->preparer_id,
476 sizeof (jvol_desc->preparer_id), NULL, in_nls);
477 convert_to_unicode((Uchar *)jvol_desc->application_id,
478 sizeof (jvol_desc->application_id), NULL, in_nls);
479 convert_to_unicode((Uchar *)jvol_desc->copyright_file_id,
480 sizeof (jvol_desc->copyright_file_id), NULL, in_nls);
481 convert_to_unicode((Uchar *)jvol_desc->abstract_file_id,
482 sizeof (jvol_desc->abstract_file_id), NULL, in_nls);
483 convert_to_unicode((Uchar *)jvol_desc->bibliographic_file_id,
484 sizeof (jvol_desc->bibliographic_file_id), NULL, in_nls);
485 }
486
487 /*
488 * Asssign Joliet & UDF addresses
489 * We ignore all files that are neither in the Joliet nor in the UDF tree
490 */
491 LOCAL void
492 assign_joliet_directory_addresses(node)
493 struct directory *node;
494 {
495 int dir_size;
496 struct directory *dpnt;
497
498 dpnt = node;
499
500 while (dpnt) {
501 if ((dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0) {
502 /*
503 * If we already have an extent for this
504 * (i.e. it came from a multisession disc), then
505 * don't reassign a new extent.
506 */
507 dpnt->jpath_index = next_jpath_index++;
508 if (dpnt->jextent == 0) {
509 dpnt->jextent = last_extent;
510 dir_size = ISO_BLOCKS(dpnt->jsize);
511 last_extent += dir_size;
512 }
513 }
514 /* skip if hidden - but not for the rr_moved dir */
515 if (dpnt->subdir &&
516 ((dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 ||
517 dpnt == reloc_dir)) {
518 assign_joliet_directory_addresses(dpnt->subdir);
519 }
520 dpnt = dpnt->next;
521 }
522 }
523
524 LOCAL void
525 build_jpathlist(node)
526 struct directory *node;
527 {
528 struct directory *dpnt;
529
530 dpnt = node;
531
532 while (dpnt) {
533 if ((dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0) {
534 jpathlist[dpnt->jpath_index] = dpnt;
535 }
536 if (dpnt->subdir)
537 build_jpathlist(dpnt->subdir);
538 dpnt = dpnt->next;
539 }
540 } /* build_jpathlist(... */
541
542 LOCAL int
543 joliet_compare_paths(r, l)
544 void const *r;
545 void const *l;
546 {
547 struct directory const *ll = *(struct directory * const *) l;
548 struct directory const *rr = *(struct directory * const *) r;
549 int rparent,
550 lparent;
551 char *rpnt,
552 *lpnt;
553 unsigned char rtmp[2],
554 ltmp[2];
555 siconvt_t *rinls, *linls;
556
557 /* make sure root directory is first */
558 if (rr == root)
559 return (-1);
560
561 if (ll == root)
562 return (1);
563
564 rparent = rr->parent->jpath_index;
565 lparent = ll->parent->jpath_index;
566 if (rr->parent == reloc_dir) {
567 rparent = rr->self->parent_rec->filedir->jpath_index;
568 }
569 if (ll->parent == reloc_dir) {
570 lparent = ll->self->parent_rec->filedir->jpath_index;
571 }
572 if (rparent < lparent) {
573 return (-1);
574 }
575 if (rparent > lparent) {
576 return (1);
577 }
578 #ifdef APPLE_HYB
579 /*
580 * we may be using the HFS name - so select the correct input
581 * charset
582 */
583 if (USE_MAC_NAME(rr->self)) {
584 rpnt = rr->self->hfs_ent->name;
585 rinls = hfs_inls;
586 } else {
587 rpnt = rr->self->name;
588 rinls = in_nls;
589 }
590
591 if (USE_MAC_NAME(ll->self)) {
592 lpnt = ll->self->hfs_ent->name;
593 linls = hfs_inls;
594 } else {
595 lpnt = ll->self->name;
596 linls = in_nls;
597 }
598 #else
599 rpnt = rr->self->name;
600 lpnt = ll->self->name;
601 linls = rinls = in_nls;
602 #endif /* APPLE_HYB */
603
604 /* compare the Unicode names */
605
606 while (*rpnt && *lpnt) {
607 convert_to_unicode(rtmp, 2, rpnt, rinls);
608 convert_to_unicode(ltmp, 2, lpnt, linls);
609
610 if (a_to_u_2_byte(rtmp) < a_to_u_2_byte(ltmp))
611 return (-1);
612 if (a_to_u_2_byte(rtmp) > a_to_u_2_byte(ltmp))
613 return (1);
614
615 rpnt++;
616 lpnt++;
617 }
618
619 if (*rpnt)
620 return (1);
621 if (*lpnt)
622 return (-1);
623
624 return (0);
625
626 } /* compare_paths(... */
627
628 LOCAL int
629 generate_joliet_path_tables()
630 {
631 struct directory_entry *de;
632 struct directory *dpnt;
633 int fix;
634 int j;
635 int namelen;
636 char *npnt;
637 char *npnt1;
638 int tablesize;
639 unsigned int jpindex;
640
641 /* First allocate memory for the tables and initialize the memory */
642 tablesize = jpath_blocks << 11;
643 jpath_table_m = (char *)e_malloc(tablesize);
644 jpath_table_l = (char *)e_malloc(tablesize);
645 memset(jpath_table_l, 0, tablesize);
646 memset(jpath_table_m, 0, tablesize);
647
648 /* Now start filling in the path tables. Start with root directory */
649 jpath_table_index = 0;
650 jpathlist = (struct directory **)e_malloc(sizeof (struct directory *)
651 * next_jpath_index);
652 memset(jpathlist, 0, sizeof (struct directory *) * next_jpath_index);
653 build_jpathlist(root);
654
655 do {
656 fix = 0;
657 #ifdef PROTOTYPES
658 qsort(&jpathlist[1], next_jpath_index - 1, sizeof (struct directory *),
659 (int (*) (const void *, const void *)) joliet_compare_paths);
660 #else
661 qsort(&jpathlist[1], next_jpath_index - 1, sizeof (struct directory *),
662 joliet_compare_paths);
663 #endif
664
665 for (j = 1; j < next_jpath_index; j++) {
666 if (jpathlist[j]->jpath_index != j) {
667 jpathlist[j]->jpath_index = j;
668 fix++;
669 }
670 }
671 } while (fix);
672
673 for (j = 1; j < next_jpath_index; j++) {
674 dpnt = jpathlist[j];
675 if (!dpnt) {
676 comerrno(EX_BAD, _("Entry %d not in path tables\n"), j);
677 }
678 npnt = dpnt->de_name;
679
680 npnt1 = strrchr(npnt, PATH_SEPARATOR);
681 if (npnt1) {
682 npnt = npnt1 + 1;
683 }
684 de = dpnt->self;
685 if (!de) {
686 comerrno(EX_BAD,
687 _("Fatal Joliet goof - directory has amnesia\n"));
688 }
689 #ifdef APPLE_HYB
690 if (USE_MAC_NAME(de))
691 namelen = joliet_strlen(de->hfs_ent->name, jlen, hfs_inls);
692 else
693 #endif /* APPLE_HYB */
694 namelen = joliet_strlen(de->name, jlen, in_nls);
695
696 if (dpnt == root) {
697 jpath_table_l[jpath_table_index] = 1;
698 jpath_table_m[jpath_table_index] = 1;
699 } else {
700 jpath_table_l[jpath_table_index] = namelen;
701 jpath_table_m[jpath_table_index] = namelen;
702 }
703 jpath_table_index += 2;
704
705 set_731(jpath_table_l + jpath_table_index, dpnt->jextent);
706 set_732(jpath_table_m + jpath_table_index, dpnt->jextent);
707 jpath_table_index += 4;
708
709
710 if (dpnt->parent != reloc_dir) {
711 set_721(jpath_table_l + jpath_table_index,
712 dpnt->parent->jpath_index);
713 set_722(jpath_table_m + jpath_table_index,
714 dpnt->parent->jpath_index);
715 jpindex = dpnt->parent->jpath_index;
716 } else {
717 set_721(jpath_table_l + jpath_table_index,
718 dpnt->self->parent_rec->filedir->jpath_index);
719 set_722(jpath_table_m + jpath_table_index,
720 dpnt->self->parent_rec->filedir->jpath_index);
721 jpindex = dpnt->self->parent_rec->filedir->jpath_index;
722 }
723
724 if (jpindex > 0xffff) {
725 static int warned = 0;
726
727 if (!warned) {
728 warned++;
729 errmsgno(EX_BAD,
730 _("Unable to generate sane Joliet path tables - too many directories (%u)\n"),
731 jpindex);
732 if (!nolimitpathtables)
733 errmsgno(EX_BAD,
734 _("Try to use the option -no-limit-pathtables\n"));
735 }
736 if (!nolimitpathtables)
737 exit(EX_BAD);
738 /*
739 * Let it point to the root directory instead.
740 */
741 set_721(jpath_table_l + jpath_table_index, 1);
742 set_722(jpath_table_m + jpath_table_index, 1);
743 }
744
745 jpath_table_index += 2;
746
747 /*
748 * The root directory is still represented in non-unicode
749 * fashion.
750 */
751 if (dpnt == root) {
752 jpath_table_l[jpath_table_index] = 0;
753 jpath_table_m[jpath_table_index] = 0;
754 jpath_table_index++;
755 } else {
756 #ifdef APPLE_HYB
757 if (USE_MAC_NAME(de)) {
758 convert_to_unicode((Uchar *) jpath_table_l +
759 jpath_table_index,
760 namelen, de->hfs_ent->name, hfs_inls);
761 convert_to_unicode((Uchar *) jpath_table_m +
762 jpath_table_index,
763 namelen, de->hfs_ent->name, hfs_inls);
764 } else {
765 #endif /* APPLE_HYB */
766 convert_to_unicode((Uchar *) jpath_table_l +
767 jpath_table_index,
768 namelen, de->name, in_nls);
769 convert_to_unicode((Uchar *) jpath_table_m +
770 jpath_table_index,
771 namelen, de->name, in_nls);
772 #ifdef APPLE_HYB
773 }
774 #endif /* APPLE_HYB */
775
776 jpath_table_index += namelen;
777 }
778
779 if (jpath_table_index & 1) {
780 jpath_table_index++; /* For odd lengths we pad */
781 }
782 }
783
784 free(jpathlist);
785 if (jpath_table_index != jpath_table_size) {
786 errmsgno(EX_BAD,
787 _("Joliet path table lengths do not match %d expected: %d\n"),
788 jpath_table_index,
789 jpath_table_size);
790 }
791 return (0);
792 } /* generate_path_tables(... */
793
794 LOCAL void
795 generate_one_joliet_directory(dpnt, outfile)
796 struct directory *dpnt;
797 FILE *outfile;
798 {
799 unsigned int dir_index;
800 char *directory_buffer;
801 int new_reclen;
802 struct directory_entry *s_entry;
803 struct directory_entry *s_entry1;
804 struct iso_directory_record jrec;
805 unsigned int total_size;
806 int cvt_len;
807 struct directory *finddir;
808
809 total_size = ISO_ROUND_UP(dpnt->jsize);
810 directory_buffer = (char *)e_malloc(total_size);
811 memset(directory_buffer, 0, total_size);
812 dir_index = 0;
813
814 s_entry = dpnt->jcontents;
815 while (s_entry) {
816 if (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) {
817 s_entry = s_entry->jnext;
818 continue;
819 }
820 /*
821 * If this entry was a directory that was relocated,
822 * we have a bit of trouble here. We need to dig out the real
823 * thing and put it back here. In the Joliet tree, there is
824 * no relocated rock ridge, as there are no depth limits to a
825 * directory tree.
826 */
827 if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) {
828 for (s_entry1 = reloc_dir->contents; s_entry1;
829 s_entry1 = s_entry1->next) {
830 if (s_entry1->parent_rec == s_entry) {
831 break;
832 }
833 }
834 if (s_entry1 == NULL) {
835 /* We got trouble. */
836 comerrno(EX_BAD,
837 _("Unable to locate relocated directory\n"));
838 }
839 } else {
840 s_entry1 = s_entry;
841 }
842
843 /*
844 * We do not allow directory entries to cross sector
845 * boundaries. Simply pad, and then start the next entry at
846 * the next sector
847 */
848 new_reclen = s_entry1->jreclen;
849 if ((dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE) {
850 dir_index = ISO_ROUND_UP(dir_index);
851 }
852 memcpy(&jrec, &s_entry1->isorec, offsetof(struct iso_directory_record, name[0]));
853
854 #ifdef APPLE_HYB
855 /* Use the HFS name if it exists */
856 if (USE_MAC_NAME(s_entry1))
857 cvt_len = joliet_strlen(s_entry1->hfs_ent->name, jlen, hfs_inls);
858 else
859 #endif /* APPLE_HYB */
860 cvt_len = joliet_strlen(s_entry1->name, jlen, in_nls);
861
862 /*
863 * Fix the record length
864 * - this was the non-Joliet version we were seeing.
865 */
866 jrec.name_len[0] = cvt_len;
867 jrec.length[0] = s_entry1->jreclen;
868
869 /*
870 * If this is a directory,
871 * fix the correct size and extent number.
872 */
873 if ((jrec.flags[0] & ISO_DIRECTORY) != 0) {
874 if (strcmp(s_entry1->name, ".") == 0) {
875 jrec.name_len[0] = 1;
876 set_733((char *)jrec.extent, dpnt->jextent);
877 set_733((char *)jrec.size, ISO_ROUND_UP(dpnt->jsize));
878 } else if (strcmp(s_entry1->name, "..") == 0) {
879 jrec.name_len[0] = 1;
880 if (dpnt->parent == reloc_dir) {
881 set_733((char *)jrec.extent, dpnt->self->parent_rec->filedir->jextent);
882 set_733((char *)jrec.size, ISO_ROUND_UP(dpnt->self->parent_rec->filedir->jsize));
883 } else {
884 set_733((char *)jrec.extent, dpnt->parent->jextent);
885 set_733((char *)jrec.size, ISO_ROUND_UP(dpnt->parent->jsize));
886 }
887 } else {
888 if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) {
889 finddir = reloc_dir->subdir;
890 } else {
891 finddir = dpnt->subdir;
892 }
893 while (finddir && finddir->self != s_entry1) {
894 finddir = finddir->next;
895 }
896 if (!finddir) {
897 comerrno(EX_BAD,
898 _("Fatal goof - unable to find directory location\n"));
899 }
900 set_733((char *)jrec.extent, finddir->jextent);
901 set_733((char *)jrec.size,
902 ISO_ROUND_UP(finddir->jsize));
903 }
904 }
905 memcpy(directory_buffer + dir_index, &jrec,
906 offsetof(struct iso_directory_record, name[0]));
907
908 dir_index += offsetof(struct iso_directory_record, name[0]);
909
910 /*
911 * Finally dump the Unicode version of the filename.
912 * Note - . and .. are the same as with non-Joliet discs.
913 */
914 if ((jrec.flags[0] & ISO_DIRECTORY) != 0 &&
915 strcmp(s_entry1->name, ".") == 0) {
916 directory_buffer[dir_index++] = 0;
917 } else if ((jrec.flags[0] & ISO_DIRECTORY) != 0 &&
918 strcmp(s_entry1->name, "..") == 0) {
919 directory_buffer[dir_index++] = 1;
920 } else {
921 #ifdef APPLE_HYB
922 if (USE_MAC_NAME(s_entry1)) {
923 /* Use the HFS name if it exists */
924 convert_to_unicode(
925 (Uchar *) directory_buffer+dir_index,
926 cvt_len,
927 s_entry1->hfs_ent->name, hfs_inls);
928 } else
929 #endif /* APPLE_HYB */
930 {
931 convert_to_unicode(
932 (Uchar *) directory_buffer+dir_index,
933 cvt_len,
934 s_entry1->name, in_nls);
935 }
936 dir_index += cvt_len;
937 }
938
939 if (dir_index & 1) {
940 directory_buffer[dir_index++] = 0;
941 }
942 s_entry = s_entry->jnext;
943 }
944
945 if (dpnt->jsize != dir_index) {
946 errmsgno(EX_BAD,
947 _("Unexpected joliet directory length %d expected: %d '%s'\n"),
948 dpnt->jsize,
949 dir_index, dpnt->de_name);
950 }
951 xfwrite(directory_buffer, total_size, 1, outfile, 0, FALSE);
952 last_extent_written += total_size >> 11;
953 free(directory_buffer);
954 } /* generate_one_joliet_directory(... */
955
956 LOCAL int
957 joliet_sort_n_finish(this_dir)
958 struct directory *this_dir;
959 {
960 struct directory_entry *s_entry;
961 int status = 0;
962
963 /*
964 * don't want to skip this directory if it's the reloc_dir
965 * at the moment
966 */
967 if (this_dir != reloc_dir &&
968 this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) {
969 return (0);
970 }
971 for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
972 /* skip hidden entries */
973 if ((s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0) {
974 continue;
975 }
976 /*
977 * First update the path table sizes for directories.
978 *
979 * Finally, set the length of the directory entry if Joliet is
980 * used. The name is longer, but no Rock Ridge is ever used
981 * here, so depending upon the options the entry size might
982 * turn out to be about the same. The Unicode name is always
983 * a multiple of 2 bytes, so we always add 1 to make it an
984 * even number.
985 */
986 if (s_entry->isorec.flags[0] & ISO_DIRECTORY) {
987 if (strcmp(s_entry->name, ".") != 0 &&
988 strcmp(s_entry->name, "..") != 0) {
989 #ifdef APPLE_HYB
990 if (USE_MAC_NAME(s_entry))
991 /* Use the HFS name if it exists */
992 jpath_table_size +=
993 joliet_strlen(s_entry->hfs_ent->name, jlen, hfs_inls) +
994 offsetof(struct iso_path_table, name[0]);
995 else
996 #endif /* APPLE_HYB */
997 jpath_table_size +=
998 joliet_strlen(s_entry->name, jlen, in_nls) +
999 offsetof(struct iso_path_table, name[0]);
1000 if (jpath_table_size & 1) {
1001 jpath_table_size++;
1002 }
1003 } else {
1004 if (this_dir == root &&
1005 strlen(s_entry->name) == 1) {
1006
1007 jpath_table_size += 1 + offsetof(struct iso_path_table, name[0]);
1008 if (jpath_table_size & 1)
1009 jpath_table_size++;
1010 }
1011 }
1012 }
1013 if (strcmp(s_entry->name, ".") != 0 &&
1014 strcmp(s_entry->name, "..") != 0) {
1015 #ifdef APPLE_HYB
1016 if (USE_MAC_NAME(s_entry))
1017 /* Use the HFS name if it exists */
1018 s_entry->jreclen =
1019 offsetof(struct iso_directory_record, name[0])
1020 + joliet_strlen(s_entry->hfs_ent->name, jlen, hfs_inls)
1021 + 1;
1022 else
1023 #endif /* APPLE_HYB */
1024 s_entry->jreclen =
1025 offsetof(struct iso_directory_record, name[0])
1026 + joliet_strlen(s_entry->name, jlen, in_nls)
1027 + 1;
1028 } else {
1029 /*
1030 * Special - for '.' and '..' we generate the same
1031 * records we did for non-Joliet discs.
1032 */
1033 s_entry->jreclen =
1034 offsetof(struct iso_directory_record, name[0])
1035 + 1;
1036 }
1037
1038
1039 }
1040
1041 if ((this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) != 0) {
1042 return (0);
1043 }
1044 this_dir->jcontents = this_dir->contents;
1045 status = joliet_sort_directory(&this_dir->jcontents);
1046
1047 /*
1048 * Now go through the directory and figure out how large this one will
1049 * be. Do not split a directory entry across a sector boundary
1050 */
1051 s_entry = this_dir->jcontents;
1052 /*
1053 * XXX Is it ok to comment this out?
1054 */
1055 /*XXX JS this_dir->ce_bytes = 0;*/
1056 for (s_entry = this_dir->jcontents; s_entry;
1057 s_entry = s_entry->jnext) {
1058 int jreclen;
1059
1060 if ((s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0) {
1061 continue;
1062 }
1063 jreclen = s_entry->jreclen;
1064
1065 if ((this_dir->jsize & (SECTOR_SIZE - 1)) + jreclen >=
1066 SECTOR_SIZE) {
1067 this_dir->jsize = ISO_ROUND_UP(this_dir->jsize);
1068 }
1069 this_dir->jsize += jreclen;
1070 }
1071 return (status);
1072 }
1073
1074 /*
1075 * Similar to the iso9660 case,
1076 * except here we perform a full sort based upon the
1077 * regular name of the file, not the 8.3 version.
1078 */
1079 LOCAL int
1080 joliet_compare_dirs(rr, ll)
1081 const void *rr;
1082 const void *ll;
1083 {
1084 char *rpnt,
1085 *lpnt;
1086 struct directory_entry **r,
1087 **l;
1088 unsigned char rtmp[2],
1089 ltmp[2];
1090 siconvt_t *linls, *rinls;
1091
1092 r = (struct directory_entry **)rr;
1093 l = (struct directory_entry **)ll;
1094
1095 #ifdef APPLE_HYB
1096 /*
1097 * we may be using the HFS name - so select the correct input
1098 * charset
1099 */
1100 if (USE_MAC_NAME(*r)) {
1101 rpnt = (*r)->hfs_ent->name;
1102 rinls = hfs_inls;
1103 } else {
1104 rpnt = (*r)->name;
1105 rinls = in_nls;
1106 }
1107
1108 if (USE_MAC_NAME(*l)) {
1109 lpnt = (*l)->hfs_ent->name;
1110 linls = hfs_inls;
1111 } else {
1112 lpnt = (*l)->name;
1113 linls = in_nls;
1114 }
1115 #else
1116 rpnt = (*r)->name;
1117 lpnt = (*l)->name;
1118 rinls = linls = in_nls;
1119 #endif /* APPLE_HYB */
1120
1121 /*
1122 * If the entries are the same, this is an error.
1123 * Joliet specs allow for a maximum of 64 characters.
1124 * If we see different multi extent parts, it is OK to
1125 * have the same name more than once.
1126 */
1127 if (strncmp(rpnt, lpnt, jlen) == 0) {
1128 #ifdef USE_LARGEFILES
1129 if ((*r)->mxpart == (*l)->mxpart)
1130 #endif
1131 {
1132 errmsgno(EX_BAD,
1133 _("Error: %s and %s have the same Joliet name\n"),
1134 (*r)->whole_name, (*l)->whole_name);
1135 jsort_goof++;
1136 {
1137 char *p1 = rpnt;
1138 char *p2 = lpnt;
1139 int len = 0;
1140
1141 for (; *p1 == *p2; p1++, p2++, len++) {
1142 if (*p1 == '\0')
1143 break;
1144 }
1145 if (len > jsort_glen)
1146 jsort_glen = len;
1147 }
1148 }
1149 }
1150 /*
1151 * Put the '.' and '..' entries on the head of the sorted list.
1152 * For normal ASCII, this always happens to be the case, but out of
1153 * band characters cause this not to be the case sometimes.
1154 */
1155 if (strcmp(rpnt, ".") == 0)
1156 return (-1);
1157 if (strcmp(lpnt, ".") == 0)
1158 return (1);
1159
1160 if (strcmp(rpnt, "..") == 0)
1161 return (-1);
1162 if (strcmp(lpnt, "..") == 0)
1163 return (1);
1164
1165 #ifdef DVD_AUD_VID
1166 /*
1167 * There're rumors claiming that some players assume VIDEO_TS.IFO
1168 * to be the first file in VIDEO_TS/ catalog. Well, it's basically
1169 * the only file a player has to actually look for, as the whole
1170 * video content can be "rolled down" from this file alone.
1171 * <appro@fy.chalmers.se>
1172 */
1173 /*
1174 * XXX This code has to be moved from the Joliet implementation
1175 * XXX to the UDF implementation if we implement decent UDF support
1176 * XXX with a separate name space for the UDF file tree.
1177 */
1178 if (dvd_aud_vid_flag & DVD_SPEC_VIDEO) {
1179 if (strcmp(rpnt, "VIDEO_TS.IFO") == 0)
1180 return (-1);
1181 if (strcmp(lpnt, "VIDEO_TS.IFO") == 0)
1182 return (1);
1183 }
1184 #endif
1185
1186 while (*rpnt && *lpnt) {
1187 if (*rpnt == ';' && *lpnt != ';')
1188 return (-1);
1189 if (*rpnt != ';' && *lpnt == ';')
1190 return (1);
1191
1192 if (*rpnt == ';' && *lpnt == ';')
1193 return (0);
1194
1195 /*
1196 * Extensions are not special here.
1197 * Don't treat the dot as something that must be bumped to
1198 * the start of the list.
1199 */
1200 #if 0
1201 if (*rpnt == '.' && *lpnt != '.')
1202 return (-1);
1203 if (*rpnt != '.' && *lpnt == '.')
1204 return (1);
1205 #endif
1206
1207 convert_to_unicode(rtmp, 2, rpnt, rinls);
1208 convert_to_unicode(ltmp, 2, lpnt, linls);
1209
1210 if (a_to_u_2_byte(rtmp) < a_to_u_2_byte(ltmp))
1211 return (-1);
1212 if (a_to_u_2_byte(rtmp) > a_to_u_2_byte(ltmp))
1213 return (1);
1214
1215 rpnt++;
1216 lpnt++;
1217 }
1218 if (*rpnt)
1219 return (1);
1220 if (*lpnt)
1221 return (-1);
1222 #ifdef USE_LARGEFILES
1223 /*
1224 * (*r)->mxpart == (*l)->mxpart cannot happen here
1225 */
1226 if ((*r)->mxpart < (*l)->mxpart)
1227 return (-1);
1228 else if ((*r)->mxpart > (*l)->mxpart)
1229 return (1);
1230 #endif
1231 return (0);
1232 }
1233
1234
1235 /*
1236 * Function: sort_directory
1237 *
1238 * Purpose: Sort the directory in the appropriate ISO9660
1239 * order.
1240 *
1241 * Notes: Returns 0 if OK, returns > 0 if an error occurred.
1242 */
1243 LOCAL int
1244 joliet_sort_directory(sort_dir)
1245 struct directory_entry **sort_dir;
1246 {
1247 int dcount = 0;
1248 int i;
1249 struct directory_entry *s_entry;
1250 struct directory_entry **sortlist;
1251
1252 s_entry = *sort_dir;
1253 while (s_entry) {
1254 /*
1255 * only colletc non-hidden entries
1256 */
1257 if ((s_entry->de_flags & (INHIBIT_JOLIET_ENTRY|INHIBIT_UDF_ENTRY)) !=
1258 (INHIBIT_JOLIET_ENTRY|INHIBIT_UDF_ENTRY))
1259 dcount++;
1260 s_entry = s_entry->next;
1261 }
1262
1263 /* OK, now we know how many there are. Build a vector for sorting. */
1264 sortlist = (struct directory_entry **)
1265 e_malloc(sizeof (struct directory_entry *) * dcount);
1266
1267 dcount = 0;
1268 s_entry = *sort_dir;
1269 while (s_entry) {
1270 /*
1271 * only collect non-hidden entries
1272 */
1273 if ((s_entry->de_flags & (INHIBIT_JOLIET_ENTRY|INHIBIT_UDF_ENTRY)) !=
1274 (INHIBIT_JOLIET_ENTRY|INHIBIT_UDF_ENTRY)) {
1275 sortlist[dcount] = s_entry;
1276 dcount++;
1277 }
1278 s_entry = s_entry->next;
1279 }
1280
1281 jsort_goof = 0;
1282 jsort_glen = 0;
1283 #ifdef PROTOTYPES
1284 qsort(sortlist, dcount, sizeof (struct directory_entry *),
1285 (int (*) (const void *, const void *)) joliet_compare_dirs);
1286 #else
1287 qsort(sortlist, dcount, sizeof (struct directory_entry *),
1288 joliet_compare_dirs);
1289 #endif
1290
1291 if (jsort_goof) {
1292 errmsgno(EX_BAD,
1293 _("Joliet file names differ after %d chars\n"),
1294 jsort_glen);
1295 if (jsort_glen > JLONGMAX) {
1296 errmsgno(EX_BAD,
1297 _("Cannot use Joliet, please remove -J from the option list.\n"));
1298 } else if (jsort_glen > JMAX) {
1299 errmsgno(EX_BAD,
1300 _("Try to use the option -joliet-long\n"));
1301 }
1302 }
1303
1304 /* Now reassemble the linked list in the proper sorted order */
1305 for (i = 0; i < dcount - 1; i++) {
1306 sortlist[i]->jnext = sortlist[i + 1];
1307 }
1308
1309 sortlist[dcount - 1]->jnext = NULL;
1310 *sort_dir = sortlist[0];
1311
1312 free(sortlist);
1313 return (jsort_goof);
1314 }
1315
1316 EXPORT int
1317 joliet_sort_tree(node)
1318 struct directory *node;
1319 {
1320 struct directory *dpnt;
1321 int ret = 0;
1322
1323 dpnt = node;
1324
1325 while (dpnt) {
1326 ret = joliet_sort_n_finish(dpnt);
1327 if (ret) {
1328 break;
1329 }
1330 if (dpnt->subdir)
1331 ret = joliet_sort_tree(dpnt->subdir);
1332 if (ret) {
1333 break;
1334 }
1335 dpnt = dpnt->next;
1336 }
1337 return (ret);
1338 }
1339
1340 LOCAL void
1341 generate_joliet_directories(node, outfile)
1342 struct directory *node;
1343 FILE *outfile;
1344 {
1345 struct directory *dpnt;
1346
1347 dpnt = node;
1348
1349 while (dpnt) {
1350 if ((dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0) {
1351 /*
1352 * In theory we should never reuse a directory, so this
1353 * doesn't make much sense.
1354 */
1355 if (dpnt->jextent > session_start) {
1356 generate_one_joliet_directory(dpnt, outfile);
1357 }
1358 }
1359 /* skip if hidden - but not for the rr_moved dir */
1360 if (dpnt->subdir &&
1361 (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) ||
1362 dpnt == reloc_dir)) {
1363 generate_joliet_directories(dpnt->subdir, outfile);
1364 }
1365 dpnt = dpnt->next;
1366 }
1367 }
1368
1369
1370 /*
1371 * Function to write the EVD for the disc.
1372 */
1373 LOCAL int
1374 jpathtab_write(outfile)
1375 FILE *outfile;
1376 {
1377 /* Next we write the path tables */
1378 xfwrite(jpath_table_l, jpath_blocks << 11, 1, outfile, 0, FALSE);
1379 xfwrite(jpath_table_m, jpath_blocks << 11, 1, outfile, 0, FALSE);
1380 last_extent_written += 2 * jpath_blocks;
1381 free(jpath_table_l);
1382 free(jpath_table_m);
1383 jpath_table_l = NULL;
1384 jpath_table_m = NULL;
1385 return (0);
1386 }
1387
1388 LOCAL int
1389 jdirtree_size(starting_extent)
1390 UInt32_t starting_extent;
1391 {
1392 assign_joliet_directory_addresses(root);
1393 return (0);
1394 }
1395
1396 LOCAL int
1397 jroot_gen()
1398 {
1399 jroot_record.length[0] =
1400 1 + offsetof(struct iso_directory_record, name[0]);
1401 jroot_record.ext_attr_length[0] = 0;
1402 set_733((char *)jroot_record.extent, root->jextent);
1403 set_733((char *)jroot_record.size, ISO_ROUND_UP(root->jsize));
1404 iso9660_date(jroot_record.date, root_statbuf.st_mtime);
1405 jroot_record.flags[0] = ISO_DIRECTORY;
1406 jroot_record.file_unit_size[0] = 0;
1407 jroot_record.interleave[0] = 0;
1408 set_723(jroot_record.volume_sequence_number, volume_sequence_number);
1409 jroot_record.name_len[0] = 1;
1410 return (0);
1411 }
1412
1413 LOCAL int
1414 jdirtree_write(outfile)
1415 FILE *outfile;
1416 {
1417 generate_joliet_directories(root, outfile);
1418 return (0);
1419 }
1420
1421 /*
1422 * Function to write the EVD for the disc.
1423 */
1424 LOCAL int
1425 jvd_write(outfile)
1426 FILE *outfile;
1427 {
1428 struct iso_primary_descriptor jvol_desc;
1429
1430 /* Next we write out the boot volume descriptor for the disc */
1431 jvol_desc = vol_desc;
1432 get_joliet_vol_desc(&jvol_desc);
1433 xfwrite(&jvol_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
1434 last_extent_written++;
1435 return (0);
1436 }
1437
1438 /*
1439 * Functions to describe padding block at the start of the disc.
1440 */
1441 LOCAL int
1442 jpathtab_size(starting_extent)
1443 UInt32_t starting_extent;
1444 {
1445 jpath_table[0] = starting_extent;
1446 jpath_table[1] = 0;
1447 jpath_table[2] = jpath_table[0] + jpath_blocks;
1448 jpath_table[3] = 0;
1449
1450 last_extent += 2 * jpath_blocks;
1451 return (0);
1452 }
1453
1454 struct output_fragment joliet_desc = {NULL, oneblock_size, jroot_gen, jvd_write, "Joliet Volume Descriptor" };
1455 struct output_fragment jpathtable_desc = {NULL, jpathtab_size, generate_joliet_path_tables, jpathtab_write, "Joliet path table" };
1456 struct output_fragment jdirtree_desc = {NULL, jdirtree_size, NULL, jdirtree_write, "Joliet directory tree" };