⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
	osigpipe = (volatile FTPSigProc) signal(SIGPIPE, BrokenData);

	gGotBrokenData = 0;
	gCanBrokenDataJmp = 0;

#ifdef HAVE_SIGSETJMP
	sj = sigsetjmp(gBrokenDataJmp, 1);
#else
	sj = setjmp(gBrokenDataJmp);
#endif	/* HAVE_SIGSETJMP */

	if (sj != 0) {
		(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
		FTPShutdownHost(vcip);
		vcip->errNo = kErrRemoteHostClosedConnection;
		return(vcip->errNo);
	}
	gCanBrokenDataJmp = 1;

	if (result == 0) {
		/* This line sets the buffer pointer so that the first thing
		 * BufferGets will do is reset and fill the buffer using
		 * real I/O.
		 */
		secBufPtr = secondaryBuf + sizeof(secondaryBuf);
		secBufLimit = (char *) 0;
		memset(secondaryBuf, 0, sizeof(secondaryBuf));

		for (;;) {
			memset(line, 0, sizeof(line));
			if (cip->xferTimeout > 0)
				(void) alarm(cip->xferTimeout);
			nread = BufferGets(line, sizeof(line), cip->dataSocket, secondaryBuf, &secBufPtr, &secBufLimit, sizeof(secondaryBuf));
			if (nread <= 0) {
				if (nread < 0)
					break;
				if (blankLines != 0)
					(void) AddLine(llines, line);
			} else {
				cip->bytesTransferred += (longest_int) nread;

				if ((line[0] == '.') && ((line[1] == '\0') || ((line[1] == '.') && ((line[2] == '\0') || (iscntrl(line[2]))))))
					continue;	/* Skip . and .. */

				(void) AddLine(llines, line);
			}
		}
		if (cip->xferTimeout > 0)
			(void) alarm(0);
		result = FTPEndDataCmd(cip, 1);
		if (result < 0) {
			result = kErrLISTFailed;
			cip->errNo = kErrLISTFailed;
		}
		result = kNoErr;
		cip->numListings++;
	} else if (result == kErrGeneric) {
		result = kErrLISTFailed;
		cip->errNo = kErrLISTFailed;
	}
	(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
#endif	/* NO_SIGNALS */
	return (result);
}	/* FTPListToMemory2 */




static void
AutomaticallyUseASCIIModeDependingOnExtension(const FTPCIPtr cip, const char *const pathName, int *const xtype)
{
	if ((*xtype == kTypeBinary) && (cip->asciiFilenameExtensions != NULL)) {
		if (FilenameExtensionIndicatesASCII(pathName, cip->asciiFilenameExtensions)) {
			/* Matched -- send this file in ASCII mode
			 * instead of binary since it's extension
			 * appears to be that of a text file.
			 */
			*xtype = kTypeAscii;
		}
	}
}	/* AutomaticallyUseASCIIModeDependingOnExtension */




/* The purpose of this is to provide updates for the progress meters
 * during lags.  Return zero if the operation timed-out.
 */
static int
WaitForRemoteOutput(const FTPCIPtr cip)
{
	fd_set ss, ss2;
	struct timeval tv;
	int result;
	int fd;
	int wsecs;
	int xferTimeout;
	int ocancelXfer;

	xferTimeout = cip->xferTimeout;
	if (xferTimeout < 1)
		return (1);

	fd = cip->dataSocket;
	if (fd < 0)
		return (1);

	ocancelXfer = cip->cancelXfer;
	wsecs = 0;
	cip->stalled = 0;

	while ((xferTimeout <= 0) || (wsecs < xferTimeout)) {
		if ((cip->cancelXfer != 0) && (ocancelXfer == 0)) {
			/* leave cip->stalled -- could have been stalled and then canceled. */
			return (1);
		}
		FD_ZERO(&ss);
		FD_SET(fd, &ss);
		ss2 = ss;
		tv.tv_sec = 1;
		tv.tv_usec = 0;
		result = select(fd + 1, NULL, SELECT_TYPE_ARG234 &ss, SELECT_TYPE_ARG234 &ss2, &tv);
		if (result == 1) {
			/* ready */
			cip->stalled = 0;
			return (1);
		} else if (result < 0) {
			if (errno != EINTR) {
				perror("select");
				cip->stalled = 0;
				return (1);
			}
		} else {
			wsecs++;
			cip->stalled = wsecs;
		}
		FTPUpdateIOTimer(cip);
	}

#if !defined(NO_SIGNALS)
	/* Shouldn't get here -- alarm() should have
	 * went off by now.
	 */
	(void) kill(getpid(), SIGALRM);
#endif	/* NO_SIGNALS */

	cip->dataTimedOut = 1;
	return (0);	/* timed-out */
}	/* WaitForRemoteOutput */




static int
FTPPutOneF(
	const FTPCIPtr cip,
	const char *const file,
	const char *volatile dstfile,
	int xtype,
	const int fdtouse,
	const int appendflag,
	const char *volatile tmppfx,
	const char *volatile tmpsfx,
	const int resumeflag,
	const int deleteflag,
	const ConfirmResumeUploadProc resumeProc)
{
	char *buf, *cp;
	const char *cmd;
	const char *odstfile;
	size_t bufSize;
	size_t l;
	int tmpResult, result;
	int nread, nwrote;
	volatile int fd;
	char dstfile2[512];
#if ASCII_TRANSLATION
	char *src, *srclim, *dst;
	int ntowrite;
	char inbuf[256];
#endif
	int fstatrc, statrc;
	longest_int startPoint = 0;
	struct Stat st;
	time_t mdtm;
#if !defined(NO_SIGNALS)
	int sj;
	volatile FTPSigProc osigpipe;
	volatile FTPCIPtr vcip;
	volatile int vfd, vfdtouse;
#endif	/* NO_SIGNALS */
	volatile int vzaction;
	int zaction = kConfirmResumeProcSaidBestGuess;

	if (cip->buf == NULL) {
		Error(cip, kDoPerror, "Transfer buffer not allocated.\n");
		cip->errNo = kErrNoBuf;
		return (cip->errNo);
	}

	cip->usingTAR = 0;
	if (fdtouse < 0) {
		fd = Open(file, O_RDONLY|O_BINARY, 0);
		if (fd < 0) {
			Error(cip, kDoPerror, "Cannot open local file %s for reading.\n", file);
			cip->errNo = kErrOpenFailed;
			return (cip->errNo);
		}
	} else {
		fd = fdtouse;
	}

	fstatrc = Fstat(fd, &st);
	if ((fstatrc == 0) && (S_ISDIR(st.st_mode))) {
		if (fdtouse < 0) {
			(void) close(fd);
		}
		Error(cip, kDontPerror, "%s is a directory.\n", (file != NULL) ? file : "that");
		cip->errNo = kErrOpenFailed;
		return (cip->errNo);
	}

	/* For Put, we can't recover very well if it turns out restart
	 * didn't work, so check beforehand.
	 */
	if (cip->hasREST == kCommandAvailabilityUnknown) {
		(void) FTPSetTransferType(cip, kTypeBinary);
		if (SetStartOffset(cip, (longest_int) 1) == kNoErr) {
			/* Now revert -- we still may not end up
			 * doing it.
			 */
			SetStartOffset(cip, (longest_int) -1);
		}
	}

	if (fdtouse < 0) {
		AutomaticallyUseASCIIModeDependingOnExtension(cip, dstfile, &xtype);
		(void) FTPFileSizeAndModificationTime(cip, dstfile, &startPoint, xtype, &mdtm);

		if (appendflag == kAppendYes) {
			zaction = kConfirmResumeProcSaidAppend;
		} else if (
				(cip->hasREST == kCommandNotAvailable) ||
				(xtype != kTypeBinary) ||
				(fstatrc < 0)
		) {
			zaction = kConfirmResumeProcSaidOverwrite;
		} else if (resumeflag == kResumeYes) {
			zaction = kConfirmResumeProcSaidBestGuess;
		} else {
			zaction = kConfirmResumeProcSaidOverwrite;
		}

		statrc = -1;
		if ((mdtm != kModTimeUnknown) || (startPoint != kSizeUnknown)) {
			/* Then we know the file exists.  We will
			 * ask the user what to do, if possible, below.
			 */
			statrc = 0;
		} else if ((resumeProc != NoConfirmResumeUploadProc) && (cip->hasMDTM != kCommandAvailable) && (cip->hasSIZE != kCommandAvailable)) {
			/* We already checked if the file had a filesize
			 * or timestamp above, but if the server indicated
			 * it did not support querying those directly,
			 * we now need to try to determine if the file
			 * exists in a few other ways.
			 */
			statrc = FTPFileExists2(cip, dstfile, 0, 0, 0, 1, 1);
		}

		if (
			(resumeProc != NoConfirmResumeUploadProc) &&
			(statrc == 0)
		) {
			zaction = (*resumeProc)(file, (longest_int) st.st_size, st.st_mtime, &dstfile, startPoint, mdtm, &startPoint);
		}

		if (zaction == kConfirmResumeProcSaidCancel) {
			/* User wants to cancel this file and any
			 * remaining in batch.
			 */
			cip->errNo = kErrUserCanceled;
			return (cip->errNo);
		}

		if (zaction == kConfirmResumeProcSaidBestGuess) {
			if ((mdtm != kModTimeUnknown) && (st.st_mtime > (mdtm + 1))) {
				/* Local file is newer than remote,
				 * overwrite the remote file instead
				 * of trying to resume it.
				 *
				 * Note:  Add one second fudge factor
				 * for Windows' file timestamps being
				 * imprecise to one second.
				 */
				zaction = kConfirmResumeProcSaidOverwrite;
			} else if ((longest_int) st.st_size == startPoint) {
				/* Already sent file, done. */
				zaction = kConfirmResumeProcSaidSkip;
			} else if ((startPoint != kSizeUnknown) && ((longest_int) st.st_size > startPoint)) {
				zaction = kConfirmResumeProcSaidResume;
			} else {
				zaction = kConfirmResumeProcSaidOverwrite;
			}
		}

		if (zaction == kConfirmResumeProcSaidSkip) {
			/* Nothing done, but not an error. */
			if (fdtouse < 0) {
				(void) close(fd);
			}
			if (deleteflag == kDeleteYes) {
				if (unlink(file) < 0) {
					cip->errNo = kErrLocalDeleteFailed;
					return (cip->errNo);
				}
			}
			return (kNoErr);
		} else if (zaction == kConfirmResumeProcSaidResume) {
			/* Resume; proc set the startPoint. */
			if ((longest_int) st.st_size == startPoint) {
				/* Already sent file, done. */
				if (fdtouse < 0) {
					(void) close(fd);
				}

				if (deleteflag == kDeleteYes) {
					if (unlink(file) < 0) {
						cip->errNo = kErrLocalDeleteFailed;
						return (cip->errNo);
					}
				}
				return (kNoErr);
			} else if (Lseek(fd, (off_t) startPoint, SEEK_SET) != (off_t) -1) {
				cip->startPoint = startPoint;
			}
		} else if (zaction == kConfirmResumeProcSaidAppend) {
			/* append: leave startPoint at zero, we will append everything. */
			cip->startPoint = startPoint = 0;
		} else /* if (zaction == kConfirmResumeProcSaidOverwrite) */ {
			/* overwrite: leave startPoint at zero */
			cip->startPoint = startPoint = 0;
		}
	}

	if ((cip->numUploads == 0) && (cip->dataSocketSBufSize > 0)) {
		/* If dataSocketSBufSize is non-zero, it means you
		 * want to explicitly try to set the size of the
		 * socket's I/O buffer.
		 *
		 * If it is zero, it means you want to just use the
		 * TCP stack's default value, which is typically
		 * between 8 and 64 kB.
		 *
		 * If you try to set the buffer larger than 64 kB,
		 * the TCP stack should try to use RFC 1323 to
		 * negotiate "TCP Large Windows" which may yield
		 * significant performance gains.
		 */
		if (cip->hasSTORBUFSIZE == kCommandAvailable)
			(void) FTPCmd(cip, "SITE STORBUFSIZE %lu", (unsigned long) cip->dataSocketSBufSize);
		else if (cip->hasSBUFSIZ == kCommandAvailable)
			(void) FTPCmd(cip, "SITE SBUFSIZ %lu", (unsigned long) cip->dataSocketSBufSize);
		else if (cip->hasSBUFSZ == kCommandAvailable)
			(void) FTPCmd(cip, "SITE SBUFSZ %lu", (unsigned long) cip->dataSocketSBufSize);
		/* At least one server implemenation has RBUFSZ but not
		 * SBUFSZ and instead uses RBUFSZ for both.
		 */
		else if ((cip->hasSBUFSZ != kCommandAvailable) && (cip->hasRBUFSZ == kCommandAvailable))
			(void) FTPCmd(cip, "SITE RBUFSZ %lu", (unsigned long) cip->dataSocketSBufSize);
		else if (cip->hasBUFSIZE == kCommandAvailable)
			(void) FTPCmd(cip, "SITE BUFSIZE %lu", (unsigned long) cip->dataSocketSBufSize);
	}

#ifdef NO_SIGNALS
	vzaction = zaction;
#else	/* NO_SIGNALS */
	vcip = cip;
	vfdtouse = fdtouse;
	vfd = fd;
	vzaction = zaction;
	osigpipe = (volatile FTPSigProc) signal(SIGPIPE, BrokenData);

	gGotBrokenData = 0;
	gCanBrokenDataJmp = 0;

#ifdef HAVE_SIGSETJMP
	sj = sigsetjmp(gBrokenDataJmp, 1);
#else
	sj = setjmp(gBrokenDataJmp);
#endif	/* HAVE_SIGSETJMP */

	if (sj != 0) {
		(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
		if (vfdtouse < 0) {
			(void) close(vfd);
		}
		FTPShutdownHost(vcip);
		vcip->errNo = kErrRemoteHostClosedConnection;
		return(vcip->errNo);
	}
	gCanBrokenDataJmp = 1;
#endif	/* NO_SIGNALS */

	if (vzaction == kConfirmResumeProcSaidAppend) {
		cmd = "APPE";
		tmppfx = "";	/* Can't use that here. */
		tmpsfx = "";
	} else {
		cmd = "STOR";
		if (tmppfx == NULL)
			tmppfx = "";
		if (tmpsfx == NULL)
			tmpsfx = "";
	}

	odstfile = dstfile;
	if ((tmppfx[0] != '\0') || (tmpsfx[0] != '\0')) {
		cp = strrchr(dstfile, '/');
		if (cp == NULL)
			cp = strrchr(dstfile, '\\');
		if (cp == NULL) {
			(void) STRNCPY(dstfile2, tmppfx);
			(void) STRNCAT(dstfile2, dstfile);
			(void) STRNCAT(dstfile2, tmpsfx);
		} else {
			cp++;
			l = (size_t) (cp - dstfile);
			(void) STRNCPY(dstfile2, dstfile);
			dstfile2[l] = '\0';	/* Nuke stuff after / */
			(void) STRNCAT(dstfile2, tmppfx);
			(void) STRNCAT(dstfile2, cp);
			(void) STRNCAT(dstfile2, tmpsfx);
		}
		dstfile = dstfile2;
	}

	tmpResult = FTPStartDataCmd(
		cip,
		kNetWriting,
		xtype,
		startPoint,
		"%s %s",
		cmd,
		dstfile
	);

	if (tmpResult < 0) {
		cip->errNo = tmpResult;
		if (fdtouse < 0) {
			(void) close(fd);
		}
#if !defined(NO_SIGNALS)
		(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
#endif	/* NO_SIGNALS */
		return (cip->errNo);
	}

	if ((startPoint != 0) && (cip->startPoint == 0)) {
		/* Remote could not or would not set the start offset
		 * to what we wanted.
		 *
		 * So now we have to undo our seek.
		 */
		if (Lseek(fd, (off_t) 0, SEEK_SET) != (off_t) 0) {
			cip->errNo = kErrLseekFailed;
			if (fdtouse < 0) {
				(void) close(fd);
			}
#if !defined(NO_SIGNALS)
			(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
#endif	/* NO_SIGNALS */
			return (cip->errNo);
		}
		startPoint = 0;
	}

	result = kNoErr;
	buf = cip->buf;
	bufSize = cip->bufSize;

	FTPInitIOTimer(cip);
	if ((fstatrc == 0) && (S_ISREG(st.st_mode) != 0)) {
		cip->expectedSize = (longest_int) st.st_size;
		cip->mdtm = st.st_mtime;
	}
	cip->lname = file;	/* could be NULL */
	cip->rname = odstfile;
	if (fdtouse >= 0)
		cip->useProgressMeter = 0;
	FTPStartIOTimer(cip);

	/* Note: On Windows, we don't have to do anything special
	 * for ASCII mode, since Net ASCII's end-of-line sequence
	 * corresponds to the same thing used for DOS/Windows.
	 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -