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;
 }

Reply via email to