📄 glob.c
字号:
/* glob.c
*
* Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
* All rights reserved.
*
*/
#include "syshdrs.h"
static const char *rwx[9] = { "---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx", NULL };
/* We need to use this because using NLST gives us more stuff than
* we want back sometimes. For example, say we have:
*
* /a (directory)
* /a/b (directory)
* /a/b/b1
* /a/b/b2
* /a/b/b3
* /a/c (directory)
* /a/c/c1
* /a/c/c2
* /a/c/c3
* /a/file
*
* If you did an "echo /a/<star>" in a normal unix shell, you would expect
* to get back /a/b /a/c /a/file. But NLST gives back:
*
* /a/b/b1
* /a/b/b2
* /a/b/b3
* /a/c/c1
* /a/c/c2
* /a/c/c3
* /a/file
*
* So we use the following routine to convert into the format I expect.
*/
static void
RemoteGlobCollapse(const char *pattern, LineListPtr fileList)
{
LinePtr lp, nextLine;
string patPrefix;
string cur, prev;
char *endp, *cp, *dp;
const char *pp;
int wasGlobChar;
size_t plen;
/* Copy all characters before the first glob-char. */
dp = patPrefix;
endp = dp + sizeof(patPrefix) - 1;
wasGlobChar = 0;
for (cp = (char *) pattern; dp < endp; ) {
for (pp=kGlobChars; *pp != '\0'; pp++) {
if (*pp == *cp) {
wasGlobChar = 1;
break;
}
}
if (wasGlobChar)
break;
*dp++ = *cp++;
}
*dp = '\0';
plen = (size_t) (dp - patPrefix);
*prev = '\0';
for (lp=fileList->first; lp != NULL; lp = nextLine) {
nextLine = lp->next;
if (strncmp(lp->line, patPrefix, plen) == 0) {
(void) STRNCPY(cur, lp->line + plen);
cp = strchr(cur, '/');
if (cp == NULL)
cp = strchr(cur, '\\');
if (cp != NULL)
*cp = '\0';
if ((*prev != '\0') && (STREQ(cur, prev))) {
nextLine = RemoveLine(fileList, lp);
} else {
(void) STRNCPY(prev, cur);
/* We are playing with a dynamically
* allocated string, but since the
* following expression is guaranteed
* to be the same or shorter, we won't
* overwrite the bounds.
*/
(void) sprintf(lp->line, "%s%s", patPrefix, cur);
}
}
}
} /* RemoteGlobCollapse */
#if 0
/* May need this later. */
static void
CheckForLS_d(FTPCIPtr cip)
{
LineList lines;
char *cp;
if (cip->hasNLST_d == kCommandAvailabilityUnknown) {
if (FTPListToMemory2(cip, ".", &lines, "-d ", 0, (int *) 0) == kNoErr) {
if ((lines.first != NULL) && (lines.first == lines.last)) {
/* If we have only one item in the list, see if it really was
* an error message we would recognize.
*/
cp = strchr(lines.first->line, ':');
if ((cp != NULL) && STREQ(cp, ": No such file or directory")) {
cip->hasNLST_d = kCommandNotAvailable;
} else {
cip->hasNLST_d = kCommandAvailable;
}
} else {
cip->hasNLST_d = kCommandNotAvailable;
}
} else {
cip->hasNLST_d = kCommandNotAvailable;
}
DisposeLineListContents(&lines);
}
} /* CheckForLS_d */
#endif
static int
LsMonthNameToNum(char *cp)
{
int mon; /* 0..11 */
switch (*cp++) {
case 'A':
mon = (*cp == 'u') ? 7 : 3;
break;
case 'D':
mon = 11;
break;
case 'F':
mon = 1;
break;
default:
case 'J':
if (*cp++ == 'u')
mon = (*cp == 'l') ? 6 : 5;
else
mon = 0;
break;
case 'M':
mon = (*++cp == 'r') ? 2 : 4;
break;
case 'N':
mon = 10;
break;
case 'O':
mon = 9;
break;
case 'S':
mon = 8;
}
return (mon);
} /* LsMonthNameToNum */
static int
UnDosLine( char *const line,
const char *const curdir,
size_t curdirlen,
char *fname,
size_t fnamesize,
int *ftype,
longest_int *fsize,
time_t *ftime)
{
char *cp;
int hour, year;
char *filestart;
char *sizestart;
struct tm ftm;
/*
*
0123456789012345678901234567890123456789012345678901234567890123456789
04-27-99 10:32PM 270158 Game booklet.pdf
03-11-99 10:03PM <DIR> Get A3d Banner
We also try to parse the format from CMD.EXE, which is similar:
03/22/2001 06:23p 62,325 cls.pdf
*
*/
cp = line;
if (
isdigit((int) cp[0])
&& isdigit((int) cp[1])
&& ispunct((int) cp[2])
&& isdigit((int) cp[3])
&& isdigit((int) cp[4])
&& ispunct((int) cp[5])
&& isdigit((int) cp[6])
&& isdigit((int) cp[7])
) {
(void) memset(&ftm, 0, sizeof(struct tm));
ftm.tm_isdst = -1;
cp[2] = '\0';
ftm.tm_mon = atoi(cp + 0);
if (ftm.tm_mon > 0)
ftm.tm_mon -= 1;
cp[5] = '\0';
ftm.tm_mday = atoi(cp + 3);
if ((isdigit((int) cp[8])) && (isdigit((int) cp[9]))) {
/* Four-digit year */
cp[10] = '\0';
year = atoi(cp + 6);
if (year > 1900)
year -= 1900;
ftm.tm_year = year; /* years since 1900 */
cp += 11;
} else {
/* Two-digit year */
cp[8] = '\0';
year = atoi(cp + 6);
if (year < 98)
year += 100;
ftm.tm_year = year; /* years since 1900 */
cp += 9;
}
for (;;) {
if (*cp == '\0')
return (-1);
if (isdigit(*cp))
break;
cp++;
}
cp[2] = '\0';
hour = atoi(cp);
if (((cp[5] == 'P') || (cp[5] == 'p')) && (hour < 12))
hour += 12;
else if (((cp[5] == 'A') || (cp[5] == 'a')) && (hour == 12))
hour -= 12;
ftm.tm_hour = hour;
cp[5] = '\0';
ftm.tm_min = atoi(cp + 3);
*ftime = mktime(&ftm);
if (*ftype == (time_t) -1)
return (-1);
cp += 6;
*ftype = '-';
for (;;) {
if (*cp == '\0')
return (-1);
if ((*cp == '<') && (cp[1] == 'D')) {
/* found <DIR> */
*ftype = 'd';
cp += 5;
break; /* size field will end up being empty string */
} else if ((*cp == '<') && (cp[1] == 'J')) {
/* found <JUNCTION>
*
* Will we ever really see this?
* IIS from Win2000sp1 sends <DIR>
* for FTP, but CMD.EXE prints
* <JUNCTION>.
*/
*ftype = 'd';
cp += 10;
break;
} else if (isdigit(*cp)) {
break;
} else {
cp++;
}
}
sizestart = cp;
for (;;) {
if (*cp == '\0')
return (-1);
#ifdef HAVE_MEMMOVE
if (*cp == ',') {
/* Yuck -- US Locale dependency */
memmove(cp, cp + 1, strlen(cp + 1) + 1);
}
#endif
if (!isdigit(*cp)) {
*cp++ = '\0';
break;
}
cp++;
}
if (fsize != NULL) {
#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG)
if (*ftype == 'd')
*fsize = 0;
else
(void) sscanf(sizestart, SCANF_LONG_LONG, fsize);
#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ)
if (*ftype == 'd')
*fsize = 0;
else
*fsize = (longest_int) strtoq(sizestart, NULL, 0);
#else
*fsize = (longest_int) 0;
if (*ftype != 'd') {
long fsize2 = 0L;
(void) sscanf(sizestart, "%ld", &fsize2);
*fsize = (longest_int) fsize2;
}
#endif
}
for (;;) {
if (*cp == '\0')
return (-1);
if (!isspace(*cp)) {
break;
}
cp++;
}
filestart = cp;
if (curdirlen == 0) {
(void) Strncpy(fname, filestart, fnamesize);
} else {
(void) Strncpy(fname, curdir, fnamesize);
(void) Strncat(fname, filestart, fnamesize);
}
return (0);
}
return (-1);
} /* UnDosLine */
static int
UnLslRLine( char *const line,
const char *const curdir,
size_t curdirlen,
char *fname,
size_t fnamesize,
char *linkto,
size_t linktosize,
int *ftype,
longest_int *fsize,
time_t *ftime,
time_t now,
int thisyear,
int *plugend)
{
char *cp;
int mon = 0, dd = 0, hr = 0, min = 0, year = 0;
char *monstart, *ddstart, *hrstart, *minstart, *yearstart;
char *linktostart, *filestart = NULL;
char *sizestart;
char *pe;
struct tm ftm;
/*
* Look for the digit just before the space
* before the month name.
*
-rw-rw---- 1 gleason sysdev 33404 Mar 24 01:29 RCmd.o
-rw-rw-r-- 1 gleason sysdevzz 1829 Jul 7 1996 README
-rw-rw-r-- 1 gleason sysdevzz 1829 Jul 7 1996 README
-rw-rw-r-- 1 gleason sysdevzz 1829 Jul 7 1996 README
-rw-rw-r-- 1 gleason sysdevzz 1829 Jul 7 1996 README
*
*------------------------------^
* 0123456789012345
*------plugend--------^
* 9876543210
*
*/
for (cp = line; *cp != '\0'; cp++) {
if ( (isdigit((int) *cp))
&& (isspace((int) cp[1]))
&& (isupper((int) cp[2]))
&& (islower((int) cp[3]))
/* && (islower((int) cp[4])) */
&& (isspace((int) cp[5]))
&& (
((isdigit((int) cp[6])) && (isdigit((int) cp[7])))
|| ((isdigit((int) cp[6])) && (isspace((int) cp[7])))
|| ((isspace((int) cp[6])) && (isdigit((int) cp[7])))
)
&& (isspace((int) cp[8]))
) {
monstart = cp + 2;
ddstart = cp + 6;
if ( ((isspace((int) cp[9])) || (isdigit((int) cp[9])))
&& (isdigit((int) cp[10]))
&& (isdigit((int) cp[11]))
&& (isdigit((int) cp[12]))
&& ((isdigit((int) cp[13])) || (isspace((int) cp[13])))
) {
/* "Mon DD YYYY" form */
yearstart = cp + 9;
if (isspace((int) *yearstart))
yearstart++;
hrstart = NULL;
minstart = NULL;
filestart = cp + 15;
cp[1] = '\0'; /* end size */
cp[5] = '\0'; /* end mon */
cp[8] = '\0'; /* end dd */
cp[14] = '\0'; /* end year */
mon = LsMonthNameToNum(monstart);
dd = atoi(ddstart);
hr = 23;
min = 59;
year = atoi(yearstart);
pe = cp;
while (isdigit((int) *pe))
pe--;
while (isspace((int) *pe))
pe--;
*plugend = (int) (pe - line) + 1;
break;
} else if ( /*
* Windows NT does not 0 pad.
(isdigit((int) cp[9])) &&
*/
(isdigit((int) cp[10]))
&& (cp[11] == ':')
&& (isdigit((int) cp[12]))
&& (isdigit((int) cp[13]))
) {
/* "Mon DD HH:MM" form */
yearstart = NULL;
hrstart = cp + 9;
minstart = cp + 12;
filestart = cp + 15;
cp[1] = '\0'; /* end size */
cp[5] = '\0'; /* end mon */
cp[8] = '\0'; /* end dd */
cp[11] = '\0'; /* end hr */
cp[14] = '\0'; /* end min */
mon = LsMonthNameToNum(monstart);
dd = atoi(ddstart);
hr = atoi(hrstart);
min = atoi(minstart);
year = 0;
pe = cp;
while (isdigit((int) *pe))
pe--;
while (isspace((int) *pe))
pe--;
*plugend = (int) (pe - line) + 1;
break;
}
}
}
if (*cp == '\0')
return (-1);
linktostart = strstr(filestart, " -> ");
if (linktostart != NULL) {
*linktostart = '\0';
linktostart += 4;
(void) Strncpy(linkto, linktostart, linktosize);
} else {
*linkto = '\0';
}
if (curdirlen == 0) {
(void) Strncpy(fname, filestart, fnamesize);
} else {
(void) Strncpy(fname, curdir, fnamesize);
(void) Strncat(fname, filestart, fnamesize);
}
if (ftime != NULL) {
(void) memset(&ftm, 0, sizeof(struct tm));
ftm.tm_mon = mon;
ftm.tm_mday = dd;
ftm.tm_hour = hr;
ftm.tm_min = min;
ftm.tm_isdst = -1;
if (year == 0) {
/* We guess the year, based on what the
* current year is. We know the file
* on the remote server is either less
* than six months old or less than
* one hour into the future.
*/
ftm.tm_year = thisyear - 1900;
*ftime = mktime(&ftm);
if (*ftime == (time_t) -1) {
/* panic */
} else if (*ftime > (now + (15552000L + 86400L))) {
--ftm.tm_year;
*ftime = mktime(&ftm);
} else if (*ftime < (now - (15552000L + 86400L))) {
++ftm.tm_year;
*ftime = mktime(&ftm);
}
} else {
ftm.tm_year = year - 1900;
*ftime = mktime(&ftm);
}
}
if (fsize != NULL) {
while ((cp > line) && (isdigit((int) *cp)))
--cp;
sizestart = cp + 1;
#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG)
(void) sscanf(sizestart, SCANF_LONG_LONG, fsize);
#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ)
*fsize = (longest_int) strtoq(sizestart, NULL, 0);
#else
{
long fsize2 = 0L;
(void) sscanf(sizestart, "%ld", &fsize2);
*fsize = (longest_int) fsize2;
}
#endif
}
switch (line[0]) {
case 'd':
case 'l':
*ftype = (int) line[0];
break;
case 'b':
case 'c':
case 's':
*ftype = (int) line[0];
return (-1);
default:
*ftype = '-';
}
return (0);
} /* UnLslRLine */
int
UnLslR(FileInfoListPtr filp, LineListPtr llp, int serverType)
{
char curdir[256];
char line[256];
int hadblankline = 0;
int len;
size_t curdirlen = 0;
char fname[256];
char linkto[256];
char *cp;
longest_int fsize;
int ftype;
time_t ftime, now;
int thisyear;
struct tm *nowtm;
int rc;
LinePtr lp;
FileInfo fi;
int linesread = 0;
int linesconverted = 0;
size_t maxFileLen = 0;
size_t maxPlugLen = 0;
size_t fileLen;
int plugend;
(void) time(&now);
nowtm = localtime(&now);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -