home *** CD-ROM | disk | FTP | other *** search
/ Dream 49 / Amiga_Dream_49.iso / beos / utils / mkisofs-1.000 / mkisofs-1.11-beos / name.c < prev    next >
C/C++ Source or Header  |  1997-04-09  |  8KB  |  376 lines

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