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

📄 io.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* io.c
 *
 * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
 * All rights reserved.
 *
 */

#include "syshdrs.h"

static int gGotBrokenData = 0;

#if defined(WIN32) || defined(_WINDOWS)
#	define ASCII_TRANSLATION 0
#endif

#ifndef ASCII_TRANSLATION
#	define ASCII_TRANSLATION 1
#endif

#if !defined(NO_SIGNALS) && (USE_SIO || !defined(SIGALRM) || !defined(SIGPIPE) || !defined(SIGINT))
#	define NO_SIGNALS 1
#endif

#ifndef NO_SIGNALS

#ifdef HAVE_SIGSETJMP
static sigjmp_buf gBrokenDataJmp;
#else
static jmp_buf gBrokenDataJmp;
#endif	/* HAVE_SIGSETJMP */
static int gCanBrokenDataJmp = 0;

#endif	/* NO_SIGNALS */


#ifndef O_BINARY
	/* Needed for platforms using different EOLN sequence (i.e. DOS) */
#	ifdef _O_BINARY
#		define O_BINARY _O_BINARY
#	else
#		define O_BINARY 0
#	endif
#endif

static int WaitForRemoteInput(const FTPCIPtr cip);
static int WaitForRemoteOutput(const FTPCIPtr cip);


#ifndef NO_SIGNALS

static void
BrokenData(int signum)
{
	gGotBrokenData = signum;
	if (gCanBrokenDataJmp != 0) {
		gCanBrokenDataJmp = 0;
#ifdef HAVE_SIGSETJMP
		siglongjmp(gBrokenDataJmp, 1);
#else
		longjmp(gBrokenDataJmp, 1);
#endif	/* HAVE_SIGSETJMP */
	}
}	/* BrokenData */

#endif	/* NO_SIGNALS */




void
FTPInitIOTimer(const FTPCIPtr cip)
{
	cip->bytesTransferred = (longest_int) 0;
	cip->expectedSize = kSizeUnknown;
	cip->mdtm = kModTimeUnknown;
	cip->rname = NULL;
	cip->lname = NULL;
	cip->kBytesPerSec = -1.0;
	cip->percentCompleted = -1.0;
	cip->sec = -1.0;
	cip->secLeft = -1.0;
	cip->nextProgressUpdate = 0;
	cip->stalled = 0;
	cip->dataTimedOut = 0;
	cip->useProgressMeter = 1;
	(void) gettimeofday(&cip->t0, NULL);
}	/* FTPInitIOTimer */




void
FTPStartIOTimer(const FTPCIPtr cip)
{
	(void) gettimeofday(&cip->t0, NULL);
	if (cip->progress != (FTPProgressMeterProc) 0)
		(*cip->progress)(cip, kPrInitMsg);
}	/* FTPStartIOTimer */




void
FTPUpdateIOTimer(const FTPCIPtr cip)
{
	double sec;
	struct timeval *t0, t1;
	time_t now;

	(void) time(&now);
	if (now < cip->nextProgressUpdate)
		return;
	now += 1;
	cip->nextProgressUpdate = now;

	(void) gettimeofday(&t1, NULL);
	t0 = &cip->t0;

	if (t0->tv_usec > t1.tv_usec) {
		t1.tv_usec += 1000000;
		t1.tv_sec--;
	}
	sec = ((double) (t1.tv_usec - t0->tv_usec) * 0.000001)
		+ (t1.tv_sec - t0->tv_sec);
	if (sec > 0.0) {
		cip->kBytesPerSec = ((double) cip->bytesTransferred) / (1024.0 * sec);
	} else {
		cip->kBytesPerSec = -1.0;
	}
	if (cip->expectedSize == kSizeUnknown) {
		cip->percentCompleted = -1.0;
		cip->secLeft = -1.0;
	} else if (cip->expectedSize <= 0) {
		cip->percentCompleted = 100.0;
		cip->secLeft = 0.0;
	} else {
		cip->percentCompleted = ((double) (100.0 * (cip->bytesTransferred + cip->startPoint))) / ((double) cip->expectedSize);
		if (cip->percentCompleted >= 100.0) {
			cip->percentCompleted = 100.0;
			cip->secLeft = 0.0;
		} else if (cip->percentCompleted <= 0.0) {
			cip->secLeft = 999.0;
		}
		if (cip->kBytesPerSec > 0.0) {
			cip->secLeft = ((cip->expectedSize - cip->bytesTransferred - cip->startPoint) / 1024.0) / cip->kBytesPerSec;
			if (cip->secLeft < 0.0)
				cip->secLeft = 0.0;
		}
	}
	cip->sec = sec;
	if ((cip->progress != (FTPProgressMeterProc) 0) && (cip->useProgressMeter != 0))
		(*cip->progress)(cip, kPrUpdateMsg);
}	/* FTPUpdateIOTimer */




void
FTPStopIOTimer(const FTPCIPtr cip)
{
	cip->nextProgressUpdate = 0;	/* force last update */
	FTPUpdateIOTimer(cip);
	if (cip->progress != (FTPProgressMeterProc) 0)
		(*cip->progress)(cip, kPrEndMsg);
}	/* FTPStopIOTimer */




/* This isn't too useful -- it mostly serves as an example so you can write
 * your own function to do what you need to do with the listing.
 */
int
FTPList(const FTPCIPtr cip, const int outfd, const int longMode, const char *const lsflag)
{
	const char *cmd;
	char line[512];
	char secondaryBuf[768];
#ifndef NO_SIGNALS
	char *secBufPtr, *secBufLimit;
	int nread;
	volatile int result;
#else	/* NO_SIGNALS */
	SReadlineInfo lsSrl;
	int result;
#endif	/* NO_SIGNALS */

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

	cmd = (longMode != 0) ? "LIST" : "NLST";
	if ((lsflag == NULL) || (lsflag[0] == '\0')) {
		result = FTPStartDataCmd(cip, kNetReading, kTypeAscii, (longest_int) 0, "%s", cmd);
	} else {
		result = FTPStartDataCmd(cip, kNetReading, kTypeAscii, (longest_int) 0, "%s %s", cmd, lsflag);
	}


#ifdef NO_SIGNALS

	if (result == 0) {
		if (InitSReadlineInfo(&lsSrl, cip->dataSocket, secondaryBuf, sizeof(secondaryBuf), (int) cip->xferTimeout, 1) < 0) {
			/* Not really fdopen, but close in what we're trying to do. */
			result = kErrFdopenR;
			cip->errNo = kErrFdopenR;
			Error(cip, kDoPerror, "Could not fdopen.\n");
			return (result);
		}

		for (;;) {
			result = SReadline(&lsSrl, line, sizeof(line) - 2);
			if (result == kTimeoutErr) {
				/* timeout */
				Error(cip, kDontPerror, "Could not directory listing data -- timed out.\n");
				cip->errNo = kErrDataTimedOut;
				return (cip->errNo);
			} else if (result == 0) {
				/* end of listing -- done */
				cip->numListings++;
				break;
			} else if (result < 0) {
				/* error */
				Error(cip, kDoPerror, "Could not read directory listing data");
				result = kErrLISTFailed;
				cip->errNo = kErrLISTFailed;
				break;
			}

			(void) write(outfd, line, strlen(line));
		}

		DisposeSReadlineInfo(&lsSrl);
		if (FTPEndDataCmd(cip, 1) < 0) {
			result = kErrLISTFailed;
			cip->errNo = kErrLISTFailed;
		}
	} else if (result == kErrGeneric) {
		result = kErrLISTFailed;
		cip->errNo = kErrLISTFailed;
	}


#else	/* NO_SIGNALS */

	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;

		for (;;) {
			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;
			} else {
				cip->bytesTransferred += (longest_int) nread;
				(void) STRNCAT(line, "\n");
				(void) write(outfd, line, strlen(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;
	}
#endif	/* NO_SIGNALS */
	return (result);
}	/* FTPList */




static void
FTPRequestMlsOptions(const FTPCIPtr cip)
{
	int f;
	char optstr[128];
	size_t optstrlen;

	if (cip->usedMLS == 0) {
		/* First MLSD/MLST ? */
		cip->usedMLS = 1;

		f = cip->mlsFeatures & kPreferredMlsOpts;
		optstr[0] = '\0';

		/* TYPE */
		if ((f & kMlsOptType) != 0) {
			STRNCAT(optstr, "type;");
		}

		/* SIZE */
		if ((f & kMlsOptSize) != 0) {
			STRNCAT(optstr, "size;");
		}

		/* MODTIME */
		if ((f & kMlsOptModify) != 0) {
			STRNCAT(optstr, "modify;");
		}

		/* MODE */
		if ((f & kMlsOptUNIXmode) != 0) {
			STRNCAT(optstr, "UNIX.mode;");
		}

		/* PERM */
		if ((f & kMlsOptPerm) != 0) {
			STRNCAT(optstr, "perm;");
		}

		/* OWNER */
		if ((f & kMlsOptUNIXowner) != 0) {
			STRNCAT(optstr, "UNIX.owner;");
		}

		/* UID */
		if ((f & kMlsOptUNIXuid) != 0) {
			STRNCAT(optstr, "UNIX.uid;");
		}

		/* GROUP */
		if ((f & kMlsOptUNIXgroup) != 0) {
			STRNCAT(optstr, "UNIX.group;");
		}

		/* GID */
		if ((f & kMlsOptUNIXgid) != 0) {
			STRNCAT(optstr, "UNIX.gid;");
		}

		/* UNIQUE */
		if ((f & kMlsOptUnique) != 0) {
			STRNCAT(optstr, "unique;");
		}

		/* Tell the server what we prefer. */
		optstrlen = strlen(optstr);
		if (optstrlen > 0) {
			if (optstr[optstrlen - 1] == ';')
				optstr[optstrlen - 1] = '\0';
			(void) FTPCmd(cip, "OPTS MLST %s", optstr);
		}
	}
}	/* FTPRequestMlsOptions */




int
FTPListToMemory2(const FTPCIPtr cip, const char *const pattern, const LineListPtr llines, const char *const lsflags, const int blankLines, int *const tryMLSD)
{
	char secondaryBuf[768];
	char line[512];
	char lsflags1[128];
	const char *command = "NLST";
	const char *scp;
	char *dcp, *lim;
#ifndef NO_SIGNALS
	char *secBufPtr, *secBufLimit;
	volatile FTPSigProc osigpipe;
	volatile FTPCIPtr vcip;
	int sj;
	int nread;
	volatile int result;
#else	/* NO_SIGNALS */
	SReadlineInfo lsSrl;
	int result;
#endif	/* NO_SIGNALS */

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

	if ((llines == NULL) || (pattern == NULL) || (lsflags == NULL))
		return (kErrBadParameter);

	if ((tryMLSD != (int *) 0) && (*tryMLSD != 0) && (cip->hasMLSD == kCommandAvailable)) {
		command = "MLSD";
		if ((lsflags[0] == '-') && (strchr(lsflags, 'd') != NULL) && (cip->hasMLST == kCommandAvailable))
			command = "MLST";
		lsflags1[0] = '\0';
		FTPRequestMlsOptions(cip);
	} else {
		/* Not using MLSD. */
		if (tryMLSD != (int *) 0)
			*tryMLSD = 0;
		if (lsflags[0] == '-') {
			/* See if we should use LIST instead. */
			scp = lsflags + 1;
			dcp = lsflags1;
			lim = lsflags1 + sizeof(lsflags1) - 2;
			for (; *scp != '\0'; scp++) {
				if (*scp == 'l') {
					/* do not add the 'l' */
					command = "LIST";
				} else if (dcp < lim) {
					if (dcp == lsflags1)
						*dcp++ = '-';
					*dcp++ = *scp;
				}
			}
			*dcp = '\0';
		} else {
			(void) STRNCPY(lsflags1, lsflags);
		}
	}

	InitLineList(llines);

	result = FTPStartDataCmd(
		cip,
		kNetReading,
		kTypeAscii,
		(longest_int) 0,
		"%s%s%s%s%s",
		command,
		(lsflags1[0] == '\0') ? "" : " ",
		lsflags1,
		(pattern[0] == '\0') ? "" : " ",
		pattern
	);

#ifdef NO_SIGNALS

	if (result == 0) {
		if (InitSReadlineInfo(&lsSrl, cip->dataSocket, secondaryBuf, sizeof(secondaryBuf), (int) cip->xferTimeout, 1) < 0) {
			/* Not really fdopen, but close in what we're trying to do. */
			result = kErrFdopenR;
			cip->errNo = kErrFdopenR;
			Error(cip, kDoPerror, "Could not fdopen.\n");
			return (result);
		}

		for (;;) {
			result = SReadline(&lsSrl, line, sizeof(line) - 1);
			if (result == kTimeoutErr) {
				/* timeout */
				Error(cip, kDontPerror, "Could not directory listing data -- timed out.\n");
				cip->errNo = kErrDataTimedOut;
				return (cip->errNo);
			} else if (result == 0) {
				/* end of listing -- done */
				cip->numListings++;
				break;
			} else if (result < 0) {
				/* error */
				Error(cip, kDoPerror, "Could not read directory listing data");
				result = kErrLISTFailed;
				cip->errNo = kErrLISTFailed;
				break;
			}

			if (line[result - 1] == '\n')
				line[result - 1] = '\0';

			if ((blankLines == 0) && (result <= 1))
				continue;

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

			(void) AddLine(llines, line);
		}

		DisposeSReadlineInfo(&lsSrl);
		if (FTPEndDataCmd(cip, 1) < 0) {
			result = kErrLISTFailed;
			cip->errNo = kErrLISTFailed;
		}
	} else if (result == kErrGeneric) {
		result = kErrLISTFailed;
		cip->errNo = kErrLISTFailed;
	}


#else	/* NO_SIGNALS */
	vcip = cip;

⌨️ 快捷键说明

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