Пример #1
0
/* Deletes an item from the ls cache. */
static void
FlushLsCacheItem(int i)
{
	Trace(1, "flush ls cache item: %s\n", gLsCache[i].itempath);
	if (gLsCache[i].itempath != NULL)
		free(gLsCache[i].itempath);
	gLsCache[i].itempath = NULL;
	gLsCache[i].expiration = (time_t) 0;
	DisposeFileInfoListContents(&gLsCache[i].fil);
}	/* FlushLsCacheItem */
Пример #2
0
/* This mess is essentially the local version of Ftw with FTP
 * grafted onto it, so see that and grok that before studying this.
 */
static int
FTPFtwTraverse(const FtwInfoPtr ftwip, size_t dirPathLen, int depth)
{
	char *cp;
	size_t fnLen;
	mode_t m;
	char *filename;
	char *newBuf;
	char *path = ftwip->curPath;
	int nSubdirs;
	FtwSubDirListPtr head = NULL, tail = NULL, sdp, nextsdp;
	int rc = (-1);
	int lsl, mls, unlsrc;
	FTPCIPtr cip = (FTPCIPtr) ftwip->cip;
	FTPLineList ll;
	FTPFileInfoList fil;
	FTPLinePtr filePtr;
	FTPFileInfoPtr fip;
	int result;
	int isRootDir;
	longest_int sz;

	isRootDir = ((dirPathLen == 1) && ((path[0] == '/') || (path[0] == '\\'))) ? 1 : 0;
	filePtr = NULL;
	fip = NULL;
	mls = 0;
	lsl = 0;

	if (cip->hasMLSD == kCommandAvailable) {
		mls = 1;
		if (((result = FTPListToMemory2(cip, dirPathLen ? path : ".", &ll, "-a", 0, &mls)) < 0) || (ll.first == NULL)) {
			/* Not an error unless the first directory could not be opened. */
			DisposeLineListContents(&ll);
			return (0);
		}

		/* "MLSD" succeeded */
		unlsrc = UnMlsD(cip, &fil, &ll);
		if (unlsrc < 0) {
			DisposeLineListContents(&ll);
			return (cip->errNo = kErrInvalidMLSTResponse);
		} else if (unlsrc == 0) {
			/* empty */
			DisposeLineListContents(&ll);
			return (0);
		}
		fip = fil.first;
		DisposeLineListContents(&ll);
	} else {
		if (((result = FTPListToMemory2(cip, dirPathLen ? path : ".", &ll, "-la", 0, &mls)) < 0) || (ll.first == NULL)) {
			DisposeLineListContents(&ll);
			if (((result = FTPListToMemory2(cip, dirPathLen ? path : ".", &ll, (cip->hasNLST_a == kCommandNotAvailable) ? "" : "-a", 0, &mls)) < 0) || (ll.first == NULL)) {
				DisposeLineListContents(&ll);
				return (0);
			} else {
				/* "NLST -a" succeeded */
				RemoteGlobCollapse(cip, path, &ll);
				filePtr = ll.first;
			}
		} else {
			/* "LIST -a" succeeded */
			lsl = 1;
			unlsrc = UnLslR(cip, &fil, &ll, cip->serverType);
			if (unlsrc < 0) {
				DisposeLineListContents(&ll);
				return (cip->errNo = kErrInvalidMLSTResponse);
			} else if (unlsrc == 0) {
				/* empty */
				DisposeLineListContents(&ll);
				return (0);
			}
			fip = fil.first;
			DisposeLineListContents(&ll);
		}
	}

	nSubdirs = 0;
	++ftwip->numDirs;
	ftwip->depth = depth;
	if (ftwip->maxDepth < ftwip->depth) {
		ftwip->maxDepth = ftwip->depth;
	}
	filename = path + dirPathLen;
	if (isRootDir == 0) {	/* Root directory is a separator. */
		*filename++ = (char) ftwip->dirSeparator;
		dirPathLen++;
	}
	*filename = '\0';
	/* Path now contains dir/  */

	for (;;) {
		if ((mls != 0) || (lsl != 0)) {
			if (fip == NULL)
				break;
			cp = fip->relname;
		} else {
			if (filePtr == NULL)
				break;
			cp = filePtr->line;
		}
		if ((cp[0] == '.') && ((cp[1] == '\0') || ((cp[1] == '.') && (cp[2] == '\0'))))
			goto nxt;	/* Skip . and .. */

		ftwip->rlinkto = NULL;
		*filename = '\0';
		fnLen = strlen(cp) + 1	/* include \0 */;
		if ((fnLen + dirPathLen) > ftwip->curPathAllocSize) {
			if (ftwip->autoGrow == kFtwNoAutoGrowAndFail) {
				goto panic;
			} else if (ftwip->autoGrow == kFtwNoAutoGrowButContinue) {
				goto nxt;
			}
			newBuf = (char *) realloc(ftwip->curPath, fnLen + dirPathLen + 30 + 2 /* room for / and \0 */);
			if (newBuf == NULL)
				goto panic;
			ftwip->curPath = newBuf;
			ftwip->curPathAllocSize = fnLen + dirPathLen + 30;
			path = ftwip->curPath;
			filename = path + dirPathLen;
			if (isRootDir == 0)	/* Root directory is a separator. */
				*filename++ = (char) ftwip->dirSeparator;
			*filename = '\0';
		}
		memcpy(filename, cp, fnLen);
		ftwip->curPathLen = dirPathLen + fnLen - 1;
		ftwip->curFile = filename;
		ftwip->curFileLen = fnLen - 1;

		memset(&ftwip->curStat, 0, sizeof(ftwip->curStat));
		if (mls != 0) {
			ftwip->curType = fip->type;
			if (fip->type == 'd') {
				ftwip->curStat.st_mode = S_IFDIR;
				ftwip->curStat.st_size = (longest_int) -1;
#ifdef S_IFLNK
			} else if (fip->type == 'l') {
				ftwip->curStat.st_mode = S_IFLNK;
				ftwip->rlinkto = fip->rlinkto;
#endif
			} else if (fip->type == '-') {
				ftwip->curStat.st_mode = S_IFREG;
				ftwip->curStat.st_size = fip->size;
			} else {
				/* unknown type, skip */
				goto nxt;
			}
			if (fip->mode != (-1))
				ftwip->curStat.st_mode |= (fip->mode & 00777);
			ftwip->curStat.st_mtime = fip->mdtm;
		} else if (lsl != 0) {
			ftwip->curType = fip->type;
			if (fip->type == 'd') {
				ftwip->curStat.st_mode = S_IFDIR;
				ftwip->curStat.st_size = (longest_int) -1;
#ifdef S_IFLNK
			} else if (fip->type == 'l') {
				ftwip->curStat.st_mode = S_IFLNK;
				ftwip->rlinkto = fip->rlinkto;
#endif
			} else if (fip->type == '-') {
				ftwip->curStat.st_mode = S_IFREG;
				ftwip->curStat.st_size = fip->size;
			} else {
				/* unknown type, skip */
				goto nxt;
			}
			if (fip->mode != (-1))
				ftwip->curStat.st_mode |= (fip->mode & 00777);
			ftwip->curStat.st_mtime = fip->mdtm;

			/* Override local times in LS output! */
			result = FTPFileModificationTime(cip, path, &fip->mdtm);
			if (fip->mdtm != kModTimeUnknown) {
				ftwip->curStat.st_mtime = fip->mdtm;
			}
		} else {
			result = FTPIsDir(cip, path);
			if (result < 0) {
				/* error */
				/* could be just a stat error, so continue */
				goto nxt;
			} else if (result == 1) {
				/* directory */
				ftwip->curType = 'd';
				ftwip->curStat.st_mode = S_IFDIR | 00755;
				result = FTPFileModificationTime(cip, path, &ftwip->curStat.st_mtime);
			} else {
				/* file */
				ftwip->curType = '-';
				ftwip->curStat.st_mode = S_IFREG | 00644;
				result = FTPFileSizeAndModificationTime(cip, path, &sz, kTypeBinary, &ftwip->curStat.st_mtime);
#if defined(TRU64UNIX) || defined(DIGITAL_UNIX)
				ftwip->curStat.st_size = (off_t) sz;
#else
				ftwip->curStat.st_size = sz;
#endif
			}
		}

		{
			m = ftwip->curStat.st_mode;
			if (S_ISREG(m)) {
				++ftwip->numFiles;
				ftwip->curType = '-';
				if ((*ftwip->proc)(ftwip) < 0) {
					goto panic;
				}
			} else if (S_ISLNK(m)) {
				++ftwip->numLinks;
				ftwip->curType = 'l';
				if ((*ftwip->proc)(ftwip) < 0) {
					goto panic;
				}
			} else if (S_ISDIR(m)) {
				/* We delay entering the subdirectories
				 * until we have closed this directory.
				 * This will conserve file descriptors
				 * and also have the effect of having
				 * the files processed first.
				 */
				sdp = (FtwSubDirListPtr) malloc(sizeof(FtwSubDirList) + fnLen);
				if (sdp == NULL)
					goto panic;
				memcpy(&sdp->st, &ftwip->curStat, sizeof(sdp->st));
				memcpy(sdp->name, cp, fnLen);
				sdp->fnLen = fnLen;
				sdp->next = NULL;
				if (head == NULL) {
					head = tail = sdp;
				} else {
					tail->next = sdp;
					tail = sdp;
				}
				nSubdirs++;
			}
		}
nxt:
		if ((mls != 0) || (lsl != 0)) {
			fip = fip->next;
		} else {
			filePtr = filePtr->next;
		}
	}

	if ((mls != 0) || (lsl != 0)) {
		DisposeFileInfoListContents(&fil);
	} else {
		DisposeLineListContents(&ll);
	}

	/* Now enter each subdirectory. */
	for (sdp = head; sdp != NULL; sdp = nextsdp) {
		nextsdp = sdp->next;
		memcpy(&ftwip->curStat, &sdp->st, sizeof(ftwip->curStat));
		fnLen = sdp->fnLen;
		memcpy(filename, sdp->name, fnLen);
		ftwip->curFile = filename;
		ftwip->curFileLen = fnLen - 1;
		ftwip->curPathLen = dirPathLen + fnLen - 1;
		head = nextsdp;
		free(sdp);

		ftwip->curType = 'd';
		if ((*ftwip->proc)(ftwip) < 0) {
			goto panic;
		}
		if (FTPFtwTraverse(ftwip, dirPathLen + fnLen - 1, depth + 1) < 0)
			goto panic;

		/* Reset these, since buffer could have
		 * been reallocated.
		 */
		path = ftwip->curPath;
		filename = path + dirPathLen;
		*filename = '\0';
	}
	head = NULL;
	rc = 0;

panic:
	if (mls != 0) {
		DisposeFileInfoListContents(&fil);
	} else {
		DisposeLineListContents(&ll);
	}

	for (sdp = head; sdp != NULL; sdp = nextsdp) {
		nextsdp = sdp->next;
		free(sdp);
	}

	return (rc);
}	/* FTPFtwTraverse */
Пример #3
0
int
FTPPutFiles3(
    const FTPCIPtr cip,
    const char *const pattern,
    const char *const dstdir1,
    const int recurse,
    const int doGlob,
    const int xtype,
    int appendflag,
    const char *const tmppfx,
    const char *const tmpsfx,
    const int resumeflag,
    const int deleteflag,
    const FTPConfirmResumeUploadProc resumeProc,
    int UNUSED(reserved))
{
    FTPLineList globList;
    FTPFileInfoList files;
    FTPFileInfoPtr filePtr;
    int batchResult;
    int result;
    const char *dstdir;
    char dstdir2[512];

    LIBNCFTP_USE_VAR(reserved);
    if (cip == NULL)
        return (kErrBadParameter);
    if (strcmp(cip->magic, kLibraryMagic))
        return (kErrBadMagic);

    if (dstdir1 == NULL)
    {
        dstdir = NULL;
    }
    else
    {
        dstdir = STRNCPY(dstdir2, dstdir1);
        StrRemoveTrailingLocalPathDelim(dstdir2);
    }

    (void) FTPLocalGlob(cip, &globList, pattern, doGlob);
    if (recurse == kRecursiveYes)
    {
        appendflag = kAppendNo;
        (void) FTPLocalRecursiveFileList(cip, &globList, &files);
        if (files.first == NULL)
        {
            cip->errNo = kErrNoValidFilesSpecified;
            return (kErrNoValidFilesSpecified);
        }
        (void) ComputeRNames(&files, dstdir, 0, 1);
    }
    else
    {
        (void) LineListToFileInfoList(&globList, &files);
        (void) ComputeLNames(&files, NULL, NULL, 1);
        (void) ComputeRNames(&files, dstdir, 0, 0);
    }
    DisposeLineListContents(&globList);

#if 0
    for (filePtr = files.first; filePtr != NULL; filePtr = filePtr->next)
    {
        PrintF(cip, "  R=%s, L=%s, 2=%s, size=%lld, mdtm=%u, type=%c\n",
               filePtr->rname,
               filePtr->lname,
               filePtr->rlinkto ? filePtr->rlinkto : "",
               filePtr->size,
               (unsigned int) filePtr->mdtm,
               filePtr->type
              );
    }
#endif

    batchResult = kNoErr;
    for (filePtr = files.first; filePtr != NULL; filePtr = filePtr->next)
    {
        if (cip->connected == 0)
        {
            if (batchResult == kNoErr)
                batchResult = kErrRemoteHostClosedConnection;
            break;
        }
        if (filePtr->type == 'd')
        {
            /* mkdir */
            StrRemoveTrailingLocalPathDelim(filePtr->rname);
            result = FTPMkdir(cip, filePtr->rname, kRecursiveNo);
            if (result != kNoErr)
                batchResult = result;
#ifdef HAVE_SYMLINK
        }
        else if (filePtr->type == 'l')
        {
            /* symlink */
            /* no RFC way to create the link, though. */
            if ((filePtr->rlinkto != NULL) && (filePtr->rlinkto[0] != '\0'))
                (void) FTPSymlink(cip, filePtr->rname, filePtr->rlinkto);
#endif
        }
        else if (recurse != kRecursiveYes)
        {
            result = FTPPutOneF(cip, filePtr->lname, filePtr->rname, xtype, -1, appendflag, tmppfx, tmpsfx, resumeflag, deleteflag, resumeProc);
            if (files.nFileInfos == 1)
            {
                if (result != kNoErr)
                    batchResult = result;
            }
            else
            {
                if ((result != kNoErr) && (result != kErrLocalFileNewer) && (result != kErrRemoteFileNewer) && (result != kErrRemoteSameAsLocal))
                    batchResult = result;
            }
            if (result == kErrUserCanceled)
                cip->cancelXfer = 1;
            if (cip->cancelXfer > 0)
                break;
        }
        else
        {
            result = FTPPutOneF(cip, filePtr->lname, filePtr->rname, xtype, -1, appendflag, tmppfx, tmpsfx, resumeflag, deleteflag, resumeProc);
            if (files.nFileInfos == 1)
            {
                if (result != kNoErr)
                    batchResult = result;
            }
            else
            {
                if ((result != kNoErr) && (result != kErrLocalFileNewer) && (result != kErrRemoteFileNewer) && (result != kErrRemoteSameAsLocal))
                    batchResult = result;
            }
            if (result == kErrUserCanceled)
                cip->cancelXfer = 1;
            if (cip->cancelXfer > 0)
                break;
        }
    }
    DisposeFileInfoListContents(&files);
    if (batchResult < 0)
        cip->errNo = batchResult;
    return (batchResult);
}	/* FTPPutFiles3 */