📄 win32.c
字号:
} } Closedir((zDIR *)G.wild_dir); /* at least one entry read; nothing left */ G.wild_dir = NULL; G.notfirstcall = FALSE; /* reset for new wildspec */ if (G.have_dirname) free(G.dirname); return (char *)NULL;} /* end function do_wild() */#endif /* !SFX *//**********************//* Function mapattr() *//**********************//* Identical to MS-DOS, OS/2 versions. However, NT has a lot of extra * permission stuff, so this function should probably be extended in the * future. */int mapattr(__G) __GDEF{ /* set archive bit for file entries (file is not backed up): */ G.pInfo->file_attr = ((unsigned)G.crec.external_file_attributes | (G.crec.external_file_attributes & FILE_ATTRIBUTE_DIRECTORY ? 0 : FILE_ATTRIBUTE_ARCHIVE)) & 0xff; return 0;} /* end function mapattr() *//************************//* Function mapname() *//************************/int mapname(__G__ renamed) __GDEF int renamed;/* * returns: * MPN_OK - no problem detected * MPN_INF_TRUNC - caution (truncated filename) * MPN_INF_SKIP - info "skip entry" (dir doesn't exist) * MPN_ERR_SKIP - error -> skip entry * MPN_ERR_TOOLONG - error -> path is too long * MPN_NOMEM - error (memory allocation failed) -> skip entry * [also MPN_VOL_LABEL, MPN_CREATED_DIR] */{ char pathcomp[FILNAMSIZ]; /* path-component buffer */ char *pp, *cp=NULL; /* character pointers */ char *lastsemi = NULL; /* pointer to last semi-colon in pathcomp */#ifdef ACORN_FTYPE_NFS char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ RO_extra_block *ef_spark; /* pointer Acorn FTYPE ef block */#endif int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ int error; register unsigned workch; /* hold the character being tested *//*--------------------------------------------------------------------------- Initialize various pointers and counters and stuff. ---------------------------------------------------------------------------*/ /* can create path as long as not just freshening, or if user told us */ G.create_dirs = (!uO.fflag || renamed); G.created_dir = FALSE; /* not yet */ G.renamed_fullpath = FALSE; G.fnlen = strlen(G.filename); if (renamed) { cp = G.filename; /* point to beginning of renamed name... */ if (*cp) do { if (*cp == '\\') /* convert backslashes to forward */ *cp = '/'; } while (*PREINCSTR(cp)); cp = G.filename; /* use temporary rootpath if user gave full pathname */ 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 (strcmp(pathcomp, ".") == 0) { /* don't bother appending "./" to the path */ *pathcomp = '\0'; } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) { /* "../" dir traversal detected, skip over it */ *pathcomp = '\0'; killed_ddot = TRUE; /* set "show message" flag */ } /* when path component is not empty, append it now */ if (*pathcomp != '\0' && ((error = checkdir(__G__ pathcomp, APPEND_DIR)) & MPN_MASK) > MPN_INF_TRUNC) return error; pp = pathcomp; /* reset conversion buffer for next piece */ lastsemi = (char *)NULL; /* leave direct. semi-colons alone */ break; case ':': /* drive spec not stored, so no colon allowed */ case '\\': /* '\\' may come as normal filename char (not */ case '<': /* dir sep char!) from unix-like file system */ 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) == '/') {#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 checkdir(__G__ G.filename, GETPATH); if (G.created_dir) { 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))); } /* set dir time (note trailing '/') */ return (error & ~MPN_MASK) | MPN_CREATED_DIR; } else if (IS_OVERWRT_ALL) { /* overwrite attributes of existing directory on user's request */ /* set file attributes: */ 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))); } } /* 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 = *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -