Home | History | Annotate | Line # | Download | only in dist
      1  1.1  tsutsui /*
      2  1.1  tsutsui  * File joliet.c - handle Win95/WinNT long file/unicode extensions for iso9660.
      3  1.1  tsutsui 
      4  1.1  tsutsui    Copyright 1997 Eric Youngdale.
      5  1.1  tsutsui 
      6  1.1  tsutsui    This program is free software; you can redistribute it and/or modify
      7  1.1  tsutsui    it under the terms of the GNU General Public License as published by
      8  1.1  tsutsui    the Free Software Foundation; either version 2, or (at your option)
      9  1.1  tsutsui    any later version.
     10  1.1  tsutsui 
     11  1.1  tsutsui    This program is distributed in the hope that it will be useful,
     12  1.1  tsutsui    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1  tsutsui    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  1.1  tsutsui    GNU General Public License for more details.
     15  1.1  tsutsui 
     16  1.1  tsutsui    You should have received a copy of the GNU General Public License
     17  1.1  tsutsui    along with this program; if not, write to the Free Software
     18  1.1  tsutsui    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
     19  1.1  tsutsui 
     20  1.1  tsutsui /* APPLE_HYB James Pearson j.pearson (at) ge.ucl.ac.uk 12/3/99 */
     21  1.1  tsutsui 
     22  1.1  tsutsui /*
     23  1.1  tsutsui  * Joliet extensions for ISO9660.  These are spottily documented by
     24  1.1  tsutsui  * Microsoft.  In their infinite stupidity, they completely ignored
     25  1.1  tsutsui  * the possibility of using an SUSP record with the long filename
     26  1.1  tsutsui  * in it, and instead wrote out a duplicate directory tree with the
     27  1.1  tsutsui  * long filenames in it.
     28  1.1  tsutsui  *
     29  1.1  tsutsui  * I am not sure why they did this.  One reason is that they get the path
     30  1.1  tsutsui  * tables with the long filenames in them.
     31  1.1  tsutsui  *
     32  1.1  tsutsui  * There are two basic principles to Joliet, and the non-Unicode variant
     33  1.1  tsutsui  * known as Romeo.  Long filenames seem to be the main one, and the second
     34  1.1  tsutsui  * is that the character set and a few other things is substantially relaxed.
     35  1.1  tsutsui  *
     36  1.1  tsutsui  * The SVD is identical to the PVD, except:
     37  1.1  tsutsui  *
     38  1.1  tsutsui  *	Id is 2, not 1 (indicates SVD).
     39  1.1  tsutsui  *	escape_sequences contains UCS-2 indicator (levels 1, 2 or 3).
     40  1.1  tsutsui  *	The root directory record points to a different extent (with different
     41  1.1  tsutsui  *		size).
     42  1.1  tsutsui  *	There are different path tables for the two sets of directory trees.
     43  1.1  tsutsui  *
     44  1.1  tsutsui  * The following fields are recorded in Unicode:
     45  1.1  tsutsui  *	system_id
     46  1.1  tsutsui  *	volume_id
     47  1.1  tsutsui  *	volume_set_id
     48  1.1  tsutsui  *	publisher_id
     49  1.1  tsutsui  *	preparer_id
     50  1.1  tsutsui  *	application_id
     51  1.1  tsutsui  *	copyright_file_id
     52  1.1  tsutsui  *	abstract_file_id
     53  1.1  tsutsui  *	bibliographic_file_id
     54  1.1  tsutsui  *
     55  1.1  tsutsui  * Unicode strings are always encoded in big-endian format.
     56  1.1  tsutsui  *
     57  1.1  tsutsui  * In a directory record, everything is the same as with iso9660, except
     58  1.1  tsutsui  * that the name is recorded in unicode.  The name length is specified in
     59  1.1  tsutsui  * total bytes, not in number of unicode characters.
     60  1.1  tsutsui  *
     61  1.1  tsutsui  * The character set used for the names is different with UCS - the
     62  1.1  tsutsui  * restrictions are that the following are not allowed:
     63  1.1  tsutsui  *
     64  1.1  tsutsui  *	Characters (00)(00) through (00)(1f) (control chars)
     65  1.1  tsutsui  *	(00)(2a) '*'
     66  1.1  tsutsui  *	(00)(2f) '/'
     67  1.1  tsutsui  *	(00)(3a) ':'
     68  1.1  tsutsui  *	(00)(3b) ';'
     69  1.1  tsutsui  *	(00)(3f) '?'
     70  1.1  tsutsui  *	(00)(5c) '\'
     71  1.1  tsutsui  */
     72  1.1  tsutsui #include "config.h"
     73  1.1  tsutsui #include "mkisofs.h"
     74  1.1  tsutsui #include "iso9660.h"
     75  1.1  tsutsui 
     76  1.1  tsutsui 
     77  1.1  tsutsui #include <stdlib.h>
     78  1.1  tsutsui #include <time.h>
     79  1.1  tsutsui 
     80  1.1  tsutsui static int jpath_table_index;
     81  1.1  tsutsui static struct directory ** jpathlist;
     82  1.1  tsutsui static int next_jpath_index  = 1;
     83  1.1  tsutsui static int sort_goof;
     84  1.1  tsutsui 
     85  1.1  tsutsui static int generate_joliet_path_tables	__PR((void));
     86  1.1  tsutsui static int DECL(joliet_sort_directory, (struct directory_entry ** sort_dir));
     87  1.1  tsutsui static void DECL(assign_joliet_directory_addresses, (struct directory * node));
     88  1.1  tsutsui static int jroot_gen	__PR((void));
     89  1.1  tsutsui 
     90  1.1  tsutsui /*
     91  1.1  tsutsui  * Function:		convert_to_unicode
     92  1.1  tsutsui  *
     93  1.1  tsutsui  * Purpose:		Perform a 1/2 assed unicode conversion on a text
     94  1.1  tsutsui  *			string.
     95  1.1  tsutsui  *
     96  1.1  tsutsui  * Notes:
     97  1.1  tsutsui  */
     98  1.1  tsutsui static void FDECL3(convert_to_unicode, unsigned char *, buffer, int, size, char *, source )
     99  1.1  tsutsui {
    100  1.1  tsutsui   unsigned char * tmpbuf;
    101  1.1  tsutsui   int i;
    102  1.1  tsutsui   int j;
    103  1.1  tsutsui 
    104  1.1  tsutsui   /*
    105  1.1  tsutsui    * If we get a NULL pointer for the source, it means we have an inplace
    106  1.1  tsutsui    * copy, and we need to make a temporary working copy first.
    107  1.1  tsutsui    */
    108  1.1  tsutsui   if( source == NULL )
    109  1.1  tsutsui     {
    110  1.1  tsutsui       tmpbuf = (u_char *) e_malloc(size);
    111  1.1  tsutsui       memcpy( tmpbuf, buffer, size);
    112  1.1  tsutsui     }
    113  1.1  tsutsui   else
    114  1.1  tsutsui     {
    115  1.1  tsutsui       tmpbuf = (u_char *)source;
    116  1.1  tsutsui     }
    117  1.1  tsutsui 
    118  1.1  tsutsui   /*
    119  1.1  tsutsui    * Now start copying characters.  If the size was specified to be 0, then
    120  1.1  tsutsui    * assume the input was 0 terminated.
    121  1.1  tsutsui    */
    122  1.1  tsutsui   j = 0;
    123  1.1  tsutsui   for(i=0; i < size ; i += 2, j++)
    124  1.1  tsutsui     {
    125  1.1  tsutsui       buffer[i]       = 0;
    126  1.1  tsutsui 	/*
    127  1.1  tsutsui 	 * JS integrated from: Achim_Kaiser (at) t-online.de
    128  1.1  tsutsui 	 *
    129  1.1  tsutsui 	 * Let all valid unicode characters pass through (assuming ISO-8859-1).
    130  1.1  tsutsui 	 * Others are set to '_' .
    131  1.1  tsutsui 	 */
    132  1.1  tsutsui 	if( tmpbuf[j] != 0 &&
    133  1.1  tsutsui 	   (tmpbuf[j] <= 0x1f || (tmpbuf[j] >= 0x7F && tmpbuf[j] <= 0xA0)) )
    134  1.1  tsutsui 	{
    135  1.1  tsutsui 	  buffer[i+1]     = '_';
    136  1.1  tsutsui 	}
    137  1.1  tsutsui       else
    138  1.1  tsutsui 	{
    139  1.1  tsutsui 	  switch(tmpbuf[j])
    140  1.1  tsutsui 	    {
    141  1.1  tsutsui 	    case '*':
    142  1.1  tsutsui 	    case '/':
    143  1.1  tsutsui 	    case ':':
    144  1.1  tsutsui 	    case ';':
    145  1.1  tsutsui 	    case '?':
    146  1.1  tsutsui 	    case '\\':
    147  1.1  tsutsui 	      /*
    148  1.1  tsutsui 	       * Even Joliet has some standards as to what is allowed in a pathname.
    149  1.1  tsutsui 	       * Pretty tame in comparison to what DOS restricts you to.
    150  1.1  tsutsui 	       */
    151  1.1  tsutsui 	      buffer[i+1]     = '_';
    152  1.1  tsutsui 	      break;
    153  1.1  tsutsui 	    default:
    154  1.1  tsutsui 	      buffer[i+1]     = tmpbuf[j];
    155  1.1  tsutsui 	      break;
    156  1.1  tsutsui 	    }
    157  1.1  tsutsui 	}
    158  1.1  tsutsui     }
    159  1.1  tsutsui 
    160  1.1  tsutsui   if( source == NULL )
    161  1.1  tsutsui     {
    162  1.1  tsutsui       free(tmpbuf);
    163  1.1  tsutsui     }
    164  1.1  tsutsui }
    165  1.1  tsutsui 
    166  1.1  tsutsui /*
    167  1.1  tsutsui  * Function:		joliet_strlen
    168  1.1  tsutsui  *
    169  1.1  tsutsui  * Purpose:		Return length in bytes of string after conversion to unicode.
    170  1.1  tsutsui  *
    171  1.1  tsutsui  * Notes:		This is provided mainly as a convenience so that when more intelligent
    172  1.1  tsutsui  *			Unicode conversion for either Multibyte or 8-bit codes is available that
    173  1.1  tsutsui  *			we can easily adapt.
    174  1.1  tsutsui  */
    175  1.1  tsutsui static int FDECL1(joliet_strlen, const char *, string)
    176  1.1  tsutsui {
    177  1.1  tsutsui   int rtn;
    178  1.1  tsutsui 
    179  1.1  tsutsui   rtn = strlen(string) << 1;
    180  1.1  tsutsui 
    181  1.1  tsutsui   /*
    182  1.1  tsutsui    * We do clamp the maximum length of a Joliet string to be the
    183  1.1  tsutsui    * maximum path size.  This helps to ensure that we don't completely
    184  1.1  tsutsui    * bolix things up with very long paths.    The Joliet specs say
    185  1.1  tsutsui    * that the maximum length is 128 bytes, or 64 unicode characters.
    186  1.1  tsutsui    */
    187  1.1  tsutsui   if( rtn > 0x80)
    188  1.1  tsutsui     {
    189  1.1  tsutsui       rtn = 0x80;
    190  1.1  tsutsui     }
    191  1.1  tsutsui   return rtn;
    192  1.1  tsutsui }
    193  1.1  tsutsui 
    194  1.1  tsutsui /*
    195  1.1  tsutsui  * Function:		get_joliet_vol_desc
    196  1.1  tsutsui  *
    197  1.1  tsutsui  * Purpose:		generate a Joliet compatible volume desc.
    198  1.1  tsutsui  *
    199  1.1  tsutsui  * Notes:		Assume that we have the non-joliet vol desc
    200  1.1  tsutsui  *			already present in the buffer.  Just modifiy the
    201  1.1  tsutsui  *			appropriate fields.
    202  1.1  tsutsui  */
    203  1.1  tsutsui static void FDECL1(get_joliet_vol_desc, struct iso_primary_descriptor *, jvol_desc)
    204  1.1  tsutsui {
    205  1.1  tsutsui   jvol_desc->type[0] = ISO_VD_SUPPLEMENTARY;
    206  1.1  tsutsui 
    207  1.1  tsutsui   /*
    208  1.1  tsutsui    * For now, always do Unicode level 3.  I don't really know what 1 and 2
    209  1.1  tsutsui    * are - perhaps a more limited Unicode set.
    210  1.1  tsutsui    *
    211  1.1  tsutsui    * FIXME(eric) - how does Romeo fit in here?  As mkisofs just
    212  1.1  tsutsui    * "expands" 8 bit character codes to 16 bits and does nothing
    213  1.1  tsutsui    * special with the Unicode characters, therefore shouldn't mkisofs
    214  1.1  tsutsui    * really be stating that it's using UCS-2 Level 1, not Level 3 for
    215  1.1  tsutsui    * the Joliet directory tree.
    216  1.1  tsutsui    */
    217  1.1  tsutsui   strcpy(jvol_desc->escape_sequences, "%/@");
    218  1.1  tsutsui 
    219  1.1  tsutsui   /*
    220  1.1  tsutsui    * Until we have Unicode path tables, leave these unset.
    221  1.1  tsutsui    */
    222  1.1  tsutsui   set_733((char *) jvol_desc->path_table_size, jpath_table_size);
    223  1.1  tsutsui   set_731(jvol_desc->type_l_path_table,     jpath_table[0]);
    224  1.1  tsutsui   set_731(jvol_desc->opt_type_l_path_table, jpath_table[1]);
    225  1.1  tsutsui   set_732(jvol_desc->type_m_path_table,     jpath_table[2]);
    226  1.1  tsutsui   set_732(jvol_desc->opt_type_m_path_table, jpath_table[3]);
    227  1.1  tsutsui 
    228  1.1  tsutsui   /*
    229  1.1  tsutsui    * Set this one up.
    230  1.1  tsutsui    */
    231  1.1  tsutsui   memcpy(jvol_desc->root_directory_record, &jroot_record,
    232  1.1  tsutsui 	 sizeof(jvol_desc->root_directory_record));
    233  1.1  tsutsui 
    234  1.1  tsutsui   /*
    235  1.1  tsutsui    * Finally, we have a bunch of strings to convert to Unicode.
    236  1.1  tsutsui    * FIXME(eric) - I don't know how to do this in general, so we will
    237  1.1  tsutsui    * just be really lazy and do a char -> short conversion.  We probably
    238  1.1  tsutsui    * will want to filter any characters >= 0x80.
    239  1.1  tsutsui    */
    240  1.1  tsutsui   convert_to_unicode((u_char *)jvol_desc->system_id, sizeof(jvol_desc->system_id), NULL);
    241  1.1  tsutsui   convert_to_unicode((u_char *)jvol_desc->volume_id, sizeof(jvol_desc->volume_id), NULL);
    242  1.1  tsutsui   convert_to_unicode((u_char *)jvol_desc->volume_set_id, sizeof(jvol_desc->volume_set_id), NULL);
    243  1.1  tsutsui   convert_to_unicode((u_char *)jvol_desc->publisher_id, sizeof(jvol_desc->publisher_id), NULL);
    244  1.1  tsutsui   convert_to_unicode((u_char *)jvol_desc->preparer_id, sizeof(jvol_desc->preparer_id), NULL);
    245  1.1  tsutsui   convert_to_unicode((u_char *)jvol_desc->application_id, sizeof(jvol_desc->application_id), NULL);
    246  1.1  tsutsui   convert_to_unicode((u_char *)jvol_desc->copyright_file_id, sizeof(jvol_desc->copyright_file_id), NULL);
    247  1.1  tsutsui   convert_to_unicode((u_char *)jvol_desc->abstract_file_id, sizeof(jvol_desc->abstract_file_id), NULL);
    248  1.1  tsutsui   convert_to_unicode((u_char *)jvol_desc->bibliographic_file_id, sizeof(jvol_desc->bibliographic_file_id), NULL);
    249  1.1  tsutsui 
    250  1.1  tsutsui 
    251  1.1  tsutsui }
    252  1.1  tsutsui 
    253  1.1  tsutsui static void FDECL1(assign_joliet_directory_addresses, struct directory *, node)
    254  1.1  tsutsui {
    255  1.1  tsutsui      int		dir_size;
    256  1.1  tsutsui      struct directory * dpnt;
    257  1.1  tsutsui 
    258  1.1  tsutsui      dpnt = node;
    259  1.1  tsutsui 
    260  1.1  tsutsui      while (dpnt)
    261  1.1  tsutsui      {
    262  1.1  tsutsui 	 if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 )
    263  1.1  tsutsui 	 {
    264  1.1  tsutsui 	     /*
    265  1.1  tsutsui 	      * If we already have an extent for this (i.e. it came from
    266  1.1  tsutsui 	      * a multisession disc), then don't reassign a new extent.
    267  1.1  tsutsui 	      */
    268  1.1  tsutsui 	     dpnt->jpath_index = next_jpath_index++;
    269  1.1  tsutsui 	     if( dpnt->jextent == 0 )
    270  1.1  tsutsui 	     {
    271  1.1  tsutsui 		 dpnt->jextent = last_extent;
    272  1.1  tsutsui 		 dir_size = (dpnt->jsize + (SECTOR_SIZE - 1)) >> 11;
    273  1.1  tsutsui 		 last_extent += dir_size;
    274  1.1  tsutsui 	     }
    275  1.1  tsutsui 	 }
    276  1.1  tsutsui 
    277  1.1  tsutsui 	 /* skip if hidden - but not for the rr_moved dir */
    278  1.1  tsutsui 	 if(dpnt->subdir && (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir))
    279  1.1  tsutsui 	 {
    280  1.1  tsutsui 	     assign_joliet_directory_addresses(dpnt->subdir);
    281  1.1  tsutsui 	 }
    282  1.1  tsutsui 	 dpnt = dpnt->next;
    283  1.1  tsutsui      }
    284  1.1  tsutsui }
    285  1.1  tsutsui 
    286  1.1  tsutsui static
    287  1.1  tsutsui void FDECL1(build_jpathlist, struct directory *, node)
    288  1.1  tsutsui {
    289  1.1  tsutsui      struct directory * dpnt;
    290  1.1  tsutsui 
    291  1.1  tsutsui      dpnt = node;
    292  1.1  tsutsui 
    293  1.1  tsutsui      while (dpnt)
    294  1.1  tsutsui 
    295  1.1  tsutsui      {
    296  1.1  tsutsui        if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 )
    297  1.1  tsutsui 	 {
    298  1.1  tsutsui 	   jpathlist[dpnt->jpath_index] = dpnt;
    299  1.1  tsutsui 	 }
    300  1.1  tsutsui        if(dpnt->subdir) build_jpathlist(dpnt->subdir);
    301  1.1  tsutsui        dpnt = dpnt->next;
    302  1.1  tsutsui      }
    303  1.1  tsutsui } /* build_jpathlist(... */
    304  1.1  tsutsui 
    305  1.1  tsutsui static int FDECL2(joliet_compare_paths, void const *, r, void const *, l)
    306  1.1  tsutsui {
    307  1.1  tsutsui   struct directory const *ll = *(struct directory * const *)l;
    308  1.1  tsutsui   struct directory const *rr = *(struct directory * const *)r;
    309  1.1  tsutsui   int rparent, lparent;
    310  1.1  tsutsui 
    311  1.1  tsutsui   rparent = rr->parent->jpath_index;
    312  1.1  tsutsui   lparent = ll->parent->jpath_index;
    313  1.1  tsutsui   if( rr->parent == reloc_dir )
    314  1.1  tsutsui     {
    315  1.1  tsutsui       rparent = rr->self->parent_rec->filedir->jpath_index;
    316  1.1  tsutsui     }
    317  1.1  tsutsui 
    318  1.1  tsutsui   if( ll->parent == reloc_dir )
    319  1.1  tsutsui     {
    320  1.1  tsutsui       lparent = ll->self->parent_rec->filedir->jpath_index;
    321  1.1  tsutsui     }
    322  1.1  tsutsui 
    323  1.1  tsutsui   if (rparent < lparent)
    324  1.1  tsutsui   {
    325  1.1  tsutsui        return -1;
    326  1.1  tsutsui   }
    327  1.1  tsutsui 
    328  1.1  tsutsui   if (rparent > lparent)
    329  1.1  tsutsui   {
    330  1.1  tsutsui        return 1;
    331  1.1  tsutsui   }
    332  1.1  tsutsui #ifdef APPLE_HYB
    333  1.1  tsutsui   /* use Mac name for Joliet name */
    334  1.1  tsutsui   if (USE_MAC_NAME(mac_name, rr->self) && USE_MAC_NAME(mac_name, ll->self))
    335  1.1  tsutsui     return strcmp(rr->self->hfs_ent->name, ll->self->hfs_ent->name);
    336  1.1  tsutsui   else
    337  1.1  tsutsui #endif /* APPLE_HYB */
    338  1.1  tsutsui     return strcmp(rr->self->name, ll->self->name);
    339  1.1  tsutsui 
    340  1.1  tsutsui } /* compare_paths(... */
    341  1.1  tsutsui 
    342  1.1  tsutsui static int generate_joliet_path_tables()
    343  1.1  tsutsui {
    344  1.1  tsutsui   struct directory_entry * de;
    345  1.1  tsutsui   struct directory	 * dpnt;
    346  1.1  tsutsui   int			   fix;
    347  1.1  tsutsui   int			   j;
    348  1.1  tsutsui   int			   namelen;
    349  1.1  tsutsui   char			 * npnt;
    350  1.1  tsutsui   char			 * npnt1;
    351  1.1  tsutsui   int			   tablesize;
    352  1.1  tsutsui 
    353  1.1  tsutsui   /*
    354  1.1  tsutsui    * First allocate memory for the tables and initialize the memory
    355  1.1  tsutsui    */
    356  1.1  tsutsui   tablesize = jpath_blocks << 11;
    357  1.1  tsutsui   jpath_table_m = (char *) e_malloc(tablesize);
    358  1.1  tsutsui   jpath_table_l = (char *) e_malloc(tablesize);
    359  1.1  tsutsui   memset(jpath_table_l, 0, tablesize);
    360  1.1  tsutsui   memset(jpath_table_m, 0, tablesize);
    361  1.1  tsutsui 
    362  1.1  tsutsui   if( next_jpath_index > 0xffff )
    363  1.1  tsutsui   {
    364  1.1  tsutsui       fprintf(stderr, "Unable to generate sane path tables - too many directories (%d)\n",
    365  1.1  tsutsui 	      next_jpath_index);
    366  1.1  tsutsui       exit(1);
    367  1.1  tsutsui   }
    368  1.1  tsutsui   /*
    369  1.1  tsutsui    * Now start filling in the path tables.  Start with root directory
    370  1.1  tsutsui    */
    371  1.1  tsutsui   jpath_table_index = 0;
    372  1.1  tsutsui   jpathlist = (struct directory **) e_malloc(sizeof(struct directory *)
    373  1.1  tsutsui 					    * next_jpath_index);
    374  1.1  tsutsui   memset(jpathlist, 0, sizeof(struct directory *) * next_jpath_index);
    375  1.1  tsutsui   build_jpathlist(root);
    376  1.1  tsutsui 
    377  1.1  tsutsui   do
    378  1.1  tsutsui   {
    379  1.1  tsutsui        fix = 0;
    380  1.1  tsutsui #ifdef	__STDC__
    381  1.1  tsutsui        qsort(&jpathlist[1], next_jpath_index-1, sizeof(struct directory *),
    382  1.1  tsutsui 	     (int (*)(const void *, const void *))joliet_compare_paths);
    383  1.1  tsutsui #else
    384  1.1  tsutsui        qsort(&jpathlist[1], next_jpath_index-1, sizeof(struct directory *),
    385  1.1  tsutsui 	     joliet_compare_paths);
    386  1.1  tsutsui #endif
    387  1.1  tsutsui 
    388  1.1  tsutsui        for(j=1; j<next_jpath_index; j++)
    389  1.1  tsutsui        {
    390  1.1  tsutsui 	    if(jpathlist[j]->jpath_index != j)
    391  1.1  tsutsui 	    {
    392  1.1  tsutsui 		 jpathlist[j]->jpath_index = j;
    393  1.1  tsutsui 		 fix++;
    394  1.1  tsutsui 	    }
    395  1.1  tsutsui        }
    396  1.1  tsutsui   } while(fix);
    397  1.1  tsutsui 
    398  1.1  tsutsui   for(j=1; j<next_jpath_index; j++)
    399  1.1  tsutsui   {
    400  1.1  tsutsui        dpnt = jpathlist[j];
    401  1.1  tsutsui        if(!dpnt)
    402  1.1  tsutsui        {
    403  1.1  tsutsui 	    fprintf(stderr,"Entry %d not in path tables\n", j);
    404  1.1  tsutsui 	    exit(1);
    405  1.1  tsutsui        }
    406  1.1  tsutsui        npnt = dpnt->de_name;
    407  1.1  tsutsui 
    408  1.1  tsutsui        npnt1 = strrchr(npnt, PATH_SEPARATOR);
    409  1.1  tsutsui        if(npnt1)
    410  1.1  tsutsui        {
    411  1.1  tsutsui 	    npnt = npnt1 + 1;
    412  1.1  tsutsui        }
    413  1.1  tsutsui 
    414  1.1  tsutsui        de = dpnt->self;
    415  1.1  tsutsui        if(!de)
    416  1.1  tsutsui        {
    417  1.1  tsutsui 	    fprintf(stderr,"Fatal goof - directory has amnesia\n");
    418  1.1  tsutsui 	    exit(1);
    419  1.1  tsutsui        }
    420  1.1  tsutsui 
    421  1.1  tsutsui #ifdef APPLE_HYB
    422  1.1  tsutsui        if (USE_MAC_NAME(mac_name, de))
    423  1.1  tsutsui 	  namelen = joliet_strlen(de->hfs_ent->name);
    424  1.1  tsutsui        else
    425  1.1  tsutsui #endif /* APPLE_HYB */
    426  1.1  tsutsui           namelen = joliet_strlen(de->name);
    427  1.1  tsutsui 
    428  1.1  tsutsui        if( dpnt == root )
    429  1.1  tsutsui 	 {
    430  1.1  tsutsui 	   jpath_table_l[jpath_table_index] = 1;
    431  1.1  tsutsui 	   jpath_table_m[jpath_table_index] = 1;
    432  1.1  tsutsui 	 }
    433  1.1  tsutsui        else
    434  1.1  tsutsui 	 {
    435  1.1  tsutsui 	   jpath_table_l[jpath_table_index] = namelen;
    436  1.1  tsutsui 	   jpath_table_m[jpath_table_index] = namelen;
    437  1.1  tsutsui 	 }
    438  1.1  tsutsui        jpath_table_index += 2;
    439  1.1  tsutsui 
    440  1.1  tsutsui        set_731(jpath_table_l + jpath_table_index, dpnt->jextent);
    441  1.1  tsutsui        set_732(jpath_table_m + jpath_table_index, dpnt->jextent);
    442  1.1  tsutsui        jpath_table_index += 4;
    443  1.1  tsutsui 
    444  1.1  tsutsui        if( dpnt->parent != reloc_dir )
    445  1.1  tsutsui 	 {
    446  1.1  tsutsui 	   set_721(jpath_table_l + jpath_table_index,
    447  1.1  tsutsui 		   dpnt->parent->jpath_index);
    448  1.1  tsutsui 	   set_722(jpath_table_m + jpath_table_index,
    449  1.1  tsutsui 		   dpnt->parent->jpath_index);
    450  1.1  tsutsui 	 }
    451  1.1  tsutsui        else
    452  1.1  tsutsui 	 {
    453  1.1  tsutsui 	   set_721(jpath_table_l + jpath_table_index,
    454  1.1  tsutsui 		   dpnt->self->parent_rec->filedir->jpath_index);
    455  1.1  tsutsui 	   set_722(jpath_table_m + jpath_table_index,
    456  1.1  tsutsui 		   dpnt->self->parent_rec->filedir->jpath_index);
    457  1.1  tsutsui 	 }
    458  1.1  tsutsui 
    459  1.1  tsutsui        jpath_table_index += 2;
    460  1.1  tsutsui 
    461  1.1  tsutsui        /*
    462  1.1  tsutsui 	* The root directory is still represented in non-unicode fashion.
    463  1.1  tsutsui 	*/
    464  1.1  tsutsui        if( dpnt == root )
    465  1.1  tsutsui 	 {
    466  1.1  tsutsui 	   jpath_table_l[jpath_table_index] = 0;
    467  1.1  tsutsui 	   jpath_table_m[jpath_table_index] = 0;
    468  1.1  tsutsui 	   jpath_table_index ++;
    469  1.1  tsutsui 	 }
    470  1.1  tsutsui        else
    471  1.1  tsutsui 	 {
    472  1.1  tsutsui #ifdef APPLE_HYB
    473  1.1  tsutsui 	   if (USE_MAC_NAME(mac_name , de)) {
    474  1.1  tsutsui 	      convert_to_unicode((u_char *)jpath_table_l + jpath_table_index,
    475  1.1  tsutsui 			      namelen, de->hfs_ent->name);
    476  1.1  tsutsui 	      convert_to_unicode((u_char *)jpath_table_m + jpath_table_index,
    477  1.1  tsutsui 			      namelen, de->hfs_ent->name);
    478  1.1  tsutsui 	   }
    479  1.1  tsutsui 	   else {
    480  1.1  tsutsui #endif /* APPLE_HYB */
    481  1.1  tsutsui 	      convert_to_unicode((u_char *)jpath_table_l + jpath_table_index,
    482  1.1  tsutsui 			      namelen, de->name);
    483  1.1  tsutsui 	      convert_to_unicode((u_char *)jpath_table_m + jpath_table_index,
    484  1.1  tsutsui 			      namelen, de->name);
    485  1.1  tsutsui #ifdef APPLE_HYB
    486  1.1  tsutsui 	   }
    487  1.1  tsutsui #endif /* APPLE_HYB */
    488  1.1  tsutsui 
    489  1.1  tsutsui 	   jpath_table_index += namelen;
    490  1.1  tsutsui 	 }
    491  1.1  tsutsui 
    492  1.1  tsutsui        if(jpath_table_index & 1)
    493  1.1  tsutsui        {
    494  1.1  tsutsui 	    jpath_table_index++;  /* For odd lengths we pad */
    495  1.1  tsutsui        }
    496  1.1  tsutsui   }
    497  1.1  tsutsui 
    498  1.1  tsutsui   free(jpathlist);
    499  1.1  tsutsui   if(jpath_table_index != jpath_table_size)
    500  1.1  tsutsui   {
    501  1.1  tsutsui        fprintf(stderr,"Joliet path table lengths do not match %d %d\n",
    502  1.1  tsutsui 	       jpath_table_index,
    503  1.1  tsutsui 	       jpath_table_size);
    504  1.1  tsutsui   }
    505  1.1  tsutsui   return 0;
    506  1.1  tsutsui } /* generate_path_tables(... */
    507  1.1  tsutsui 
    508  1.1  tsutsui static void FDECL2(generate_one_joliet_directory, struct directory *, dpnt, FILE *, outfile)
    509  1.1  tsutsui {
    510  1.1  tsutsui      unsigned int			  dir_index;
    511  1.1  tsutsui      char				* directory_buffer;
    512  1.1  tsutsui      int				  new_reclen;
    513  1.1  tsutsui      struct directory_entry		* s_entry;
    514  1.1  tsutsui      struct directory_entry		* s_entry1;
    515  1.1  tsutsui      struct iso_directory_record	  jrec;
    516  1.1  tsutsui      unsigned int			  total_size;
    517  1.1  tsutsui      int				  cvt_len;
    518  1.1  tsutsui      struct directory			* finddir;
    519  1.1  tsutsui 
    520  1.1  tsutsui      total_size = (dpnt->jsize + (SECTOR_SIZE - 1)) &  ~(SECTOR_SIZE - 1);
    521  1.1  tsutsui      directory_buffer = (char *) e_malloc(total_size);
    522  1.1  tsutsui      memset(directory_buffer, 0, total_size);
    523  1.1  tsutsui      dir_index = 0;
    524  1.1  tsutsui 
    525  1.1  tsutsui      s_entry = dpnt->jcontents;
    526  1.1  tsutsui      while(s_entry)
    527  1.1  tsutsui      {
    528  1.1  tsutsui 	     if(s_entry->de_flags & INHIBIT_JOLIET_ENTRY) {
    529  1.1  tsutsui 		s_entry = s_entry->jnext;
    530  1.1  tsutsui 		continue;
    531  1.1  tsutsui 	     }
    532  1.1  tsutsui 
    533  1.1  tsutsui 	     /*
    534  1.1  tsutsui 	      * If this entry was a directory that was relocated, we have a bit
    535  1.1  tsutsui 	      * of trouble here.  We need to dig out the real thing and put it
    536  1.1  tsutsui 	      * back here.  In the Joliet tree, there is no relocated rock
    537  1.1  tsutsui 	      * ridge, as there are no depth limits to a directory tree.
    538  1.1  tsutsui 	      */
    539  1.1  tsutsui 	     if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 )
    540  1.1  tsutsui 	     {
    541  1.1  tsutsui 		 for(s_entry1 = reloc_dir->contents; s_entry1; s_entry1 = s_entry1->next)
    542  1.1  tsutsui 		 {
    543  1.1  tsutsui 		     if( s_entry1->parent_rec == s_entry )
    544  1.1  tsutsui 		     {
    545  1.1  tsutsui 			 break;
    546  1.1  tsutsui 		     }
    547  1.1  tsutsui 		 }
    548  1.1  tsutsui 		 if( s_entry1 == NULL )
    549  1.1  tsutsui 		 {
    550  1.1  tsutsui 		     /*
    551  1.1  tsutsui 		      * We got trouble.
    552  1.1  tsutsui 		      */
    553  1.1  tsutsui 		     fprintf(stderr, "Unable to locate relocated directory\n");
    554  1.1  tsutsui 		     exit(1);
    555  1.1  tsutsui 		 }
    556  1.1  tsutsui 	     }
    557  1.1  tsutsui 	     else
    558  1.1  tsutsui 	     {
    559  1.1  tsutsui 		 s_entry1 = s_entry;
    560  1.1  tsutsui 	     }
    561  1.1  tsutsui 
    562  1.1  tsutsui 	     /*
    563  1.1  tsutsui 	      * We do not allow directory entries to cross sector boundaries.
    564  1.1  tsutsui 	      * Simply pad, and then start the next entry at the next sector
    565  1.1  tsutsui 	      */
    566  1.1  tsutsui 	     new_reclen = s_entry1->jreclen;
    567  1.1  tsutsui 	     if( (dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE )
    568  1.1  tsutsui 	     {
    569  1.1  tsutsui 		 dir_index = (dir_index + (SECTOR_SIZE - 1)) &
    570  1.1  tsutsui 		     ~(SECTOR_SIZE - 1);
    571  1.1  tsutsui 	     }
    572  1.1  tsutsui 
    573  1.1  tsutsui 	     memcpy(&jrec, &s_entry1->isorec, sizeof(struct iso_directory_record) -
    574  1.1  tsutsui 		    sizeof(s_entry1->isorec.name));
    575  1.1  tsutsui 
    576  1.1  tsutsui #ifdef APPLE_HYB
    577  1.1  tsutsui 	     /* Use the HFS name if it exists */
    578  1.1  tsutsui 	     if (USE_MAC_NAME(mac_name, s_entry1))
    579  1.1  tsutsui 	       cvt_len = joliet_strlen(s_entry1->hfs_ent->name);
    580  1.1  tsutsui 	     else
    581  1.1  tsutsui #endif /* APPLE_HYB */
    582  1.1  tsutsui 	       cvt_len = joliet_strlen(s_entry1->name);
    583  1.1  tsutsui 
    584  1.1  tsutsui 	     /*
    585  1.1  tsutsui 	      * Fix the record length - this was the non-Joliet version we
    586  1.1  tsutsui 	      * were seeing.
    587  1.1  tsutsui 	      */
    588  1.1  tsutsui 	     jrec.name_len[0] = cvt_len;
    589  1.1  tsutsui 	     jrec.length[0] = s_entry1->jreclen;
    590  1.1  tsutsui 
    591  1.1  tsutsui 	     /*
    592  1.1  tsutsui 	      * If this is a directory, fix the correct size and extent
    593  1.1  tsutsui 	      * number.
    594  1.1  tsutsui 	      */
    595  1.1  tsutsui 	     if( (jrec.flags[0] & 2) != 0 )
    596  1.1  tsutsui 	     {
    597  1.1  tsutsui 		 if(strcmp(s_entry1->name,".") == 0)
    598  1.1  tsutsui 		 {
    599  1.1  tsutsui 		     jrec.name_len[0] = 1;
    600  1.1  tsutsui 		     set_733((char *) jrec.extent, dpnt->jextent);
    601  1.1  tsutsui 		     set_733((char *) jrec.size, ROUND_UP(dpnt->jsize));
    602  1.1  tsutsui 		 }
    603  1.1  tsutsui 		 else if(strcmp(s_entry1->name,"..") == 0)
    604  1.1  tsutsui 		 {
    605  1.1  tsutsui 		     jrec.name_len[0] = 1;
    606  1.1  tsutsui 		     if( dpnt->parent == reloc_dir )
    607  1.1  tsutsui 		     {
    608  1.1  tsutsui 			 set_733((char *) jrec.extent, dpnt->self->parent_rec->filedir->jextent);
    609  1.1  tsutsui 			 set_733((char *) jrec.size, ROUND_UP(dpnt->self->parent_rec->filedir->jsize));
    610  1.1  tsutsui 		     }
    611  1.1  tsutsui 		     else
    612  1.1  tsutsui 
    613  1.1  tsutsui 		     {
    614  1.1  tsutsui 			 set_733((char *) jrec.extent, dpnt->parent->jextent);
    615  1.1  tsutsui 			 set_733((char *) jrec.size, ROUND_UP(dpnt->parent->jsize));
    616  1.1  tsutsui 		     }
    617  1.1  tsutsui 		 }
    618  1.1  tsutsui 		 else
    619  1.1  tsutsui 		 {
    620  1.1  tsutsui 		     if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 )
    621  1.1  tsutsui 		     {
    622  1.1  tsutsui 			 finddir = reloc_dir->subdir;
    623  1.1  tsutsui 		     }
    624  1.1  tsutsui 		     else
    625  1.1  tsutsui 		     {
    626  1.1  tsutsui 			 finddir = dpnt->subdir;
    627  1.1  tsutsui 		     }
    628  1.1  tsutsui 		     while(1==1)
    629  1.1  tsutsui 		     {
    630  1.1  tsutsui 			 if(finddir->self == s_entry1) break;
    631  1.1  tsutsui 			 finddir = finddir->next;
    632  1.1  tsutsui 			 if(!finddir)
    633  1.1  tsutsui 			 {
    634  1.1  tsutsui 			     fprintf(stderr,"Fatal goof - unable to find directory location\n"); exit(1);
    635  1.1  tsutsui 			 }
    636  1.1  tsutsui 		     }
    637  1.1  tsutsui 		     set_733((char *) jrec.extent, finddir->jextent);
    638  1.1  tsutsui 		     set_733((char *) jrec.size, ROUND_UP(finddir->jsize));
    639  1.1  tsutsui 		 }
    640  1.1  tsutsui 	     }
    641  1.1  tsutsui 
    642  1.1  tsutsui 	     memcpy(directory_buffer + dir_index, &jrec,
    643  1.1  tsutsui 		    sizeof(struct iso_directory_record) -
    644  1.1  tsutsui 		    sizeof(s_entry1->isorec.name));
    645  1.1  tsutsui 
    646  1.1  tsutsui 
    647  1.1  tsutsui 	     dir_index += sizeof(struct iso_directory_record) -
    648  1.1  tsutsui 		 sizeof (s_entry1->isorec.name);
    649  1.1  tsutsui 
    650  1.1  tsutsui 	     /*
    651  1.1  tsutsui 	      * Finally dump the Unicode version of the filename.
    652  1.1  tsutsui 	      * Note - . and .. are the same as with non-Joliet discs.
    653  1.1  tsutsui 	      */
    654  1.1  tsutsui 	     if( (jrec.flags[0] & 2) != 0
    655  1.1  tsutsui 		 && strcmp(s_entry1->name, ".") == 0 )
    656  1.1  tsutsui 	     {
    657  1.1  tsutsui 		 directory_buffer[dir_index++] = 0;
    658  1.1  tsutsui 	     }
    659  1.1  tsutsui 	     else if( (jrec.flags[0] & 2) != 0
    660  1.1  tsutsui 		      && strcmp(s_entry1->name, "..") == 0 )
    661  1.1  tsutsui 	     {
    662  1.1  tsutsui 		 directory_buffer[dir_index++] = 1;
    663  1.1  tsutsui 	     }
    664  1.1  tsutsui 	     else
    665  1.1  tsutsui 	     {
    666  1.1  tsutsui #ifdef APPLE_HYB
    667  1.1  tsutsui 	       if (USE_MAC_NAME(mac_name, s_entry1))
    668  1.1  tsutsui 		 /* Use the HFS name if it exists */
    669  1.1  tsutsui 		 convert_to_unicode((u_char *)directory_buffer + dir_index,
    670  1.1  tsutsui 				    cvt_len,
    671  1.1  tsutsui 				    s_entry1->hfs_ent->name);
    672  1.1  tsutsui 	       else
    673  1.1  tsutsui #endif /* APPLE_HYB */
    674  1.1  tsutsui 		 convert_to_unicode((u_char *)directory_buffer + dir_index,
    675  1.1  tsutsui 				    cvt_len,
    676  1.1  tsutsui 				    s_entry1->name);
    677  1.1  tsutsui 		 dir_index += cvt_len;
    678  1.1  tsutsui 	     }
    679  1.1  tsutsui 
    680  1.1  tsutsui 	     if(dir_index & 1)
    681  1.1  tsutsui 	     {
    682  1.1  tsutsui 		 directory_buffer[dir_index++] = 0;
    683  1.1  tsutsui 	     }
    684  1.1  tsutsui 
    685  1.1  tsutsui 	     s_entry = s_entry->jnext;
    686  1.1  tsutsui      }
    687  1.1  tsutsui 
    688  1.1  tsutsui      if(dpnt->jsize != dir_index)
    689  1.1  tsutsui      {
    690  1.1  tsutsui 	 fprintf(stderr,"Unexpected joliet directory length %d %d %s\n",dpnt->jsize,
    691  1.1  tsutsui 		 dir_index, dpnt->de_name);
    692  1.1  tsutsui      }
    693  1.1  tsutsui 
    694  1.1  tsutsui      xfwrite(directory_buffer, 1, total_size, outfile);
    695  1.1  tsutsui      last_extent_written += total_size >> 11;
    696  1.1  tsutsui      free(directory_buffer);
    697  1.1  tsutsui } /* generate_one_joliet_directory(... */
    698  1.1  tsutsui 
    699  1.1  tsutsui static int FDECL1(joliet_sort_n_finish, struct directory *, this_dir)
    700  1.1  tsutsui {
    701  1.1  tsutsui   struct directory_entry  * s_entry;
    702  1.1  tsutsui   int			    status = 0;
    703  1.1  tsutsui 
    704  1.1  tsutsui   /* don't want to skip this directory if it's the reloc_dir at the moment */
    705  1.1  tsutsui   if(this_dir != reloc_dir && this_dir->dir_flags & INHIBIT_JOLIET_ENTRY)
    706  1.1  tsutsui     {
    707  1.1  tsutsui       return 0;
    708  1.1  tsutsui     }
    709  1.1  tsutsui 
    710  1.1  tsutsui   for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
    711  1.1  tsutsui     {
    712  1.1  tsutsui       /* skip hidden entries */
    713  1.1  tsutsui       if(  (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0 )
    714  1.1  tsutsui 	{
    715  1.1  tsutsui 	  continue;
    716  1.1  tsutsui 	}
    717  1.1  tsutsui 
    718  1.1  tsutsui       /*
    719  1.1  tsutsui        * First update the path table sizes for directories.
    720  1.1  tsutsui        *
    721  1.1  tsutsui        * Finally, set the length of the directory entry if Joliet is used.
    722  1.1  tsutsui        * The name is longer, but no Rock Ridge is ever used here, so
    723  1.1  tsutsui        * depending upon the options the entry size might turn out to be about
    724  1.1  tsutsui        * the same.  The Unicode name is always a multiple of 2 bytes, so
    725  1.1  tsutsui        * we always add 1 to make it an even number.
    726  1.1  tsutsui        */
    727  1.1  tsutsui       if(s_entry->isorec.flags[0] ==  2)
    728  1.1  tsutsui 	{
    729  1.1  tsutsui 	  if (strcmp(s_entry->name,".") && strcmp(s_entry->name,".."))
    730  1.1  tsutsui 	    {
    731  1.1  tsutsui #ifdef APPLE_HYB
    732  1.1  tsutsui 	   if (USE_MAC_NAME(mac_name, s_entry))
    733  1.1  tsutsui 	      /* Use the HFS name if it exists */
    734  1.1  tsutsui 	      jpath_table_size += joliet_strlen(s_entry->hfs_ent->name) + sizeof(struct iso_path_table) - 1;
    735  1.1  tsutsui 	   else
    736  1.1  tsutsui #endif /* APPLE_HYB */
    737  1.1  tsutsui 	      jpath_table_size += joliet_strlen(s_entry->name) + sizeof(struct iso_path_table) - 1;
    738  1.1  tsutsui 	      if (jpath_table_size & 1)
    739  1.1  tsutsui 		{
    740  1.1  tsutsui 		  jpath_table_size++;
    741  1.1  tsutsui 		}
    742  1.1  tsutsui 	    }
    743  1.1  tsutsui 	  else
    744  1.1  tsutsui 	    {
    745  1.1  tsutsui 	      if (this_dir == root && strlen(s_entry->name) == 1)
    746  1.1  tsutsui 		{
    747  1.1  tsutsui 		  jpath_table_size += sizeof(struct iso_path_table);
    748  1.1  tsutsui 		  if (jpath_table_size & 1) jpath_table_size++;
    749  1.1  tsutsui 		}
    750  1.1  tsutsui 	    }
    751  1.1  tsutsui 	}
    752  1.1  tsutsui 
    753  1.1  tsutsui       if (strcmp(s_entry->name,".") && strcmp(s_entry->name,".."))
    754  1.1  tsutsui 	{
    755  1.1  tsutsui #ifdef APPLE_HYB
    756  1.1  tsutsui 	 if (USE_MAC_NAME(mac_name, s_entry))
    757  1.1  tsutsui 	  /* Use the HFS name if it exists */
    758  1.1  tsutsui 	  s_entry->jreclen = 	sizeof(struct iso_directory_record)
    759  1.1  tsutsui 	    - sizeof(s_entry->isorec.name)
    760  1.1  tsutsui 	    + joliet_strlen(s_entry->hfs_ent->name)
    761  1.1  tsutsui 	    + 1;
    762  1.1  tsutsui 	 else
    763  1.1  tsutsui #endif /* APPLE_HYB */
    764  1.1  tsutsui 	  s_entry->jreclen = 	sizeof(struct iso_directory_record)
    765  1.1  tsutsui 	    - sizeof(s_entry->isorec.name)
    766  1.1  tsutsui 	    + joliet_strlen(s_entry->name)
    767  1.1  tsutsui 	    + 1;
    768  1.1  tsutsui 	}
    769  1.1  tsutsui       else
    770  1.1  tsutsui 	{
    771  1.1  tsutsui 	  /*
    772  1.1  tsutsui 	   * Special - for '.' and '..' we generate the same records we
    773  1.1  tsutsui 	   * did for non-Joliet discs.
    774  1.1  tsutsui 	   */
    775  1.1  tsutsui 	  s_entry->jreclen = 	sizeof(struct iso_directory_record)
    776  1.1  tsutsui 	    - sizeof(s_entry->isorec.name)
    777  1.1  tsutsui 	    + 1;
    778  1.1  tsutsui 	}
    779  1.1  tsutsui 
    780  1.1  tsutsui 
    781  1.1  tsutsui     }
    782  1.1  tsutsui 
    783  1.1  tsutsui   if( (this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) != 0 )
    784  1.1  tsutsui     {
    785  1.1  tsutsui       return 0;
    786  1.1  tsutsui     }
    787  1.1  tsutsui 
    788  1.1  tsutsui   this_dir->jcontents = this_dir->contents;
    789  1.1  tsutsui   status = joliet_sort_directory(&this_dir->jcontents);
    790  1.1  tsutsui 
    791  1.1  tsutsui   /*
    792  1.1  tsutsui    * Now go through the directory and figure out how large this one will be.
    793  1.1  tsutsui    * Do not split a directory entry across a sector boundary
    794  1.1  tsutsui    */
    795  1.1  tsutsui   s_entry = this_dir->jcontents;
    796  1.1  tsutsui /*
    797  1.1  tsutsui  * XXX Is it ok to comment this out?
    798  1.1  tsutsui  */
    799  1.1  tsutsui /*XXX JS  this_dir->ce_bytes = 0;*/
    800  1.1  tsutsui   for(s_entry = this_dir->jcontents; s_entry; s_entry = s_entry->jnext)
    801  1.1  tsutsui     {
    802  1.1  tsutsui       int jreclen;
    803  1.1  tsutsui 
    804  1.1  tsutsui       if( (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0 )
    805  1.1  tsutsui 	{
    806  1.1  tsutsui 	  continue;
    807  1.1  tsutsui 	}
    808  1.1  tsutsui 
    809  1.1  tsutsui       jreclen = s_entry->jreclen;
    810  1.1  tsutsui 
    811  1.1  tsutsui       if ((this_dir->jsize & (SECTOR_SIZE - 1)) + jreclen >= SECTOR_SIZE)
    812  1.1  tsutsui 	{
    813  1.1  tsutsui 	  this_dir->jsize = (this_dir->jsize + (SECTOR_SIZE - 1)) &
    814  1.1  tsutsui 	    ~(SECTOR_SIZE - 1);
    815  1.1  tsutsui 	}
    816  1.1  tsutsui       this_dir->jsize += jreclen;
    817  1.1  tsutsui     }
    818  1.1  tsutsui   return status;
    819  1.1  tsutsui }
    820  1.1  tsutsui 
    821  1.1  tsutsui /*
    822  1.1  tsutsui  * Similar to the iso9660 case, except here we perform a full sort based upon the
    823  1.1  tsutsui  * regular name of the file, not the 8.3 version.
    824  1.1  tsutsui  */
    825  1.1  tsutsui static int FDECL2(joliet_compare_dirs, const void *, rr, const void *, ll)
    826  1.1  tsutsui {
    827  1.1  tsutsui      char * rpnt, *lpnt;
    828  1.1  tsutsui      struct directory_entry ** r, **l;
    829  1.1  tsutsui 
    830  1.1  tsutsui      r = (struct directory_entry **) rr;
    831  1.1  tsutsui      l = (struct directory_entry **) ll;
    832  1.1  tsutsui      rpnt = (*r)->name;
    833  1.1  tsutsui      lpnt = (*l)->name;
    834  1.1  tsutsui 
    835  1.1  tsutsui      /*
    836  1.1  tsutsui       * If the entries are the same, this is an error.
    837  1.1  tsutsui       */
    838  1.1  tsutsui      if( strcmp(rpnt, lpnt) == 0 )
    839  1.1  tsutsui        {
    840  1.1  tsutsui 	 sort_goof++;
    841  1.1  tsutsui        }
    842  1.1  tsutsui 
    843  1.1  tsutsui      /*
    844  1.1  tsutsui       *  Put the '.' and '..' entries on the head of the sorted list.
    845  1.1  tsutsui       *  For normal ASCII, this always happens to be the case, but out of
    846  1.1  tsutsui       *  band characters cause this not to be the case sometimes.
    847  1.1  tsutsui       */
    848  1.1  tsutsui      if( strcmp(rpnt, ".") == 0 ) return -1;
    849  1.1  tsutsui      if( strcmp(lpnt, ".") == 0 ) return  1;
    850  1.1  tsutsui 
    851  1.1  tsutsui      if( strcmp(rpnt, "..") == 0 ) return -1;
    852  1.1  tsutsui      if( strcmp(lpnt, "..") == 0 ) return  1;
    853  1.1  tsutsui 
    854  1.1  tsutsui      while(*rpnt && *lpnt)
    855  1.1  tsutsui      {
    856  1.1  tsutsui 	  if(*rpnt == ';' && *lpnt != ';') return -1;
    857  1.1  tsutsui 	  if(*rpnt != ';' && *lpnt == ';') return 1;
    858  1.1  tsutsui 
    859  1.1  tsutsui 	  if(*rpnt == ';' && *lpnt == ';') return 0;
    860  1.1  tsutsui 
    861  1.1  tsutsui 	  /*
    862  1.1  tsutsui 	   * Extensions are not special here.  Don't treat the dot as something that
    863  1.1  tsutsui 	   * must be bumped to the start of the list.
    864  1.1  tsutsui 	   */
    865  1.1  tsutsui #if 0
    866  1.1  tsutsui 	  if(*rpnt == '.' && *lpnt != '.') return -1;
    867  1.1  tsutsui 	  if(*rpnt != '.' && *lpnt == '.') return 1;
    868  1.1  tsutsui #endif
    869  1.1  tsutsui 
    870  1.1  tsutsui 	  if(*rpnt < *lpnt) return -1;
    871  1.1  tsutsui 	  if(*rpnt > *lpnt) return 1;
    872  1.1  tsutsui 	  rpnt++;  lpnt++;
    873  1.1  tsutsui      }
    874  1.1  tsutsui      if(*rpnt) return 1;
    875  1.1  tsutsui      if(*lpnt) return -1;
    876  1.1  tsutsui      return 0;
    877  1.1  tsutsui }
    878  1.1  tsutsui 
    879  1.1  tsutsui 
    880  1.1  tsutsui /*
    881  1.1  tsutsui  * Function:		sort_directory
    882  1.1  tsutsui  *
    883  1.1  tsutsui  * Purpose:		Sort the directory in the appropriate ISO9660
    884  1.1  tsutsui  *			order.
    885  1.1  tsutsui  *
    886  1.1  tsutsui  * Notes:		Returns 0 if OK, returns > 0 if an error occurred.
    887  1.1  tsutsui  */
    888  1.1  tsutsui static int FDECL1(joliet_sort_directory, struct directory_entry **, sort_dir)
    889  1.1  tsutsui {
    890  1.1  tsutsui      int dcount = 0;
    891  1.1  tsutsui      int i;
    892  1.1  tsutsui      struct directory_entry * s_entry;
    893  1.1  tsutsui      struct directory_entry ** sortlist;
    894  1.1  tsutsui 
    895  1.1  tsutsui      s_entry = *sort_dir;
    896  1.1  tsutsui      while(s_entry)
    897  1.1  tsutsui      {
    898  1.1  tsutsui 	  /* skip hidden entries */
    899  1.1  tsutsui 	  if (!(s_entry->de_flags & INHIBIT_JOLIET_ENTRY))
    900  1.1  tsutsui 	    dcount++;
    901  1.1  tsutsui 	  s_entry = s_entry->next;
    902  1.1  tsutsui      }
    903  1.1  tsutsui 
    904  1.1  tsutsui      /*
    905  1.1  tsutsui       * OK, now we know how many there are.  Build a vector for sorting.
    906  1.1  tsutsui       */
    907  1.1  tsutsui      sortlist =   (struct directory_entry **)
    908  1.1  tsutsui 	  e_malloc(sizeof(struct directory_entry *) * dcount);
    909  1.1  tsutsui 
    910  1.1  tsutsui      dcount = 0;
    911  1.1  tsutsui      s_entry = *sort_dir;
    912  1.1  tsutsui      while(s_entry)
    913  1.1  tsutsui      {
    914  1.1  tsutsui 	  /* skip hidden entries */
    915  1.1  tsutsui 	  if (!(s_entry->de_flags & INHIBIT_JOLIET_ENTRY)) {
    916  1.1  tsutsui 	    sortlist[dcount] = s_entry;
    917  1.1  tsutsui 	    dcount++;
    918  1.1  tsutsui 	  }
    919  1.1  tsutsui 	  s_entry = s_entry->next;
    920  1.1  tsutsui      }
    921  1.1  tsutsui 
    922  1.1  tsutsui      sort_goof = 0;
    923  1.1  tsutsui #ifdef	__STDC__
    924  1.1  tsutsui      qsort(sortlist, dcount, sizeof(struct directory_entry *),
    925  1.1  tsutsui 	   (int (*)(const void *, const void *))joliet_compare_dirs);
    926  1.1  tsutsui #else
    927  1.1  tsutsui      qsort(sortlist, dcount, sizeof(struct directory_entry *),
    928  1.1  tsutsui 	   joliet_compare_dirs);
    929  1.1  tsutsui #endif
    930  1.1  tsutsui 
    931  1.1  tsutsui      /*
    932  1.1  tsutsui       * Now reassemble the linked list in the proper sorted order
    933  1.1  tsutsui       */
    934  1.1  tsutsui      for(i=0; i<dcount-1; i++)
    935  1.1  tsutsui      {
    936  1.1  tsutsui 	  sortlist[i]->jnext = sortlist[i+1];
    937  1.1  tsutsui      }
    938  1.1  tsutsui 
    939  1.1  tsutsui      sortlist[dcount-1]->jnext = NULL;
    940  1.1  tsutsui      *sort_dir = sortlist[0];
    941  1.1  tsutsui 
    942  1.1  tsutsui      free(sortlist);
    943  1.1  tsutsui      return sort_goof;
    944  1.1  tsutsui }
    945  1.1  tsutsui 
    946  1.1  tsutsui int FDECL1(joliet_sort_tree, struct directory *, node)
    947  1.1  tsutsui {
    948  1.1  tsutsui   struct directory * dpnt;
    949  1.1  tsutsui   int ret = 0;
    950  1.1  tsutsui 
    951  1.1  tsutsui   dpnt = node;
    952  1.1  tsutsui 
    953  1.1  tsutsui   while (dpnt){
    954  1.1  tsutsui     ret = joliet_sort_n_finish(dpnt);
    955  1.1  tsutsui     if( ret )
    956  1.1  tsutsui       {
    957  1.1  tsutsui 	break;
    958  1.1  tsutsui       }
    959  1.1  tsutsui     if(dpnt->subdir) ret = joliet_sort_tree(dpnt->subdir);
    960  1.1  tsutsui     if( ret )
    961  1.1  tsutsui       {
    962  1.1  tsutsui 	break;
    963  1.1  tsutsui       }
    964  1.1  tsutsui     dpnt = dpnt->next;
    965  1.1  tsutsui   }
    966  1.1  tsutsui   return ret;
    967  1.1  tsutsui }
    968  1.1  tsutsui 
    969  1.1  tsutsui static void FDECL2(generate_joliet_directories, struct directory *, node, FILE*, outfile){
    970  1.1  tsutsui   struct directory * dpnt;
    971  1.1  tsutsui 
    972  1.1  tsutsui   dpnt = node;
    973  1.1  tsutsui 
    974  1.1  tsutsui   while (dpnt)
    975  1.1  tsutsui     {
    976  1.1  tsutsui       if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 )
    977  1.1  tsutsui 	{
    978  1.1  tsutsui 	  /*
    979  1.1  tsutsui 	   * In theory we should never reuse a directory, so this doesn't
    980  1.1  tsutsui 	   * make much sense.
    981  1.1  tsutsui 	   */
    982  1.1  tsutsui 	  if( dpnt->jextent > session_start )
    983  1.1  tsutsui 	    {
    984  1.1  tsutsui 	      generate_one_joliet_directory(dpnt, outfile);
    985  1.1  tsutsui 	    }
    986  1.1  tsutsui 	}
    987  1.1  tsutsui       /* skip if hidden - but not for the rr_moved dir */
    988  1.1  tsutsui       if(dpnt->subdir && (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir))
    989  1.1  tsutsui 	generate_joliet_directories(dpnt->subdir, outfile);
    990  1.1  tsutsui       dpnt = dpnt->next;
    991  1.1  tsutsui     }
    992  1.1  tsutsui }
    993  1.1  tsutsui 
    994  1.1  tsutsui 
    995  1.1  tsutsui /*
    996  1.1  tsutsui  * Function to write the EVD for the disc.
    997  1.1  tsutsui  */
    998  1.1  tsutsui static int FDECL1(jpathtab_write, FILE *, outfile)
    999  1.1  tsutsui {
   1000  1.1  tsutsui   /*
   1001  1.1  tsutsui    * Next we write the path tables
   1002  1.1  tsutsui    */
   1003  1.1  tsutsui   xfwrite(jpath_table_l, 1, jpath_blocks << 11, outfile);
   1004  1.1  tsutsui   xfwrite(jpath_table_m, 1, jpath_blocks << 11, outfile);
   1005  1.1  tsutsui   last_extent_written += 2*jpath_blocks;
   1006  1.1  tsutsui   free(jpath_table_l);
   1007  1.1  tsutsui   free(jpath_table_m);
   1008  1.1  tsutsui   jpath_table_l = NULL;
   1009  1.1  tsutsui   jpath_table_m = NULL;
   1010  1.1  tsutsui   return 0;
   1011  1.1  tsutsui }
   1012  1.1  tsutsui 
   1013  1.1  tsutsui static int FDECL1(jdirtree_size, int, starting_extent)
   1014  1.1  tsutsui {
   1015  1.1  tsutsui   assign_joliet_directory_addresses(root);
   1016  1.1  tsutsui   return 0;
   1017  1.1  tsutsui }
   1018  1.1  tsutsui 
   1019  1.1  tsutsui static int jroot_gen()
   1020  1.1  tsutsui {
   1021  1.1  tsutsui      jroot_record.length[0] = 1 + sizeof(struct iso_directory_record)
   1022  1.1  tsutsui 	  - sizeof(jroot_record.name);
   1023  1.1  tsutsui      jroot_record.ext_attr_length[0] = 0;
   1024  1.1  tsutsui      set_733((char *) jroot_record.extent, root->jextent);
   1025  1.1  tsutsui      set_733((char *) jroot_record.size, ROUND_UP(root->jsize));
   1026  1.1  tsutsui      iso9660_date(jroot_record.date, root_statbuf.st_mtime);
   1027  1.1  tsutsui      jroot_record.flags[0] = 2;
   1028  1.1  tsutsui      jroot_record.file_unit_size[0] = 0;
   1029  1.1  tsutsui      jroot_record.interleave[0] = 0;
   1030  1.1  tsutsui      set_723(jroot_record.volume_sequence_number, volume_sequence_number);
   1031  1.1  tsutsui      jroot_record.name_len[0] = 1;
   1032  1.1  tsutsui      return 0;
   1033  1.1  tsutsui }
   1034  1.1  tsutsui 
   1035  1.1  tsutsui static int FDECL1(jdirtree_write, FILE *, outfile)
   1036  1.1  tsutsui {
   1037  1.1  tsutsui   generate_joliet_directories(root, outfile);
   1038  1.1  tsutsui   return 0;
   1039  1.1  tsutsui }
   1040  1.1  tsutsui 
   1041  1.1  tsutsui /*
   1042  1.1  tsutsui  * Function to write the EVD for the disc.
   1043  1.1  tsutsui  */
   1044  1.1  tsutsui static int FDECL1(jvd_write, FILE *, outfile)
   1045  1.1  tsutsui {
   1046  1.1  tsutsui   struct iso_primary_descriptor jvol_desc;
   1047  1.1  tsutsui 
   1048  1.1  tsutsui   /*
   1049  1.1  tsutsui    * Next we write out the boot volume descriptor for the disc
   1050  1.1  tsutsui    */
   1051  1.1  tsutsui   jvol_desc = vol_desc;
   1052  1.1  tsutsui   get_joliet_vol_desc(&jvol_desc);
   1053  1.1  tsutsui   xfwrite(&jvol_desc, 1, 2048, outfile);
   1054  1.1  tsutsui   last_extent_written ++;
   1055  1.1  tsutsui   return 0;
   1056  1.1  tsutsui }
   1057  1.1  tsutsui 
   1058  1.1  tsutsui /*
   1059  1.1  tsutsui  * Functions to describe padding block at the start of the disc.
   1060  1.1  tsutsui  */
   1061  1.1  tsutsui static int FDECL1(jpathtab_size, int, starting_extent)
   1062  1.1  tsutsui {
   1063  1.1  tsutsui   jpath_table[0] = starting_extent;
   1064  1.1  tsutsui   jpath_table[1] = 0;
   1065  1.1  tsutsui   jpath_table[2] = jpath_table[0] + jpath_blocks;
   1066  1.1  tsutsui   jpath_table[3] = 0;
   1067  1.1  tsutsui 
   1068  1.1  tsutsui   last_extent += 2*jpath_blocks;
   1069  1.1  tsutsui   return 0;
   1070  1.1  tsutsui }
   1071  1.1  tsutsui 
   1072  1.1  tsutsui struct output_fragment joliet_desc    = {NULL, oneblock_size, jroot_gen,jvd_write};
   1073  1.1  tsutsui struct output_fragment jpathtable_desc= {NULL, jpathtab_size, generate_joliet_path_tables,     jpathtab_write};
   1074  1.1  tsutsui struct output_fragment jdirtree_desc  = {NULL, jdirtree_size, NULL,     jdirtree_write};
   1075