📄 os2.c
字号:
/*--------------------------------------------------------------------------- GETPATH: copy full FAT path to the string pointed at by pathcomp (want filename to reflect name used on disk, not EAs; if full path is HPFS, buildpathFAT and buildpathHPFS will be identical). Also free both paths. ---------------------------------------------------------------------------*/ if (FUNCTION == GETPATH) { Trace((stderr, "getting and freeing FAT path [%s]\n", FnFilter1(G.os2.buildpathFAT))); Trace((stderr, "freeing HPFS path [%s]\n", FnFilter1(G.os2.buildpathHPFS))); strcpy(pathcomp, G.os2.buildpathFAT); free(G.os2.buildpathFAT); free(G.os2.buildpathHPFS); G.os2.buildpathHPFS = G.os2.buildpathFAT = G.os2.endHPFS = G.os2.endFAT = (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) { char *p = pathcomp; int error = MPN_OK; Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp))); while ((*G.os2.endHPFS = *p++) != '\0') { /* copy to HPFS filename */ ++G.os2.endHPFS; if ((G.os2.endHPFS-G.os2.buildpathHPFS) >= FILNAMSIZ) { *--G.os2.endHPFS = '\0'; Info(slide, 1, ((char *)slide, LoadFarString(PathTooLongTrunc), FnFilter1(G.filename), FnFilter2(G.os2.buildpathHPFS))); error = MPN_INF_TRUNC; /* filename truncated */ } }/* GRR: how can longnameEA ever be set before this point??? we don't want * to save the original name to EAs if user renamed it, do we? * * if (!G.os2.longnameEA && ((G.os2.longnameEA = !IsFileNameValid(name)) != 0)) */ if (G.pInfo->vollabel || IsFileNameValid(G.os2.buildpathHPFS)) { G.os2.longnameEA = FALSE; p = pathcomp; while ((*G.os2.endFAT = *p++) != '\0') /* copy to FAT filename, too */ ++G.os2.endFAT; } else { G.os2.longnameEA = TRUE; if ((G.os2.lastpathcomp = (char *)malloc(strlen(pathcomp)+1)) == (char *)NULL) { Info(slide, 1, ((char *)slide, "checkdir warning: cannot save longname EA: out of memory\n")); G.os2.longnameEA = FALSE; /* can't set .LONGNAME extended attribute */ error = MPN_INF_TRUNC; } else /* used and freed in close_outfile() */ strcpy(G.os2.lastpathcomp, pathcomp); map2fat(pathcomp, &G.os2.endFAT); /* map, put in FAT fn, update endFAT */ } Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n", FnFilter1(G.os2.buildpathHPFS), FnFilter2(G.os2.buildpathFAT))); return error; /* could check for existence, prompt for new name... */ } /* end if (FUNCTION == APPEND_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. ---------------------------------------------------------------------------*/ if (FUNCTION == INIT) { Trace((stderr, "initializing buildpathHPFS and buildpathFAT to "));#ifdef ACORN_FTYPE_NFS if ((G.os2.buildpathHPFS = (char *)malloc(G.os2.fnlen+G.os2.rootlen+ (uO.acorn_nfs_ext ? 5 : 1)))#else if ((G.os2.buildpathHPFS = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1))#endif == (char *)NULL) return MPN_NOMEM;#ifdef ACORN_FTYPE_NFS if ((G.os2.buildpathFAT = (char *)malloc(G.os2.fnlen+G.os2.rootlen+ (uO.acorn_nfs_ext ? 5 : 1)))#else if ((G.os2.buildpathFAT = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1))#endif == (char *)NULL) { free(G.os2.buildpathHPFS); return MPN_NOMEM; } if (G.pInfo->vollabel) { /* use root or renamed path, but don't store *//* GRR: for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */ if (G.os2.renamed_fullpath && pathcomp[1] == ':') *G.os2.buildpathHPFS = (char)ToLower(*pathcomp); else if (!G.os2.renamed_fullpath && G.os2.rootlen > 1 && G.os2.rootpath[1] == ':') *G.os2.buildpathHPFS = (char)ToLower(*G.os2.rootpath); else { ULONG lMap; DosQueryCurrentDisk(&G.os2.nLabelDrive, &lMap); *G.os2.buildpathHPFS = (char)(G.os2.nLabelDrive - 1 + 'a'); } G.os2.nLabelDrive = *G.os2.buildpathHPFS - 'a' + 1; /* save for mapname() */ if (uO.volflag == 0 || *G.os2.buildpathHPFS < 'a' || /* no labels/bogus? */ (uO.volflag == 1 && !isfloppy(G.os2.nLabelDrive))) { /* -$: no fixed */ free(G.os2.buildpathHPFS); free(G.os2.buildpathFAT); return MPN_VOL_LABEL; /* skipping with message */ } *G.os2.buildpathHPFS = '\0'; } else if (G.os2.renamed_fullpath) /* pathcomp = valid data */ strcpy(G.os2.buildpathHPFS, pathcomp); else if (G.os2.rootlen > 0) strcpy(G.os2.buildpathHPFS, G.os2.rootpath); else *G.os2.buildpathHPFS = '\0'; G.os2.endHPFS = G.os2.buildpathHPFS; G.os2.endFAT = G.os2.buildpathFAT; while ((*G.os2.endFAT = *G.os2.endHPFS) != '\0') { ++G.os2.endFAT; ++G.os2.endHPFS; } Trace((stderr, "[%s]\n", FnFilter1(G.os2.buildpathHPFS))); return MPN_OK; }/*--------------------------------------------------------------------------- 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. Note that under OS/2 and MS-DOS, if a candidate extract-to directory specification includes a drive letter (leading "x:"), it is treated just as if it had a trailing '/'--that is, one directory level will be created if the path doesn't exist, unless this is otherwise pro- hibited (e.g., freshening). ---------------------------------------------------------------------------*/#if (!defined(SFX) || defined(SFX_EXDIR)) if (FUNCTION == ROOT) { Trace((stderr, "initializing root path to [%s]\n", FnFilter1(pathcomp))); if (pathcomp == (char *)NULL) { G.os2.rootlen = 0; return MPN_OK; } if (G.os2.rootlen > 0) /* rootpath was already set, nothing to do */ return MPN_OK; if ((G.os2.rootlen = strlen(pathcomp)) > 0) { int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE; char *tmproot; if ((tmproot = (char *)malloc(G.os2.rootlen+3)) == (char *)NULL) { G.os2.rootlen = 0; return MPN_NOMEM; } strcpy(tmproot, pathcomp); if (isalpha((uch)tmproot[0]) && tmproot[1] == ':') has_drive = TRUE; /* drive designator */ if (tmproot[G.os2.rootlen-1] == '/') { tmproot[--G.os2.rootlen] = '\0'; had_trailing_pathsep = TRUE; } if (has_drive && (G.os2.rootlen == 2)) { if (!had_trailing_pathsep) /* i.e., original wasn't "x:/" */ add_dot = TRUE; /* relative path: add '.' before '/' */ } else if (G.os2.rootlen > 0) { /* need not check "x:." and "x:/" */#ifdef MSC /* MSC 6.00 bug: stat(non-existent-dir) == 0 [exists!] */ if (GetFileTime(tmproot) == -1 || SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))#else if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))#endif { /* path does not exist */ if (!G.create_dirs /* || iswild(tmproot) */ ) { free(tmproot); G.os2.rootlen = 0; return MPN_INF_SKIP; /* treat as stored file */ } /* create directory (could add loop here scanning tmproot * to create more than one level, but really necessary?) */ if (MKDIR(tmproot, 0777) == -1) { Info(slide, 1, ((char *)slide, LoadFarString(CantCreateExtractDir), FnFilter1(tmproot))); free(tmproot); G.os2.rootlen = 0; /* path didn't exist, tried to create, failed: */ /* file exists, or need 2+ directory levels */ return MPN_ERR_SKIP; } } } if (add_dot) /* had just "x:", make "x:." */ tmproot[G.os2.rootlen++] = '.'; tmproot[G.os2.rootlen++] = '/'; tmproot[G.os2.rootlen] = '\0'; if ((G.os2.rootpath = realloc(tmproot, G.os2.rootlen+1)) == NULL) { free(tmproot); G.os2.rootlen = 0; return MPN_NOMEM; } Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.os2.rootpath))); } return MPN_OK; }#endif /* !SFX || SFX_EXDIR *//*--------------------------------------------------------------------------- END: free rootpath, immediately prior to program exit. ---------------------------------------------------------------------------*/ if (FUNCTION == END) { Trace((stderr, "freeing rootpath\n")); if (G.os2.rootlen > 0) { free(G.os2.rootpath); G.os2.rootlen = 0; } return MPN_OK; } return MPN_INVALID; /* should never reach */} /* end function checkdir() *//***********************//* Function isfloppy() */ /* more precisely, is it removable? *//***********************/static int isfloppy(nDrive) int nDrive; /* 1 == A:, 2 == B:, etc. */{ uch ParmList[1] = {0}; uch DataArea[1] = {0}; char Name[3]; HFILE handle;#ifdef __32BIT__ ULONG rc; ULONG action;#else USHORT rc; USHORT action;#endif Name[0] = (char) (nDrive + 'A' - 1); Name[1] = ':'; Name[2] = 0; rc = DosOpen(Name, &handle, &action, 0L, FILE_NORMAL, FILE_OPEN, OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0L); if (rc == ERROR_NOT_READY) /* must be removable */ return TRUE; else if (rc) { /* other error: do default a/b heuristic instead */ Trace((stderr, "error in DosOpen(DASD): guessing...\n", rc)); return (nDrive == 1 || nDrive == 2)? TRUE : FALSE; } rc = DosDevIOCtl(DataArea, sizeof(DataArea), ParmList, sizeof(ParmList), DSK_BLOCKREMOVABLE, IOCTL_DISK, handle); DosClose(handle); if (rc) { /* again, just check for a/b */ Trace((stderr, "error in DosDevIOCtl category IOCTL_DISK, function " "DSK_BLOCKREMOVABLE\n (rc = 0x%04x): guessing...\n", rc)); return (nDrive == 1 || nDrive == 2)? TRUE : FALSE; } else { return DataArea[0] ? FALSE : TRUE; }} /* end function isfloppy() */static int IsFileNameValid(const char *name){ HFILE hf;#ifdef __32BIT__ ULONG uAction;#else USHORT uAction;#endif switch( DosOpen((PSZ) name, &hf, &uAction, 0, 0, FILE_OPEN, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0) ) { case ERROR_INVALID_NAME: case ERROR_FILENAME_EXCED_RANGE: return FALSE; case NO_ERROR: DosClose(hf); default: return TRUE; }}/**********************//* Function map2fat() *//**********************/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 = (char *)NULL; /* last dot not converted to underscore */ int dotname = FALSE; /* flag: path component begins with dot */ /* ("." and ".." don't count) */ register unsigned workch; /* hold the character being tested */ /* Only need check those characters which are legal in HPFS but not * in FAT: to get here, must already have passed through mapname. * (GRR: oops, small bug--if char was quoted, no longer have any * knowledge of that.) Also must truncate path component to ensure * 8.3 compliance... */ while ((workch = (uch)*ppc++) != 0) { switch (workch) { case '[': /* add '"' '+' ',' '=' ?? */ 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, unchanged... */ ++ppc; /* skip second dot, since it will */ } else { /* be "added" at end of if-block */ *pEnd++ = '_'; /* FAT doesn't allow null filename */ dotname = TRUE; /* bodies, so map .exrc -> _.exrc */ } /* (extra '_' now, "dot" below) */ } else if (dotname) { /* found a second dot, but still */ dotname = FALSE; /* have extra leading underscore: */ *pEnd = '\0'; /* remove it by shifting chars */ pEnd = *pEndFAT + 1; /* left one space (e.g., .p1.p2: */ while (pEnd[1]) { /* __p1 -> _p1_p2 -> _p1.p2 when */ *pEnd = pEnd[1]; /* finished) [opt.: since first */ ++pEnd; /* two chars are same, can start */ } /* shifting at second position] */ } last_dot = pEnd; /* point at last dot so far... */ *pEnd++ = '_'; /* convert dot 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 == (char *)NULL) { /* no dots: check for underscores... */ char *plu = strrchr(pBegin, '_'); /* pointer to last underscore */ if (plu == (char *)NULL) { /* no dots, no underscores: truncate at 8 */ *pEndFAT += 8; /* chars (could insert '.' and keep 11...) */ if (*pEndFAT > pEnd) *pEndFAT = pEnd; /* oops...didn't have 8 chars to truncate */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -