]> git.ipfire.org Git - thirdparty/util-linux.git/blob - include/closestream.h
include: add close_fd() for noticing write errors before close()
[thirdparty/util-linux.git] / include / closestream.h
1 #ifndef UTIL_LINUX_CLOSESTREAM_H
2 #define UTIL_LINUX_CLOSESTREAM_H
3
4 #include <stdio.h>
5 #ifdef HAVE_STDIO_EXT_H
6 #include <stdio_ext.h>
7 #endif
8 #include <unistd.h>
9
10 #include "c.h"
11 #include "nls.h"
12
13 #ifndef HAVE___FPENDING
14 static inline int
15 __fpending(FILE *stream __attribute__((__unused__)))
16 {
17 return 0;
18 }
19 #endif
20
21 static inline int
22 close_stream(FILE * stream)
23 {
24 const int some_pending = (__fpending(stream) != 0);
25 const int prev_fail = (ferror(stream) != 0);
26 const int fclose_fail = (fclose(stream) != 0);
27 if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) {
28 if (!fclose_fail)
29 errno = 0;
30 return EOF;
31 }
32 return 0;
33 }
34
35 /* Meant to be used atexit(close_stdout); */
36 static inline void
37 close_stdout(void)
38 {
39 if (close_stream(stdout) != 0 && !(errno == EPIPE)) {
40 if (errno)
41 warn(_("write error"));
42 else
43 warnx(_("write error"));
44 _exit(EXIT_FAILURE);
45 }
46
47 if (close_stream(stderr) != 0)
48 _exit(EXIT_FAILURE);
49 }
50
51 #ifndef HAVE_FSYNC
52 static inline int
53 fsync(int fd __attribute__((__unused__)))
54 {
55 return 0;
56 }
57 #endif
58
59 static inline int
60 close_fd(int fd)
61 {
62 const int fsync_fail = (fsync(fd) != 0);
63 const int close_fail = (close(fd) != 0);
64
65 if (fsync_fail || close_fail)
66 return EOF;
67 return 0;
68 }
69
70 #endif /* UTIL_LINUX_CLOSESTREAM_H */