diff options
author | Pádraig Brady <P@draigBrady.com> | 2023-03-13 21:26:21 +0000 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2023-03-13 21:26:21 +0000 |
commit | 73d372dcc166afc387b4d130ecc00e5dce1fc89a (patch) | |
tree | a747b30181005d03df9253c1672a16691156c4f3 | |
parent | f26af5983313f1f4cf04143cecee68551ed6502f (diff) | |
download | coreutils-73d372dcc166afc387b4d130ecc00e5dce1fc89a.tar.gz |
tee: avoid undefined behavior after fclose()
* iopoll.c (fclose_wait): Rename from confusing fclose_nonblock name.
Also adjust to do no operations on the stream after fclose()
as this is undefined. Instead use fflush() to determine EAGAIN status.
(fwrite_wait): Renamed from confusing fwrite_nonblock name.
-rw-r--r-- | src/iopoll.c | 12 | ||||
-rw-r--r-- | src/iopoll.h | 4 | ||||
-rw-r--r-- | src/tee.c | 4 |
3 files changed, 11 insertions, 9 deletions
diff --git a/src/iopoll.c b/src/iopoll.c index b211dafc8..321a1245e 100644 --- a/src/iopoll.c +++ b/src/iopoll.c @@ -204,23 +204,25 @@ fail: /* wrapper for fclose() that also waits for F if non blocking. */ extern bool -fclose_nonblock (FILE *f) +fclose_wait (FILE *f) { for (;;) { - if (fclose (f) == 0) - return true; + if (fflush (f) == 0) + break; if (! fwait_for_nonblocking_write (f)) - return false; + break; } + + return fclose (f) == 0; } /* wrapper for fwrite() that also waits for F if non blocking. */ extern bool -fwrite_nonblock (char const *buf, ssize_t size, FILE *f) +fwrite_wait (char const *buf, ssize_t size, FILE *f) { for (;;) { diff --git a/src/iopoll.h b/src/iopoll.h index 79d5ccfef..0177a4d25 100644 --- a/src/iopoll.h +++ b/src/iopoll.h @@ -5,5 +5,5 @@ int iopoll (int fdin, int fdout, bool block); bool iopoll_input_ok (int fdin); bool iopoll_output_ok (int fdout); -bool fclose_nonblock (FILE *f); -bool fwrite_nonblock (char const *buf, ssize_t size, FILE *f); +bool fclose_wait (FILE *f); +bool fwrite_wait (char const *buf, ssize_t size, FILE *f); @@ -314,7 +314,7 @@ tee_files (int nfiles, char **files, bool pipe_check) Standard output is the first one. */ for (i = 0; i <= nfiles; i++) if (descriptors[i] - && ! fwrite_nonblock (buffer, bytes_read, descriptors[i])) + && ! fwrite_wait (buffer, bytes_read, descriptors[i])) { if (fail_output (descriptors, files, i)) ok = false; @@ -332,7 +332,7 @@ tee_files (int nfiles, char **files, bool pipe_check) /* Close the files, but not standard output. */ for (i = 1; i <= nfiles; i++) - if (descriptors[i] && ! fclose_nonblock (descriptors[i])) + if (descriptors[i] && ! fclose_wait (descriptors[i])) { error (0, errno, "%s", quotef (files[i])); ok = false; |