⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 joliet.c

📁 刻录光盘的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * File joliet.c - handle Win95/WinNT long file/unicode extensions for iso9660.   Copyright 1997 Eric Youngdale.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2, or (at your option)   any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */static char rcsid[] ="$Id: joliet.c,v 1.14 1999/03/07 17:41:19 eric Exp $";/* * Joliet extensions for ISO9660.  These are spottily documented by * Microsoft.  In their infinite stupidity, they completely ignored * the possibility of using an SUSP record with the long filename * in it, and instead wrote out a duplicate directory tree with the * long filenames in it. * * I am not sure why they did this.  One reason is that they get the path * tables with the long filenames in them. * * There are two basic principles to Joliet, and the non-Unicode variant * known as Romeo.  Long filenames seem to be the main one, and the second * is that the character set and a few other things is substantially relaxed. * * The SVD is identical to the PVD, except: * *	Id is 2, not 1 (indicates SVD). *	escape_sequences contains UCS-2 indicator (levels 1, 2 or 3). *	The root directory record points to a different extent (with different *		size). *	There are different path tables for the two sets of directory trees. * * The following fields are recorded in Unicode: *	system_id *	volume_id *	volume_set_id *	publisher_id *	preparer_id *	application_id *	copyright_file_id *	abstract_file_id *	bibliographic_file_id * * Unicode strings are always encoded in big-endian format. * * In a directory record, everything is the same as with iso9660, except * that the name is recorded in unicode.  The name length is specified in * total bytes, not in number of unicode characters. * * The character set used for the names is different with UCS - the * restrictions are that the following are not allowed: * *	Characters (00)(00) through (00)(1f) (control chars) *	(00)(2a) '*' *	(00)(2f) '/' *	(00)(3a) ':' *	(00)(3b) ';' *	(00)(3f) '?' *	(00)(5c) '\' */#include "config.h"#include "mkisofs.h"#include "iso9660.h"#include <stdlib.h>#include <time.h>#ifdef	USE_LIBSCHILY#include <standard.h>#endifstatic int jpath_table_index;static struct directory ** jpathlist;static int next_jpath_index  = 1;static int sort_goof;static int generate_joliet_path_tables	__PR((void));static int DECL(joliet_sort_directory, (struct directory_entry ** sort_dir));static void DECL(assign_joliet_directory_addresses, (struct directory * node));static int jroot_gen	__PR((void));/*  * Function:		convert_to_unicode * * Purpose:		Perform a 1/2 assed unicode conversion on a text *			string. * * Notes:		 */static void FDECL3(convert_to_unicode, unsigned char *, buffer, int, size, char *, source ){  unsigned char * tmpbuf;  int i;  int j;  /*   * If we get a NULL pointer for the source, it means we have an inplace   * copy, and we need to make a temporary working copy first.   */  if( source == NULL )    {      tmpbuf = (u_char *) e_malloc(size);      memcpy( tmpbuf, buffer, size);    }  else    {      tmpbuf = (u_char *)source;    }  /*   * Now start copying characters.  If the size was specified to be 0, then   * assume the input was 0 terminated.   */  j = 0;  for(i=0; (i+1) < size ; i += 2, j++)	/* Size may be odd !!! */    {      buffer[i]       = 0;	/*	 * JS integrated from: Achim_Kaiser@t-online.de	 *	 * Let all valid unicode characters pass through (assuming ISO-8859-1).	 * Others are set to '_' . 	 */ 	if( tmpbuf[j] != 0 &&  	   (tmpbuf[j] <= 0x1f || (tmpbuf[j] >= 0x7F && tmpbuf[j] <= 0xA0)) )	{	  buffer[i+1]     = '_';	}      else	{	  switch(tmpbuf[j])	    {	    case '*':	    case '/':	    case ':':	    case ';':	    case '?':	    case '\\':	      /*	       * Even Joliet has some standards as to what is allowed in a pathname.	       * Pretty tame in comparison to what DOS restricts you to.	       */	      buffer[i+1]     = '_';	      break;	    default:	      buffer[i+1]     = tmpbuf[j];	      break;	    }	}   }   if( size&1 )				/* beautification */   {      buffer[size-1] = 0;    }  if( source == NULL )    {      free(tmpbuf);    }}/*  * Function:		joliet_strlen * * Purpose:		Return length in bytes of string after conversion to unicode. * * Notes:		This is provided mainly as a convenience so that when more intelligent *			Unicode conversion for either Multibyte or 8-bit codes is available that *			we can easily adapt. */static int FDECL1(joliet_strlen, const char *, string){  int rtn;  rtn = strlen(string) << 1;  /*    * We do clamp the maximum length of a Joliet string to be the   * maximum path size.  This helps to ensure that we don't completely   * bolix things up with very long paths.    The Joliet specs say   * that the maximum length is 128 bytes, or 64 unicode characters.   */  if( rtn > 0x80)    {      rtn = 0x80;    }  return rtn;}/*  * Function:		get_joliet_vol_desc * * Purpose:		generate a Joliet compatible volume desc. * * Notes:		Assume that we have the non-joliet vol desc *			already present in the buffer.  Just modifiy the *			appropriate fields. */static void FDECL1(get_joliet_vol_desc, struct iso_primary_descriptor *, jvol_desc){  jvol_desc->type[0] = ISO_VD_SUPPLEMENTARY;  /*   * For now, always do Unicode level 3.  I don't really know what 1 and 2   * are - perhaps a more limited Unicode set.   *   * FIXME(eric) - how does Romeo fit in here?  As mkisofs just   * "expands" 8 bit character codes to 16 bits and does nothing   * special with the Unicode characters, therefore shouldn't mkisofs   * really be stating that it's using UCS-2 Level 1, not Level 3 for   * the Joliet directory tree.     */  strcpy(jvol_desc->escape_sequences, "%/@");  /*   * Until we have Unicode path tables, leave these unset.   */  set_733((char *) jvol_desc->path_table_size, jpath_table_size);  set_731(jvol_desc->type_l_path_table,     jpath_table[0]);  set_731(jvol_desc->opt_type_l_path_table, jpath_table[1]);  set_732(jvol_desc->type_m_path_table,     jpath_table[2]);  set_732(jvol_desc->opt_type_m_path_table, jpath_table[3]);  /*   * Set this one up.   */  memcpy(jvol_desc->root_directory_record, &jroot_record, 	 offsetof(struct iso_directory_record, name[0]) + 1);  /*   * Finally, we have a bunch of strings to convert to Unicode.   * FIXME(eric) - I don't know how to do this in general, so we will   * just be really lazy and do a char -> short conversion.  We probably   * will want to filter any characters >= 0x80.   */  convert_to_unicode((u_char *)jvol_desc->system_id, sizeof(jvol_desc->system_id), NULL);  convert_to_unicode((u_char *)jvol_desc->volume_id, sizeof(jvol_desc->volume_id), NULL);  convert_to_unicode((u_char *)jvol_desc->volume_set_id, sizeof(jvol_desc->volume_set_id), NULL);  convert_to_unicode((u_char *)jvol_desc->publisher_id, sizeof(jvol_desc->publisher_id), NULL);  convert_to_unicode((u_char *)jvol_desc->preparer_id, sizeof(jvol_desc->preparer_id), NULL);  convert_to_unicode((u_char *)jvol_desc->application_id, sizeof(jvol_desc->application_id), NULL);  convert_to_unicode((u_char *)jvol_desc->copyright_file_id, sizeof(jvol_desc->copyright_file_id), NULL);  convert_to_unicode((u_char *)jvol_desc->abstract_file_id, sizeof(jvol_desc->abstract_file_id), NULL);  convert_to_unicode((u_char *)jvol_desc->bibliographic_file_id, sizeof(jvol_desc->bibliographic_file_id), NULL);}static void FDECL1(assign_joliet_directory_addresses, struct directory *, node){     int		dir_size;     struct directory * dpnt;     dpnt = node;          while (dpnt)     {	 if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 )	 {	     /*	      * If we already have an extent for this (i.e. it came from	      * a multisession disc), then don't reassign a new extent.	      */	     dpnt->jpath_index = next_jpath_index++;	     if( dpnt->jextent == 0 )	     {		 dpnt->jextent = last_extent;		 dir_size = (dpnt->jsize + (SECTOR_SIZE - 1)) >> 11;		 last_extent += dir_size;	     }	 }	 /* skip if hidden - but not for the rr_moved dir */	 if(dpnt->subdir && (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir)) 	 {	     assign_joliet_directory_addresses(dpnt->subdir);	 }	 dpnt = dpnt->next;     }}static void FDECL1(build_jpathlist, struct directory *, node){     struct directory * dpnt;          dpnt = node;          while (dpnt)     {       if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 )	 {	   jpathlist[dpnt->jpath_index] = dpnt;	 }       if(dpnt->subdir) build_jpathlist(dpnt->subdir);       dpnt = dpnt->next;     }} /* build_jpathlist(... */static int FDECL2(joliet_compare_paths, void const *, r, void const *, l) {  struct directory const *ll = *(struct directory * const *)l;  struct directory const *rr = *(struct directory * const *)r;  int rparent, lparent;  rparent = rr->parent->jpath_index;  lparent = ll->parent->jpath_index;  if( rr->parent == reloc_dir )    {      rparent = rr->self->parent_rec->filedir->jpath_index;    }  if( ll->parent == reloc_dir )    {      lparent = ll->self->parent_rec->filedir->jpath_index;    }  if (rparent < lparent)  {       return -1;  }  if (rparent > lparent)   {       return 1;  }  return strcmp(rr->self->name, ll->self->name);  } /* compare_paths(... */static int generate_joliet_path_tables(){  struct directory_entry * de;  struct directory	 * dpnt;  int			   fix;  int			   j;  int			   namelen;  char			 * npnt;  char			 * npnt1;  int			   tablesize;  /*   * First allocate memory for the tables and initialize the memory    */  tablesize = jpath_blocks << 11;  jpath_table_m = (char *) e_malloc(tablesize);  jpath_table_l = (char *) e_malloc(tablesize);  memset(jpath_table_l, 0, tablesize);  memset(jpath_table_m, 0, tablesize);  if( next_jpath_index > 0xffff )  {#ifdef	USE_LIBSCHILY      comerrno(EX_BAD, "Unable to generate sane path tables - too many directories (%d)\n",	      next_jpath_index);#else      fprintf(stderr, "Unable to generate sane path tables - too many directories (%d)\n",	      next_jpath_index);      exit(1);#endif  }  /*   * Now start filling in the path tables.  Start with root directory    */  jpath_table_index = 0;  jpathlist = (struct directory **) e_malloc(sizeof(struct directory *) 					    * next_jpath_index);  memset(jpathlist, 0, sizeof(struct directory *) * next_jpath_index);  build_jpathlist(root);  do  {       fix = 0;#ifdef	__STDC__       qsort(&jpathlist[1], next_jpath_index-1, sizeof(struct directory *), 	     (int (*)(const void *, const void *))joliet_compare_paths);#else       qsort(&jpathlist[1], next_jpath_index-1, sizeof(struct directory *), 	     joliet_compare_paths);#endif       for(j=1; j<next_jpath_index; j++)       {	    if(jpathlist[j]->jpath_index != j)	    {		 jpathlist[j]->jpath_index = j;		 fix++;	    }       }  } while(fix);  for(j=1; j<next_jpath_index; j++)  {       dpnt = jpathlist[j];       if(!dpnt)       {#ifdef	USE_LIBSCHILY	    comerrno(EX_BAD, "Entry %d not in path tables\n", j);#else	    fprintf(stderr,"Entry %d not in path tables\n", j);	    exit(1);#endif       }       npnt = dpnt->de_name;              npnt1 = strrchr(npnt, PATH_SEPARATOR);       if(npnt1)        { 	    npnt = npnt1 + 1;       }              de = dpnt->self;       if(!de)        {#ifdef	USE_LIBSCHILY	    comerrno(EX_BAD, "Fatal Joliet goof - directory has amnesia\n"); #else	    fprintf(stderr,"Fatal Joliet goof - directory has amnesia\n"); 	    exit(1);#endif       }              namelen = joliet_strlen(de->name);       if( dpnt == root )	 {	   jpath_table_l[jpath_table_index] = 1;	   jpath_table_m[jpath_table_index] = 1;	 }       else	 {	   jpath_table_l[jpath_table_index] = namelen;	   jpath_table_m[jpath_table_index] = namelen;	 }       jpath_table_index += 2;              set_731(jpath_table_l + jpath_table_index, dpnt->jextent);        set_732(jpath_table_m + jpath_table_index, dpnt->jextent);        jpath_table_index += 4;              if( dpnt->parent != reloc_dir )	 {	   set_721(jpath_table_l + jpath_table_index, 		   dpnt->parent->jpath_index); 	   set_722(jpath_table_m + jpath_table_index, 		   dpnt->parent->jpath_index); 	 }       else	 {	   set_721(jpath_table_l + jpath_table_index, 		   dpnt->self->parent_rec->filedir->jpath_index); 	   set_722(jpath_table_m + jpath_table_index, 		   dpnt->self->parent_rec->filedir->jpath_index); 	 }       jpath_table_index += 2;              /*	* The root directory is still represented in non-unicode fashion.	*/       if( dpnt == root )	 {	   jpath_table_l[jpath_table_index] = 0;	   jpath_table_m[jpath_table_index] = 0;	   jpath_table_index ++;	 }       else	 {	   convert_to_unicode((u_char *)jpath_table_l + jpath_table_index,  			      namelen, de->name);	   convert_to_unicode((u_char *)jpath_table_m + jpath_table_index, 			      namelen, de->name);	   jpath_table_index += namelen;	 }       if(jpath_table_index & 1)        {	    jpath_table_index++;  /* For odd lengths we pad */       }  }    free(jpathlist);  if(jpath_table_index != jpath_table_size)  {#ifdef	USE_LIBSCHILY       errmsgno(EX_BAD, "Joliet path table lengths do not match %d expected: %d\n",	       jpath_table_index,	       jpath_table_size);#else       fprintf(stderr, "Joliet path table lengths do not match %d expected: %d\n",	       jpath_table_index,	       jpath_table_size);#endif  }  return 0;} /* generate_path_tables(... */static void FDECL2(generate_one_joliet_directory, struct directory *, dpnt, FILE *, outfile){     unsigned int			  dir_index;     char				* directory_buffer;     int				  new_reclen;     struct directory_entry		* s_entry;     struct directory_entry		* s_entry1;     struct iso_directory_record	  jrec;     unsigned int			  total_size;     int				  cvt_len;     struct directory			* finddir;          total_size = (dpnt->jsize + (SECTOR_SIZE - 1)) &  ~(SECTOR_SIZE - 1);     directory_buffer = (char *) e_malloc(total_size);     memset(directory_buffer, 0, total_size);     dir_index = 0;          s_entry = dpnt->jcontents;     while(s_entry)      {	     if(s_entry->de_flags & INHIBIT_JOLIET_ENTRY) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -