|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.