From 6651c4a12f77166c689dd7bfc702c5fe48a1d724 Mon Sep 17 00:00:00 2001 From: EJ Date: Fri, 9 Jan 2026 14:25:45 +0200 Subject: [PATCH] Fix usages of `fread` and `fwrite` From `man 3 fread`: > The function **fread()** does not distinguish between end-of-file and > error; callers must use `feof(3)` and `ferror(3)` to determine which > occurred. > The function **fwrite()** returns a value less than _nitems_ only if a > write error has occurred. So we don't need to loop and check for `fwrite`, since it only returns anything smaller than `size` if it failed. It also doesn't set `ferror` so that's the wrong way to test for an error. Also, while `man` says nothing about `errno`, the UNIX spec for `fread` and `fwrite` says: > Otherwise, if a read error occurs, the error indicator for the stream > is set and _errno_ is set to indicate the error. (See [here](https://pubs.opengroup.org/onlinepubs/7908799/xsh/fread.html)) So I removed the TODO comment about it. --- nob.h | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/nob.h b/nob.h index c7bc3ffc..c7ba6706 100644 --- a/nob.h +++ b/nob.h @@ -1756,7 +1756,6 @@ NOBDEF bool nob_write_entire_file(const char *path, const void *data, size_t siz { bool result = true; - const char *buf = NULL; FILE *f = fopen(path, "wb"); if (f == NULL) { nob_log(NOB_ERROR, "Could not open file %s for writing: %s\n", path, strerror(errno)); @@ -1769,15 +1768,10 @@ NOBDEF bool nob_write_entire_file(const char *path, const void *data, size_t siz // ^ // data - buf = (const char*)data; - while (size > 0) { - size_t n = fwrite(buf, 1, size, f); - if (ferror(f)) { - nob_log(NOB_ERROR, "Could not write into file %s: %s\n", path, strerror(errno)); - nob_return_defer(false); - } - size -= n; - buf += n; + size_t n = fwrite(data, 1, size, f); + if (n < size) { + nob_log(NOB_ERROR, "Could not write into file %s: %s\n", path, strerror(errno)); + nob_return_defer(false); } defer: @@ -2102,7 +2096,6 @@ NOBDEF bool nob_read_entire_file(const char *path, Nob_String_Builder *sb) fread(sb->items + sb->count, m, 1, f); if (ferror(f)) { - // TODO: Afaik, ferror does not set errno. So the error reporting in defer is not correct in this case. nob_return_defer(false); } sb->count = new_count;