diff --git a/sys/src/ape/lib/ap/stdio/_IO_getc.c b/sys/src/ape/lib/ap/stdio/_IO_getc.c index 3f99922c2..fbd126df3 100644 --- a/sys/src/ape/lib/ap/stdio/_IO_getc.c +++ b/sys/src/ape/lib/ap/stdio/_IO_getc.c @@ -8,7 +8,7 @@ int _IO_getc(FILE *f){ default: /* CLOSED, WR, ERR, EOF */ return EOF; case OPEN: - _IO_setvbuf(f); + if(_IO_setvbuf(f)!=0) return EOF; case RDWR: case RD: if(f->flags&STRING) return EOF; @@ -17,6 +17,7 @@ int _IO_getc(FILE *f){ else n = f->bufl; cnt=read(f->fd, f->buf, n); + if(f->state==CLOSED) return EOF; switch(cnt){ case -1: f->state=ERR; return EOF; case 0: f->state=END; return EOF; diff --git a/sys/src/ape/lib/ap/stdio/_IO_newfile.c b/sys/src/ape/lib/ap/stdio/_IO_newfile.c new file mode 100644 index 000000000..6a016ec5d --- /dev/null +++ b/sys/src/ape/lib/ap/stdio/_IO_newfile.c @@ -0,0 +1,27 @@ +/* + * pANS stdio -- fopen + */ +#include "iolib.h" + +#define _PLAN9_SOURCE +#include + +FILE *_IO_newfile(void) +{ + static FILE *fx=0; + static Lock fl; + FILE *f; + int i; + + lock(&fl); + for(i=0; i= &_IO_stream[FOPEN_MAX]) fx=_IO_stream; + if(fx->state==CLOSED) + break; + } + f = fx; + unlock(&fl); + if(f->state!=CLOSED) + return NULL; + return f; +} diff --git a/sys/src/ape/lib/ap/stdio/_IO_putc.c b/sys/src/ape/lib/ap/stdio/_IO_putc.c index 8cef77fd3..375b43eb0 100644 --- a/sys/src/ape/lib/ap/stdio/_IO_putc.c +++ b/sys/src/ape/lib/ap/stdio/_IO_putc.c @@ -19,7 +19,8 @@ int _IO_putc(int c, FILE *f){ case CLOSED: return EOF; case OPEN: - _IO_setvbuf(f); + if(_IO_setvbuf(f)!=0) + return EOF; /* fall through */ case RDWR: case END: diff --git a/sys/src/ape/lib/ap/stdio/fclose.c b/sys/src/ape/lib/ap/stdio/fclose.c index d14e83746..c3b157022 100644 --- a/sys/src/ape/lib/ap/stdio/fclose.c +++ b/sys/src/ape/lib/ap/stdio/fclose.c @@ -3,12 +3,28 @@ */ #include "iolib.h" int fclose(FILE *f){ - int error=0; + int d, error=0; + char *p; + if(!f) return EOF; if(f->state==CLOSED) return EOF; if(fflush(f)==EOF) error=EOF; - if(f->flags&BALLOC) free(f->buf); - if(!(f->flags&STRING) && close(f->fd)<0) error=EOF; + if(f->flags&BALLOC){ + if((p = f->buf)!=0){ + f->buf = 0; + f->wp = 0; + f->rp = 0; + f->lp = 0; + free(p); + } + } + if(!(f->flags&STRING)){ + if((d = f->fd)>=0){ + f->fd = -1; + if(close(d) < 0) + error = EOF; + } + } f->state=CLOSED; f->flags=0; return error; diff --git a/sys/src/ape/lib/ap/stdio/fdopen.c b/sys/src/ape/lib/ap/stdio/fdopen.c index 0c585b965..cb10d98e7 100644 --- a/sys/src/ape/lib/ap/stdio/fdopen.c +++ b/sys/src/ape/lib/ap/stdio/fdopen.c @@ -14,10 +14,8 @@ */ FILE *fdopen(const int fd, const char *mode){ FILE *f; - for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++) - if(f->state==CLOSED) - break; - if(f==&_IO_stream[FOPEN_MAX]) + + if((f = _IO_newfile()) == NULL) return NULL; f->fd=fd; if(mode[0]=='a') diff --git a/sys/src/ape/lib/ap/stdio/fflush.c b/sys/src/ape/lib/ap/stdio/fflush.c index 50a9da28f..28833f4c8 100644 --- a/sys/src/ape/lib/ap/stdio/fflush.c +++ b/sys/src/ape/lib/ap/stdio/fflush.c @@ -21,7 +21,8 @@ int fflush(FILE *f){ case WR: cnt=(f->flags&LINEBUF?f->lp:f->wp)-f->buf; if(cnt && write(f->fd, f->buf, cnt)!=cnt){ - f->state=ERR; + if(f->state!=CLOSED) + f->state=ERR; return EOF; } f->rp=f->wp=f->buf; diff --git a/sys/src/ape/lib/ap/stdio/fopen.c b/sys/src/ape/lib/ap/stdio/fopen.c index edf27172c..a10da3a42 100644 --- a/sys/src/ape/lib/ap/stdio/fopen.c +++ b/sys/src/ape/lib/ap/stdio/fopen.c @@ -2,10 +2,11 @@ * pANS stdio -- fopen */ #include "iolib.h" + FILE *fopen(const char *name, const char *mode){ FILE *f; - for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++) - if(f->state==CLOSED) - return freopen(name, mode, f); - return NULL; + + if((f = _IO_newfile()) == NULL) + return NULL; + return freopen(name, mode, f); } diff --git a/sys/src/ape/lib/ap/stdio/fread.c b/sys/src/ape/lib/ap/stdio/fread.c index c064a5649..1b54af2c6 100644 --- a/sys/src/ape/lib/ap/stdio/fread.c +++ b/sys/src/ape/lib/ap/stdio/fread.c @@ -12,7 +12,7 @@ size_t fread(void *p, size_t recl, size_t nrec, FILE *f){ s=(char *)p; n=recl*nrec; - while(n>0){ + while(n>0 && f->state!=CLOSED){ d=f->wp-f->rp; if(d>0){ if(d>n) @@ -23,7 +23,8 @@ size_t fread(void *p, size_t recl, size_t nrec, FILE *f){ if(f->buf==f->unbuf || (n >= BIGN && f->state==RD && !(f->flags&STRING))){ d=read(f->fd, s, n); if(d<=0){ - f->state=(d==0)?END:ERR; + if(f->state!=CLOSED) + f->state=(d==0)?END:ERR; goto ret; } }else{ diff --git a/sys/src/ape/lib/ap/stdio/fwrite.c b/sys/src/ape/lib/ap/stdio/fwrite.c index 4dc18d99e..2ec20cae5 100644 --- a/sys/src/ape/lib/ap/stdio/fwrite.c +++ b/sys/src/ape/lib/ap/stdio/fwrite.c @@ -12,7 +12,7 @@ size_t fwrite(const void *p, size_t recl, size_t nrec, FILE *f){ s=(char *)p; n=recl*nrec; - while(n>0){ + while(n>0 && f->state!=CLOSED){ d=f->rp-f->wp; if(d>0){ if(d>n) @@ -26,7 +26,8 @@ size_t fwrite(const void *p, size_t recl, size_t nrec, FILE *f){ if(f->flags&APPEND) lseek(f->fd, 0L, SEEK_END); if(write(f->fd, f->buf, d)!=d){ - f->state=ERR; + if(f->state!=CLOSED) + f->state=ERR; goto ret; } f->wp=f->rp=f->buf; @@ -35,7 +36,8 @@ size_t fwrite(const void *p, size_t recl, size_t nrec, FILE *f){ lseek(f->fd, 0L, SEEK_END); d=write(f->fd, s, n); if(d<=0){ - f->state=ERR; + if(f->state!=CLOSED) + f->state=ERR; goto ret; } } else { diff --git a/sys/src/ape/lib/ap/stdio/iolib.h b/sys/src/ape/lib/ap/stdio/iolib.h index 3a5bd63a0..57eb96085 100644 --- a/sys/src/ape/lib/ap/stdio/iolib.h +++ b/sys/src/ape/lib/ap/stdio/iolib.h @@ -42,3 +42,4 @@ int _IO_setvbuf(FILE *); FILE *_IO_sopenr(const char*); FILE *_IO_sopenw(void); char *_IO_sclose(FILE *); +FILE *_IO_newfile(void); diff --git a/sys/src/ape/lib/ap/stdio/mkfile b/sys/src/ape/lib/ap/stdio/mkfile index 17be0da58..76e51b27b 100644 --- a/sys/src/ape/lib/ap/stdio/mkfile +++ b/sys/src/ape/lib/ap/stdio/mkfile @@ -2,6 +2,7 @@ APE=/sys/src/ape <$APE/config LIB=/$objtype/lib/ape/libap.a OFILES=\ + _IO_newfile.$O\ _IO_getc.$O\ _IO_putc.$O\ _dtoa.$O\ diff --git a/sys/src/ape/lib/ap/stdio/rdline.c b/sys/src/ape/lib/ap/stdio/rdline.c index 6281a97e8..dafe71da4 100644 --- a/sys/src/ape/lib/ap/stdio/rdline.c +++ b/sys/src/ape/lib/ap/stdio/rdline.c @@ -12,7 +12,8 @@ char *rdline(FILE *f, char **ep){ default: /* CLOSED, WR, ERR, EOF */ return NULL; case OPEN: - _IO_setvbuf(f); + if(_IO_setvbuf(f)!=0) + return NULL; case RDWR: f->state=RD; case RD: @@ -46,6 +47,8 @@ char *rdline(FILE *f, char **ep){ break; } cnt=read(f->fd, f->wp, cnt); + if(f->state==CLOSED) + return NULL; if(cnt==-1){ f->state=ERR; return NULL; diff --git a/sys/src/ape/lib/ap/stdio/sopenr.c b/sys/src/ape/lib/ap/stdio/sopenr.c index 279ec726b..964493abf 100644 --- a/sys/src/ape/lib/ap/stdio/sopenr.c +++ b/sys/src/ape/lib/ap/stdio/sopenr.c @@ -6,8 +6,9 @@ FILE *_IO_sopenr(const char *s){ FILE *f; - for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++) if(f->state==CLOSED) break; - if(f==&_IO_stream[FOPEN_MAX]) return NULL; + + if((f=_IO_newfile())==NULL) + return NULL; f->buf=f->rp=(char *)s; /* what an annoyance const is */ f->bufl=strlen(s); f->wp=f->buf+f->bufl; diff --git a/sys/src/ape/lib/ap/stdio/sopenw.c b/sys/src/ape/lib/ap/stdio/sopenw.c index d13634333..4973da357 100644 --- a/sys/src/ape/lib/ap/stdio/sopenw.c +++ b/sys/src/ape/lib/ap/stdio/sopenw.c @@ -5,8 +5,9 @@ FILE *_IO_sopenw(void){ FILE *f; - for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++) if(f->state==CLOSED) break; - if(f==&_IO_stream[FOPEN_MAX]) return NULL; + + if((f=_IO_newfile())==NULL) + return NULL; f->buf=f->rp=f->wp=0; f->state=OPEN; f->flags=STRING;