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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*
  2.  * File name.c - map full Unix file names to unique 8.3 names that
  3.  * would be valid on DOS.
  4.  *
  5.    Written by Eric Youngdale (1993).
  6.    Copyright 1993 Yggdrasil Computing, Incorporated
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2, or (at your option)
  10.    any later version.
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18. static char rcsid[] ="$Id: name.c,v 1.11 1999/03/02 03:41:26 eric Exp $";
  19. #include "config.h"
  20. #include "mkisofs.h"
  21. #include <ctype.h>
  22. extern int allow_leading_dots;
  23.    
  24. /*
  25.  * Function: iso9660_file_length
  26.  *
  27.  * Purpose: Map file name to 8.3 format, return length
  28.  * of result.
  29.  *
  30.  * Arguments: name file name we need to map.
  31.  * sresult directory entry structure to contain mapped name.
  32.  * dirflag flag indicating whether this is a directory or not.
  33.  *
  34.  * Notes: This procedure probably needs to be rationalized somehow.
  35.  * New options to affect the behavior of this function
  36.  * would also be nice to have.
  37.  */
  38. int FDECL3(iso9660_file_length,
  39.    const char*, name, 
  40.    struct directory_entry *, sresult, 
  41.    int, dirflag)
  42. {
  43.   char * c;
  44.   int   chars_after_dot  = 0;
  45.   int   chars_before_dot = 0;
  46.   int   current_length   = 0;
  47.   int   extra    = 0;
  48.   int   ignore    = 0;
  49.   char * last_dot;
  50.   const char * pnt;
  51.   int   priority    = 32767;
  52.   char * result;
  53.   int   seen_dot    = 0;
  54.   int   seen_semic    = 0;
  55.   int   tildes    = 0;
  56.   result = sresult->isorec.name;
  57.   if (sresult->priority)
  58.     priority = sresult->priority;
  59.   /*
  60.    * For the '.' entry, generate the correct record, and return
  61.    * 1 for the length.
  62.    */
  63.   if(strcmp(name,".") == 0)
  64.     {
  65.       if(result) 
  66. {
  67.   *result = 0;
  68. }
  69.       return 1;
  70.     }
  71.   /*
  72.    * For the '..' entry, generate the correct record, and return
  73.    * 1 for the length.
  74.    */
  75.   if(strcmp(name,"..") == 0)
  76.     {
  77.       if(result) 
  78. {
  79.   *result++ = 1;
  80.   *result++ = 0;
  81. }
  82.       return 1;
  83.     }
  84.   /*
  85.    * Now scan the directory one character at a time, and figure out
  86.    * what to do.
  87.    */
  88.   pnt = name;
  89.   /*
  90.    * Find the '.' that we intend to use for the extension.  Usually this
  91.    * is the last dot, but if we have . followed by nothing or a ~, we
  92.    * would consider this to be unsatisfactory, and we keep searching.
  93.    */
  94.   last_dot = strrchr (pnt,'.');
  95.   if(    (last_dot != NULL)
  96.       && (    (last_dot[1] == '~')
  97.      || (last_dot[1] == '')) )
  98.     {
  99.       c = last_dot;
  100.       *c = '';
  101.       last_dot = strrchr (pnt,'.');
  102.       *c = '.';
  103.     }
  104.   while(*pnt)
  105.     {
  106. #ifdef VMS
  107.       if( strcmp(pnt,".DIR;1") == 0 ) 
  108. {
  109.   break;
  110. }
  111. #endif
  112.       /*
  113.        * This character indicates a Unix style of backup file
  114.        * generated by some editors.  Lower the priority of
  115.        * the file.
  116.        */
  117.       if(*pnt == '#') 
  118. {
  119.   priority = 1; 
  120.   pnt++; 
  121.   continue; 
  122. }
  123.       /*
  124.        * This character indicates a Unix style of backup file
  125.        * generated by some editors.  Lower the priority of
  126.        * the file.
  127.        */
  128.       if(*pnt == '~') 
  129. {
  130.   priority = 1; 
  131.   tildes++; 
  132.   pnt++; 
  133.   continue;
  134. }
  135.       /*
  136.        * This might come up if we had some joker already try and put
  137.        * iso9660 version numbers into the file names.  This would be
  138.        * a silly thing to do on a Unix box, but we check for it
  139.        * anyways.  If we see this, then we don't have to add our
  140.        * own version number at the end.
  141.        * UNLESS the ';' is part of the filename and no version
  142.        * number is following. [VK]
  143.        */
  144.        if(*pnt == ';')
  145.  {
  146.    /* [VK] */
  147.    if (pnt[1] != '' && (pnt[1] < '0' || pnt[1] > '9'))
  148.      {
  149.        pnt++;
  150.        ignore++;
  151.        continue;
  152.      }
  153.  }
  154.       /*
  155.        * If we have a name with multiple '.' characters, we ignore everything
  156.        * after we have gotten the extension.
  157.        */
  158.       if(ignore) 
  159. {
  160.   pnt++; 
  161.   continue;
  162. }
  163.       /*
  164.        * Spin past any iso9660 version number we might have.
  165.        */
  166.       if(seen_semic)
  167. {
  168.   if(*pnt >= '0' && *pnt <= '9') 
  169.     {
  170.       *result++ = *pnt;
  171.     }
  172.   extra++;
  173.   pnt++;
  174.   continue;
  175. }
  176. /*
  177.  * If we have full names, the names we generate will not
  178.  * work on a DOS machine, since they are not guaranteed
  179.  * to be 8.3.  Nonetheless, in many cases this is a useful
  180.  * option.  We still only allow one '.' character in the
  181.  * name, however.
  182.  */
  183. /*
  184.  *  Multiple '.' characters will be allowed if we have
  185.  *  the "untranslated" option turned on.
  186.  *  davids@kithrup.com
  187.  */
  188.       if(full_iso9660_filenames) 
  189. {
  190.   /* Here we allow a more relaxed syntax. */
  191.   if(*pnt == '.' && !allow_untranslated)
  192.     {
  193.       if (seen_dot) 
  194. {
  195.   ignore++; 
  196.   continue;
  197. }
  198.       seen_dot++;
  199.     }
  200.   if(current_length < 30) 
  201.     {
  202.       if( *pnt & 0x80 )
  203. {
  204.   *result++ = '_';
  205. }
  206.       else
  207. {
  208.   *result++ = ((islower((unsigned char)*pnt) && !allow_untranslated) ? toupper((unsigned char)*pnt) : *pnt);
  209. }
  210.     }
  211. }
  212.       else
  213.   /* 
  214.    * Dos style filenames.  We really restrict the
  215.    * names here.
  216.    */
  217.   /* It would be nice to have .tar.gz transform to .tgz,
  218.    * .ps.gz to .psz, ...
  219.    */
  220.   if(*pnt == '.') 
  221.     {
  222.       if (!chars_before_dot && !allow_leading_dots) 
  223. {
  224.   /* DOS can't read files with dot first */
  225.   chars_before_dot++;
  226.   if (result) 
  227.     {
  228.       *result++ = '_'; /* Substitute underscore */
  229.     }
  230. }
  231.       else if( pnt != last_dot )
  232. {
  233.   /*
  234.    * If this isn't the dot that we use for the extension,
  235.    * then change the character into a '_' instead.
  236.    */
  237.   if(chars_before_dot < 8) 
  238.     {
  239.       chars_before_dot++;
  240.       if(result) 
  241. {
  242.   *result++ = '_';
  243. }
  244.     }
  245. }
  246.       else 
  247. {
  248.   if (seen_dot) 
  249.     {
  250.       ignore++; continue;
  251.     }
  252.   if(result) 
  253.     {
  254.       *result++ = '.';
  255.     }
  256.   seen_dot++;
  257. }
  258.     }
  259.   else 
  260.     {
  261.       if(    (seen_dot && (chars_after_dot < 3) && ++chars_after_dot)
  262.      || (!seen_dot && (chars_before_dot < 8) && ++chars_before_dot) )
  263. {
  264.   if(result) 
  265.     {
  266.       switch (*pnt) 
  267. {
  268. default:
  269.   if( *pnt & 0x80 )
  270.     {
  271.       *result++ = '_';
  272.     }
  273.   else
  274.     {
  275.       *result++ = islower((unsigned char)*pnt) ? toupper((unsigned char)*pnt) : *pnt;
  276.     }
  277.   break;
  278. /* 
  279.  * Descriptions of DOS's 'Parse Filename'
  280.  * (function 29H) describes V1 and V2.0+
  281.  * separator and terminator characters.
  282.  * These characters in a DOS name make
  283.  * the file visible but un-manipulable
  284.  * (all useful operations error off.
  285.  */
  286. /* separators */
  287. case '+':
  288. case '=':
  289. case '%': /* not legal DOS filename */
  290. case ':':
  291. case ';': /* already handled */
  292. case '.': /* already handled */
  293. case ',': /* already handled */
  294. case 't':
  295. case ' ':
  296.   /* V1 only separators */
  297. case '/':
  298. case '"':
  299. case '[':
  300. case ']':
  301.   /* terminators */
  302. case '>':
  303. case '<':
  304. case '|':
  305.   /* Hmm - what to do here?  Skip?
  306.    * Win95 looks like it substitutes '_'
  307.    */
  308.   *result++ = '_';
  309.   break;
  310. } /* switch (*pnt) */
  311.     } /* if (result) */
  312. } /* if (chars_{after,before}_dot) ... */
  313.     } /* else *pnt == '.' */
  314. } /* else DOS file names */
  315.       current_length++;
  316.       pnt++;
  317.     } /* while (*pnt) */
  318.   
  319.   /*
  320.    * OK, that wraps up the scan of the name.  Now tidy up a few other
  321.    * things.
  322.    */
  323.   /*
  324.    * Look for emacs style of numbered backups, like foo.c.~3~.  If
  325.    * we see this, convert the version number into the priority
  326.    * number.  In case of name conflicts, this is what would end
  327.    * up being used as the 'extension'.
  328.    */
  329.   if(tildes == 2)
  330.     {
  331.       int prio1 = 0;
  332.       pnt = name;
  333.       while (*pnt && *pnt != '~') 
  334. {
  335.   pnt++;
  336. }
  337.       if (*pnt) 
  338. {
  339.   pnt++;
  340. }
  341.       while(*pnt && *pnt != '~')
  342. {
  343.   prio1 = 10*prio1 + *pnt - '0';
  344.   pnt++;
  345. }
  346.       priority = prio1;
  347.     }
  348.   
  349.   /*
  350.    * If this is not a directory, force a '.' in case we haven't
  351.    * seen one, and add a version number if we haven't seen one
  352.    * of those either.
  353.    */
  354.   if (!dirflag)
  355.     {
  356.       if (!seen_dot && !omit_period) 
  357. {
  358.   if (result) *result++ = '.'; 
  359.   extra++;
  360. }
  361.       if(!omit_version_number && !seen_semic) 
  362. {
  363.   if(result)
  364.     {
  365.       *result++ = ';';
  366.       *result++ = '1';
  367.     };
  368.   extra += 2;
  369. }
  370.     }
  371.     
  372.   if(result) 
  373.     {
  374.       *result++ = 0;
  375.     }
  376.   sresult->priority = priority;
  377.   return (chars_before_dot + chars_after_dot + seen_dot + extra);
  378. }