📄 cmds.c
字号:
result = kErrInvalidDirParam;
cip->errNo = kErrInvalidDirParam;
return result;
}
if ((cdCwd[0] == '\0') || (strcmp(cdCwd, ".") == 0)) {
result = 0;
return (result);
}
cp = cip->buf;
cp[cip->bufSize - 2] = '\0';
if ((cdCwd[0] == '.') && (cdCwd[1] == '.') && ((cdCwd[2] == '\0') || IsLocalPathDelim(cdCwd[2]))) {
PathCat(cip->buf, cip->bufSize, gRemoteCWD, cdCwd);
} else {
(void) Strncpy(cip->buf, cdCwd, cip->bufSize);
}
if (cp[cip->bufSize - 2] != '\0')
return (kErrBadParameter);
StrRemoveTrailingLocalPathDelim(cp);
do {
startcp = cp;
cp = StrFindLocalPathDelim(cp + 0);
if (cp != NULL) {
*cp++ = '\0';
}
lastSubDir = (cp == NULL);
result = nFTPChdirAndGetCWD(cip, (*startcp != '\0') ? startcp : "/", lastSubDir ? 0 : 1);
if (result < 0) {
cip->errNo = result;
}
} while ((!lastSubDir) && (result == 0));
return (result);
} /* Chdirs */
/* Remote change of working directory command. */
void
ChdirCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
int result;
LineList ll;
LinePtr lp;
ARGSUSED(gUnusedArg);
if (argc <= 1) {
if (gStartDir[0] != '\0') {
(void) STRNCPY(gPrevRemoteCWD, gRemoteCWD);
result = Chdirs(&gConn, gStartDir);
if (result != kNoErr) {
/* State is incoherent if this happens! */
FTPPerror(&gConn, result, kErrCWDFailed, "Could not chdir to", gStartDir);
}
} else {
PrintCmdUsage(cmdp);
}
} else {
InitLineList(&ll);
result = FTPRemoteGlob(&gConn, &ll, argv[1], (aip->noglobargv[1] != 0) ? kGlobNo: kGlobYes);
if (result < 0) {
FTPPerror(&gConn, result, kErrGlobFailed, argv[0], argv[1]);
} else {
lp = ll.first;
if ((lp != NULL) && (lp->line != NULL)) {
if ((strcmp(lp->line, "-") == 0) && (gPrevRemoteCWD[0] != '\0')) {
free(lp->line);
lp->line = StrDup(gPrevRemoteCWD);
if (lp->line == NULL) {
result = kErrMallocFailed;
gConn.errNo = kErrMallocFailed;
} else {
(void) STRNCPY(gPrevRemoteCWD, gRemoteCWD);
result = Chdirs(&gConn, lp->line);
}
} else {
(void) STRNCPY(gPrevRemoteCWD, gRemoteCWD);
result = Chdirs(&gConn, lp->line);
}
if (result != kNoErr)
FTPPerror(&gConn, result, kErrCWDFailed, "Could not chdir to", lp->line);
}
}
DisposeLineListContents(&ll);
}
} /* ChdirCmd */
/* Chmod files on the remote host, if it supports it. */
void
ChmodCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
int i, result;
ARGSUSED(gUnusedArg);
for (i=2; i<argc; i++) {
result = FTPChmod(
&gConn, argv[i], argv[1],
(aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes
);
if (result < 0) {
FTPPerror(&gConn, result, kErrChmodFailed, "chmod", argv[i]);
/* but continue */
}
}
/* Really should just flush only the modified directories... */
FlushLsCache();
} /* ChmodCmd */
/* Close the current session to a remote FTP server. */
void
CloseCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
ARGSUSED(gUnusedArg);
if (gConn.connected == 0)
(void) printf("Already closed.\n");
else
CloseHost();
} /* CloseCmd */
/* User interface to the program's debug-mode setting. */
void
DebugCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
ARGSUSED(gUnusedArg);
if (argc > 1)
SetDebug(atoi(argv[1]));
else
SetDebug(!gDebug);
} /* DebugCmd */
/* Delete files on the remote host. */
void
DeleteCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
int result;
int i, c;
int recursive = kRecursiveNo;
ARGSUSED(gUnusedArg);
GetoptReset();
while ((c = Getopt(argc, argv, "rf")) > 0) switch(c) {
case 'r':
recursive = kRecursiveYes;
break;
case 'f':
/* ignore */
break;
default:
PrintCmdUsage(cmdp);
return;
}
for (i=gOptInd; i<argc; i++) {
result = FTPDelete(
&gConn, argv[i], recursive,
(aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes
);
if (result < 0) {
FTPPerror(&gConn, result, kErrDELEFailed, "delete", argv[i]);
/* but continue */
}
}
/* Really should just flush only the modified directories... */
FlushLsCache();
} /* DeleteCmd */
/* Command shell echo command. This is mostly useful for testing the command
* shell, as a sample command which prints some output.
*/
void
EchoCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
int i;
int result;
int np = 0;
LineList ll;
LinePtr lp;
ARGSUSED(gUnusedArg);
for (i=1; i<argc; i++) {
InitLineList(&ll);
result = FTPLocalGlob(&gConn, &ll, argv[i], (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes);
if (result < 0) {
FTPPerror(&gConn, result, kErrGlobFailed, "local glob", argv[i]);
} else {
for (lp = ll.first; lp != NULL; lp = lp->next) {
if (lp->line != NULL) {
if (np > 0)
(void) printf(" ");
(void) printf("%s", lp->line);
np++;
}
}
}
DisposeLineListContents(&ll);
}
(void) printf("\n");
} /* EchoCmd */
static int
NcFTPConfirmResumeDownloadProc(
const char *volatile *localpath,
volatile longest_int localsize,
volatile time_t localmtime,
const char *volatile remotepath,
volatile longest_int remotesize,
volatile time_t remotemtime,
volatile longest_int *volatile startPoint)
{
int zaction = kConfirmResumeProcSaidBestGuess;
char tstr[80], ans[32];
static char newname[128]; /* arrggh... static. */
if (gResumeAnswerAll != kConfirmResumeProcNotUsed)
return (gResumeAnswerAll);
if (gAutoResume != 0)
return (kConfirmResumeProcSaidBestGuess);
tstr[sizeof(tstr) - 1] = '\0';
(void) strftime(tstr, sizeof(tstr) - 1, "%c", localtime((time_t *) &localmtime));
(void) printf(
#if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
"\nThe local file \"%s\" already exists.\n\tLocal: %12lld bytes, dated %s.\n",
#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
"\nThe local file \"%s\" already exists.\n\tLocal: %12qd bytes, dated %s.\n",
#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
"\nThe local file \"%s\" already exists.\n\tLocal: %12I64d bytes, dated %s.\n",
#else
"\nThe local file \"%s\" already exists.\n\tLocal: %12ld bytes, dated %s.\n",
#endif
*localpath,
localsize,
tstr
);
if ((remotemtime != kModTimeUnknown) && (remotesize != kSizeUnknown)) {
(void) strftime(tstr, sizeof(tstr) - 1, "%c", localtime((time_t *) &remotemtime));
(void) printf(
#if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
"\tRemote: %12lld bytes, dated %s.\n",
#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
"\tRemote: %12qd bytes, dated %s.\n",
#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
"\tRemote: %12I64d bytes, dated %s.\n",
#else
"\tRemote: %12ld bytes, dated %s.\n",
#endif
remotesize,
tstr
);
if ((remotemtime == localmtime) && (remotesize == localsize)) {
(void) printf("\t(Files are identical, skipped)\n\n");
return (kConfirmResumeProcSaidSkip);
}
} else if (remotesize != kSizeUnknown) {
(void) printf(
#if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
"\tRemote: %12lld bytes, date unknown.\n",
#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
"\tRemote: %12qd bytes, date unknown.\n",
#elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
"\tRemote: %12I64d bytes, date unknown.\n",
#else
"\tRemote: %12ld bytes, date unknown.\n",
#endif
remotesize
);
} else if (remotemtime != kModTimeUnknown) {
(void) strftime(tstr, sizeof(tstr) - 1, "%c", localtime((time_t *) &remotemtime));
(void) printf(
"\tRemote: size unknown, dated %s.\n",
tstr
);
}
printf("\n");
(void) memset(ans, 0, sizeof(ans));
for (;;) {
(void) printf("\t[O]verwrite?");
if ((gConn.hasREST == kCommandAvailable) && (remotesize != kSizeUnknown) && (remotesize > localsize))
printf(" [R]esume?");
printf(" [A]ppend to? [S]kip? [N]ew Name?\n");
(void) printf("\t[O!]verwrite all?");
if ((gConn.hasREST == kCommandAvailable) && (remotesize != kSizeUnknown) && (remotesize > localsize))
printf(" [R!]esume all?");
printf(" [S!]kip all? [C]ancel > ");
fflush(stdin);
(void) fgets(ans, sizeof(ans) - 1, stdin);
switch ((int) ans[0]) {
case 'c':
case 'C':
ans[0] = 'C';
ans[1] = '\0';
zaction = kConfirmResumeProcSaidCancel;
break;
case 'o':
case 'O':
ans[0] = 'O';
zaction = kConfirmResumeProcSaidOverwrite;
break;
case 'r':
case 'R':
if ((gConn.hasREST != kCommandAvailable) || (remotesize == kSizeUnknown)) {
printf("\tResume is not available on this server.\n\n");
ans[0] = '\0';
break;
} else if (remotesize < localsize) {
printf("\tCannot resume when local file is already larger than the remote file.\n\n");
ans[0] = '\0';
break;
} else if (remotesize <= localsize) {
printf("\tLocal file is already the same size as the remote file.\n\n");
ans[0] = '\0';
break;
}
ans[0] = 'R';
*startPoint = localsize;
zaction = kConfirmResumeProcSaidResume;
if (OneTimeMessage("auto-resume") != 0) {
printf("\n\tNOTE: If you want NcFTP to guess automatically, \"set auto-resume yes\"\n\n");
}
break;
case 's':
case 'S':
ans[0] = 'S';
zaction = kConfirmResumeProcSaidSkip;
break;
case 'n':
case 'N':
ans[0] = 'N';
ans[1] = '\0';
zaction = kConfirmResumeProcSaidOverwrite;
break;
case 'a':
case 'A':
ans[0] = 'A';
ans[1] = '\0';
zaction = kConfirmResumeProcSaidAppend;
break;
case 'g':
case 'G':
ans[0] = 'G';
zaction = kConfirmResumeProcSaidBestGuess;
break;
default:
ans[0] = '\0';
}
if (ans[0] != '\0')
break;
}
if (ans[0] == 'N') {
(void) memset(newname, 0, sizeof(newname));
printf("\tSave as: ");
fflush(stdin);
(void) fgets(newname, sizeof(newname) - 1, stdin);
newname[strlen(newname) - 1] = '\0';
if (newname[0] == '\0') {
/* Nevermind. */
printf("Skipped %s.\n", remotepath);
zaction = kConfirmResumeProcSaidSkip;
} else {
*localpath = newname;
}
}
if (ans[1] == '!')
gResumeAnswerAll = zaction;
return (zaction);
} /* NcFTPConfirmResumeDownloadProc */
/* Download files from the remote system. */
void
GetCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
int opt;
int renameMode = 0;
int recurseFlag = kRecursiveNo;
int appendFlag = kAppendNo;
int resumeFlag = kResumeYes;
int tarflag = kTarYes;
const char *dstdir = NULL;
int rc;
int i;
int doGlob;
int xtype = gBm.xferType;
int nD = 0;
int deleteFlag = kDeleteNo;
char pattern[256];
vsigproc_t osigint;
ConfirmResumeDownloadProc confirmProc;
confirmProc = NcFTPConfirmResumeDownloadProc;
gResumeAnswerAll = kConfirmResumeProcNotUsed; /* Ask at least once each time */
ARGSUSED(gUnusedArg);
GetoptReset();
while ((opt = Getopt(argc, argv, "aAzfrRTD")) >= 0) switch (opt) {
case 'a':
xtype = kTypeAscii;
break;
case 'A':
/* Append to local files, instead of truncating
* them first.
*/
appendFlag = kAppendYes;
break;
case 'f':
case 'Z':
/* Do not try to resume a download, even if it
* appeared that some of the file was transferred
* already.
*/
resumeFlag = kResumeNo;
confirmProc = NoConfirmResumeDownloadProc;
break;
case 'z':
/* Special flag that lets you specify the
* destination file. Normally a "get" will
* write the file by the same name as the
* remote file's basename.
*/
renameMode = 1;
break;
case 'r':
case 'R':
/* If the item is a directory, get the
* directory and all its contents.
*/
recurseFlag = kRecursiveYes;
break;
case 'T':
/* If they said "-R", they may want to
* turn off TAR mode if they are trying
* to resume the whole directory.
* The disadvantage to TAR mode is that
* it always downloads the whole thing,
* which is why there is a flag to
* disable this.
*/
tarflag = kTarNo;
break;
case 'D':
/* You can delete the remote file after
* you downloaded it successfully by using
* the -DD option. It requires two -D's
* to minimize the odds of accidentally
* using a single -D.
*/
nD++;
break;
default:
PrintCmdUsage(cmdp);
return;
}
if (nD >= 2)
deleteFlag = kDeleteYes;
if (renameMode != 0) {
if (gOptInd > argc - 2) {
PrintCmdUsage(cmdp);
(void) fprintf(stderr, "\nFor get with rename, try \"get -z remote-path-name local-path-name\".\n");
return;
}
osigint = NcSignal(SIGINT, XferCanceller);
rc = FTPGetOneFile3(&gConn, argv[gOptInd], argv[gOptInd + 1], xtype, (-1), resumeFlag, appendFlag, deleteFlag, NoConfirmResumeDownloadProc, 0);
if (rc < 0)
FTPPerror(&gConn, rc, kErrCouldNotStartDataTransfer, "get", argv[gOptInd]);
} else {
osigint = NcSignal(SIGINT, XferCanceller);
for (i=gOptInd; i<argc; i++) {
doGlob = (aip->noglobargv[i] != 0) ? kGlobNo: kGlobYes;
STRNCPY(pattern, argv[i]);
StrRemoveTrailingSlashes(pattern);
rc = FTPGetFiles3(&gConn, pattern, dstdir, recurseFlag, doGlob, xtype, resumeFlag, appendFlag, deleteFlag, tarflag, confirmProc, 0);
if (rc < 0)
FTPPerror(&gConn, rc, kErrCouldNotStartDataTransfer, "get", argv[i]);
}
}
(void) NcSignal(SIGINT, osigint);
(void) fflush(stdin);
if (deleteFlag == kDeleteYes) {
/* Directory is now out of date */
FlushLsCache();
}
} /* GetCmd */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -