Annotation of coherent/b/bin/unzip/mapname.c, revision 1.1.1.1

1.1       root        1: /*---------------------------------------------------------------------------
                      2: 
                      3:   mapname.c
                      4: 
                      5:   This routine changes DEC-20, VAX/VMS, and DOS-style filenames into normal
                      6:   Unix names (and vice versa, in some cases); it also creates any necessary 
                      7:   directories, if the -d switch was specified.
                      8: 
                      9:   ---------------------------------------------------------------------------
                     10: 
                     11:   Notes:
                     12: 
                     13:      - This routine REALLY needs to be rewritten (different routines for
                     14:        each output OS, with different rules for different parts of the path
                     15:        name).  If each zip program stores local-format names (like the VMS
                     16:        one did at one time), it would probably be best to convert to an in-
                     17:        termediate format first (assuming we're not extracting under the same
                     18:        OS as that under which the zipfile was created), then from that to
                     19:        the current operating system's format.
                     20:      - The strcpy and strcat operations on both cdp and filename may over-
                     21:        write memory, since they don't check lengths.  With a kilobyte in
                     22:        which to work, this is probably not that big a deal, but it could
                     23:        cause problems eventually.
                     24: 
                     25:   ---------------------------------------------------------------------------*/
                     26: 
                     27: 
                     28: #include "unzip.h"
                     29: 
                     30: 
                     31: /*******************/
                     32: /* Mapname Defines */
                     33: /*******************/
                     34: 
                     35: #ifdef VMS
                     36: #  define PERMS   0
                     37: #else
                     38: #  define PERMS   0777
                     39: #endif
                     40: 
                     41: #ifndef NO_MKDIR
                     42: #  if (defined(DOS_OS2) && !defined(__GO32__))
                     43: #    if (_MSC_VER >= 600)       /* have special MSC mkdir prototype */
                     44: #      include <direct.h>
                     45: #    else                       /* own prototype because dir.h conflicts? */
                     46:        int mkdir(const char *path);
                     47: #    endif /* ?(MSC 6.0 or later) */
                     48: #    define MKDIR(path,mode)   mkdir(path)
                     49: #  else /* !DOS_OS2 || __GO32__ */
                     50: #    ifdef MACOS
                     51: #      define MKDIR(path,mode)   macmkdir(path,gnVRefNum,glDirID)
                     52: #    else /* !MACOS */
                     53: #      define MKDIR(path,mode)   mkdir(path,mode)
                     54: #    endif /* ?MACOS */
                     55: #  endif /* ?(DOS_OS2 && !__GO32__)  */
                     56: #endif /* !NO_MKDIR */
                     57: 
                     58: 
                     59: 
                     60: 
                     61: /************************/
                     62: /*  Function mapname()  */
                     63: /************************/
                     64: 
                     65: int mapname(create_dirs)   /* return 0 if no error, 1 if caution (filename */
                     66:     int create_dirs;       /*  truncated), 2 if warning (skip file because */
                     67: {                          /*  dir doesn't exist), 3 if error (skip file) */
                     68: #ifdef NO_MKDIR
                     69:     char command[FILNAMSIZ+40]; /* buffer for system() call */
                     70: #endif
                     71: #ifdef VMS
                     72:     int stat_val;               /* temp. holder for stat() return value */
                     73:     char *dp, *xp;              /* pointers to directory name */
                     74:     char *np;                   /* pointer into filename */
                     75: #endif /* VMS */
                     76: #ifdef DOS_VMS
                     77:     char *last_dot=NULL;        /* last dot not converted to underscore */
                     78: #endif /* DOS_VMS */
                     79: #ifdef OS2
                     80:     char *last;
                     81:     extern char longfilename[]; /*  AFTER file created and closed */
                     82:     extern int longname;        /* used also in file_io.c:  set EAs */
                     83:     int longdir;
                     84: #endif /* OS2 */
                     85:     char name[FILNAMSIZ];       /* file name buffer */
                     86:     char *pp, *cp, *cdp;        /* character pointers */
                     87:     char delim = '\0';          /* directory delimiter */
                     88:     int quote = FALSE;          /* flags */
                     89:     int indir = FALSE;
                     90:     int done = FALSE;
                     91:     int created = FALSE;
                     92:     register unsigned workch;   /* hold the character being tested */
                     93: 
                     94: 
                     95: /*---------------------------------------------------------------------------
                     96:     Initialize various pointers and counters and stuff.
                     97:   ---------------------------------------------------------------------------*/
                     98: 
                     99: #ifdef MAP_DEBUG
                    100:     fprintf(stderr, "%s ", filename);   /* echo name of this file */
                    101: #endif
                    102:     cdp = (char *)NULL;
                    103:     pp = name;                  /* point to translation buffer */
                    104:     *name = '\0';               /* initialize buffer */
                    105:     if (!jflag) {               /* -j => junk pathnames */
                    106:         cdp = (char *)malloc(strlen(filename) + 3);   /* place for holding */
                    107:         if (cdp == (char *)NULL) {                    /*  directory name */
                    108:             fprintf(stderr, "mapname:  out of memory [%s]\n", filename);
                    109:             return 3;
                    110:         }
                    111: #ifdef VMS
                    112:         *cdp++ = '[';
                    113:         xp = cdp;               /* always points to last non-NULL char */
                    114:         *cdp++ = '.';
                    115: #endif /* VMS */
                    116: #ifdef MACOS
                    117:         *cdp = ':';             /* the Mac uses ':' as a directory separator */
                    118:         cdp[1] = '\0';
                    119: #else /* !MACOS */
                    120:         *cdp = '\0';
                    121: #endif /* ?MACOS */
                    122:     }
                    123: 
                    124: /*---------------------------------------------------------------------------
                    125:     Begin main loop through characters in filename.
                    126:   ---------------------------------------------------------------------------*/
                    127: 
                    128:     for (cp = filename; (workch = (unsigned char) *cp++) != 0  &&  !done;) {
                    129: 
                    130:         if (quote) {                 /* if char quoted, */
                    131:             *pp++ = (char) workch;   /*  include it literally */
                    132:             quote = FALSE;
                    133:         } else if (indir) {          /* if in directory name, */
                    134:             if (workch == (unsigned)delim)  /*  look for end delimiter */
                    135:                 indir = FALSE;
                    136:         } else
                    137:             switch (workch) {
                    138:             case '<':                /* discard DEC-20 directory name */
                    139:                 indir = TRUE;
                    140:                 delim = '>';
                    141:                 break;
                    142:             case '[':                /* discard VMS directory name */
                    143:                 indir = TRUE;
                    144:                 delim = ']';
                    145:                 break;
                    146:             case '/':                /* discard Unix path name  */
                    147:             case '\\':               /*  or MS-DOS path name... */
                    148:                                      /*  iff -j flag was given  */
                    149:                 /*
                    150:                  * Special processing case:  if -j flag was not specified on
                    151:                  * command line and create_dirs is TRUE, create any necessary
                    152:                  * directories included in the pathname.  Creation of dirs is
                    153:                  * straightforward on BSD and MS-DOS machines but requires use
                    154:                  * of the system() command on SysV systems (or any others which
                    155:                  * don't have mkdir()).  The stat() check is necessary with
                    156:                  * MSC because it doesn't have an EEXIST errno, and it saves
                    157:                  * the overhead of multiple system() calls on SysV machines.
                    158:                  */
                    159: 
                    160:                 if (!jflag) {
                    161:                     *pp = '\0';
                    162: #ifdef VMS
                    163:                     dp = name;
                    164:                     while (*++xp = *dp++);  /* copy name to cdp */
                    165:                     last_dot = NULL;        /* dir name:  no dots allowed */
                    166:                     strcpy(xp, ".dir");     /* add extension for stat check */
                    167:                     stat_val = stat(cdp, &statbuf);
                    168:                     *xp = '\0';             /* remove extension for all else */
                    169:                     if (stat_val) {         /* doesn't exist, so create */
                    170: #else /* !VMS */
                    171: #ifdef MSDOS
                    172:                     if (last_dot != NULL) {  /* one dot in dir name is legal */
                    173:                         *last_dot = '.';
                    174:                         last_dot = NULL;
                    175:                     }
                    176: #endif /* MSDOS */
                    177:                     strcat(cdp, name);
                    178: #ifdef OS2
                    179:                     if ((longdir = !IsFileNameValid(cdp)) != 0) {
                    180:                         last = strrchr(cdp, '/');
                    181:                         strcpy(longfilename, last ? last + 1 : cdp);
                    182:                         fprintf(stderr, "renaming directory \"%s\"", cdp);
                    183:                         ChangeNameForFAT(cdp);
                    184:                         fprintf(stderr, " to \"%s\"\n", cdp);
                    185:                     }
                    186: #endif /* OS2 */
                    187:                     if (stat(cdp, &statbuf)) {  /* doesn't exist, so create */
                    188: #endif /* ?VMS */
                    189:                         if (!create_dirs) /* told not to create (freshening) */
                    190:                             return 2;
                    191: #ifdef NO_MKDIR
                    192:                         sprintf(command,
                    193:                           "IFS=\" \t\n\" /bin/mkdir %s 2>/dev/null", cdp);
                    194:                         if (system(command)) {
                    195: #else /* !NO_MKDIR */
                    196:                         if (MKDIR(cdp, PERMS) == -1) {
                    197: #endif /* ?NO_MKDIR */
                    198:                             perror(cdp);
                    199:                             free(cdp);
                    200:                             fprintf(stderr, "mapame:  unable to process [%s]\n",
                    201:                               filename);
                    202:                             return 3;
                    203:                         }
                    204:                         created = TRUE;
                    205: #ifdef OS2
                    206:                         if (longdir)
                    207:                             SetLongNameEA(cdp, longfilename);
                    208: #endif /* OS2 */
                    209:                     } else if (!(statbuf.st_mode & S_IFDIR)) {
                    210:                         fprintf(stderr,
                    211:                           "mapname:  %s exists but is not a directory\n", cdp);
                    212:                         free(cdp);
                    213:                         fprintf(stderr, "mapame:  unable to process [%s]\n",
                    214:                           filename);
                    215:                         return 3;
                    216:                     }
                    217: #ifdef VMS
                    218:                     *xp = '/';  /* for now... (mkdir()) */
                    219: #else /* !VMS */
                    220: #ifdef MACOS
                    221:                     strcat(cdp, ":");
                    222: #else /* !MACOS */
                    223:                     strcat(cdp, "/");
                    224: #endif /* ?MACOS */
                    225: #endif /* ?VMS */
                    226:                 }
                    227:                 pp = name;
                    228:                 break;
                    229:             case ':':
                    230: #ifdef UNIX                       /* colon is a valid character in Unix */
                    231:                 *pp++ = workch;   /*  filenames, so keep it; anywhere else, */
                    232: #else /* !UNIX */                 /*  change it to an underscore (should  */
                    233:                 *pp++ = '_';      /*  NOT have stored drive/node names!!) */
                    234: #endif /* ?UNIX */
                    235:              /* pp = name;  (OLD) discard DEC dev: or node:: name */
                    236:                 break;
                    237:             case '.':                   /* DEC-20 generation number or */
                    238: #ifdef DOS_VMS                          /*  MS-DOS or VMS separator */
                    239:                 last_dot = pp;          /* point at last dot so far... */
                    240:                 *pp++ = '_';            /* convert dot to underscore */
                    241: #else /* !DOS_VMS */
                    242:                 *pp++ = workch;
                    243: #endif /* ?DOS_VMS */
                    244:                 break;
                    245:             case ';':                   /* VMS generation or DEC-20 attrib */
                    246: #ifdef MACOS
                    247:                 if (V_flag || macflag)
                    248: #else /* !MACOS */
                    249:                 if (V_flag)                 /* if requested, save VMS ";##" */
                    250: #endif /* ?MACOS */                         /*  version info or Macintosh */
                    251:                     *pp++ = (char) workch;  /*  (?) info; otherwise discard */
                    252:                 else                        /*  everything starting with */
                    253:                     done = TRUE;            /*  semicolon.  (Worry about */
                    254:                 break;                      /*  DEC-20 later.) */
                    255:             case '\026':                /* control-V quote for special chars */
                    256:                 quote = TRUE;           /* set flag for next character */
                    257:                 break;
                    258:             case ' ':
                    259: #if (defined(VMS) || defined(MTS))
                    260:                 *pp++ = '_';            /* change spaces to underscore */
                    261: #else /* !(VMS || MTS) */               /*  under VMS and MTS, and under DOS */
                    262: #ifdef DOS_OS2                          /*  and OS/2 if -s not specified. */
                    263:                 if (!sflag)
                    264:                     *pp++ = '_';
                    265:                 else
                    266: #endif /* DOS_OS2 */
                    267:                 *pp++ = (char) workch;  /* otherwise, leave as spaces */
                    268: #endif /* ?(VMS || MTS) */
                    269:                 break;
                    270:             default:
                    271: #ifdef MACOS
                    272:                 if ((macflag && ((unsigned)workch > 0x1F)) || isprint(workch))
                    273: #else /* !MACOS */
                    274: #if (defined(DOS_OS2) || (defined(UNIX) && !defined(VMS)))  /* allow non-US */
                    275:                 if (isprint(workch) || (128 <= workch && workch <= 254))
                    276: #else /* !(DOS_OS2 || UNIX) */
                    277:                 if (isprint(workch))    /* other printable, just keep */
                    278: #endif /* ?(DOS_OS2 || UNIX) */
                    279: #endif /* ?MACOS */
                    280:                     *pp++ = (char) workch;
                    281:             } /* end switch */
                    282:     } /* end for loop */
                    283:     *pp = '\0';                         /* done with name:  terminate it */
                    284: #ifdef DOS_VMS                          /*  and put a dot back in if VMS */
                    285:     if (last_dot != NULL)               /*  or MS-DOS */
                    286:         *last_dot = '.';
                    287: #endif /* DOS_VMS */
                    288: 
                    289: /*---------------------------------------------------------------------------
                    290:     We COULD check for existing names right now, create a "unique" name, etc.
                    291:     At present, we do this in extract_or_test_files() (immediately after we
                    292:     return from here).  If conversion went bad, the name'll either be nulled
                    293:     out (in which case we'll return non-0), or following procedures won't be
                    294:     able to create the extracted file and other error msgs will result.
                    295:   ---------------------------------------------------------------------------*/
                    296: 
                    297:     if (filename[strlen(filename) - 1] == '/') {
                    298:         /* A directory was extracted. It had a trailing /, 
                    299:          * don't report the error below. */
                    300:         if (created) {
                    301:             printf("   Creating: %s", filename);
                    302: #ifdef OS2
                    303:             SetPathInfo(filename, lrec.last_mod_file_date,
                    304:                                   lrec.last_mod_file_time, -1);
                    305:             if (extra_field)
                    306:                 SetEAs(filename, extra_field);
                    307: #endif
                    308:             printf("\n");
                    309:         }
                    310:         return 2; /* but skip file */
                    311:     }
                    312: 
                    313:     if (*name == '\0') {
                    314:         fprintf(stderr, "mapname:  conversion of [%s] failed\n", filename);
                    315:         return 3;
                    316:     }
                    317: 
                    318: #ifdef OS2
                    319:     if (!longname && ((longname = !IsFileNameValid(name)) != 0)) {
                    320:         /* in case of second call after user renamed the file, skip this */
                    321:         last = strrchr(name, '/');      /* THIS time, save for file_io */
                    322:         last = last ? last + 1 : name;  /* only last component */
                    323:         strcpy(longfilename, last);
                    324:         fprintf(stderr, "renaming \"%s\"", name);
                    325:         ChangeNameForFAT(last);
                    326:         fprintf(stderr, " to \"%s\"\n", name);
                    327:     }
                    328: #endif /* OS2 */
                    329: 
                    330: #ifdef VMS
                    331:     /* convert filename to legal VMS one, substituting underscores for
                    332:      * all invalid characters */
                    333:     for (np = name;  *np;  ++np)
                    334:         if (!(isdigit(*np) || isalpha(*np) || (*np == '$') ||
                    335:             (*np == '-') || (*np == '_') || (*np == '.') || (*np == ';')))
                    336:             *np = '_';
                    337: #endif /* VMS */
                    338: 
                    339:     if (!jflag) {
                    340: #ifdef VMS
                    341:         *xp++ = ']';                 /* proper end-of-dir-name delimiter */
                    342:         if (xp == cdp) {             /* no path-name stuff, so... */
                    343:             strcpy(filename, name);  /* copy file name into global */
                    344:             cdp -= 2;                /*   prepare to free malloc'd space */
                    345:         } else {                     /* we've added path-name stuff... */
                    346:             *xp = '\0';              /*   so terminate and convert to */
                    347:             dp = cdp;                /*   VMS subdir separators (skip */
                    348:             while (*++dp)            /*   first char:  better not be */
                    349:                 if (*dp == '/')      /*   "/"):  change all slashes */
                    350:                     *dp = '.';       /*   to dots */
                    351:             cdp -= 2;                /*   include leading bracket and dot */
                    352:             strcpy(filename, cdp);   /* copy VMS-style path name into global */
                    353:             strcat(filename, name);  /* concatenate file name to global */
                    354:         }
                    355: #else /* !VMS */
                    356:         strcpy(filename, cdp);       /* either "" or slash-terminated path */
                    357:         strcat(filename, name);      /* append file name to path name */
                    358: #endif /* ?VMS */
                    359:         free(cdp);
                    360:     } else
                    361:         strcpy(filename, name);      /* copy converted name into global */
                    362: 
                    363: #if PATH_MAX < (FILNAMSIZ - 1)
                    364:     /* check the length of the file name and truncate if necessary */
                    365:     if (PATH_MAX < strlen(filename)) {
                    366:         fprintf(stderr, "caution:  truncating filename\n");
                    367:         filename[PATH_MAX] = '\0';
                    368:         fprintf(stderr, "[ %s ]\n", filename);
                    369:         return 1;             /* 1:  warning error */
                    370:     }
                    371: #endif
                    372: 
                    373:     return 0;
                    374: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.