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

📄 stdio.c

📁 uCLinux下的一个TCP/IP协议栈源码
💻 C
📖 第 1 页 / 共 2 页
字号:

	if(c == '\n' && fp->flags.ascii){
		pushdown(&fp->ibuf,fp->eol,strlen(fp->eol));
	} else {
		pushdown(&fp->ibuf,&c,1);
	}
	return c;
}
size_t
fwrite(
void *ptr,
size_t size,
size_t n,
FILE *fp
){
	struct mbuf *bp;
	uint8 *icp,*ocp;
	size_t bytes;
	size_t cnt;
	size_t asize;
	int room;
	int newlines = 0;
	int eollen = 1;
	int doflush = 0;
	
	if(fp == NULL || fp->cookie != _COOKIE || size == 0)
		return 0;
	icp = ptr;
	if(n == 1)	/* Avoid multiply in common case when n==1 */
		bytes = size;
	else
		bytes = size*n;

	/* Optimization for large binary file writes */
	if(fp->type == _FL_FILE && !fp->flags.ascii && bytes >= fp->bufsize){
		fflush(fp);
		if(fp->flags.append)
			_LSEEK(fp->fd,0L,SEEK_END);
		else
			_LSEEK(fp->fd,fp->offset,SEEK_SET);
		cnt = _WRITE(fp->fd,icp,bytes);
		if(cnt > 0)
			fp->offset += cnt;
		if(cnt != bytes)
			return cnt/size;
		return n;
	}
	if(fp->flags.ascii){
		/* Count the newlines in the input buffer */
		newlines = memcnt(ptr,'\n',bytes);
		if(newlines != 0){
			eollen = strlen(fp->eol);
			if(fp->bufmode == _IOLBF)
				doflush = 1;
		}
	}
	while(bytes != 0){
		bp = fp->obuf;
		if(bp != NULL && bp->cnt + eollen > bp->size){
			/* Current obuf is full; flush it */
			if(fflush(fp) == EOF)
				return (bytes - n*size)/size;
		}
		if((bp = fp->obuf) == NULL){
			/* Allocate a new output buffer. The size is the
			 * larger of the buffer size or the amount of data
			 * we have to write (including any expanded newlines)
			 */
			asize = bytes+(eollen-1)*newlines;
			asize = max(fp->bufsize,asize);
			bp = fp->obuf = ambufw(asize);
		}
		if(fp->flags.ascii && newlines != 0){
			/* Copy text to buffer, expanding newlines */
			ocp = bp->data + bp->cnt;
			room = bp->size - bp->cnt;
			for(;room >= eollen && bytes != 0;icp++,bytes--){
				if(*icp == '\n'){
					memcpy(ocp,fp->eol,eollen);
					ocp += eollen;
					room -= eollen;
					newlines--;
				} else {
					*ocp++ = *icp;
					room--;
				}
			}
			bp->cnt = ocp - bp->data;
		} else {
			/* Simply copy binary data to buffer */
			cnt = min(bp->size - bp->cnt,bytes);
			memcpy(bp->data+bp->cnt,icp,cnt);
			bp->cnt += cnt;
			icp += cnt;
			bytes -= cnt;
		}
	}
	/* The final flush. Flush if the stream is unbuffered,
	 * the output buffer is full, or the stream is line buffered
	 * and we've written at least one newline (not necessarily the
	 * last character)
	 */
	if(fp->bufmode == _IONBF || bp->cnt == bp->size || doflush){
		if(fflush(fp) == EOF)
			return (bytes - n*size)/size;
	}
	return n;
}
static struct mbuf *
_fillbuf(FILE *fp,int cnt)
{
	struct mbuf *bp;
	int i;

	if(fp->ibuf != NULL)
		return fp->ibuf;	/* Stuff already in the input buffer */

	switch(fp->type){
	case _FL_ASY:
		fp->ibuf = ambufw(BUFSIZ);
		i = asy_read(fp->fd,fp->ibuf->data,BUFSIZ);
		if(i < 0)
			return NULL;
		fp->ibuf->cnt = i;
		return fp->ibuf;
	case _FL_PIPE:
		while(fp->ibuf == NULL)
			if((errno = kwait(&fp->ibuf)) != 0)	/* Wait for something */
				return NULL;
		return fp->ibuf;
	case _FL_SOCK:
		/* Always grab everything available from a socket */
		if(recv_mbuf(fp->fd,&fp->ibuf,0,NULL,0) <= 0
		 && errno != EALARM){
			fp->flags.eof = 1;
		}
		return fp->ibuf;
	case _FL_FILE:
		/* Read from file */
		cnt = max(fp->bufsize,cnt);
		bp = ambufw(cnt);		
		_LSEEK(fp->fd,fp->offset,SEEK_SET);
		cnt = _READ(fp->fd,bp->data,cnt);
		if(cnt < 0)
			fp->flags.err = 1;
		if(cnt == 0)
			fp->flags.eof = 1;
		if(cnt <= 0){
			free_p(&bp);	/* Nothing successfully read */
			return NULL;
		}
		fp->offset += cnt;	/* Update pointer */
		/* Buffer successfully read, store it */
		bp->cnt = cnt;
		fp->ibuf = bp;
		return bp;
	case _FL_DISPLAY:	/* Displays are write-only */
		return NULL;
	}
	return NULL;	/* Can't happen */
}
size_t
fread(
void *ptr,
size_t size,
size_t n,
FILE *fp
){
	struct mbuf *bp;
	size_t bytes;
	size_t cnt;
	int c;
	size_t tot = 0;
	uint8 *ocp;
	uint8 *cp;

	if(fp == NULL || fp->cookie != _COOKIE || size == 0)
		return 0;
	fflush(fp);
	bytes = n*size;

	ocp = ptr;
	while(bytes != 0){
		/* Optimization for large binary file reads */
		if(fp->ibuf == NULL
		 && fp->type == _FL_FILE && !fp->flags.ascii
		 && bytes >= BUFSIZ){
			_LSEEK(fp->fd,fp->offset,SEEK_SET);
			tot = _READ(fp->fd,ocp,bytes);
			if(tot > 0)
				fp->offset += tot;
			if(tot != bytes)
				return tot/size;
			return n;
		}
		/* Replenish input buffer if necessary */
		if(fp->ibuf == NULL){
			if(tot != 0 && fp->flags.partread){
				/* Would block for more data */
				return tot/size;	
			}
		 	if(_fillbuf(fp,bytes) == NULL){
				/* eof or error */
				return tot/size;
			}
		}
		/* In this pass, read the lesser of the buffer size,
		 * the requested amount, or the amount up to the next
		 * eol sequence (if ascii mode)
		 */
		bp = fp->ibuf;
		cnt = min(bp->cnt,bytes);
		if(fp->flags.ascii
		 && (cp = memchr(bp->data,fp->eol[0],cnt)) != NULL)
			cnt = min(cnt,cp - bp->data);
		if(cnt != 0){
			cnt = pullup(&fp->ibuf,ocp,cnt);
			ocp += cnt;
			tot += cnt;
			bytes -= cnt;
		} else {
			/* Hit a eol sequence, use fgetc to translate */
			if((c = fgetc(fp)) == EOF)
				return tot/size;

			*ocp++ = c;
			tot++;
			bytes--;
		}
	}
	if(fp->type == _FL_PIPE)
		ksignal(&fp->obuf,1);
	return n;
}
void
perror(const char *s)
{
	fprintf(stderr,"%s: errno %d",s,errno);
	if(errno < sys_nerr)
		fprintf(stderr,": %s\n",sys_errlist[errno]);
	else if(EMIN <= errno && errno <= EMAX)
		fprintf(stderr,": %s\n",Sock_errlist[errno-EMIN]);
	else
		fprintf(stderr,"\n");
}
int
setvbuf(
FILE *fp,
char *buf,	/* Ignored; we alloc our own */
int type,
int size
){
	if(fp == NULL || fp->cookie != _COOKIE)
		return -1;
	fflush(fp);
	if(size == 0)
		type = _IONBF;
	switch(type){
	case _IOFBF:
		fp->bufsize = size;
		break;
	case _IOLBF:
		fp->bufsize = size;
		break;
	case _IONBF:
		fp->bufsize = 1;
		break;
	default:
		return -1;	/* Invalid */
	}
	fp->bufmode = type;
	return 0;
}
void
setbuf(FILE *fp,char *buf)
{
	if(buf == NULL)
		setvbuf(fp,NULL,_IONBF,0);
	else
		setvbuf(fp,buf,_IOFBF,BUFSIZ);
}
FILE *
tmpfile(void)
{
	static int num;
	struct stat statbuf;
	FILE *fp;
	char *fname;
	char *tmpdir;
	char *cp;

	/* Determine directory to use. First look for $TMP environment
	 * variable, then use the compiled-in-default, then use the
	 * current directory.
	 */
	if((cp = getenv("TMP")) != NULL
	 && stat(cp,&statbuf) == 0 && (statbuf.st_mode & S_IFDIR)){
		fname = malloc(strlen(cp) + 11);
		tmpdir = malloc(strlen(cp) + 2);
		strcpy(tmpdir,cp);
		strcat(tmpdir,"/");
	} else if(stat(Tmpdir,&statbuf) == 0 && (statbuf.st_mode & S_IFDIR)){
		fname = malloc(strlen(Tmpdir) + 11);
		tmpdir = malloc(strlen(Tmpdir) + 2);
		strcpy(tmpdir,Tmpdir);
		strcat(tmpdir,"/");
	} else {
		fname = malloc(10);
		tmpdir = strdup("");
	}
	for(;;){
		sprintf(fname,"%stemp.%03d",tmpdir,num);
		if(stat(fname,&statbuf) == -1 && errno == ENOENT)
			break;
		num++;
	}
	free(tmpdir);
	fp = fopen(fname,"w+b");
	free(fname);
	if(fp != NULL)
		fp->flags.tmp = 1;
	return fp;
}
/* Do everything to close a stream except freeing the descriptor
 * The reference count is left unchanged, and the descriptor is still
 * on the list
 */
static void
_fclose(FILE *fp)
{
	struct stat statbuf;
	char *buf;
	long i;
	int n;

	if(fp == NULL || fp->cookie != _COOKIE)
		return;
	if(_clrtmp && fp->flags.tmp){
		/* Wipe temp file for security */
		rewind(fp);
		fstat(fileno(fp),&statbuf);
		buf = malloc(BUFSIZ);
		memset(buf,0,BUFSIZ);
		i = statbuf.st_size;
		while(i > 0){
			n = fwrite(buf,1,min(i,BUFSIZ),fp);
			kwait(NULL);
			if(n < BUFSIZ)
				break;
			i -= n;
		}
		free(buf);
	}
	fflush(fp);
	switch(fp->type){
	case _FL_ASY:
		asy_close(fp->fd);
		break;
	case _FL_SOCK:
		close_s(fp->fd);
		break;
	case _FL_FILE:
		_CLOSE(fp->fd);
		fp->offset = 0;
		break;
	case _FL_DISPLAY:
		closedisplay(fp->ptr);
		fp->ptr = NULL;
		break;
	}
	free_p(&fp->obuf);	/* Should be NULL anyway */
	fp->obuf = NULL;
	free_p(&fp->ibuf);
	fp->ibuf = NULL;
	if(fp->flags.tmp)
		unlink(fp->ptr);
	free(fp->ptr);
	fp->ptr = NULL;
	fp->flags.err = fp->flags.eof = fp->flags.ascii = 0;
	fp->flags.append = fp->flags.tmp = fp->flags.partread = 0;
	fp->fd = -1;
}
/* allocate a new file pointer structure, init a few fields and put on list */
static FILE *
_fcreat(void)
{
	FILE *fp;

	if((fp = (FILE *)calloc(1,sizeof(FILE))) == NULL)
		return NULL;

	fp->cookie = _COOKIE;
	fp->refcnt = 1;
	fp->next = _Files;
	_Files = fp;
	if(fp->next != NULL)
		fp->next->prev = fp;
	return fp;
}

int
read(int fd,void *buf,unsigned cnt)
{
	int type = _fd_type(fd);

	if(fd < 0){
		errno = EINVAL;
		return -1;
	}
	switch(type){
	case _FL_FILE:
		return _READ(fd,buf,cnt);
	case _FL_SOCK:
		return recv(fd,buf,cnt,0);
	case _FL_ASY:
		return asy_read(fd,buf,cnt);
	default:
		errno = EINVAL;
		return -1;
	}
}
int
write(int fd,const void *buf,unsigned cnt)
{
	int type = _fd_type(fd);

	if(fd < 0){
		errno = EINVAL;
		return -1;
	}
	switch(type){
	case _FL_FILE:
		return _WRITE(fd,buf,cnt);
	case _FL_SOCK:
		return send(fd,buf,cnt,0);
	case _FL_ASY:
		return asy_write(fd,buf,cnt);
	default:
		errno = EINVAL;
		return -1;
	}
}

/* This entry point is provided for applications that want to call open()
 * directly, instead of using fopen()
 */
int
open(const char *file,int mode)
{
	return _open(file,mode);
}

int
close(int fd)
{
	int type = _fd_type(fd);

	if(fd < 0){
		errno = EINVAL;
		return -1;
	}
	switch(type){
	case _FL_FILE:
		return _CLOSE(fd);
	case _FL_SOCK:
		return close_s(fd);
	case _FL_ASY:
		return asy_close(fd);
	default:
		errno = EINVAL;
		return -1;
	}
}

void
fcloseall(void)
{
	FILE *fp,*fpnext;

	flushall();
	for(fp = _Files;fp != NULL;fp=fpnext){
		fpnext = fp->next;
		fclose(fp);
	}
}
void
flushall(void)
{
	FILE *fp;

	for(fp = _Files;fp != NULL;fp=fp->next){
		fflush(fp);
	}
}
FILE *
fdup(FILE *fp)
{
	FILE *nfp;

	if(fp == NULL || fp->cookie != _COOKIE)
		return NULL;	/* Invalid arg */
	switch(fp->type){
	case _FL_FILE:
		/* Allocate new file pointer structure so each can
		 * have its own read/write pointer and buffering
		 */
		if((nfp = _fcreat()) == NULL)
			return NULL;
		nfp->fd = _DUP(fp->fd);
		nfp->offset = fp->offset;
		nfp->type = fp->type;
		nfp->bufmode = fp->bufmode;
		nfp->flags = fp->flags;
		strcpy(nfp->eol,fp->eol);
		nfp->bufsize = fp->bufsize;
		nfp->ptr = strdup(fp->ptr);
		fp = nfp;
		break;
	default:	/* These just share the same file pointer */
		fp->refcnt++;
		break;
	}
	return fp;
}
char *
fpname(FILE *fp)
{
	if(fp == NULL || fp->cookie != _COOKIE)
		return NULL;
	if(fp->type == _FL_FILE)
		return fp->ptr;
	return NULL;
}

void
exit(int n)
{
	fcloseall();
	_exit(n);
}

int
dofiles(int argc,char *argv[],void *p)
{
	FILE *fp;
	int i;

	printf("fp       fd   ref  eol   type mod buf  flags\n");
	for(fp = _Files;fp != NULL;fp = fp->next){
		printf("%p ",fp);
		if(fp->fd != -1)
			printf("%-4d",fp->fd);
		else
			printf("    ");
		printf(" %-3d ",fp->refcnt);
		for(i=0;i<EOL_LEN-1;i++){
			if(fp->eol[i] != '\0')
				printf(" %02x",fp->eol[i]);
			else
				printf("   ");
		}
		switch(fp->type){
		case _FL_SOCK:
			printf(" sock");
			break;
		case _FL_FILE:
			printf(" file");
			break;
		case _FL_DISPLAY:
			printf(" disp");
			break;
		case _FL_PIPE:
			printf(" pipe");
			break;
		case _FL_ASY:
			printf(" asy ");
		}
		printf("%4s",fp->flags.ascii ? " txt" : " bin");
		switch(fp->bufmode){
		case _IONBF:
			printf(" none");
			break;
		case _IOLBF:
			printf(" line");
			break;
		case _IOFBF:
			printf(" full");
			break;
		}
		if(fp->flags.eof)
			printf(" EOF");
		if(fp->flags.err)
			printf(" ERR");
		if(fp->flags.append)
			printf(" APND");
		if(fp->flags.tmp)
			printf(" TMP");
		if(fp->type == _FL_FILE && fp->ptr != NULL)
			printf(" (%s seek=%lu)",(char *)fp->ptr,ftell(fp));
		putchar('\n');
	}
	return 0;
}

⌨️ 快捷键说明

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