joliet.c
上传用户:xiejiait
上传日期:2007-01-06
资源大小:881k
文件大小:28k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

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