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

📄 io.c

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

#if ASCII_TRANSLATION
	if (xtype == kTypeAscii) {
		/* ascii */
		for (;;) {
#if !defined(NO_SIGNALS)
			gCanBrokenDataJmp = 0;
#endif	/* NO_SIGNALS */
			nread = read(fd, inbuf, sizeof(inbuf));
			if (nread < 0) {
				if (errno == EINTR) {
					continue;
				} else {
					result = kErrReadFailed;
					cip->errNo = kErrReadFailed;
					Error(cip, kDoPerror, "Local read failed.\n");
				}
				break;
			} else if (nread == 0) {
				break;
			}
			cip->bytesTransferred += (longest_int) nread;

#if !defined(NO_SIGNALS)
			gCanBrokenDataJmp = 1;
#endif	/* NO_SIGNALS */
			src = inbuf;
			srclim = src + nread;
			dst = cip->buf;		/* must be 2x sizeof inbuf or more. */
			while (src < srclim) {
				if (*src == '\n')
					*dst++ = '\r';
				*dst++ = *src++;
			}
			ntowrite = (size_t) (dst - cip->buf);
			cp = cip->buf;

#if !defined(NO_SIGNALS)
			if (cip->xferTimeout > 0)
				(void) alarm(cip->xferTimeout);
#endif	/* NO_SIGNALS */
			do {
				if (! WaitForRemoteOutput(cip)) {	/* could set cancelXfer */
					cip->errNo = result = kErrDataTimedOut;
					Error(cip, kDontPerror, "Remote write timed out.\n");
					goto brk;
				}
				if (cip->cancelXfer > 0) {
					FTPAbortDataTransfer(cip);
					result = cip->errNo = kErrDataTransferAborted;
					goto brk;
				}

#ifdef NO_SIGNALS
				nwrote = SWrite(cip->dataSocket, cp, (size_t) ntowrite, (int) cip->xferTimeout, kNoFirstSelect);
				if (nwrote < 0) {
					if (nwrote == kTimeoutErr) {
						cip->errNo = result = kErrDataTimedOut;
						Error(cip, kDontPerror, "Remote write timed out.\n");
					} else if ((gGotBrokenData != 0) || (errno == EPIPE)) {
						cip->errNo = result = kErrSocketWriteFailed;
						errno = EPIPE;
						Error(cip, kDoPerror, "Lost data connection to remote host.\n");
					} else if (errno == EINTR) {
						continue;
					} else {
						cip->errNo = result = kErrSocketWriteFailed;
						Error(cip, kDoPerror, "Remote write failed.\n");
					}
					(void) shutdown(cip->dataSocket, 2);
					goto brk;
				}
#else	/* NO_SIGNALS */
				nwrote = write(cip->dataSocket, cp, ntowrite);
				if (nwrote < 0) {
					if ((gGotBrokenData != 0) || (errno == EPIPE)) {
						cip->errNo = result = kErrSocketWriteFailed;
						errno = EPIPE;
						Error(cip, kDoPerror, "Lost data connection to remote host.\n");
					} else if (errno == EINTR) {
						continue;
					} else {
						cip->errNo = result = kErrSocketWriteFailed;
						Error(cip, kDoPerror, "Remote write failed.\n");
					}
					(void) shutdown(cip->dataSocket, 2);
					goto brk;
				}
#endif	/* NO_SIGNALS */
				cp += nwrote;
				ntowrite -= nwrote;
			} while (ntowrite > 0);
			FTPUpdateIOTimer(cip);
		}
	} else
#endif	/* ASCII_TRANSLATION */
	{
		/* binary */
		for (;;) {
#if !defined(NO_SIGNALS)
			gCanBrokenDataJmp = 0;
#endif	/* NO_SIGNALS */
			cp = buf;
			nread = read(fd, cp, bufSize);
			if (nread < 0) {
				if (errno == EINTR) {
					continue;
				} else {
					result = kErrReadFailed;
					cip->errNo = kErrReadFailed;
					Error(cip, kDoPerror, "Local read failed.\n");
				}
				break;
			} else if (nread == 0) {
				break;
			}
			cip->bytesTransferred += (longest_int) nread;

#if !defined(NO_SIGNALS)
			gCanBrokenDataJmp = 1;
			if (cip->xferTimeout > 0)
				(void) alarm(cip->xferTimeout);
#endif	/* NO_SIGNALS */
			do {
				if (! WaitForRemoteOutput(cip)) {	/* could set cancelXfer */
					cip->errNo = result = kErrDataTimedOut;
					Error(cip, kDontPerror, "Remote write timed out.\n");
					goto brk;
				}
				if (cip->cancelXfer > 0) {
					FTPAbortDataTransfer(cip);
					result = cip->errNo = kErrDataTransferAborted;
					goto brk;
				}

#ifdef NO_SIGNALS
				nwrote = SWrite(cip->dataSocket, cp, (size_t) nread, (int) cip->xferTimeout, kNoFirstSelect);
				if (nwrote < 0) {
					if (nwrote == kTimeoutErr) {
						cip->errNo = result = kErrDataTimedOut;
						Error(cip, kDontPerror, "Remote write timed out.\n");
					} else if ((gGotBrokenData != 0) || (errno == EPIPE)) {
						cip->errNo = result = kErrSocketWriteFailed;
						errno = EPIPE;
						Error(cip, kDoPerror, "Lost data connection to remote host.\n");
					} else if (errno == EINTR) {
						continue;
					} else {
						cip->errNo = result = kErrSocketWriteFailed;
						Error(cip, kDoPerror, "Remote write failed.\n");
					}
					(void) shutdown(cip->dataSocket, 2);
					cip->dataSocket = -1;
					goto brk;
				}
#else	/* NO_SIGNALS */
				nwrote = write(cip->dataSocket, cp, nread);
				if (nwrote < 0) {
					if ((gGotBrokenData != 0) || (errno == EPIPE)) {
						cip->errNo = result = kErrSocketWriteFailed;
						errno = EPIPE;
						Error(cip, kDoPerror, "Lost data connection to remote host.\n");
					} else if (errno == EINTR) {
						continue;
					} else {
						cip->errNo = result = kErrSocketWriteFailed;
						Error(cip, kDoPerror, "Remote write failed.\n");
					}
					(void) shutdown(cip->dataSocket, 2);
					cip->dataSocket = -1;
					goto brk;
				}
#endif	/* NO_SIGNALS */
				cp += nwrote;
				nread -= nwrote;
			} while (nread > 0);
			FTPUpdateIOTimer(cip);
		}
	}
brk:

	if (fdtouse < 0) {
		(void) Fstat(fd, &st);
	}

	if (fdtouse < 0) {
		if (shutdown(fd, 1) == 0) {
			/* This looks very bizarre, since
			 * we will be checking the socket
			 * for readability here!
			 *
			 * The reason for this is that we
			 * want to be able to timeout a
			 * small put.  So, we close the
			 * write end of the socket first,
			 * which tells the server we're
			 * done writing.  We then wait
			 * for the server to close down
			 * the whole socket, which tells
			 * us that the file was completed.
			 */
			(void) WaitForRemoteInput(cip);	/* Close could block. */
		}
	}

#if !defined(NO_SIGNALS)
	gCanBrokenDataJmp = 0;
	if (cip->xferTimeout > 0)
		(void) alarm(0);
#endif	/* NO_SIGNALS */
	tmpResult = FTPEndDataCmd(cip, 1);
	if ((tmpResult < 0) && (result == kNoErr)) {
		cip->errNo = result = kErrSTORFailed;
	}
	FTPStopIOTimer(cip);

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

	if (result == kNoErr) {
		/* The store succeeded;  If we were
		 * uploading to a temporary file,
		 * move the new file to the new name.
		 */
		cip->numUploads++;

		if ((tmppfx[0] != '\0') || (tmpsfx[0] != '\0')) {
			if ((result = FTPRename(cip, dstfile, odstfile)) < 0) {
				/* May fail if file was already there,
				 * so delete the old one so we can move
				 * over it.
				 */
				if (FTPDelete(cip, odstfile, kRecursiveNo, kGlobNo) == kNoErr) {
					result = FTPRename(cip, dstfile, odstfile);
					if (result < 0) {
						Error(cip, kDontPerror, "Could not rename %s to %s: %s.\n", dstfile, odstfile, FTPStrError(cip->errNo));
					}
				} else {
					Error(cip, kDontPerror, "Could not delete old %s, so could not rename %s to that: %s\n", odstfile, dstfile, FTPStrError(cip->errNo));
				}
			}
		}

		if (FTPUtime(cip, odstfile, st.st_atime, st.st_mtime, st.st_ctime) != kNoErr) {
			if (cip->errNo != kErrUTIMENotAvailable)
				Error(cip, kDontPerror, "Could not preserve times for %s: %s.\n", odstfile, FTPStrError(cip->errNo));
		}

		if (deleteflag == kDeleteYes) {
			if (unlink(file) < 0) {
				result = cip->errNo = kErrLocalDeleteFailed;
			}
		}
	}

#if !defined(NO_SIGNALS)
	(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
#endif	/* NO_SIGNALS */
	return (result);
}	/* FTPPutOneF */




int
FTPPutOneFile3(
	const FTPCIPtr cip,
	const char *const file,
	const char *const dstfile,
	const int xtype,
	const int fdtouse,
	const int appendflag,
	const char *const tmppfx,
	const char *const tmpsfx,
	const int resumeflag,
	const int deleteflag,
	const ConfirmResumeUploadProc resumeProc,
	int UNUSED(reserved))
{
	int result;

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

	if ((dstfile == NULL) || (dstfile[0] == '\0'))
		return (kErrBadParameter);
	if (fdtouse < 0) {
		if ((file == NULL) || (file[0] == '\0'))
			return (kErrBadParameter);
	}
	result = FTPPutOneF(cip, file, dstfile, xtype, fdtouse, appendflag, tmppfx, tmpsfx, resumeflag, deleteflag, resumeProc);
	return (result);
}	/* FTPPutOneFile3 */




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 ConfirmResumeUploadProc resumeProc,
	int UNUSED(reserved))
{
	LineList globList;
	FileInfoList files;
	FileInfoPtr 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=%d, 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 != kErrLocalSameAsRemote))
					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 != kErrLocalSameAsRemote))
					batchResult = result;
			}
			if (result == kErrUserCanceled)
				cip->cancelXfer = 1;
			if (cip->cancelXfer > 0)
				break;
		}
	}
	DisposeFileInfoListContents(&files);
	if (batchResult < 0)
		cip->errNo = batchResult;
	return (batchResult);
}	/* FTPPutFiles3 */




/* The purpose of this is to provide updates for the progress meters
 * during lags.  Return zero if the operation timed-out.
 */
static int
WaitForRemoteInput(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, SELECT_TYPE_ARG234 &ss, NULL, SELECT_TYPE_ARG234 &ss2, &tv);
		if (result == 1) {
			/* ready */
			cip->stalled = 0;
			return (1);
		} else if (result < 0) {
			if (result != 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 */
}	/* WaitForRemoteInput */


⌨️ 快捷键说明

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