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

📄 io.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
							 * was a different file altogether,
							 * since it is larger than the
							 * remote copy.  Re-do it all.
							 */
							zaction = kConfirmResumeProcSaidOverwrite;
						} else {
							/* We have a file by the same time,
							 * but smaller start point.  Leave
							 * the startpoint as is since it
							 * is most likely valid.
							 */
						}
					} else if (mdtm < st.st_mtime) {
						/* Remote file is older than
						 * local file.  Don't overwrite
						 * our file.
						 */
						cip->errNo = kErrLocalFileNewer;
						return (cip->errNo);
					} else /* if (mdtm > st.st_mtime) */ {
						/* File has a newer timestamp
						 * altogether, assume the remote
						 * file is an entirely new file
						 * and replace ours with it.
						 */
						zaction = kConfirmResumeProcSaidOverwrite;
					}
				} else {
						zaction = kConfirmResumeProcSaidOverwrite;
				}
			}
		} else {
			zaction = kConfirmResumeProcSaidOverwrite;
		}

		if (zaction == kConfirmResumeProcSaidCancel) {
			/* User wants to cancel this file and any
			 * remaining in batch.
			 */
			cip->errNo = kErrUserCanceled;
			return (cip->errNo);
		} else if (zaction == kConfirmResumeProcSaidSkip) {
			/* Nothing done, but not an error. */
			if (deleteflag == kDeleteYes)
				(void) FTPDelete(cip, file, kRecursiveNo, kGlobNo);
			return (kNoErr);
		} else if (zaction == kConfirmResumeProcSaidResume) {
			/* Resume; proc set the startPoint. */
			if (startPoint == expectedSize) {
				/* Don't go to all the trouble of downloading nothing. */
				/* Nothing done, but not an error. */
				if (deleteflag == kDeleteYes)
					(void) FTPDelete(cip, file, kRecursiveNo, kGlobNo);
				return (kNoErr);
			} else if (startPoint > expectedSize) {
				/* Cannot set start point past end of remote file */
				cip->errNo = result = kErrSetStartPoint;
				return (result);
			}
			fd = Open(dstfile, O_WRONLY|O_APPEND|O_BINARY, 00666);
		} else if (zaction == kConfirmResumeProcSaidAppend) {
			/* leave startPoint at zero, we will append everything. */
			startPoint = (longest_int) 0;
			fd = Open(dstfile, O_WRONLY|O_CREAT|O_APPEND|O_BINARY, 00666);
		} else /* if (zaction == kConfirmResumeProcSaidOverwrite) */ {
			created = 1;
			startPoint = (longest_int) 0;
			fd = Open(dstfile, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 00666);
		}

		if (fd < 0) {
			Error(cip, kDoPerror, "Cannot open local file %s for writing.\n", dstfile);
			result = kErrOpenFailed;
			cip->errNo = kErrOpenFailed;
			return (result);
		}

		if ((expectedSize == (longest_int) 0) && (startPoint <= (longest_int) 0) && (zaction != kConfirmResumeProcSaidOverwrite)) {
			/* Don't go to all the trouble of downloading nothing. */
#if defined(WIN32) || defined(_WINDOWS)
			/* Note: Windows doesn't allow zero-size files. */
			(void) write(fd, "\r\n", 2);
#endif
			(void) close(fd);
			if (mdtm != kModTimeUnknown) {
				cip->mdtm = mdtm;
				(void) time(&ut.actime);
				ut.modtime = mdtm;
				(void) utime(dstfile, &ut);
			}
			if (deleteflag == kDeleteYes)
				(void) FTPDelete(cip, file, kRecursiveNo, kGlobNo);
			return (kNoErr);
		}
	} else {
		fd = fdtouse;
	}

	if ((cip->numDownloads == 0) && (cip->dataSocketRBufSize > 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->hasRETRBUFSIZE == kCommandAvailable)
			(void) FTPCmd(cip, "SITE RETRBUFSIZE %lu", (unsigned long) cip->dataSocketRBufSize);
		else if (cip->hasRBUFSIZ == kCommandAvailable)
			(void) FTPCmd(cip, "SITE RBUFSIZ %lu", (unsigned long) cip->dataSocketRBufSize);
		else if (cip->hasRBUFSZ == kCommandAvailable)
			(void) FTPCmd(cip, "SITE RBUFSZ %lu", (unsigned long) cip->dataSocketRBufSize);
		else if (cip->hasBUFSIZE == kCommandAvailable)
			(void) FTPCmd(cip, "SITE BUFSIZE %lu", (unsigned long) cip->dataSocketSBufSize);
	}

#ifdef NO_SIGNALS
#else	/* NO_SIGNALS */
	vcip = cip;
	vfdtouse = fdtouse;
	vfd = fd;
	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 */

	tmpResult = FTPStartDataCmd(cip, kNetReading, xtype, startPoint, "RETR %s", file);

	if (tmpResult < 0) {
		result = tmpResult;
		if (result == kErrGeneric)
			result = kErrRETRFailed;
		cip->errNo = result;
		if (fdtouse < 0) {
			(void) close(fd);
			if ((created != 0) && (appendflag == kAppendNo) && (cip->startPoint == 0))
				(void) unlink(dstfile);
		}
#if !defined(NO_SIGNALS)
		(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
#endif	/* NO_SIGNALS */
		return (result);
	}

	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;
	}

	buf = cip->buf;
	bufSize = cip->bufSize;

	FTPInitIOTimer(cip);
	cip->mdtm = mdtm;
	(void) time(&ut.actime);
	ut.modtime = mdtm;
	cip->expectedSize = expectedSize;
	cip->lname = dstfile;	/* could be NULL */
	cip->rname = file;
	if (fdtouse >= 0)
		cip->useProgressMeter = 0;
	FTPStartIOTimer(cip);

#if ASCII_TRANSLATION
	if (xtype == kTypeAscii) {
		/* Ascii */
		for (;;) {
			if (! WaitForRemoteInput(cip)) {	/* could set cancelXfer */
				cip->errNo = result = kErrDataTimedOut;
				Error(cip, kDontPerror, "Remote read timed out.\n");
				break;
			}
			if (cip->cancelXfer > 0) {
				FTPAbortDataTransfer(cip);
				result = cip->errNo = kErrDataTransferAborted;
				break;
			}
#ifdef TESTING_ABOR
			if (cip->bytesTransferred > 0) {
				cip->cancelXfer = 1;
				FTPAbortDataTransfer(cip);
				result = cip->errNo = kErrDataTransferAborted;
				break;
			}
#endif /* TESTING_ABOR */
#ifdef NO_SIGNALS
			nread = SRead(cip->dataSocket, buf, bufSize, (int) cip->xferTimeout, kFullBufferNotRequired|kNoFirstSelect);
			if (nread == kTimeoutErr) {
				cip->errNo = result = kErrDataTimedOut;
				Error(cip, kDontPerror, "Remote read timed out.\n");
				break;
			} else if (nread < 0) {
				if ((gGotBrokenData != 0) || (errno == EPIPE)) {
					result = cip->errNo = kErrSocketReadFailed;
					errno = EPIPE;
					Error(cip, kDoPerror, "Lost data connection to remote host.\n");
				} else if (errno == EINTR) {
					continue;
				} else {
					Error(cip, kDoPerror, "Remote read failed.\n");
					result = kErrSocketReadFailed;
					cip->errNo = kErrSocketReadFailed;
				}
				break;
			} else if (nread == 0) {
				break;
			}
#else
			gCanBrokenDataJmp = 1;
			if (cip->xferTimeout > 0)
				(void) alarm(cip->xferTimeout);
			nread = read(cip->dataSocket, buf, bufSize);
			if (nread < 0) {
				if ((gGotBrokenData != 0) || (errno == EPIPE)) {
					result = cip->errNo = kErrSocketReadFailed;
					errno = EPIPE;
					Error(cip, kDoPerror, "Lost data connection to remote host.\n");
					(void) shutdown(cip->dataSocket, 2);
				} else if (errno == EINTR) {
					continue;
				} else {
					result = cip->errNo = kErrSocketReadFailed;
					Error(cip, kDoPerror, "Remote read failed.\n");
					(void) shutdown(cip->dataSocket, 2);
				}
				break;
			} else if (nread == 0) {
				break;
			}

			gCanBrokenDataJmp = 0;
#endif	/* NO_SIGNALS */

			src = buf;
			srclim = src + nread;
			dst = outbuf;
			dstlim = dst + sizeof(outbuf);
			while (src < srclim) {
				if (*src == '\r') {
					src++;
					continue;
				}
				if (dst >= dstlim) {
					nwrote = write(fd, outbuf, (size_t) (dst - outbuf));
					if (nwrote == (int) (dst - outbuf)) {
						/* Success. */
						dst = outbuf;
					} else if ((gGotBrokenData != 0) || (errno == EPIPE)) {
						result = kErrWriteFailed;
						cip->errNo = kErrWriteFailed;
						errno = EPIPE;
						(void) shutdown(cip->dataSocket, 2);
						goto brk;
					} else {
						Error(cip, kDoPerror, "Local write failed.\n");
						result = kErrWriteFailed;
						cip->errNo = kErrWriteFailed;
						(void) shutdown(cip->dataSocket, 2);
						goto brk;
					}
				}
				*dst++ = *src++;
			}
			if (dst > outbuf) {
				nwrote = write(fd, outbuf, (size_t) (dst - outbuf));
				if (nwrote != (int) (dst - outbuf)) {
					if ((gGotBrokenData != 0) || (errno == EPIPE)) {
						result = kErrWriteFailed;
						cip->errNo = kErrWriteFailed;
						errno = EPIPE;
						(void) shutdown(cip->dataSocket, 2);
						goto brk;
					} else {
						Error(cip, kDoPerror, "Local write failed.\n");
						result = kErrWriteFailed;
						cip->errNo = kErrWriteFailed;
						(void) shutdown(cip->dataSocket, 2);
						goto brk;
					}
				}
			}

			if (mdtm != kModTimeUnknown) {
				(void) utime(dstfile, &ut);
			}
			cip->bytesTransferred += (longest_int) nread;
			FTPUpdateIOTimer(cip);
		}
	} else
#endif	/* ASCII_TRANSLATION */
	{
		/* Binary */
		for (;;) {
			if (! WaitForRemoteInput(cip)) {	/* could set cancelXfer */
				cip->errNo = result = kErrDataTimedOut;
				Error(cip, kDontPerror, "Remote read timed out.\n");
				break;
			}
			if (cip->cancelXfer > 0) {
				FTPAbortDataTransfer(cip);
				result = cip->errNo = kErrDataTransferAborted;
				break;
			}
#ifdef TESTING_ABOR
			if (cip->bytesTransferred > 0) {
				cip->cancelXfer = 1;
				FTPAbortDataTransfer(cip);
				result = cip->errNo = kErrDataTransferAborted;
				break;
			}
#endif /* TESTING_ABOR */
#ifdef NO_SIGNALS
			nread = SRead(cip->dataSocket, buf, bufSize, (int) cip->xferTimeout, kFullBufferNotRequired|kNoFirstSelect);
			if (nread == kTimeoutErr) {
				cip->errNo = result = kErrDataTimedOut;
				Error(cip, kDontPerror, "Remote read timed out.\n");
				break;
			} else if (nread < 0) {
				if ((gGotBrokenData != 0) || (errno == EPIPE)) {
					result = cip->errNo = kErrSocketReadFailed;
					errno = EPIPE;
					Error(cip, kDoPerror, "Lost data connection to remote host.\n");
				} else if (errno == EINTR) {
					continue;
				} else {
					Error(cip, kDoPerror, "Remote read failed.\n");
					result = kErrSocketReadFailed;
					cip->errNo = kErrSocketReadFailed;
				}
				break;
			} else if (nread == 0) {
				break;
			}
#else
			gCanBrokenDataJmp = 1;
			if (cip->xferTimeout > 0)
				(void) alarm(cip->xferTimeout);
			nread = read(cip->dataSocket, buf, bufSize);
			if (nread < 0) {
				if ((gGotBrokenData != 0) || (errno == EPIPE)) {
					result = cip->errNo = kErrSocketReadFailed;
					errno = EPIPE;
					Error(cip, kDoPerror, "Lost data connection to remote host.\n");
				} else if (errno == EINTR) {
					continue;
				} else {
					result = cip->errNo = kErrSocketReadFailed;
					Error(cip, kDoPerror, "Remote read failed.\n");
				}
				(void) shutdown(cip->dataSocket, 2);
				break;
			} else if (nread == 0) {
				break;
			}
			gCanBrokenDataJmp = 0;
#endif	/* NO_SIGNALS */

			nwrote = write(fd, buf, nread);
			if (nwrote != nread) {
				if ((gGotBrokenData != 0) || (errno == EPIPE)) {
					result = kErrWriteFailed;
					cip->errNo = kErrWriteFailed;
					errno = EPIPE;
				} else {
					Error(cip, kDoPerror, "Local write failed.\n");
					result = kErrWriteFailed;
					cip->errNo = kErrWriteFailed;
				}
				(void) shutdown(cip->dataSocket, 2);
				break;
			}

			/* Ugggh... do this after each write operation
			 * so it minimizes the chance of a user killing
			 * the process before we reset the timestamps.
			 */
			if (mdtm != kModTimeUnknown) {
				(void) utime(dstfile, &ut);
			}
			cip->bytesTransferred += (longest_int) nread;
			FTPUpdateIOTimer(cip);
		}
	}

#if ASCII_TRANSLATION
brk:
#endif

#if !defined(NO_SIGNALS)
	if (cip->xferTimeout > 0)
		(void) alarm(0);
	gCanBrokenDataJmp = 0;
#endif	/* NO_SIGNALS */

	if (fdtouse < 0) {
		/* If they gave us a descriptor (fdtouse >= 0),
		 * leave it open, otherwise we opened it, so
		 * we need to close it.
		 */
		(void) close(fd);
		fd = -1;
	}

	tmpResult = FTPEndDataCmd(cip, 1);
	if ((tmpResult < 0) && (result == 0)) {
		result = kErrRETRFailed;
		cip->errNo = kErrRETRFailed;
	}
	FTPStopIOTimer(cip);
#if !defined(NO_SIGNALS)
	(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
#endif	/* NO_SIGNALS */

	if ((mdtm != kModTimeUnknown) && (cip->bytesTransferred > 0)) {
		(void) utime(dstfile, &ut);
	}

	if (result == kNoErr) {
		cip->numDownloads++;

		if (deleteflag == kDeleteYes) {
			result = FTPDelete(cip, file, kRecursiveNo, kGlobNo);
		}
	}

	return (result);
}	/* FTPGetOneF */




int
FTPGetOneFile3(
	const FTPCIPtr cip,
	const char *const file,
	const char *const dstfile,
	const int xtype,
	const int fdtouse,
	const int resumeflag,
	const int appendflag,
	const int deleteflag,
	const ConfirmResumeDownloadProc resumeProc,
	int UNUSED(reserved))
{
	int result;

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

	if ((file == NULL) || (file[0] == '\0'))
		return (kErrBadParameter);
	if (fdtouse < 0) {
		if ((dstfile == NULL) || (ds

⌨️ 快捷键说明

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