On Mon, Jul 11, 2022 at 01:27:23PM -0500, Scott Cheloha wrote: > On Mon, Jul 11, 2022 at 08:31:04AM -0600, Todd C. Miller wrote: > > On Sun, 10 Jul 2022 20:58:35 -0900, Philip Guenther wrote: > > > > > Three thoughts: > > > 1) Since stdio errors are sticky, is there any real advantage to checking > > > each call instead of just checking the final fclose()? > > My thinking was that we have no idea how many arguments we're going to > print, so we may as well fail as soon as possible. > > Maybe in more complex programs there would be a code-length or > complexity-reducing upside to deferring the ferror(3) check until, > say, the end of a subroutine or something. > > > > [...] > > > > Will that really catch all errors? From what I can tell, fclose(3) > > can succeed even if the error flag was set. The pattern I prefer > > is to use a final fflush(3) followed by a call to ferror(3) before > > the fclose(3). > > [...]
Bump. The standard's error cases for fflush(3) are identical to those for fclose(3): https://pubs.opengroup.org/onlinepubs/9699919799/functions/fflush.html https://pubs.opengroup.org/onlinepubs/9699919799/functions/fclose.html Is the fact that our fclose(3) can succeed even if the error flag is set a bug? Also, can I go ahead with this? With this patch, echo(1) fails if we (for example) try to write to a full file system. So we are certainly catching more stdio failures: $ /bin/echo test > /tmp/myfile /tmp: write failed, file system is full $ echo $? 0 $ obj/echo test > /tmp/myfile /tmp: write failed, file system is full echo: stdout: No space left on device $ echo $? 1 Progress! Note that the shell builtin already fails in this case: $ type echo echo is a shell builtin $ echo test > /tmp/myfile /tmp: write failed, file system is full jetsam$ echo $? 1 Index: echo.c =================================================================== RCS file: /cvs/src/bin/echo/echo.c,v retrieving revision 1.10 diff -u -p -r1.10 echo.c --- echo.c 9 Oct 2015 01:37:06 -0000 1.10 +++ echo.c 30 Jul 2022 23:10:24 -0000 @@ -53,12 +53,15 @@ main(int argc, char *argv[]) nflag = 0; while (*argv) { - (void)fputs(*argv, stdout); - if (*++argv) - putchar(' '); + if (fputs(*argv, stdout) == EOF) + err(1, "stdout"); + if (*++argv && putchar(' ') == EOF) + err(1, "stdout"); } - if (!nflag) - putchar('\n'); + if (!nflag && putchar('\n') == EOF) + err(1, "stdout"); + if (fflush(stdout) == EOF || fclose(stdout) == EOF) + err(1, "stdout"); return 0; }