Annotation of coherent/b/bin/unzip/mapname.c, revision 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.