?? amiga.c
字號:
/* supress G.rootpath even when user gave a relative pathname */# if 1 G.renamed_fullpath = (renamed && strpbrk(G.filename, ":/");# else G.renamed_fullpath = (renamed && (strchr(G.filename, ':') || strchr(G.filename, '/')));# endif#endif if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM) return MPN_NOMEM; /* initialize path buffer, unless no memory */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (uO.jflag) /* junking directories */ cp = (char *)strrchr(G.filename, '/'); if (cp == (char *)NULL) /* no '/' or not junking dirs */ cp = G.filename; /* point to internal zipfile-member pathname */ else ++cp; /* point to start of last component of path *//*--------------------------------------------------------------------------- Begin main loop through characters in filename. ---------------------------------------------------------------------------*/ while ((workch = (uch)*cp++) != 0) { switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; if (((error = checkdir(__G__ pathcomp, APPEND_DIR)) & MPN_MASK) > MPN_INF_TRUNC) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = NULL; /* leave directory semi-colons alone */ break; case '.': if (pp == pathcomp) { /* nothing appended yet... */ if (*cp == '/') { /* don't bother appending "./" to */ ++cp; /* the path: skip behind the '/' */ break; } else if (!uO.ddotflag && *cp == '.' && cp[1] == '/') { /* "../" dir traversal detected */ cp += 2; /* skip over behind the '/' */ killed_ddot = TRUE; /* set "show message" flag */ break; } } *pp++ = '.'; break; case ';': /* VMS version (or DEC-20 attrib?) */ lastsemi = pp; /* keep for now; remove VMS ";##" */ *pp++ = (char)workch; /* later, if requested */ break; default: /* allow ISO European characters in filenames: */ if (isprint(workch) || (160 <= workch && workch <= 255)) *pp++ = (char)workch; } /* end switch */ } /* end while loop */ /* Show warning when stripping insecure "parent dir" path components */ if (killed_ddot && QCOND2) { Info(slide, 0, ((char *)slide, "warning: skipped \"../\" path component(s) in %s\n", FnFilter1(G.filename))); if (!(error & ~MPN_MASK)) error = (error & MPN_MASK) | PK_WARN; }/*--------------------------------------------------------------------------- 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 (G.created_dir) { if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %s\n", FnFilter1(G.filename))); } /* set dir time (note trailing '/') */ return (error & ~MPN_MASK) | MPN_CREATED_DIR; } /* dir existed already; don't look for data to extract */ return (error & ~MPN_MASK) | MPN_INF_SKIP; } *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'; } if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", FnFilter1(G.filename))); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } error = (error & ~MPN_MASK) | checkdir(__G__ pathcomp, APPEND_NAME); if ((error & MPN_MASK) == MPN_INF_TRUNC) { /* GRR: OK if truncated here: warn and continue */ /* (warn in checkdir?) */ } checkdir(__G__ G.filename, GETPATH); return error;} /* end function mapname() *//***********************//* Function checkdir() *//***********************/int checkdir(__G__ pathcomp, flag) __GDEF char *pathcomp; int flag;/* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - (on APPEND_NAME) truncated filename * MPN_INF_SKIP - path doesn't exist, not allowed to create * MPN_ERR_SKIP - path doesn't exist, tried to create and failed; or path * exists and is not a directory, but is supposed to be * MPN_ERR_TOOLONG - path is too long * MPN_NOMEM - can't allocate memory for filename buffers */{/* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in amiga.h: *//* 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. ---------------------------------------------------------------------------*//* GRR: check path length after each segment: warn about truncation */ if (FUNCTION == APPEND_DIR) { int too_long = FALSE; Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp))); while ((*G.build_end = *pathcomp++) != '\0') ++G.build_end; /* Truncate components over 30 chars? Nah, the filesystem handles it. */ if ((G.build_end-G.buildpath) > FILNAMSIZ-3) /* room for "/a\0" */ too_long = TRUE; /* check if extracting dir? */ if (SSTAT(G.buildpath, &G.statbuf)) { /* path doesn't exist */ if (!G.create_dirs) { /* told not to create (freshening) */ free(G.buildpath); return MPN_INF_SKIP; /* path doesn't exist: nothing to do */ } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); free(G.buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } if (MKDIR(G.buildpath, 0777) == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, "checkdir error: cannot create %s\n\ unable to process %s.\n", FnFilter2(G.buildpath), FnFilter1(G.filename))); free(G.buildpath); /* path didn't exist, tried to create, failed */ return MPN_ERR_SKIP; } G.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", FnFilter2(G.buildpath), FnFilter1(G.filename))); free(G.buildpath); /* path existed but wasn't dir */ return MPN_ERR_SKIP; } if (too_long) { Info(slide, 1, ((char *)slide, "checkdir error: path too long: %s\n", FnFilter1(G.buildpath))); free(G.buildpath); /* no room for filenames: fatal */ return MPN_ERR_TOOLONG; } *G.build_end++ = '/'; *G.build_end = '\0'; Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); return MPN_OK; } /* end if (FUNCTION == APPEND_DIR) *//*--------------------------------------------------------------------------- GETPATH: copy full path to the string pointed at by pathcomp, and free G.buildpath. Not our responsibility to worry whether pathcomp has room. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { strcpy(pathcomp, G.buildpath); Trace((stderr, "getting and freeing path [%s]\n", FnFilter1(pathcomp))); free(G.buildpath); G.buildpath = G.build_end = (char *)NULL; return MPN_OK; }/*--------------------------------------------------------------------------- APPEND_NAME: assume the path component is the filename; append it and return without checking for existence. ---------------------------------------------------------------------------*/ if (FUNCTION == APPEND_NAME) { Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); while ((*G.build_end = *pathcomp++) != '\0') { ++G.build_end; if ((G.build_end-G.buildpath) >= FILNAMSIZ) { *--G.build_end = '\0'; Info(slide, 0x201, ((char *)slide, "checkdir warning: path too long; truncating\n\ %s\n -> %s\n", FnFilter1(G.filename), FnFilter2(G.buildpath))); return MPN_INF_TRUNC; /* filename truncated */ } } Trace((stderr, "buildpath now = [%s]\n", FnFilter1(G.buildpath))); /* could check for existence here, prompt for new name... */ return MPN_OK; }/*--------------------------------------------------------------------------- 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. ---------------------------------------------------------------------------*/ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpath to ")); if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1)) == (char *)NULL) return MPN_NOMEM; if ((G.rootlen > 0) && !G.renamed_fullpath) { strcpy(G.buildpath, G.rootpath); G.build_end = G.buildpath + G.rootlen; } else { *G.buildpath = '\0'; G.build_end = G.buildpath; } Trace((stderr, "[%s]\n", FnFilter1(G.buildpath))); return MPN_OK; }/*--------------------------------------------------------------------------- ROOT: if appropriate, store the path in G.rootpath and create it if necessary; 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", FnFilter1(pathcomp))); if (pathcomp == (char *)NULL) { G.rootlen = 0; return MPN_OK; } if (G.rootlen > 0) /* rootpath was already set, nothing to do */ return MPN_OK; if ((G.rootlen = strlen(pathcomp)) > 0) { if (stat(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) { /* path does not exist */ if (!G.create_dirs) { G.rootlen = 0; /* skip (or treat as stored file) */ return MPN_INF_SKIP; } /* create the directory (could add loop here scanning pathcomp * to create more than one level, but why really necessary?) */ if (MKDIR(pathcomp, 0777) == -1) { Info(slide, 1, ((char *)slide, "checkdir: cannot create extraction directory: %s\n", FnFilter1(pathcomp))); G.rootlen = 0; /* path didn't exist, tried to create, and failed: */ /* file exists, or 2+ subdir levels required */ return MPN_ERR_SKIP; } } if ((G.rootpath = (char *)malloc(G.rootlen+2)) == NULL) { G.rootlen = 0; return MPN_NOMEM; } strcpy(G.rootpath, pathcomp); if (G.rootpath[G.rootlen-1] != ':' && G.rootpath[G.rootlen-1] != '/') G.rootpath[G.rootlen++] = '/'; G.rootpath[G.rootlen] = '\0'; Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath))); } return MPN_OK; }#endif /* !SFX || SFX_EXDIR *//*--------------------------------------------------------------------------- END: free G.rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (G.rootlen > 0) { free(G.rootpath); G.rootlen = 0; } return MPN_OK; } return MPN_INVALID; /* should never reach */} /* end function checkdir() */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -