LCOV - code coverage report
Current view: top level - lib - close-stream.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 6 9 66.7 %
Date: 2018-01-30 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /* Close a stream, with nicer error checking than fclose's.
       2             : 
       3             :    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006, 2007 Free
       4             :    Software Foundation, Inc.
       5             : 
       6             :    This program is free software: you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      18             : 
      19             : #include <config.h>
      20             : 
      21             : #include "close-stream.h"
      22             : 
      23             : #include <errno.h>
      24             : #include <stdbool.h>
      25             : 
      26             : #include "fpending.h"
      27             : 
      28             : #if USE_UNLOCKED_IO
      29             : # include "unlocked-io.h"
      30             : #endif
      31             : 
      32             : /* Close STREAM.  Return 0 if successful, EOF (setting errno)
      33             :    otherwise.  A failure might set errno to 0 if the error number
      34             :    cannot be determined.
      35             : 
      36             :    If a program writes *anything* to STREAM, that program should close
      37             :    STREAM and make sure that it succeeds before exiting.  Otherwise,
      38             :    suppose that you go to the extreme of checking the return status
      39             :    of every function that does an explicit write to STREAM.  The last
      40             :    printf can succeed in writing to the internal stream buffer, and yet
      41             :    the fclose(STREAM) could still fail (due e.g., to a disk full error)
      42             :    when it tries to write out that buffered data.  Thus, you would be
      43             :    left with an incomplete output file and the offending program would
      44             :    exit successfully.  Even calling fflush is not always sufficient,
      45             :    since some file systems (NFS and CODA) buffer written/flushed data
      46             :    until an actual close call.
      47             : 
      48             :    Besides, it's wasteful to check the return value from every call
      49             :    that writes to STREAM -- just let the internal stream state record
      50             :    the failure.  That's what the ferror test is checking below.  */
      51             : 
      52             : int
      53       13086 : close_stream (FILE *stream)
      54             : {
      55       13086 :   bool some_pending = (__fpending (stream) != 0);
      56       13086 :   bool prev_fail = (ferror (stream) != 0);
      57       13086 :   bool fclose_fail = (fclose (stream) != 0);
      58             : 
      59             :   /* Return an error indication if there was a previous failure or if
      60             :      fclose failed, with one exception: ignore an fclose failure if
      61             :      there was no previous error, no data remains to be flushed, and
      62             :      fclose failed with EBADF.  That can happen when a program like cp
      63             :      is invoked like this `cp a b >&-' (i.e., with standard output
      64             :      closed) and doesn't generate any output (hence no previous error
      65             :      and nothing to be flushed).  */
      66             : 
      67       13086 :   if (prev_fail || (fclose_fail && (some_pending || errno != EBADF)))
      68             :     {
      69           0 :       if (! fclose_fail)
      70           0 :         errno = 0;
      71           0 :       return EOF;
      72             :     }
      73             : 
      74       13086 :   return 0;
      75             : }

Generated by: LCOV version 1.10