?? stdio.c
字號:
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 + -