📄 cmds.c
字号:
/* cmds.c
*
* Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
* All rights reserved.
*
*/
#include "syshdrs.h"
int
FTPChdir(const FTPCIPtr cip, const char *const cdCwd)
{
int result;
if (cip == NULL)
return (kErrBadParameter);
if (strcmp(cip->magic, kLibraryMagic))
return (kErrBadMagic);
if (cdCwd == NULL) {
result = kErrInvalidDirParam;
cip->errNo = kErrInvalidDirParam;
} else {
if (cdCwd[0] == '\0') /* But allow FTPChdir(cip, ".") to go through. */
result = 2;
else if (strcmp(cdCwd, "..") == 0)
result = FTPCmd(cip, "CDUP");
else
result = FTPCmd(cip, "CWD %s", cdCwd);
if (result >= 0) {
if (result == 2) {
result = kNoErr;
} else {
result = kErrCWDFailed;
cip->errNo = kErrCWDFailed;
}
}
}
return (result);
} /* FTPChdir */
int
FTPChmod(const FTPCIPtr cip, const char *const pattern, const char *const mode, const int doGlob)
{
LineList fileList;
LinePtr filePtr;
char *file;
int onceResult, batchResult;
if (cip == NULL)
return (kErrBadParameter);
if (strcmp(cip->magic, kLibraryMagic))
return (kErrBadMagic);
batchResult = FTPRemoteGlob(cip, &fileList, pattern, doGlob);
if (batchResult != kNoErr)
return (batchResult);
for (batchResult = kNoErr, filePtr = fileList.first;
filePtr != NULL;
filePtr = filePtr->next)
{
file = filePtr->line;
if (file == NULL) {
batchResult = kErrBadLineList;
cip->errNo = kErrBadLineList;
break;
}
onceResult = FTPCmd(cip, "SITE CHMOD %s %s", mode, file);
if (onceResult < 0) {
batchResult = onceResult;
break;
}
if (onceResult != 2) {
batchResult = kErrChmodFailed;
cip->errNo = kErrChmodFailed;
}
}
DisposeLineListContents(&fileList);
return (batchResult);
} /* FTPChmod */
static int
FTPRmdirRecursiveL2(const FTPCIPtr cip)
{
LineList fileList;
LinePtr filePtr;
char *file;
int result;
result = FTPRemoteGlob(cip, &fileList, "**", kGlobYes);
if (result != kNoErr) {
return (result);
}
for (filePtr = fileList.first;
filePtr != NULL;
filePtr = filePtr->next)
{
file = filePtr->line;
if (file == NULL) {
cip->errNo = kErrBadLineList;
break;
}
if ((file[0] == '.') && ((file[1] == '\0') || ((file[1] == '.') && (file[2] == '\0'))))
continue; /* Skip . and .. */
if (FTPChdir(cip, file) == kNoErr) {
/* It was a directory.
* Go in and wax it.
*/
result = FTPRmdirRecursiveL2(cip);
if (FTPChdir(cip, "..") != kNoErr) {
/* Panic -- we can no longer
* cd back to the directory
* we were in before.
*/
result = kErrCannotGoToPrevDir;
cip->errNo = kErrCannotGoToPrevDir;
return (result);
}
if ((result < 0) && (result != kErrGlobNoMatch))
return (result);
result = FTPRmdir(cip, file, kRecursiveNo, kGlobNo);
if (result != kNoErr) {
/* Well, we couldn't remove the empty
* directory. Perhaps we screwed up
* and the directory wasn't empty.
*/
return (result);
}
} else {
/* Assume it was a file -- remove it. */
result = FTPDelete(cip, file, kRecursiveNo, kGlobNo);
/* Try continuing to remove the rest,
* even if this failed.
*/
}
}
DisposeLineListContents(&fileList);
return (result);
} /* FTPRmdirRecursiveL2 */
static int
FTPRmdirRecursive(const FTPCIPtr cip, const char *const dir)
{
int result, result2;
/* Preserve old working directory. */
(void) FTPGetCWD(cip, cip->buf, cip->bufSize);
result = FTPChdir(cip, dir);
if (result != kNoErr) {
return (result);
}
result = FTPRmdirRecursiveL2(cip);
if (FTPChdir(cip, cip->buf) != kNoErr) {
/* Could not cd back to the original user directory -- bad. */
if (result != kNoErr) {
result = kErrCannotGoToPrevDir;
cip->errNo = kErrCannotGoToPrevDir;
}
return (result);
}
/* Now rmdir the last node, the root of the tree
* we just went through.
*/
result2 = FTPRmdir(cip, dir, kRecursiveNo, kGlobNo);
if ((result2 != kNoErr) && (result == kNoErr))
result = result2;
return (result);
} /* FTPRmdirRecursive */
int
FTPDelete(const FTPCIPtr cip, const char *const pattern, const int recurse, const int doGlob)
{
LineList fileList;
LinePtr filePtr;
char *file;
int onceResult, batchResult;
if (cip == NULL)
return (kErrBadParameter);
if (strcmp(cip->magic, kLibraryMagic))
return (kErrBadMagic);
batchResult = FTPRemoteGlob(cip, &fileList, pattern, doGlob);
if (batchResult != kNoErr)
return (batchResult);
for (batchResult = kNoErr, filePtr = fileList.first;
filePtr != NULL;
filePtr = filePtr->next)
{
file = filePtr->line;
if (file == NULL) {
batchResult = kErrBadLineList;
cip->errNo = kErrBadLineList;
break;
}
onceResult = FTPCmd(cip, "DELE %s", file);
if (onceResult < 0) {
batchResult = onceResult;
break;
}
if (onceResult != 2) {
if (recurse != kRecursiveYes) {
batchResult = kErrDELEFailed;
cip->errNo = kErrDELEFailed;
} else {
onceResult = FTPCmd(cip, "RMD %s", file);
if (onceResult < 0) {
batchResult = onceResult;
break;
}
if (onceResult != 2) {
onceResult = FTPRmdirRecursive(cip, file);
if (onceResult < 0) {
batchResult = kErrRMDFailed;
cip->errNo = kErrRMDFailed;
}
}
}
}
}
DisposeLineListContents(&fileList);
return (batchResult);
} /* FTPDelete */
int
FTPGetCWD(const FTPCIPtr cip, char *const newCwd, const size_t newCwdSize)
{
ResponsePtr rp;
char *l, *r;
int result;
if (cip == NULL)
return (kErrBadParameter);
if (strcmp(cip->magic, kLibraryMagic))
return (kErrBadMagic);
if ((newCwd == NULL) || (newCwdSize == 0)) {
result = kErrInvalidDirParam;
cip->errNo = kErrInvalidDirParam;
} else {
rp = InitResponse();
if (rp == NULL) {
result = kErrMallocFailed;
cip->errNo = kErrMallocFailed;
Error(cip, kDontPerror, "Malloc failed.\n");
} else {
result = RCmd(cip, rp, "PWD");
if (result == 2) {
if ((r = strrchr(rp->msg.first->line, '"')) != NULL) {
/* "xxxx" is current directory.
* Strip out just the xxxx to copy into the remote cwd.
*/
l = strchr(rp->msg.first->line, '"');
if ((l != NULL) && (l != r)) {
*r = '\0';
++l;
(void) Strncpy(newCwd, l, newCwdSize);
*r = '"'; /* Restore, so response prints correctly. */
}
} else {
/* xxxx is current directory.
* Mostly for VMS.
*/
if ((r = strchr(rp->msg.first->line, ' ')) != NULL) {
*r = '\0';
(void) Strncpy(newCwd, (rp->msg.first->line), newCwdSize);
*r = ' '; /* Restore, so response prints correctly. */
}
}
result = kNoErr;
} else if (result > 0) {
result = kErrPWDFailed;
cip->errNo = kErrPWDFailed;
}
DoneWithResponse(cip, rp);
}
}
return (result);
} /* FTPGetCWD */
int
FTPChdirAndGetCWD(const FTPCIPtr cip, const char *const cdCwd, char *const newCwd, const size_t newCwdSize)
{
ResponsePtr rp;
char *l, *r;
int result;
if (cip == NULL)
return (kErrBadParameter);
if (strcmp(cip->magic, kLibraryMagic))
return (kErrBadMagic);
if ((newCwd == NULL) || (cdCwd == NULL)) {
result = kErrInvalidDirParam;
cip->errNo = kErrInvalidDirParam;
} else {
if (cdCwd[0] == '\0') { /* But allow FTPChdir(cip, ".") to go through. */
result = FTPGetCWD(cip, newCwd, newCwdSize);
return (result);
}
rp = InitResponse();
if (rp == NULL) {
result = kErrMallocFailed;
cip->errNo = kErrMallocFailed;
Error(cip, kDontPerror, "Malloc failed.\n");
} else {
if (strcmp(cdCwd, "..") == 0)
result = RCmd(cip, rp, "CDUP");
else
result = RCmd(cip, rp, "CWD %s", cdCwd);
if (result == 2) {
l = strchr(rp->msg.first->line, '"');
if ((l == rp->msg.first->line) && ((r = strrchr(rp->msg.first->line, '"')) != NULL) && (l != r)) {
/* "xxxx" is current directory.
* Strip out just the xxxx to copy into the remote cwd.
*
* This is nice because we didn't have to do a PWD.
*/
*r = '\0';
++l;
(void) Strncpy(newCwd, l, newCwdSize);
*r = '"'; /* Restore, so response prints correctly. */
DoneWithResponse(cip, rp);
result = kNoErr;
} else {
DoneWithResponse(cip, rp);
result = FTPGetCWD(cip, newCwd, newCwdSize);
}
} else if (result > 0) {
result = kErrCWDFailed;
cip->errNo = kErrCWDFailed;
DoneWithResponse(cip, rp);
} else {
DoneWithResponse(cip, rp);
}
}
}
return (result);
} /* FTPChdirAndGetCWD */
int
FTPChdir3(FTPCIPtr cip, const char *const cdCwd, char *const newCwd, const size_t newCwdSize, int flags)
{
char *cp, *startcp;
int result;
int lastSubDir;
int mkd, pwd;
if (cip == NULL)
return (kErrBadParameter);
if (strcmp(cip->magic, kLibraryMagic))
return (kErrBadMagic);
if (cdCwd == NULL) {
result = kErrInvalidDirParam;
cip->errNo = kErrInvalidDirParam;
return result;
}
if (flags == kChdirOnly)
return (FTPChdir(cip, cdCwd));
if (flags == kChdirAndGetCWD) {
return (FTPChdirAndGetCWD(cip, cdCwd, newCwd, newCwdSize));
} else if (flags == kChdirAndMkdir) {
result = FTPMkdir(cip, cdCwd, kRecursiveYes);
if (result == kNoErr)
result = FTPChdir(cip, cdCwd);
return result;
} else if (flags == (kChdirAndMkdir|kChdirAndGetCWD)) {
result = FTPMkdir(cip, cdCwd, kRecursiveYes);
if (result == kNoErr)
result = FTPChdirAndGetCWD(cip, cdCwd, newCwd, newCwdSize);
return result;
}
/* else: (flags | kChdirOneSubdirAtATime) == true */
cp = cip->buf;
cp[cip->bufSize - 1] = '\0';
(void) Strncpy(cip->buf, cdCwd, cip->bufSize);
if (cp[cip->bufSize - 1] != '\0')
return (kErrBadParameter);
mkd = (flags & kChdirAndMkdir);
pwd = (flags & kChdirAndGetCWD);
if ((cdCwd[0] == '\0') || (strcmp(cdCwd, ".") == 0)) {
result = 0;
if (flags == kChdirAndGetCWD)
result = FTPGetCWD(cip, newCwd, newCwdSize);
return (result);
}
lastSubDir = 0;
do {
startcp = cp;
cp = StrFindLocalPathDelim(cp);
if (cp != NULL) {
/* If this is the first slash in an absolute
* path, then startcp will be empty. We will
* use this below to treat this as the root
* directory.
*/
*cp++ = '\0';
} else {
lastSubDir = 1;
}
if (strcmp(startcp, ".") == 0) {
result = 0;
if ((lastSubDir != 0) && (pwd != 0))
result = FTPGetCWD(cip, newCwd, newCwdSize);
} else if ((lastSubDir != 0) && (pwd != 0)) {
result = FTPChdirAndGetCWD(cip, (*startcp != '\0') ? startcp : "/", newCwd, newCwdSize);
} else {
result = FTPChdir(cip, (*startcp != '\0') ? startcp : "/");
}
if (result < 0) {
if ((mkd != 0) && (*startcp != '\0')) {
if (FTPCmd(cip, "MKD %s", startcp) == 2) {
result = FTPChdir(cip, startcp);
} else {
/* couldn't change nor create */
cip->errNo = result;
}
} else {
cip->errNo = result;
}
}
} while ((!lastSubDir) && (result == 0));
return (result);
} /* FTPChdir3 */
int
FTPMkdir2(const FTPCIPtr cip, const char *const newDir, const int recurse, const char *const curDir)
{
int result, result2;
char *cp, *newTreeStart, *cp2;
char dir[512];
char dir2[512];
char c;
if (cip == NULL)
return (kErrBadParameter);
if (strcmp(cip->magic, kLibraryMagic))
return (kErrBadMagic);
if ((newDir == NULL) || (newDir[0] == '\0')) {
cip->errNo = kErrInvalidDirParam;
return (kErrInvalidDirParam);
}
/* Preserve old working directory. */
if ((curDir == NULL) || (curDir[0] == '\0')) {
/* This hack is nice so you can eliminate an
* unnecessary "PWD" command on the server,
* since if you already knew what directory
* you're in. We want to minimize the number
* of client-server exchanges when feasible.
*/
(void) FTPGetCWD(cip, cip->buf, cip->bufSize);
}
result = FTPChdir(cip, newDir);
if (result == kNoErr) {
/* Directory already exists -- but we
* must now change back to where we were.
*/
result2 = FTPChdir(cip, ((curDir == NULL) || (curDir[0] == '\0')) ? cip->buf : curDir);
if (result2 < 0) {
result = kErrCannotGoToPrevDir;
cip->errNo = kErrCannotGoToPrevDir;
return (result);
}
/* Don't need to create it. */
return (kNoErr);
}
if (recurse == kRecursiveNo) {
result = FTPCmd(cip, "MKD %s", newDir);
if (result > 0) {
if (result != 2) {
Error(cip, kDontPerror, "MKD %s failed; [%s]\n", newDir, cip->lastFTPCmdResultStr);
result = kErrMKDFailed;
cip->errNo = kErrMKDFailed;
return (result);
} else {
result = kNoErr;
}
}
} else {
(void) STRNCPY(dir, newDir);
/* Strip trailing slashes. */
cp = dir + strlen(dir) - 1;
for (;;) {
if (cp <= dir) {
if ((newDir == NULL) || (newDir[0] == '\0')) {
cip->errNo = kErrInvalidDirParam;
result = kErrInvalidDirParam;
return (result);
}
}
if ((*cp != '/') && (*cp != '\\')) {
cp[1] = '\0';
break;
}
--cp;
}
(void) STRNCPY(dir2, dir);
if ((strrchr(dir, '/') == dir) || (strrchr(dir, '\\') == dir)) {
/* Special case "mkdir /subdir" */
result = FTPCmd(cip, "MKD %s", dir);
if (result < 0) {
return (result);
}
if (result != 2) {
Error(cip, kDontPerror, "MKD %s failed; [%s]\n", dir, cip->lastFTPCmdResultStr);
result = kErrMKDFailed;
cip->errNo = kErrMKDFailed;
return (result);
}
/* Haven't chdir'ed, don't need to goto goback. */
return (kNoErr);
}
for (;;) {
cp = strrchr(dir, '/');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -