diff --git a/src/libc/stdio/fdopen.c b/src/libc/stdio/fdopen.c index ca4f675..93614ce 100644 --- a/src/libc/stdio/fdopen.c +++ b/src/libc/stdio/fdopen.c @@ -6,6 +6,7 @@ FILE *fdopen(int fd, char const *mode) { FILE *fp = calloc(1, sizeof *fp); if(!fp) goto err; + fp->fd = -1; int flags = __fp_parse_mode(mode, fp); if(flags < 0) goto err; @@ -17,8 +18,6 @@ FILE *fdopen(int fd, char const *mode) return fp; err: - if(fp && fp->bufowned) - free(fp->buf); - free(fp); + __fp_close(fp, true); return NULL; } diff --git a/src/libc/stdio/feof.c b/src/libc/stdio/feof.c index f5a9722..9f5ae5d 100644 --- a/src/libc/stdio/feof.c +++ b/src/libc/stdio/feof.c @@ -2,5 +2,12 @@ int feof(FILE *fp) { - return fp->eof; + if(!fp->buf) + return fp->eof; + + /* If there is read data to be accessed, the flag doesn't count */ + if(fp->bufdir == __FILE_BUF_READ && fp->bufpos < fp->bufread) + return 0; + else + return fp->eof; } diff --git a/src/libc/stdio/fflush.c b/src/libc/stdio/fflush.c index 41f9eb3..43971c9 100644 --- a/src/libc/stdio/fflush.c +++ b/src/libc/stdio/fflush.c @@ -25,8 +25,9 @@ int fflush(FILE *fp) /* In writing mode, write pending data */ if(fp->bufdir == __FILE_BUF_WRITE && fp->bufpos > 0) { ssize_t written = __fp_write(fp, fp->buf, fp->bufpos); + int rc = (written == (ssize_t)fp->bufpos ? 0 : EOF); fp->bufpos = 0; - return (written == (ssize_t)fp->bufpos ? 0 : EOF); + return rc; } return 0; diff --git a/src/libc/stdio/fileutil.c b/src/libc/stdio/fileutil.c index 87302e9..4afe624 100644 --- a/src/libc/stdio/fileutil.c +++ b/src/libc/stdio/fileutil.c @@ -21,8 +21,13 @@ int __fp_open(FILE *fp, int fd, bool use_buffering) void __fp_close(FILE *fp, bool free_fp) { - fflush(fp); - close(fp->fd); + if(!fp) + return; + + if(fp->fd >= 0) { + fflush(fp); + close(fp->fd); + } if(fp->bufowned) free(fp->buf); if(free_fp) @@ -31,19 +36,18 @@ void __fp_close(FILE *fp, bool free_fp) void __fp_buffer_mode_read(FILE *fp) { - if(fp->buf && fp->bufdir == __FILE_BUF_WRITE && fp->bufpos > 0) { + if(fp->bufmode != _IONBF && fp->bufdir == __FILE_BUF_WRITE && + fp->bufpos > 0) fflush(fp); - fp->bufdir = __FILE_BUF_READ; - } + fp->bufdir = __FILE_BUF_READ; } void __fp_buffer_mode_write(FILE *fp) { - if(fp->buf && fp->bufdir == __FILE_BUF_READ - && fp->bufpos < fp->bufread) { + if(fp->bufmode != _IONBF && fp->bufdir == __FILE_BUF_READ && + fp->bufpos < fp->bufread) fflush(fp); - fp->bufdir = __FILE_BUF_WRITE; - } + fp->bufdir = __FILE_BUF_WRITE; } ssize_t __fp_read(FILE *fp, void *data, size_t size) @@ -63,6 +67,7 @@ ssize_t __fp_read(FILE *fp, void *data, size_t size) } fp->fdpos += rc; + read_ += rc; } return read_; @@ -83,6 +88,7 @@ ssize_t __fp_write(FILE *fp, void const *data, size_t size) break; fp->fdpos += rc; + written += rc; } return written; diff --git a/src/libc/stdio/fopen.c b/src/libc/stdio/fopen.c index 469ac3a..51d63a1 100644 --- a/src/libc/stdio/fopen.c +++ b/src/libc/stdio/fopen.c @@ -7,6 +7,7 @@ FILE *fopen(char const * restrict filename, char const * restrict mode) { FILE *fp = calloc(1, sizeof *fp); if(!fp) goto err; + fp->fd = -1; int flags = __fp_parse_mode(mode, fp); if(flags < 0) goto err; @@ -18,8 +19,6 @@ FILE *fopen(char const * restrict filename, char const * restrict mode) return fp; err: - if(fp && fp->bufowned) - free(fp->buf); - free(fp); + __fp_close(fp, true); return NULL; } diff --git a/src/libc/stdio/fread.c b/src/libc/stdio/fread.c index 5d6a241..e8bc584 100644 --- a/src/libc/stdio/fread.c +++ b/src/libc/stdio/fread.c @@ -19,7 +19,8 @@ size_t fread(void *data, size_t membsize, size_t nmemb, FILE *fp) size_t size_read = 0; while(size_read < size) { - /* Take what's available in the buffer (may be 0) */ + /* Take what's available in the buffer (may be 0, but only + during the first iteration) */ size_t size_frag = fp->bufread - fp->bufpos; if(size_frag > size - size_read) size_frag = size - size_read; diff --git a/src/libc/stdio/freopen.c b/src/libc/stdio/freopen.c index 6255c83..6eeedd9 100644 --- a/src/libc/stdio/freopen.c +++ b/src/libc/stdio/freopen.c @@ -9,6 +9,7 @@ FILE *freopen(char const * restrict filename, char const * restrict mode, { __fp_close(fp, false); memset(fp, 0, sizeof *fp); + fp->fd = -1; int flags = __fp_parse_mode(mode, fp); if(flags < 0) goto err; @@ -20,8 +21,6 @@ FILE *freopen(char const * restrict filename, char const * restrict mode, return fp; err: - if(fp && fp->bufowned) - free(fp->buf); - free(fp); + __fp_close(fp, true); return NULL; }