diff options
Diffstat (limited to 'gnu/usr.sbin/mkisofs/name.c')
-rw-r--r-- | gnu/usr.sbin/mkisofs/name.c | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/gnu/usr.sbin/mkisofs/name.c b/gnu/usr.sbin/mkisofs/name.c new file mode 100644 index 00000000000..ff02cd1f1aa --- /dev/null +++ b/gnu/usr.sbin/mkisofs/name.c @@ -0,0 +1,376 @@ +/* $OpenBSD: name.c,v 1.1 1997/09/15 06:01:53 downsj Exp $ */ +/* + * 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. */ + +static char rcsid[] ="$From: name.c,v 1.4 1997/04/10 02:58:26 eric Rel $"; + +#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') + || (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. + */ + if(*pnt == ';') + { + seen_semic = 1; + *result++ = *pnt++; + 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) + { + *result++ = (islower(*pnt) ? toupper(*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) + || ((chars_before_dot < 8) && ++chars_before_dot) ) + { + if(result) + { + switch (*pnt) + { + default: + *result++ = islower(*pnt) ? toupper(*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 ':': + 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); +} |