
1: /* Close a stream, with nicer error checking than fclose's. 2: 3: Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 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 2, or (at your option) 9: 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, write to the Free Software Foundation, 18: Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 19: 20: #include <config.h> 21: 22: #include "close-stream.h" 23: 24: #include <errno.h> 25: #include <stdbool.h> 26: 27: #include "__fpending.h" 28: 29: #if USE_UNLOCKED_IO 30: # include "unlocked-io.h" 31: #endif 32: 33: /* Close STREAM. Return 0 if successful, EOF (setting errno) 34: otherwise. A failure might set errno to 0 if the error number 35: cannot be determined. 36: 37: If a program writes *anything* to STREAM, that program should close 38: STREAM and make sure that it succeeds before exiting. Otherwise, 39: suppose that you go to the extreme of checking the return status 40: of every function that does an explicit write to STREAM. The last 41: printf can succeed in writing to the internal stream buffer, and yet 42: the fclose(STREAM) could still fail (due e.g., to a disk full error) 43: when it tries to write out that buffered data. Thus, you would be 44: left with an incomplete output file and the offending program would 45: exit successfully. Even calling fflush is not always sufficient, 46: since some file systems (NFS and CODA) buffer written/flushed data 47: until an actual close call. 48: 49: Besides, it's wasteful to check the return value from every call 50: that writes to STREAM -- just let the internal stream state record 51: the failure. That's what the ferror test is checking below. */ 52: 53: int 54: close_stream (FILE *stream) 55: { 56: bool some_pending = (__fpending (stream) != 0); 57: bool prev_fail = (ferror (stream) != 0); 58: bool fclose_fail = (fclose (stream) != 0); 59: 60: /* Return an error indication if there was a previous failure or if 61: fclose failed, with one exception: ignore an fclose failure if 62: there was no previous error, no data remains to be flushed, and 63: fclose failed with EBADF. That can happen when a program like cp 64: is invoked like this `cp a b >&-' (i.e., with standard output 65: closed) and doesn't generate any output (hence no previous error 66: and nothing to be flushed). */ 67: 68: if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) 69: { 70: if (! fclose_fail) 71: errno = 0; 72: return EOF; 73: } 74: 75: return 0; 76: }