123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- /*
- * File name.c - map full Unix file names to unique 8.3 names that
- * would be valid on DOS.
- *
- Written by Eric Youngdale (1993).
- Copyright 1993 Yggdrasil Computing, Incorporated
- 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. */
- #include "config.h"
- #include "mkisofs.h"
- #include <ctype.h>
- extern int allow_leading_dots;
- /*
- * Function: iso9660_file_length
- *
- * Purpose: Map file name to 8.3 format, return length
- * of result.
- *
- * Arguments: name file name we need to map.
- * sresult directory entry structure to contain mapped name.
- * dirflag flag indicating whether this is a directory or not.
- *
- * Notes: This procedure probably needs to be rationalized somehow.
- * New options to affect the behavior of this function
- * would also be nice to have.
- */
- int FDECL3(iso9660_file_length,
- const char*, name,
- struct directory_entry *, sresult,
- int, dirflag)
- {
- char * c;
- int chars_after_dot = 0;
- int chars_before_dot = 0;
- int current_length = 0;
- int extra = 0;
- int ignore = 0;
- char * last_dot;
- const char * pnt;
- int priority = 32767;
- char * result;
- int seen_dot = 0;
- int seen_semic = 0;
- int tildes = 0;
- result = sresult->isorec.name;
- /*
- * For the '.' entry, generate the correct record, and return
- * 1 for the length.
- */
- if(strcmp(name,".") == 0)
- {
- if(result)
- {
- *result = 0;
- }
- return 1;
- }
- /*
- * For the '..' entry, generate the correct record, and return
- * 1 for the length.
- */
- if(strcmp(name,"..") == 0)
- {
- if(result)
- {
- *result++ = 1;
- *result++ = 0;
- }
- return 1;
- }
- /*
- * Now scan the directory one character at a time, and figure out
- * what to do.
- */
- pnt = name;
- /*
- * Find the '.' that we intend to use for the extension. Usually this
- * is the last dot, but if we have . followed by nothing or a ~, we
- * would consider this to be unsatisfactory, and we keep searching.
- */
- last_dot = strrchr (pnt,'.');
- if( (last_dot != NULL)
- && ( (last_dot[1] == '~')
- || (last_dot[1] == '\0')) )
- {
- c = last_dot;
- *c = '\0';
- last_dot = strrchr (pnt,'.');
- *c = '.';
- }
- while(*pnt)
- {
- #ifdef VMS
- if( strcmp(pnt,".DIR;1") == 0 )
- {
- break;
- }
- #endif
- /*
- * This character indicates a Unix style of backup file
- * generated by some editors. Lower the priority of
- * the file.
- */
- if(*pnt == '#')
- {
- priority = 1;
- pnt++;
- continue;
- }
- /*
- * This character indicates a Unix style of backup file
- * generated by some editors. Lower the priority of
- * the file.
- */
- if(*pnt == '~')
- {
- priority = 1;
- tildes++;
- pnt++;
- continue;
- }
- /*
- * This might come up if we had some joker already try and put
- * iso9660 version numbers into the file names. This would be
- * a silly thing to do on a Unix box, but we check for it
- * anyways. If we see this, then we don't have to add our
- * own version number at the end.
- * UNLESS the ';' is part of the filename and no version
- * number is following. [VK]
- */
- if(*pnt == ';')
- {
- /* [VK] */
- if (pnt[1] != '\0' && (pnt[1] < '0' || pnt[1] > '9'))
- {
- pnt++;
- ignore++;
- continue;
- }
- }
- /*
- * If we have a name with multiple '.' characters, we ignore everything
- * after we have gotten the extension.
- */
- if(ignore)
- {
- pnt++;
- continue;
- }
- /*
- * Spin past any iso9660 version number we might have.
- */
- if(seen_semic)
- {
- if(*pnt >= '0' && *pnt <= '9')
- {
- *result++ = *pnt;
- }
- extra++;
- pnt++;
- continue;
- }
- /*
- * If we have full names, the names we generate will not
- * work on a DOS machine, since they are not guaranteed
- * to be 8.3. Nonetheless, in many cases this is a useful
- * option. We still only allow one '.' character in the
- * name, however.
- */
- if(full_iso9660_filenames)
- {
- /* Here we allow a more relaxed syntax. */
- if(*pnt == '.')
- {
- if (seen_dot)
- {
- ignore++;
- continue;
- }
- seen_dot++;
- }
- if(current_length < 30)
- {
- if( !isascii (*pnt))
- {
- *result++ = '_';
- }
- else
- {
- *result++ = (islower((unsigned char)*pnt) ? toupper((unsigned char)*pnt) : *pnt);
- }
- }
- }
- else
- {
- /*
- * Dos style filenames. We really restrict the
- * names here.
- */
- /* It would be nice to have .tar.gz transform to .tgz,
- * .ps.gz to .psz, ...
- */
- if(*pnt == '.')
- {
- if (!chars_before_dot && !allow_leading_dots)
- {
- /* DOS can't read files with dot first */
- chars_before_dot++;
- if (result)
- {
- *result++ = '_'; /* Substitute underscore */
- }
- }
- else if( pnt != last_dot )
- {
- /*
- * If this isn't the dot that we use for the extension,
- * then change the character into a '_' instead.
- */
- if(chars_before_dot < 8)
- {
- chars_before_dot++;
- if(result)
- {
- *result++ = '_';
- }
- }
- }
- else
- {
- if (seen_dot)
- {
- ignore++; continue;
- }
- if(result)
- {
- *result++ = '.';
- }
- seen_dot++;
- }
- }
- else
- {
- if( (seen_dot && (chars_after_dot < 3) && ++chars_after_dot)
- || (!seen_dot && (chars_before_dot < 8) && ++chars_before_dot) )
- {
- if(result)
- {
- switch (*pnt)
- {
- default:
- if( !isascii (*pnt) )
- {
- *result++ = '_';
- }
- else
- {
- *result++ = islower((unsigned char)*pnt) ? toupper((unsigned char)*pnt) : *pnt;
- }
- break;
- /*
- * Descriptions of DOS's 'Parse Filename'
- * (function 29H) describes V1 and V2.0+
- * separator and terminator characters.
- * These characters in a DOS name make
- * the file visible but un-manipulable
- * (all useful operations error off.
- */
- /* separators */
- case '+':
- case '=':
- case '%': /* not legal DOS filename */
- case ':':
- case ';': /* already handled */
- case '.': /* already handled */
- case ',': /* already handled */
- case '\t':
- case ' ':
- /* V1 only separators */
- case '/':
- case '"':
- case '[':
- case ']':
- /* terminators */
- case '>':
- case '<':
- case '|':
- /* Hmm - what to do here? Skip?
- * Win95 looks like it substitutes '_'
- */
- *result++ = '_';
- break;
- } /* switch (*pnt) */
- } /* if (result) */
- } /* if (chars_{after,before}_dot) ... */
- } /* else *pnt == '.' */
- } /* else DOS file names */
- current_length++;
- pnt++;
- } /* while (*pnt) */
- /*
- * OK, that wraps up the scan of the name. Now tidy up a few other
- * things.
- */
- /*
- * Look for emacs style of numbered backups, like foo.c.~3~. If
- * we see this, convert the version number into the priority
- * number. In case of name conflicts, this is what would end
- * up being used as the 'extension'.
- */
- if(tildes == 2)
- {
- int prio1 = 0;
- pnt = name;
- while (*pnt && *pnt != '~')
- {
- pnt++;
- }
- if (*pnt)
- {
- pnt++;
- }
- while(*pnt && *pnt != '~')
- {
- prio1 = 10*prio1 + *pnt - '0';
- pnt++;
- }
- priority = prio1;
- }
- /*
- * If this is not a directory, force a '.' in case we haven't
- * seen one, and add a version number if we haven't seen one
- * of those either.
- */
- if (!dirflag)
- {
- if (!seen_dot && !omit_period)
- {
- if (result) *result++ = '.';
- extra++;
- }
- if(!omit_version_number && !seen_semic)
- {
- if(result)
- {
- *result++ = ';';
- *result++ = '1';
- };
- extra += 2;
- }
- }
- if(result)
- {
- *result++ = 0;
- }
- sresult->priority = priority;
- return (chars_before_dot + chars_after_dot + seen_dot + extra);
- }
|