]> git.ipfire.org Git - thirdparty/util-linux.git/blob - include/closestream.h
libmount: fix comment referring to passno field
[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 CLOSE_EXIT_CODE
14 # define CLOSE_EXIT_CODE EXIT_FAILURE
15 #endif
16
17 static inline int
18 close_stream(FILE * stream)
19 {
20 #ifdef HAVE___FPENDING
21 const int some_pending = (__fpending(stream) != 0);
22 #endif
23 const int prev_fail = (ferror(stream) != 0);
24 const int fclose_fail = (fclose(stream) != 0);
25
26 if (prev_fail || (fclose_fail && (
27 #ifdef HAVE___FPENDING
28 some_pending ||
29 #endif
30 errno != EBADF))) {
31 if (!fclose_fail && !(errno == EPIPE))
32 errno = 0;
33 return EOF;
34 }
35 return 0;
36 }
37
38 /* Meant to be used atexit(close_stdout); */
39 static inline void
40 close_stdout(void)
41 {
42 if (stdout && close_stream(stdout) != 0 && !(errno == EPIPE)) {
43 if (errno)
44 warn(_("write error"));
45 else
46 warnx(_("write error"));
47 _exit(CLOSE_EXIT_CODE);
48 }
49
50 if (stderr && close_stream(stderr) != 0)
51 _exit(CLOSE_EXIT_CODE);
52
53 stdout = NULL;
54 stderr = NULL;
55 }
56
57 static inline void
58 close_stdout_atexit(void)
59 {
60 /*
61 * Note that close stdout at exit disables ASAN to report memory leaks
62 */
63 #if !defined(__SANITIZE_ADDRESS__)
64 atexit(close_stdout);
65 #endif
66 }
67
68 #ifndef HAVE_FSYNC
69 static inline int
70 fsync(int fd __attribute__((__unused__)))
71 {
72 return 0;
73 }
74 #endif
75
76 static inline int
77 close_fd(int fd)
78 {
79 const int fsync_fail = (fsync(fd) != 0);
80 const int close_fail = (close(fd) != 0);
81
82 if (fsync_fail || close_fail)
83 return EOF;
84 return 0;
85 }
86
87 #endif /* UTIL_LINUX_CLOSESTREAM_H */