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