?? win32.c
字號:
if (G.filename[0] == '/') { G.renamed_fullpath = TRUE; pathcomp[0] = '/'; /* copy the '/' and terminate */ pathcomp[1] = '\0'; ++cp; } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') { G.renamed_fullpath = TRUE; pp = pathcomp; *pp++ = *cp++; /* copy the "d:" (+ '/', possibly) */ *pp++ = *cp++; if (*cp == '/') *pp++ = *cp++; /* otherwise add "./"? */ *pp = '\0'; } } /* pathcomp is ignored unless renamed_fullpath is TRUE: */ if ((error = checkdir(__G__ pathcomp, INIT)) != 0) /* init path buffer */ return error; /* ...unless no mem or vol label on hard disk */ *pathcomp = '\0'; /* initialize translation buffer */ pp = pathcomp; /* point to translation buffer */ if (!renamed) { /* cp already set if renamed */ if (uO.jflag) /* junking directories */ cp = (char *)MBSRCHR(G.filename, '/'); if (cp == 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. ---------------------------------------------------------------------------*/ for (; (workch = (uch)*cp) != 0; INCSTR(cp)) { switch (workch) { case '/': /* can assume -j flag not given */ *pp = '\0'; maskDOSdevice(__G__ pathcomp); 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[1] == '/') { /* don't bother appending "./" to */ ++cp; /* the path: skip behind the '/' */ break; } else if (!uO.ddotflag && cp[1] == '.' && cp[2] == '/') { /* "../" dir traversal detected */ cp += 2; /* skip over behind the '/' */ killed_ddot = TRUE; /* set "show message" flag */ break; } } *pp++ = '.'; break; case ':': /* drive names not stored in zipfile, */ case '<': /* so no colons allowed */ case '>': /* no redirection symbols allowed either */ case '|': /* no pipe signs allowed */ case '"': /* no double quotes allowed */ case '?': /* no wildcards allowed */ case '*': *pp++ = '_'; /* these rules apply equally to FAT and NTFS */ break; case ';': /* start of VMS version? */ lastsemi = pp; /* remove VMS version later... */ *pp++ = ';'; /* but keep semicolon for now */ break;#ifdef ACORN_FTYPE_NFS case ',': /* NFS filetype extension */ lastcomma = pp; *pp++ = ','; /* keep for now; may need to remove */ break; /* later, if requested */#endif case ' ': /* keep spaces unless specifically */ /* NT cannot create filenames with spaces on FAT volumes */ if (uO.sflag || IsVolumeOldFAT(__G__ G.filename)) *pp++ = '_'; else *pp++ = ' '; break; default: /* allow European characters in filenames: */ if (isprint(workch) || workch >= 127)#ifdef _MBCS { memcpy(pp, cp, CLEN(cp)); INCSTR(pp); }#else *pp++ = (char)workch;#endif } /* 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 (lastchar(G.filename, G.fnlen) == '/') { checkdir(__G__ G.filename, GETPATH); if (G.created_dir) {#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(G.filename) + 1); INTERN_TO_ISO(G.filename, ansi_name);# define Ansi_Fname ansi_name#else# define Ansi_Fname G.filename#endif if (QCOND2) { Info(slide, 0, ((char *)slide, " creating: %-22s\n", FnFilter1(G.filename))); } /* set file attributes: The default for newly created directories is "DIR attribute flags set", so there is no need to change attributes unless one of the DOS style attribute flags is set. The readonly attribute need not be masked, since it does not prevent modifications in the new directory. */ if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) { if (!SetFileAttributes(Ansi_Fname, G.pInfo->file_attr & 0x7F)) Info(slide, 1, ((char *)slide, "\nwarning (%d): could not set file attributes for %s\n", (int)GetLastError(), FnFilter1(G.filename))); }#ifdef NTSD_EAS /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */ if (G.extra_field) { /* zipfile e.f. may have extended attribs */ int err = EvalExtraFields(__G__ G.filename, G.extra_field, G.lrec.extra_field_length); if (err == IZ_EF_TRUNC) { if (uO.qflag) Info(slide, 1, ((char *)slide, "%-22s ", FnFilter1(G.filename))); Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD), makeword(G.extra_field+2)-10, uO.qflag? "\n":"")); } }#endif /* NTSD_EAS */ /* 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; /* semi-colon was kept: expect #'s after */ while (isdigit((uch)(*pp))) ++pp; if (*pp == '\0') /* only digits between ';' and end: nuke */ *lastsemi = '\0'; }#ifdef ACORN_FTYPE_NFS /* translate Acorn filetype information if asked to do so */ if (uO.acorn_nfs_ext && (ef_spark = (RO_extra_block *) getRISCOSexfield(G.extra_field, G.lrec.extra_field_length)) != (RO_extra_block *)NULL) { /* file *must* have a RISC OS extra field */ long ft = (long)makelong((ef_spark->loadaddr); /*32-bit*/ if (lastcomma) { pp = lastcomma + 1; while (isxdigit((uch)(*pp))) ++pp; if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */ } if ((ft & 1<<31)==0) ft=0x000FFD00; sprintf(pathcomp+strlen(pathcomp), ",%03x", (int)(ft>>8) & 0xFFF); }#endif /* ACORN_FTYPE_NFS */ maskDOSdevice(__G__ pathcomp); if (*pathcomp == '\0') { Info(slide, 1, ((char *)slide, "mapname: conversion of %s failed\n", FnFilter1(G.filename))); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } checkdir(__G__ pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */ checkdir(__G__ G.filename, GETPATH); if (G.pInfo->vollabel) { /* set the volume label now */ char drive[4];#ifdef __RSXNT__ /* RSXNT/EMX C rtl uses OEM charset */ char *ansi_name = (char *)alloca(strlen(G.filename) + 1); INTERN_TO_ISO(G.filename, ansi_name);# define Ansi_Fname ansi_name#else# define Ansi_Fname G.filename#endif /* Build a drive string, e.g. "b:" */ drive[0] = (char)('a' + G.nLabelDrive - 1); strcpy(drive + 1, ":\\"); if (QCOND2) Info(slide, 0, ((char *)slide, "labelling %s %-22s\n", drive, FnFilter1(G.filename))); if (!SetVolumeLabel(drive, Ansi_Fname)) { Info(slide, 1, ((char *)slide, "mapname: error setting volume label\n")); return (error & ~MPN_MASK) | MPN_ERR_SKIP; } /* success: skip the "extraction" quietly */ return (error & ~MPN_MASK) | MPN_INF_SKIP;#undef Ansi_Fname } Trace((stderr, "mapname returns with filename = [%s] (error = %d)\n\n", FnFilter1(G.filename), error)); return error;} /* end function mapname() *//****************************//* Function maskDOSdevice() *//****************************/static void maskDOSdevice(__G__ pathcomp) __GDEF char *pathcomp;{/*--------------------------------------------------------------------------- Put an underscore in front of the file name if the file name is a DOS/WINDOWS device name like CON.*, AUX.*, PRN.*, etc. Trying to extract such a file would fail at best and wedge us at worst. ---------------------------------------------------------------------------*/#if !defined(S_IFCHR) && defined(_S_IFCHR)# define S_IFCHR _S_IFCHR#endif#if !defined(S_ISCHR)# if defined(_S_ISCHR)# define S_ISCHR(m) _S_ISCHR(m)# elif defined(S_IFCHR)# define S_ISCHR(m) ((m) & S_IFCHR)# endif#endif#ifdef DEBUG if (stat(pathcomp, &G.statbuf) == 0) { Trace((stderr, "maskDOSdevice() stat(\"%s\", buf) st_mode result: %X, %o\n", FnFilter1(pathcomp), G.statbuf.st_mode, G.statbuf.st_mode)); } else { Trace((stderr, "maskDOSdevice() stat(\"%s\", buf) failed\n", FnFilter1(pathcomp))); }#endif if (stat(pathcomp, &G.statbuf) == 0 && S_ISCHR(G.statbuf.st_mode)) { extent i; /* pathcomp contains a name of a DOS character device (builtin or * installed device driver). * Prepend a '_' to allow creation of the item in the file system. */ for (i = strlen(pathcomp) + 1; i > 0; --i) pathcomp[i] = pathcomp[i - 1]; pathcomp[0] = '_'; }} /* end function maskDOSdevice() *//**********************//* Function map2fat() */ /* Not quite identical to OS/2 version *//**********************/static void map2fat(pathcomp, pEndFAT) char *pathcomp, **pEndFAT;{ char *ppc = pathcomp; /* variable pointer to pathcomp */ char *pEnd = *pEndFAT; /* variable pointer to buildpathFAT */ char *pBegin = *pEndFAT; /* constant pointer to start of this comp. */ char *last_dot = NULL; /* last dot not converted to underscore */ register unsigned workch; /* hold the character being tested */ /* Only need check those characters which are legal in NTFS but not * in FAT: to get here, must already have passed through mapname. * Also must truncate path component to ensure 8.3 compliance. */ while ((workch = (uch)*ppc++) != 0) { switch (workch) { case '[': case ']': case '+': case ',': case ';': case '=': *pEnd++ = '_'; /* convert brackets to underscores */ break; case '.': if (pEnd == *pEndFAT) { /* nothing appended yet... */ if (*ppc == '\0') /* don't bother appending a */ break; /* "./" component to the path */ else if (*ppc == '.' && ppc[1] == '\0') { /* "../" */ *pEnd++ = '.'; /* add first dot, */ *pEnd++ = '.'; /* add second dot, and */ ++ppc; /* skip over to pathcomp's end */ } else { /* FAT doesn't allow null filename */ *pEnd++ = '_'; /* bodies, so map .exrc -> _exrc */ } /* (_.exr would keep max 3 chars) */ } else { /* found dot within path component */ last_dot = pEnd; /* point at last dot so far... */ *pEnd++ = '_'; /* convert to underscore for now */ } break; default: *pEnd++ = (char)workch; } /* end switch */ } /* end while loop */ *pEnd = '\0'; /* terminate buildpathFAT */ /* NOTE: keep in mind that pEnd points to the end of the path * component, and *pEndFAT still points to the *beginning* of it... * Also note that the algorithm does not try to get too fancy: * if there are no dots already, the name either gets truncated * at 8 characters or the last underscore is converted to a dot * (only if more characters are saved that way). In no case is * a dot inserted between existing characters. */ if (last_dot == NULL) { /* no dots: check for underscores... */ char *plu = MBSRCHR(pBegin, '_'); /* pointer to last underscore */ if ((plu != NULL) && /* found underscore: convert to dot? */ (MIN(plu - pBegin, 8) + MIN(pEnd - plu - 1, 3) > 8)) { last_dot = plu; /* be lazy: drop through to next if-blk */ } else if ((pEnd - *pEndFAT) > 8) { /* no underscore; or converting underscore to dot would save less chars than leaving everything in the basename */ *pEndFAT += 8; /* truncate at 8 chars */ **pEndFAT = '\0'; } else *pEndFAT = pEnd; /* whole thing fits into 8 chars or less */ } if (last_dot != NULL) { /* one dot is OK: */ *last_dot = '.'; /* put it back in */ if ((last_dot - pBegin) > 8) { char *p, *q; int i; p = last_dot; q = last_dot = pBegin + 8; for (i = 0; (i < 4) && *p; ++i) /* too many chars in basename: */ *q++
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -