2 * File joliet.c - handle Win95/WinNT long file/unicode extensions for iso9660.
4 Copyright 1997 Eric Youngdale.
6 Copyright (C) 2009 Free Software Foundation, Inc.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, see <http://www.gnu.org/licenses/>.
23 * Joliet extensions for ISO9660. These are spottily documented by
24 * Microsoft. In their infinite stupidity, they completely ignored
25 * the possibility of using an SUSP record with the long filename
26 * in it, and instead wrote out a duplicate directory tree with the
27 * long filenames in it.
29 * I am not sure why they did this. One reason is that they get the path
30 * tables with the long filenames in them.
32 * There are two basic principles to Joliet, and the non-Unicode variant
33 * known as Romeo. Long filenames seem to be the main one, and the second
34 * is that the character set and a few other things is substantially relaxed.
36 * The SVD is identical to the PVD, except:
38 * Id is 2, not 1 (indicates SVD).
39 * escape_sequences contains UCS-2 indicator (levels 1, 2 or 3).
40 * The root directory record points to a different extent (with different
42 * There are different path tables for the two sets of directory trees.
44 * The following fields are recorded in Unicode:
53 * bibliographic_file_id
55 * Unicode strings are always encoded in big-endian format.
57 * In a directory record, everything is the same as with iso9660, except
58 * that the name is recorded in unicode. The name length is specified in
59 * total bytes, not in number of unicode characters.
61 * The character set used for the names is different with UCS - the
62 * restrictions are that the following are not allowed:
64 * Characters (00)(00) through (00)(1f) (control chars)
80 static unsigned int jpath_table_index
;
81 static struct directory
** jpathlist
;
82 static int next_jpath_index
= 1;
85 static int generate_joliet_path_tables
__PR((void));
86 static int DECL(joliet_sort_directory
, (struct directory_entry
** sort_dir
));
87 static void DECL(assign_joliet_directory_addresses
, (struct directory
* node
));
88 static int jroot_gen
__PR((void));
91 * Function: convert_to_unicode
93 * Purpose: Perform a 1/2 assed unicode conversion on a text
98 static void FDECL3(convert_to_unicode
, unsigned char *, buffer
, int, size
, char *, source
)
100 unsigned char * tmpbuf
;
105 * If we get a NULL pointer for the source, it means we have an inplace
106 * copy, and we need to make a temporary working copy first.
110 tmpbuf
= (uint8_t *) e_malloc(size
);
111 memcpy( tmpbuf
, buffer
, size
);
115 tmpbuf
= (uint8_t *)source
;
119 * Now start copying characters. If the size was specified to be 0, then
120 * assume the input was 0 terminated.
123 for(i
=0; i
< size
; i
+= 2, j
++)
127 * JS integrated from: Achim_Kaiser@t-online.de
129 * Let all valid unicode characters pass through (assuming ISO-8859-1).
130 * Others are set to '_' .
132 if( tmpbuf
[j
] != 0 &&
133 (tmpbuf
[j
] <= 0x1f || (tmpbuf
[j
] >= 0x7F && tmpbuf
[j
] <= 0xA0)) )
148 * Even Joliet has some standards as to what is allowed in a pathname.
149 * Pretty tame in comparison to what DOS restricts you to.
154 buffer
[i
+1] = tmpbuf
[j
];
167 * Function: joliet_strlen
169 * Purpose: Return length in bytes of string after conversion to unicode.
171 * Notes: This is provided mainly as a convenience so that when more intelligent
172 * Unicode conversion for either Multibyte or 8-bit codes is available that
173 * we can easily adapt.
175 static int FDECL1(joliet_strlen
, const char *, string
)
179 rtn
= strlen(string
) << 1;
182 * We do clamp the maximum length of a Joliet string to be the
183 * maximum path size. This helps to ensure that we don't completely
184 * bolix things up with very long paths. The Joliet specs say
185 * that the maximum length is 128 bytes, or 64 unicode characters.
195 * Function: get_joliet_vol_desc
197 * Purpose: generate a Joliet compatible volume desc.
199 * Notes: Assume that we have the non-joliet vol desc
200 * already present in the buffer. Just modifiy the
201 * appropriate fields.
203 static void FDECL1(get_joliet_vol_desc
, struct iso_primary_descriptor
*, jvol_desc
)
205 jvol_desc
->type
[0] = ISO_VD_SUPPLEMENTARY
;
208 * For now, always do Unicode level 3. I don't really know what 1 and 2
209 * are - perhaps a more limited Unicode set.
211 * FIXME(eric) - how does Romeo fit in here? As mkisofs just
212 * "expands" 8 bit character codes to 16 bits and does nothing
213 * special with the Unicode characters, therefore shouldn't mkisofs
214 * really be stating that it's using UCS-2 Level 1, not Level 3 for
215 * the Joliet directory tree.
217 strcpy(jvol_desc
->escape_sequences
, "%/@");
220 * Until we have Unicode path tables, leave these unset.
222 set_733((char *) jvol_desc
->path_table_size
, jpath_table_size
);
223 set_731(jvol_desc
->type_l_path_table
, jpath_table
[0]);
224 set_731(jvol_desc
->opt_type_l_path_table
, jpath_table
[1]);
225 set_732(jvol_desc
->type_m_path_table
, jpath_table
[2]);
226 set_732(jvol_desc
->opt_type_m_path_table
, jpath_table
[3]);
231 memcpy(jvol_desc
->root_directory_record
, &jroot_record
,
232 sizeof(struct iso_directory_record
));
235 * Finally, we have a bunch of strings to convert to Unicode.
236 * FIXME(eric) - I don't know how to do this in general, so we will
237 * just be really lazy and do a char -> short conversion. We probably
238 * will want to filter any characters >= 0x80.
240 convert_to_unicode((uint8_t *)jvol_desc
->system_id
, sizeof(jvol_desc
->system_id
), NULL
);
241 convert_to_unicode((uint8_t *)jvol_desc
->volume_id
, sizeof(jvol_desc
->volume_id
), NULL
);
242 convert_to_unicode((uint8_t *)jvol_desc
->volume_set_id
, sizeof(jvol_desc
->volume_set_id
), NULL
);
243 convert_to_unicode((uint8_t *)jvol_desc
->publisher_id
, sizeof(jvol_desc
->publisher_id
), NULL
);
244 convert_to_unicode((uint8_t *)jvol_desc
->preparer_id
, sizeof(jvol_desc
->preparer_id
), NULL
);
245 convert_to_unicode((uint8_t *)jvol_desc
->application_id
, sizeof(jvol_desc
->application_id
), NULL
);
246 convert_to_unicode((uint8_t *)jvol_desc
->copyright_file_id
, sizeof(jvol_desc
->copyright_file_id
), NULL
);
247 convert_to_unicode((uint8_t *)jvol_desc
->abstract_file_id
, sizeof(jvol_desc
->abstract_file_id
), NULL
);
248 convert_to_unicode((uint8_t *)jvol_desc
->bibliographic_file_id
, sizeof(jvol_desc
->bibliographic_file_id
), NULL
);
253 static void FDECL1(assign_joliet_directory_addresses
, struct directory
*, node
)
256 struct directory
* dpnt
;
262 if( (dpnt
->dir_flags
& INHIBIT_JOLIET_ENTRY
) == 0 )
265 * If we already have an extent for this (i.e. it came from
266 * a multisession disc), then don't reassign a new extent.
268 dpnt
->jpath_index
= next_jpath_index
++;
269 if( dpnt
->jextent
== 0 )
271 dpnt
->jextent
= last_extent
;
272 dir_size
= (dpnt
->jsize
+ (SECTOR_SIZE
- 1)) >> 11;
273 last_extent
+= dir_size
;
277 /* skip if hidden - but not for the rr_moved dir */
278 if(dpnt
->subdir
&& (!(dpnt
->dir_flags
& INHIBIT_JOLIET_ENTRY
) || dpnt
== reloc_dir
))
280 assign_joliet_directory_addresses(dpnt
->subdir
);
287 void FDECL1(build_jpathlist
, struct directory
*, node
)
289 struct directory
* dpnt
;
296 if( (dpnt
->dir_flags
& INHIBIT_JOLIET_ENTRY
) == 0 )
298 jpathlist
[dpnt
->jpath_index
] = dpnt
;
300 if(dpnt
->subdir
) build_jpathlist(dpnt
->subdir
);
303 } /* build_jpathlist(... */
305 static int FDECL2(joliet_compare_paths
, void const *, r
, void const *, l
)
307 struct directory
const *ll
= *(struct directory
* const *)l
;
308 struct directory
const *rr
= *(struct directory
* const *)r
;
309 int rparent
, lparent
;
311 rparent
= rr
->parent
->jpath_index
;
312 lparent
= ll
->parent
->jpath_index
;
313 if( rr
->parent
== reloc_dir
)
315 rparent
= rr
->self
->parent_rec
->filedir
->jpath_index
;
318 if( ll
->parent
== reloc_dir
)
320 lparent
= ll
->self
->parent_rec
->filedir
->jpath_index
;
323 if (rparent
< lparent
)
328 if (rparent
> lparent
)
333 return strcmp(rr
->self
->name
, ll
->self
->name
);
335 } /* compare_paths(... */
337 static int generate_joliet_path_tables()
339 struct directory_entry
* de
;
340 struct directory
* dpnt
;
349 * First allocate memory for the tables and initialize the memory
351 tablesize
= jpath_blocks
<< 11;
352 jpath_table_m
= (char *) e_malloc(tablesize
);
353 jpath_table_l
= (char *) e_malloc(tablesize
);
354 memset(jpath_table_l
, 0, tablesize
);
355 memset(jpath_table_m
, 0, tablesize
);
357 if( next_jpath_index
> 0xffff )
359 fprintf (stderr
, _("Unable to generate sane path tables - too many directories (%d)\n"),
364 * Now start filling in the path tables. Start with root directory
366 jpath_table_index
= 0;
367 jpathlist
= (struct directory
**) e_malloc(sizeof(struct directory
*)
369 memset(jpathlist
, 0, sizeof(struct directory
*) * next_jpath_index
);
370 build_jpathlist(root
);
376 qsort(&jpathlist
[1], next_jpath_index
-1, sizeof(struct directory
*),
377 (int (*)(const void *, const void *))joliet_compare_paths
);
379 qsort(&jpathlist
[1], next_jpath_index
-1, sizeof(struct directory
*),
380 joliet_compare_paths
);
383 for(j
=1; j
<next_jpath_index
; j
++)
385 if(jpathlist
[j
]->jpath_index
!= j
)
387 jpathlist
[j
]->jpath_index
= j
;
393 for(j
=1; j
<next_jpath_index
; j
++)
398 fprintf (stderr
, _("Entry %d not in path tables\n"), j
);
401 npnt
= dpnt
->de_name
;
403 npnt1
= strrchr(npnt
, PATH_SEPARATOR
);
412 fprintf (stderr
, _("Fatal goof - directory has amnesia\n"));
416 namelen
= joliet_strlen(de
->name
);
420 jpath_table_l
[jpath_table_index
] = 1;
421 jpath_table_m
[jpath_table_index
] = 1;
425 jpath_table_l
[jpath_table_index
] = namelen
;
426 jpath_table_m
[jpath_table_index
] = namelen
;
428 jpath_table_index
+= 2;
430 set_731(jpath_table_l
+ jpath_table_index
, dpnt
->jextent
);
431 set_732(jpath_table_m
+ jpath_table_index
, dpnt
->jextent
);
432 jpath_table_index
+= 4;
434 if( dpnt
->parent
!= reloc_dir
)
436 set_721(jpath_table_l
+ jpath_table_index
,
437 dpnt
->parent
->jpath_index
);
438 set_722(jpath_table_m
+ jpath_table_index
,
439 dpnt
->parent
->jpath_index
);
443 set_721(jpath_table_l
+ jpath_table_index
,
444 dpnt
->self
->parent_rec
->filedir
->jpath_index
);
445 set_722(jpath_table_m
+ jpath_table_index
,
446 dpnt
->self
->parent_rec
->filedir
->jpath_index
);
449 jpath_table_index
+= 2;
452 * The root directory is still represented in non-unicode fashion.
456 jpath_table_l
[jpath_table_index
] = 0;
457 jpath_table_m
[jpath_table_index
] = 0;
458 jpath_table_index
++;
462 convert_to_unicode((uint8_t *)jpath_table_l
+ jpath_table_index
,
464 convert_to_unicode((uint8_t *)jpath_table_m
+ jpath_table_index
,
466 jpath_table_index
+= namelen
;
469 if(jpath_table_index
& 1)
471 jpath_table_index
++; /* For odd lengths we pad */
476 if(jpath_table_index
!= jpath_table_size
)
478 fprintf(stderr
, _("Joliet path table lengths do not match %d %d\n"),
483 } /* generate_path_tables(... */
485 static void FDECL2(generate_one_joliet_directory
, struct directory
*, dpnt
, FILE *, outfile
)
487 unsigned int dir_index
;
488 char * directory_buffer
;
490 struct directory_entry
* s_entry
;
491 struct directory_entry
* s_entry1
;
492 struct iso_directory_record jrec
;
493 unsigned int total_size
;
495 struct directory
* finddir
;
497 total_size
= (dpnt
->jsize
+ (SECTOR_SIZE
- 1)) & ~(SECTOR_SIZE
- 1);
498 directory_buffer
= (char *) e_malloc(total_size
);
499 memset(directory_buffer
, 0, total_size
);
502 s_entry
= dpnt
->jcontents
;
505 if(s_entry
->de_flags
& INHIBIT_JOLIET_ENTRY
) {
506 s_entry
= s_entry
->jnext
;
511 * If this entry was a directory that was relocated, we have a bit
512 * of trouble here. We need to dig out the real thing and put it
513 * back here. In the Joliet tree, there is no relocated rock
514 * ridge, as there are no depth limits to a directory tree.
516 if( (s_entry
->de_flags
& RELOCATED_DIRECTORY
) != 0 )
518 for(s_entry1
= reloc_dir
->contents
; s_entry1
; s_entry1
= s_entry1
->next
)
520 if( s_entry1
->parent_rec
== s_entry
)
525 if( s_entry1
== NULL
)
530 fprintf (stderr
, _("Unable to locate relocated directory\n"));
540 * We do not allow directory entries to cross sector boundaries.
541 * Simply pad, and then start the next entry at the next sector
543 new_reclen
= s_entry1
->jreclen
;
544 if( (dir_index
& (SECTOR_SIZE
- 1)) + new_reclen
>= SECTOR_SIZE
)
546 dir_index
= (dir_index
+ (SECTOR_SIZE
- 1)) &
550 memcpy(&jrec
, &s_entry1
->isorec
, sizeof(struct iso_directory_record
) -
551 sizeof(s_entry1
->isorec
.name
));
553 cvt_len
= joliet_strlen(s_entry1
->name
);
556 * Fix the record length - this was the non-Joliet version we
559 jrec
.name_len
[0] = cvt_len
;
560 jrec
.length
[0] = s_entry1
->jreclen
;
563 * If this is a directory, fix the correct size and extent
566 if( (jrec
.flags
[0] & 2) != 0 )
568 if(strcmp(s_entry1
->name
,".") == 0)
570 jrec
.name_len
[0] = 1;
571 set_733((char *) jrec
.extent
, dpnt
->jextent
);
572 set_733((char *) jrec
.size
, ROUND_UP(dpnt
->jsize
));
574 else if(strcmp(s_entry1
->name
,"..") == 0)
576 jrec
.name_len
[0] = 1;
577 if( dpnt
->parent
== reloc_dir
)
579 set_733((char *) jrec
.extent
, dpnt
->self
->parent_rec
->filedir
->jextent
);
580 set_733((char *) jrec
.size
, ROUND_UP(dpnt
->self
->parent_rec
->filedir
->jsize
));
585 set_733((char *) jrec
.extent
, dpnt
->parent
->jextent
);
586 set_733((char *) jrec
.size
, ROUND_UP(dpnt
->parent
->jsize
));
591 if( (s_entry
->de_flags
& RELOCATED_DIRECTORY
) != 0 )
593 finddir
= reloc_dir
->subdir
;
597 finddir
= dpnt
->subdir
;
601 if(finddir
->self
== s_entry1
) break;
602 finddir
= finddir
->next
;
605 fprintf (stderr
, _("Fatal goof - unable to find directory location\n"));
609 set_733((char *) jrec
.extent
, finddir
->jextent
);
610 set_733((char *) jrec
.size
, ROUND_UP(finddir
->jsize
));
614 memcpy(directory_buffer
+ dir_index
, &jrec
,
615 sizeof(struct iso_directory_record
) -
616 sizeof(s_entry1
->isorec
.name
));
619 dir_index
+= sizeof(struct iso_directory_record
) -
620 sizeof (s_entry1
->isorec
.name
);
623 * Finally dump the Unicode version of the filename.
624 * Note - . and .. are the same as with non-Joliet discs.
626 if( (jrec
.flags
[0] & 2) != 0
627 && strcmp(s_entry1
->name
, ".") == 0 )
629 directory_buffer
[dir_index
++] = 0;
631 else if( (jrec
.flags
[0] & 2) != 0
632 && strcmp(s_entry1
->name
, "..") == 0 )
634 directory_buffer
[dir_index
++] = 1;
638 convert_to_unicode((uint8_t *)directory_buffer
+ dir_index
,
641 dir_index
+= cvt_len
;
646 directory_buffer
[dir_index
++] = 0;
649 s_entry
= s_entry
->jnext
;
652 if(dpnt
->jsize
!= dir_index
)
654 fprintf (stderr
, _("Unexpected joliet directory length %d %d %s\n"),
655 dpnt
->jsize
, dir_index
, dpnt
->de_name
);
658 xfwrite(directory_buffer
, 1, total_size
, outfile
);
659 last_extent_written
+= total_size
>> 11;
660 free(directory_buffer
);
661 } /* generate_one_joliet_directory(... */
663 static int FDECL1(joliet_sort_n_finish
, struct directory
*, this_dir
)
665 struct directory_entry
* s_entry
;
668 /* don't want to skip this directory if it's the reloc_dir at the moment */
669 if(this_dir
!= reloc_dir
&& this_dir
->dir_flags
& INHIBIT_JOLIET_ENTRY
)
674 for(s_entry
= this_dir
->contents
; s_entry
; s_entry
= s_entry
->next
)
676 /* skip hidden entries */
677 if( (s_entry
->de_flags
& INHIBIT_JOLIET_ENTRY
) != 0 )
683 * First update the path table sizes for directories.
685 * Finally, set the length of the directory entry if Joliet is used.
686 * The name is longer, but no Rock Ridge is ever used here, so
687 * depending upon the options the entry size might turn out to be about
688 * the same. The Unicode name is always a multiple of 2 bytes, so
689 * we always add 1 to make it an even number.
691 if(s_entry
->isorec
.flags
[0] == 2)
693 if (strcmp(s_entry
->name
,".") && strcmp(s_entry
->name
,".."))
695 jpath_table_size
+= joliet_strlen(s_entry
->name
) + sizeof(struct iso_path_table
) - 1;
696 if (jpath_table_size
& 1)
703 if (this_dir
== root
&& strlen(s_entry
->name
) == 1)
705 jpath_table_size
+= sizeof(struct iso_path_table
);
706 if (jpath_table_size
& 1) jpath_table_size
++;
711 if (strcmp(s_entry
->name
,".") && strcmp(s_entry
->name
,".."))
713 s_entry
->jreclen
= sizeof(struct iso_directory_record
)
714 - sizeof(s_entry
->isorec
.name
)
715 + joliet_strlen(s_entry
->name
)
721 * Special - for '.' and '..' we generate the same records we
722 * did for non-Joliet discs.
724 s_entry
->jreclen
= sizeof(struct iso_directory_record
)
725 - sizeof(s_entry
->isorec
.name
)
732 if( (this_dir
->dir_flags
& INHIBIT_JOLIET_ENTRY
) != 0 )
737 this_dir
->jcontents
= this_dir
->contents
;
738 status
= joliet_sort_directory(&this_dir
->jcontents
);
741 * Now go through the directory and figure out how large this one will be.
742 * Do not split a directory entry across a sector boundary
744 s_entry
= this_dir
->jcontents
;
746 * XXX Is it ok to comment this out?
748 /*XXX JS this_dir->ce_bytes = 0;*/
749 for(s_entry
= this_dir
->jcontents
; s_entry
; s_entry
= s_entry
->jnext
)
753 if( (s_entry
->de_flags
& INHIBIT_JOLIET_ENTRY
) != 0 )
758 jreclen
= s_entry
->jreclen
;
760 if ((this_dir
->jsize
& (SECTOR_SIZE
- 1)) + jreclen
>= SECTOR_SIZE
)
762 this_dir
->jsize
= (this_dir
->jsize
+ (SECTOR_SIZE
- 1)) &
765 this_dir
->jsize
+= jreclen
;
771 * Similar to the iso9660 case, except here we perform a full sort based upon the
772 * regular name of the file, not the 8.3 version.
774 static int FDECL2(joliet_compare_dirs
, const void *, rr
, const void *, ll
)
777 struct directory_entry
** r
, **l
;
779 r
= (struct directory_entry
**) rr
;
780 l
= (struct directory_entry
**) ll
;
785 * If the entries are the same, this is an error.
787 if( strcmp(rpnt
, lpnt
) == 0 )
793 * Put the '.' and '..' entries on the head of the sorted list.
794 * For normal ASCII, this always happens to be the case, but out of
795 * band characters cause this not to be the case sometimes.
797 if( strcmp(rpnt
, ".") == 0 ) return -1;
798 if( strcmp(lpnt
, ".") == 0 ) return 1;
800 if( strcmp(rpnt
, "..") == 0 ) return -1;
801 if( strcmp(lpnt
, "..") == 0 ) return 1;
803 while(*rpnt
&& *lpnt
)
805 if(*rpnt
== ';' && *lpnt
!= ';') return -1;
806 if(*rpnt
!= ';' && *lpnt
== ';') return 1;
808 if(*rpnt
== ';' && *lpnt
== ';') return 0;
811 * Extensions are not special here. Don't treat the dot as something that
812 * must be bumped to the start of the list.
815 if(*rpnt
== '.' && *lpnt
!= '.') return -1;
816 if(*rpnt
!= '.' && *lpnt
== '.') return 1;
819 if(*rpnt
< *lpnt
) return -1;
820 if(*rpnt
> *lpnt
) return 1;
830 * Function: sort_directory
832 * Purpose: Sort the directory in the appropriate ISO9660
835 * Notes: Returns 0 if OK, returns > 0 if an error occurred.
837 static int FDECL1(joliet_sort_directory
, struct directory_entry
**, sort_dir
)
841 struct directory_entry
* s_entry
;
842 struct directory_entry
** sortlist
;
847 /* skip hidden entries */
848 if (!(s_entry
->de_flags
& INHIBIT_JOLIET_ENTRY
))
850 s_entry
= s_entry
->next
;
854 * OK, now we know how many there are. Build a vector for sorting.
856 sortlist
= (struct directory_entry
**)
857 e_malloc(sizeof(struct directory_entry
*) * dcount
);
863 /* skip hidden entries */
864 if (!(s_entry
->de_flags
& INHIBIT_JOLIET_ENTRY
)) {
865 sortlist
[dcount
] = s_entry
;
868 s_entry
= s_entry
->next
;
873 qsort(sortlist
, dcount
, sizeof(struct directory_entry
*),
874 (int (*)(const void *, const void *))joliet_compare_dirs
);
876 qsort(sortlist
, dcount
, sizeof(struct directory_entry
*),
877 joliet_compare_dirs
);
881 * Now reassemble the linked list in the proper sorted order
883 for(i
=0; i
<dcount
-1; i
++)
885 sortlist
[i
]->jnext
= sortlist
[i
+1];
888 sortlist
[dcount
-1]->jnext
= NULL
;
889 *sort_dir
= sortlist
[0];
895 int FDECL1(joliet_sort_tree
, struct directory
*, node
)
897 struct directory
* dpnt
;
903 ret
= joliet_sort_n_finish(dpnt
);
908 if(dpnt
->subdir
) ret
= joliet_sort_tree(dpnt
->subdir
);
918 static void FDECL2(generate_joliet_directories
, struct directory
*, node
, FILE*, outfile
){
919 struct directory
* dpnt
;
925 if( (dpnt
->dir_flags
& INHIBIT_JOLIET_ENTRY
) == 0 )
928 * In theory we should never reuse a directory, so this doesn't
931 if( dpnt
->jextent
> session_start
)
933 generate_one_joliet_directory(dpnt
, outfile
);
936 /* skip if hidden - but not for the rr_moved dir */
937 if(dpnt
->subdir
&& (!(dpnt
->dir_flags
& INHIBIT_JOLIET_ENTRY
) || dpnt
== reloc_dir
))
938 generate_joliet_directories(dpnt
->subdir
, outfile
);
945 * Function to write the EVD for the disc.
947 static int FDECL1(jpathtab_write
, FILE *, outfile
)
950 * Next we write the path tables
952 xfwrite(jpath_table_l
, 1, jpath_blocks
<< 11, outfile
);
953 xfwrite(jpath_table_m
, 1, jpath_blocks
<< 11, outfile
);
954 last_extent_written
+= 2*jpath_blocks
;
957 jpath_table_l
= NULL
;
958 jpath_table_m
= NULL
;
962 static int FDECL1(jdirtree_size
, int, starting_extent
)
964 assign_joliet_directory_addresses(root
);
968 static int jroot_gen()
970 jroot_record
.length
[0] = 1 + sizeof(struct iso_directory_record
)
971 - sizeof(jroot_record
.name
);
972 jroot_record
.ext_attr_length
[0] = 0;
973 set_733((char *) jroot_record
.extent
, root
->jextent
);
974 set_733((char *) jroot_record
.size
, ROUND_UP(root
->jsize
));
975 iso9660_date(jroot_record
.date
, root_statbuf
.st_mtime
);
976 jroot_record
.flags
[0] = 2;
977 jroot_record
.file_unit_size
[0] = 0;
978 jroot_record
.interleave
[0] = 0;
979 set_723(jroot_record
.volume_sequence_number
, volume_sequence_number
);
980 jroot_record
.name_len
[0] = 1;
984 static int FDECL1(jdirtree_write
, FILE *, outfile
)
986 generate_joliet_directories(root
, outfile
);
991 * Function to write the EVD for the disc.
993 static int FDECL1(jvd_write
, FILE *, outfile
)
995 struct iso_primary_descriptor jvol_desc
;
998 * Next we write out the boot volume descriptor for the disc
1000 jvol_desc
= vol_desc
;
1001 get_joliet_vol_desc(&jvol_desc
);
1002 xfwrite(&jvol_desc
, 1, 2048, outfile
);
1003 last_extent_written
++;
1008 * Functions to describe padding block at the start of the disc.
1010 static int FDECL1(jpathtab_size
, int, starting_extent
)
1012 jpath_table
[0] = starting_extent
;
1014 jpath_table
[2] = jpath_table
[0] + jpath_blocks
;
1017 last_extent
+= 2*jpath_blocks
;
1021 struct output_fragment joliet_desc
= {NULL
, oneblock_size
, jroot_gen
,jvd_write
};
1022 struct output_fragment jpathtable_desc
= {NULL
, jpathtab_size
, generate_joliet_path_tables
, jpathtab_write
};
1023 struct output_fragment jdirtree_desc
= {NULL
, jdirtree_size
, NULL
, jdirtree_write
};