📄 ls.c
字号:
datestr,
expad,
diritemp->relname,
l1,
l2,
fTail
);
Trace(0, "%s %12s %s%s %s%s%s%s%s\n",
plugstr,
sizestr,
expad,
datestr,
expad,
diritemp->relname,
l1,
l2,
fTail
);
}
} /* LsL */
/* Does "ls -1", or the simple single-column /bin/ls-style format, with
* one file per line.
*/
void
Ls1(FileInfoListPtr dirp, int endChars, FILE *stream)
{
char fTail[2];
int i;
int fType;
FileInfoVec diritemv;
FileInfoPtr diritemp;
fTail[0] = '\0';
fTail[1] = '\0';
diritemv = dirp->vec;
for (i=0; ; i++) {
diritemp = diritemv[i];
if (diritemp == NULL)
break;
fType = (int) diritemp->type;
if (endChars != 0) {
if (fType == 'd')
fTail[0] = '/';
else
fTail[0] = '\0';
}
(void) fprintf(stream, "%s%s\n",
diritemp->relname,
fTail
);
Trace(0, "%s%s\n",
diritemp->relname,
fTail
);
}
} /* Ls1 */
/* Prints a directory listing in the specified format on the specified
* output stream. It may or may not need to request it from the remote
* server, depending on whether it was cached.
*/
void
Ls(const char *const item, int listmode, const char *const options, FILE *stream)
{
char itempath[512];
FileInfoList fil;
FileInfoListPtr filp;
LinePtr linePtr, nextLinePtr;
LineList dirContents;
int parsed;
int linkedTo;
int endChars;
int rlisted;
int opt;
const char *cp;
int sortBy;
int sortOrder;
int unknownOpts;
char optstr[32];
char unoptstr[32];
int doNotUseCache;
int wasInCache;
int mlsd;
int ci;
InitLineList(&dirContents);
InitFileInfoList(&fil);
sortBy = 'n'; /* Sort by filename. */
sortOrder = 'a'; /* Sort in ascending order. */
linkedTo = 0;
endChars = (listmode == 'C') ? 1 : 0;
unknownOpts = 0;
memset(unoptstr, 0, sizeof(unoptstr));
unoptstr[0] = '-';
doNotUseCache = 0;
rlisted = 0;
for (cp = options; *cp != '\0'; cp++) {
opt = *cp;
switch (opt) {
case 't':
sortBy = 't'; /* Sort by modification time. */
break;
case 'S':
sortBy = 's'; /* Sort by size. */
break;
case 'r':
sortOrder = 'd'; /* descending order */
break;
case 'L':
linkedTo = 1;
break;
case 'f':
doNotUseCache = 1;
break;
case 'F':
case 'p':
endChars = 1;
break;
case '1':
case 'C':
case 'l':
listmode = opt;
break;
case '-':
break;
default:
if (unknownOpts < ((int) sizeof(unoptstr) - 2))
unoptstr[unknownOpts + 1] = opt;
unknownOpts++;
break;
}
}
/* Create a possibly relative path into an absolute path. */
PathCat(itempath, sizeof(itempath), gRemoteCWD,
(item == NULL) ? "." : item);
if (unknownOpts > 0) {
/* Can't handle these -- pass them through
* to the server.
*/
Trace(0, "ls caching not used because of ls flags: %s\n", unoptstr);
optstr[0] = '-';
optstr[1] = listmode;
optstr[2] = '\0';
(void) STRNCAT(optstr, options);
if ((FTPListToMemory2(&gConn, (item == NULL) ? "" : item, &dirContents, optstr, 1, 0)) < 0) {
if (stream != NULL)
(void) fprintf(stderr, "List failed.\n");
return;
}
rlisted = 1;
parsed = -1;
wasInCache = 0;
filp = NULL;
} else if ((doNotUseCache != 0) || ((ci = LsCacheLookup(itempath)) < 0)) {
/* Not in cache. */
wasInCache = 0;
mlsd = 1;
if ((FTPListToMemory2(&gConn, (item == NULL) ? "" : item, &dirContents, "-l", 1, &mlsd)) < 0) {
if (stream != NULL)
(void) fprintf(stderr, "List failed.\n");
return;
}
rlisted = 1;
filp = &fil;
if (mlsd != 0) {
parsed = UnMlsD(filp, &dirContents);
if (parsed < 0) {
Trace(0, "UnMlsD: %d\n", parsed);
}
} else {
parsed = UnLslR(filp, &dirContents, gConn.serverType);
if (parsed < 0) {
Trace(0, "UnLslR: %d\n", parsed);
}
}
if (parsed >= 0) {
VectorizeFileInfoList(filp);
if (filp->vec == NULL) {
if (stream != NULL)
(void) fprintf(stderr, "List processing failed.\n");
return;
}
}
} else {
filp = &gLsCache[ci].fil;
wasInCache = 1;
parsed = 1;
Trace(0, "ls cache hit: %s\n", itempath);
}
if (rlisted != 0) {
Trace(0, "Remote listing contents {\n");
for (linePtr = dirContents.first;
linePtr != NULL;
linePtr = nextLinePtr)
{
nextLinePtr = linePtr->next;
Trace(0, " %s\n", linePtr->line);
}
Trace(0, "}\n");
}
if (parsed >= 0) {
SortFileInfoList(filp, sortBy, sortOrder);
if (stream != NULL) {
if (listmode == 'l')
LsL(filp, endChars, linkedTo, stream);
else if (listmode == '1')
Ls1(filp, endChars, stream);
else
LsC(filp, endChars, stream);
}
if (wasInCache == 0) {
LsCacheAdd(itempath, filp);
}
} else if (stream != NULL) {
for (linePtr = dirContents.first;
linePtr != NULL;
linePtr = nextLinePtr)
{
nextLinePtr = linePtr->next;
(void) fprintf(stream, "%s\n", linePtr->line);
Trace(0, " %s\n", linePtr->line);
}
}
DisposeLineListContents(&dirContents);
} /* Ls */
#if defined(WIN32) || defined(_WINDOWS)
/* Prints a local directory listing in the specified format on the specified
* output stream.
*/
void
LLs(const char *const item, int listmode, const char *const options, FILE *stream)
{
char itempath[512];
int linkedTo;
int endChars;
int opt;
const char *cp;
int sortBy;
int sortOrder;
int unknownOpts;
char unoptstr[32];
LineList ll;
FileInfoPtr fip, fip2;
FileInfoList fil;
struct Stat st;
int result;
size_t len;
InitLineList(&ll);
InitFileInfoList(&fil);
sortBy = 'n'; /* Sort by filename. */
sortOrder = 'a'; /* Sort in ascending order. */
linkedTo = 0;
endChars = (listmode == 'C') ? 1 : 0;
unknownOpts = 0;
memset(unoptstr, 0, sizeof(unoptstr));
unoptstr[0] = '-';
for (cp = options; *cp != '\0'; cp++) {
opt = *cp;
switch (opt) {
case 't':
sortBy = 't'; /* Sort by modification time. */
break;
case 'S':
sortBy = 's'; /* Sort by size. */
break;
case 'r':
sortOrder = 'd'; /* descending order */
break;
case 'L':
linkedTo = 1;
break;
case 'f':
break;
case 'F':
case 'p':
endChars = 1;
break;
case '1':
case 'C':
case 'l':
listmode = opt;
break;
case '-':
break;
default:
if (unknownOpts < ((int) sizeof(unoptstr) - 2))
unoptstr[unknownOpts + 1] = opt;
unknownOpts++;
break;
}
}
if ((item == NULL) || (strcmp(item, ".") == 0))
STRNCPY(itempath, "*.*");
else {
STRNCPY(itempath, item);
if (strpbrk(itempath, "*?") == NULL)
STRNCAT(itempath, "\\*.*");
}
InitLineList(&ll);
result = FTPLocalGlob(&gConn, &ll, itempath, kGlobYes);
if (result < 0) {
FTPPerror(&gConn, result, kErrGlobFailed, "local glob", itempath);
DisposeLineListContents(&ll);
return;
}
if (LineListToFileInfoList(&ll, &fil) < 0)
return;
DisposeLineListContents(&ll);
for (fip = fil.first; fip != NULL; fip = fip2) {
fip2 = fip->next;
if (Stat(fip->relname, &st) < 0) {
fip2 = RemoveFileInfo(&fil, fip);
continue;
}
cp = StrRFindLocalPathDelim(fip->relname);
if (cp != NULL) {
/* FTPLocalGlob will tack on the pathnames too,
* which we don't want for this hack.
*/
cp++;
len = strlen(cp);
memmove(fip->relname, cp, len + 1);
} else {
len = strlen(fip->relname);
}
if (len > fil.maxFileLen)
fil.maxFileLen = len;
fip->relnameLen = len;
fip->rname = StrDup(fip->relname);
fip->lname = StrDup(fip->relname);
fip->plug = StrDup("---------- 1 user group");
if (S_ISDIR(st.st_mode)) {
fip->type = 'd';
fip->plug[0] = 'd';
} else {
fip->type = '-';
fip->size = st.st_size;
}
fip->mdtm = st.st_mtime;
}
fil.maxPlugLen = strlen("---------- 1 user group");
VectorizeFileInfoList(&fil);
SortFileInfoList(&fil, sortBy, sortOrder);
if (stream != NULL) {
if (listmode == 'l')
LsL(&fil, endChars, linkedTo, stream);
else if (listmode == '1')
Ls1(&fil, endChars, stream);
else
LsC(&fil, endChars, stream);
}
DisposeFileInfoListContents(&fil);
} /* LLs */
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -