📄 nt.c
字号:
/* 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 '[':
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 == NULL) { /* no dots: check for underscores... */
char *plu = strrchr(pBegin, '_'); /* pointer to last underscore */
if (plu == NULL) { /* no dots, no underscores: truncate at 8 chars */
*pEndFAT += 8; /* (or could insert '.' and keep 11...?) */
if (*pEndFAT > pEnd)
*pEndFAT = pEnd; /* oops...didn't have 8 chars to truncate */
else
**pEndFAT = '\0';
} else if (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) {
*pEndFAT += 8; /* more fits into just basename than if */
**pEndFAT = '\0'; /* convert last underscore to dot */
} else
*pEndFAT = pEnd; /* whole thing fits into 8 chars or less */
}
if (last_dot != NULL) { /* one dot (or two, in the case of */
*last_dot = '.'; /* "..") is OK: put it back in */
if ((last_dot - pBegin) > 8) {
char *p=last_dot, *q=pBegin+8;
int i;
for (i = 0; (i < 4) && *p; ++i) /* too many chars in basename: */
*q++ = *p++; /* shift .ext left and trun- */
*q = '\0'; /* cate/terminate it */
*pEndFAT = q;
} else if ((pEnd - last_dot) > 4) { /* too many chars in extension */
*pEndFAT = last_dot + 4;
**pEndFAT = '\0';
} else
*pEndFAT = pEnd; /* filename is fine; point at terminating zero */
}
} /* end function map2fat() */
/***********************/ /* Borrowed from os2.c for UnZip 5.1. */
/* Function checkdir() */ /* Difference: no EA stuff */
/***********************/ /* HPFS stuff works on NTFS too */
int checkdir(pathcomp, flag)
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 *buildpathHPFS; /* full path (so far) to extracted file, */
static char *buildpathFAT; /* both HPFS/EA (main) and FAT versions */
static char *endHPFS; /* corresponding pointers to end of */
static char *endFAT; /* 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) {
char *p = pathcomp;
int too_long=FALSE;
Trace((stderr, "appending dir segment [%s]\n", pathcomp));
while ((*endHPFS = *p++) != '\0') /* copy to HPFS filename */
++endHPFS;
if (IsFileNameValid(buildpathHPFS)) {
p = pathcomp;
while ((*endFAT = *p++) != '\0') /* copy to FAT filename, too */
++endFAT;
} else {
/* GRR: check error return? */
map2fat(pathcomp, &endFAT); /* map, put in FAT fn, update endFAT */
}
/* GRR: could do better check, see if overrunning buffer as we go:
* check endHPFS-buildpathHPFS 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. */
/* next check: need to append '/', at least one-char name, '\0' */
if ((endHPFS-buildpathHPFS) > FILNAMSIZ-3)
too_long = TRUE; /* check if extracting dir? */
if (stat(buildpathFAT, &statbuf)) /* path doesn't exist */
{
if (!create_dirs) { /* told not to create (freshening) */
free(buildpathHPFS);
free(buildpathFAT);
return 2; /* path doesn't exist: nothing to do */
}
if (too_long) { /* GRR: should allow FAT extraction w/o EAs */
FPRINTF(stderr, "checkdir error: path too long: %s\n",
buildpathHPFS);
fflush(stderr);
free(buildpathHPFS);
free(buildpathFAT);
return 4; /* no room for filenames: fatal */
}
if (MKDIR(buildpathFAT, 0777) == -1) { /* create the directory */
FPRINTF(stderr, "checkdir error: can't create %s\n\
unable to process %s.\n", buildpathFAT, filename);
fflush(stderr);
free(buildpathHPFS);
free(buildpathFAT);
return 3; /* path didn't exist, tried to create, failed */
}
created_dir = TRUE;
} else if (!S_ISDIR(statbuf.st_mode)) {
FPRINTF(stderr, "checkdir error: %s exists but is not directory\n\
unable to process %s.\n", buildpathFAT, filename);
fflush(stderr);
free(buildpathHPFS);
free(buildpathFAT);
return 3; /* path existed but wasn't dir */
}
if (too_long) {
FPRINTF(stderr, "checkdir error: path too long: %s\n",
buildpathHPFS);
fflush(stderr);
free(buildpathHPFS);
free(buildpathFAT);
return 4; /* no room for filenames: fatal */
}
*endHPFS++ = '/';
*endFAT++ = '/';
*endHPFS = *endFAT = '\0';
Trace((stderr, "buildpathHPFS now = [%s]\n", buildpathHPFS));
Trace((stderr, "buildpathFAT now = [%s]\n", buildpathFAT));
return 0;
} /* end if (FUNCTION == APPEND_DIR) */
/*---------------------------------------------------------------------------
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", buildpathFAT));
Trace((stderr, "freeing HPFS path [%s]\n", buildpathHPFS));
strcpy(pathcomp, buildpathFAT);
free(buildpathFAT);
free(buildpathHPFS);
buildpathHPFS = buildpathFAT = endHPFS = endFAT = NULL;
return 0;
}
/*---------------------------------------------------------------------------
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 = 0;
Trace((stderr, "appending filename [%s]\n", pathcomp));
while ((*endHPFS = *p++) != '\0') { /* copy to HPFS filename */
++endHPFS;
if ((endHPFS-buildpathHPFS) >= FILNAMSIZ) {
*--endHPFS = '\0';
FPRINTF(stderr, "checkdir warning: path too long; truncating\n\
%s\n -> %s\n", filename, buildpathHPFS);
fflush(stderr);
error = 1; /* filename truncated */
}
}
if ( pInfo->vollabel || IsFileNameValid(buildpathHPFS)) {
p = pathcomp;
while ((*endFAT = *p++) != '\0') /* copy to FAT filename, too */
++endFAT;
} else {
map2fat(pathcomp, &endFAT); /* map, put in FAT fn, update endFAT */
}
Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT: %s\n",
buildpathHPFS, 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) {
/* HG: variable not used here */
/* char *p; */
Trace((stderr, "initializing buildpathHPFS and buildpathFAT to "));
if ((buildpathHPFS = (char *)malloc(fnlen+rootlen+1)) == NULL)
return 10;
if ((buildpathFAT = (char *)malloc(fnlen+rootlen+1)) == NULL) {
free(buildpathHPFS);
return 10;
}
if (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 (renamed_fullpath && pathcomp[1] == ':')
*buildpathHPFS = ToLower(*pathcomp);
else if (!renamed_fullpath && rootpath && rootpath[1] == ':')
*buildpathHPFS = ToLower(*rootpath);
else {
char tmpN[MAX_PATH], *tmpP;
if (GetFullPathName(".", MAX_PATH, tmpN, &tmpP) > MAX_PATH)
{ /* by definition of MAX_PATH we should never get here */
FPRINTF(stderr,
"checkdir warning: current dir path too long\n");
return 1; /* can't get drive letter */
}
nLabelDrive = *tmpN - 'a' + 1;
*buildpathHPFS = (char)(nLabelDrive - 1 + 'a');
}
nLabelDrive = *buildpathHPFS - 'a' + 1; /* save for mapname() */
if (volflag == 0 || *buildpathHPFS < 'a' || /* no labels/bogus? */
(volflag == 1 && !isfloppy(nLabelDrive))) { /* -$: no fixed */
free(buildpathHPFS);
free(buildpathFAT);
return IZ_VOL_LABEL; /* skipping with message */
}
*buildpathHPFS = '\0';
} else if (renamed_fullpath) /* pathcomp = valid data */
strcpy(buildpathHPFS, pathcomp);
else if (rootlen > 0)
strcpy(buildpathHPFS, rootpath);
else
*buildpathHPFS = '\0';
endHPFS = buildpathHPFS;
endFAT = buildpathFAT;
while ((*endFAT = *endHPFS) != '\0') {
++endFAT;
++endHPFS;
}
Trace((stderr, "[%s]\n", buildpathHPFS));
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. 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", pathcomp));
if (pathcomp == NULL) {
rootlen = 0;
return 0;
}
if ((rootlen = strlen(pathcomp)) > 0) {
int had_trailing_pathsep=FALSE, has_drive=FALSE, xtra=2;
if (isalpha(pathcomp[0]) && pathcomp[1] == ':')
has_drive = TRUE; /* drive designator */
if (pathcomp[rootlen-1] == '/') {
pathcomp[--rootlen] = '\0';
had_trailing_pathsep = TRUE;
}
if (has_drive && (rootlen == 2)) {
if (!had_trailing_pathsep) /* i.e., original wasn't "x:/" */
xtra = 3; /* room for '.' + '/' + 0 at end of "x:" */
} else if (rootlen > 0) { /* need not check "x:." and "x:/" */
if (SSTAT(pathcomp, &statbuf) || !S_ISDIR(statbuf.st_mode)) {
/* path does not exist */
if (!create_dirs /* || iswild(pathcomp) */
#ifdef OLD_EXDIR
|| (!has_drive && !had_trailing_pathsep)
#endif
) {
rootlen = 0;
return 2; /* treat as stored file */
}
/* create directory (could add loop here to scan pathcomp
* and create more than one level, but really necessary?) */
if (MKDIR(pathcomp, 0777) == -1) {
FPRINTF(stderr,
"checkdir: can't create extraction directory: %s\n",
pathcomp);
fflush(stderr);
rootlen = 0; /* path didn't exist, tried to create, */
return 3; /* failed: file exists, or need 2+ levels */
}
}
}
if ((rootpath = (char *)malloc(rootlen+xtra)) == NULL) {
rootlen = 0;
return 10;
}
strcpy(rootpath, pathcomp);
if (xtra == 3) /* had just "x:", make "x:." */
rootpath[rootlen++] = '.';
rootpath[rootlen++] = '/';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -