📄 aosvs.c
字号:
---------------------------------------------------------------------------*/ while ((workch = (uch)*cp++) != 0) { if (quote) { /* if character quoted, */ *pp++ = (char)workch; /* include it literally */ quote = FALSE; } else switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave directory semi-colons alone */ break; case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; *pp++ = ';'; /* keep for now; remove VMS ";##" */ break; /* later, if requested */ case '\026': /* control-V quote for special chars */ quote = TRUE; /* set flag for next character */ break;#ifdef MTS case ' ': /* change spaces to underscore under */ *pp++ = '_'; /* MTS; leave as spaces under Unix */ break;#endif default: /* allow European characters in filenames: */ if (isprint(workch) || (128 <= workch && workch <= 254)) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ *pp = '\0'; /* done with pathcomp: terminate it */ /* if not saving them, remove VMS version numbers (appended ";###") */ if (!uO.V_flag && lastsemi) { pp = lastsemi + 1; while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; }/*--------------------------------------------------------------------------- Report if directory was created (and no file to create: filename ended in '/'), check name to be sure it exists, and combine path and name be- fore exiting. ---------------------------------------------------------------------------*/ if (G.filename[strlen(G.filename) - 1] == '/') { checkdir(__G__ G.filename, GETPATH); if (created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %s\n", G.filename)); } return IZ_CREATED_DIR; /* set dir time (note trailing '/') */ } return 2; /* dir existed already; don't look for data to extract */ } if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", G.filename)); return 3; } checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ checkdir(__G__ G.filename, GETPATH); return error;} /* end function mapname() */#if 0 /*========== NOTES ==========*/ extract-to dir: a:path/ buildpath: path1/path2/ ... (NULL-terminated) pathcomp: filename mapname(): loop over chars in zipfile member name checkdir(path component, COMPONENT | CREATEDIR) --> map as required? (d:/tmp/unzip/) (disk:[tmp.unzip.) (d:/tmp/unzip/jj/) (disk:[tmp.unzip.jj.) (d:/tmp/unzip/jj/temp/) (disk:[tmp.unzip.jj.temp.) finally add filename itself and check for existence? (could use with rename) (d:/tmp/unzip/jj/temp/msg.outdir) (disk:[tmp.unzip.jj.temp]msg.outdir) checkdir(name, GETPATH) --> copy path to name and free space#endif /* 0 *//***********************//* Function checkdir() *//***********************/int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag;/* * returns: 1 - (on APPEND_NAME) truncated filename * 2 - path doesn't exist, not allowed to create * 3 - path doesn't exist, tried to create and failed; or * path exists and is not a directory, but is supposed to be * 4 - path is too long * 10 - can't allocate memory for filename buffers */{ static int rootlen = 0; /* length of rootpath */ static char *rootpath; /* user's "extract-to" directory */ static char *buildpath; /* full path (so far) to extracted file */ static char *end; /* pointer to end of buildpath ('\0') */# define FN_MASK 7# define FUNCTION (flag & FN_MASK)/*--------------------------------------------------------------------------- APPEND_DIR: append the path component to the path being built and check for its existence. If doesn't exist and we are creating directories, do so for this one; else signal success or error as appropriate. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_DIR) { int too_long = FALSE;#ifdef SHORT_NAMES char *old_end = end;#endif Trace((stderr, "appending dir segment [%s]\n", pathcomp)); while ((*end = *pathcomp++) != '\0') ++end;#ifdef SHORT_NAMES /* path components restricted to 14 chars, typically */ if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(end = old_end + FILENAME_MAX) = '\0';#endif /* GRR: could do better check, see if overrunning buffer as we go: * check end-buildpath after each append, set warning variable if * within 20 of FILNAMSIZ; then if var set, do careful check when * appending. Clear variable when begin new path. */ if ((end-buildpath) > FILNAMSIZ-3) /* need '/', one-char name, '\0' */ too_long = TRUE; /* check if extracting directory? */ /* for AOS/VS, try to create so as to not use searchlist: */ if ( /*stat(buildpath, &G.statbuf)*/ 1) { if (!G.create_dirs) { /* told not to create (freshening) */ free(buildpath); return 2; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", buildpath)); free(buildpath); return 4; /* no room for filenames: fatal */ } /* create the directory */ if (zvs_credir(buildpath,-1L,-1L,-1L,(char *) -1,-1,0L,-1,-1) == -1) { Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ unable to process %s.\n", buildpath, G.filename)); free(buildpath); return 3; /* path didn't exist, tried to create, failed */ } created_dir = TRUE; } else if (!S_ISDIR(G.statbuf.st_mode)) { Info(slide, 1, ((char *)slide, "checkdir error: %s exists but is not directory\n\ unable to process %s.\n", buildpath, G.filename)); free(buildpath); return 3; /* path existed but wasn't dir */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", buildpath)); free(buildpath); return 4; /* no room for filenames: fatal */ } *end++ = '/'; *end = '\0'; Trace((stderr, "buildpath now = [%s]\n", buildpath)); return 0; } /* end if (FUNCTION == APPEND_DIR) *//*--------------------------------------------------------------------------- GETPATH: copy full path to the string pointed at by pathcomp, and free buildpath. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { strcpy(pathcomp, buildpath); Trace((stderr, "getting and freeing path [%s]\n", pathcomp)); free(buildpath); buildpath = end = (char *)NULL; return 0; }/*--------------------------------------------------------------------------- APPEND_NAME: assume the path component is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) {#ifdef SHORT_NAMES char *old_end = end;#endif Trace((stderr, "appending filename [%s]\n", pathcomp)); while ((*end = *pathcomp++) != '\0') { ++end;#ifdef SHORT_NAMES /* truncate name at 14 characters, typically */ if ((end-old_end) > FILENAME_MAX) /* GRR: proper constant? */ *(end = old_end + FILENAME_MAX) = '\0';#endif if ((end-buildpath) >= FILNAMSIZ) { *--end = '\0'; Info(slide, 1, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", G.filename, buildpath)); return 1; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", buildpath)); return 0; /* could check for existence here, prompt for new name... */ }/*--------------------------------------------------------------------------- INIT: allocate and initialize buffer space for the file currently being extracted. If file was renamed with an absolute path, don't prepend the extract-to path. ---------------------------------------------------------------------------*//* GRR: for VMS and TOPS-20, add up to 13 to strlen */ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpath to ")); if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1)) == (char *)NULL) return 10; if ((rootlen > 0) && !renamed_fullpath) { strcpy(buildpath, rootpath); end = buildpath + rootlen; } else { *buildpath = '\0'; end = buildpath; } Trace((stderr, "[%s]\n", buildpath)); return 0; }/*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in rootpath and create it if neces- sary; else assume it's a zipfile member and return. This path segment gets used in extracting all members from every zipfile specified on the command line. ---------------------------------------------------------------------------*/#if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", pathcomp)); if (pathcomp == (char *)NULL) { rootlen = 0; return 0; } if ((rootlen = strlen(pathcomp)) > 0) { if (pathcomp[rootlen-1] == '/') { pathcomp[--rootlen] = '\0'; } if (rootlen > 0 && (stat(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))) /* path does not exist */ { if (!G.create_dirs /* || iswild(pathcomp) */ ) { rootlen = 0; return 2; /* skip (or treat as stored file) */ } /* create the directory (could add loop here to scan pathcomp * and create more than one level, but why really necessary?) */ if (zvs_credir(pathcomp,-1L,-1L,-1L,(char *) -1,-1,0L,-1,-1) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory: %s\n", pathcomp)); rootlen = 0; /* path didn't exist, tried to create, and */ return 3; /* failed: file exists, or 2+ levels required */ } } if ((rootpath = (char *)malloc(rootlen+2)) == (char *)NULL) { rootlen = 0; return 10; } strcpy(rootpath, pathcomp); rootpath[rootlen++] = '/'; rootpath[rootlen] = '\0'; Trace((stderr, "rootpath now = [%s]\n", rootpath)); } return 0; }#endif /* !SFX || SFX_EXDIR *//*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (rootlen > 0) { free(rootpath); rootlen = 0; } return 0; } return 99; /* should never reach */} /* end function checkdir() */#ifdef MORE/**************************//* Function screenlines() *//**************************/int screenlines(){ char *envptr, *getenv(); int n; /* GRR: this is overly simplistic; should use winsize struct and * appropriate TIOCGWINSZ ioctl(), assuming exists on enough systems */ envptr = getenv("LINES"); if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) return 24; /* VT-100 assumed to be minimal hardware */ else return n;}#endif /* MORE *//****************************//* Function close_outfile() *//****************************/void close_outfile(__G) /* GRR: change to return PK-style warning level */ __GDEF{/*--------------------------------------------------------------------------- If symbolic links are supported, allocate a storage area, put the uncom- pressed "data" in it, and create the link. Since we know it's a symbolic link to start with, we shouldn't have to worry about overflowing unsigned ints with unsigned longs. ---------------------------------------------------------------------------*/#ifdef SYMLINKS if (G.symlnk) { unsigned ucsize = (unsigned)G.lrec.ucsize; char *linktarget = (char *)malloc((unsigned)G.lrec.ucsize+1); fclose(G.outfile); /* close "data" file... */ G.outfile = fopen(G.filename, FOPR); /* ...and reopen for reading */ if (!linktarget || fread(linktarget, 1, ucsize, G.outfile) != (int)ucsize) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed\n", G.filename)); if (linktarget) free(linktarget); fclose(G.outfile); return; } fclose(G.outfile); /* close "data" file for good... */ unlink(G.filename); /* ...and delete it */ linktarget[ucsize] = '\0'; if (QCOND2) Info(slide, 0, ((char *)slide, "-> %s ", linktarget)); if (symlink(linktarget, G.filename)) /* create the real link */ perror("symlink error"); free(linktarget); return; /* can't set time on symlinks */ }#endif /* SYMLINKS */ fclose(G.outfile);/*--------------------------------------------------------------------------- Change the file permissions from default ones to those stored in the zipfile. ---------------------------------------------------------------------------*/#ifndef NO_CHMOD if (chmod(G.filename, 0xffff & G.pInfo->file_attr)) perror("chmod (file attributes) error");#endif/*--------------------------------------------------------------------------- AOS/VS only allows setting file times at creation but has its own permis- sions scheme which is better invoked here if the necessary information was in fact stored. In theory, we should look through an entire series of extra fields that might exist for the same file, but we're not going to bother. If we set up other types of extra fields, or if we run into other environments that add their own stuff to existing entries in ZIP files, we'll have to. NOTE: already copied extra-field stuff into zzextrafld structure when file was created. ---------------------------------------------------------------------------*/ if (G.extra_field != NULL) { if (!memcmp(ZEXTRA_HEADID, zzextrafld.extra_header_id, sizeof(zzextrafld.extra_header_id)) && !memcmp(ZEXTRA_SENTINEL, zzextrafld.extra_sentinel, sizeof(zzextrafld.extra_sentinel)) && zzextrafld.fstat_packet.norm_fstat_packet.styp_type != $FLNK) /* (AOS/VS links don't have ACLs) */ { /* vs_path was set (in this case) when we created the file */ if (sys_sacl(vs_path, zzextrafld.aclbuf)) { Info(slide, 0x201, ((char *)slide, "error: cannot set ACL for %s\n", G.filename)); perror("sys_sacl()"); } } }} /* end function close_outfile() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -