]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
include: add stream error checking facility
authorSami Kerola <kerolasa@iki.fi>
Wed, 4 Apr 2012 17:22:08 +0000 (19:22 +0200)
committerSami Kerola <kerolasa@iki.fi>
Wed, 4 Apr 2012 17:45:37 +0000 (19:45 +0200)
The close_stream() is copied from GNU lib.  Inspiration to do this is
talk by Jim Meyering - Goodbye World! The perils of relying on output
streams in C.

Reference: http://www.irill.org/events/ghm-gnu-hackers-meeting/videos/jim-meyering-goodbye-world-the-perils-of-relying-on-output-streams-in-c
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
include/Makefile.am
include/closestream.h [new file with mode: 0644]

index b939f89fef66fb5b8bfdf32f3b73fcd37773ced3..f6934ecfe090eb0e043abbce53b7ade03c89f9e4 100644 (file)
@@ -7,6 +7,7 @@ dist_noinst_HEADERS = \
        c.h \
        canonicalize.h \
        carefulputc.h \
+       closestream.h \
        cpuset.h \
        crc32.h \
        env.h \
diff --git a/include/closestream.h b/include/closestream.h
new file mode 100644 (file)
index 0000000..fb507ea
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef UTIL_LINUX_CLOSESTREAM_H
+#define UTIL_LINUX_CLOSESTREAM_H
+
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <unistd.h>
+
+#include "c.h"
+#include "nls.h"
+
+static inline int
+close_stream(FILE * stream)
+{
+       const int some_pending = (__fpending(stream) != 0);
+       const int prev_fail = (ferror(stream) != 0);
+       const int fclose_fail = (fclose(stream) != 0);
+       if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) {
+               if (!fclose_fail)
+                       errno = 0;
+               return EOF;
+       }
+       return 0;
+}
+
+/* Meant to be used atexit(close_stdout); */
+static inline void
+close_stdout(void)
+{
+       if (close_stream(stdout) != 0 && !(errno == EPIPE)) {
+               if (errno)
+                       warn(_("write error"));
+               else
+                       warnx(_("write error"));
+               _exit(EXIT_FAILURE);
+       }
+
+       if (close_stream(stderr) != 0)
+               _exit(EXIT_FAILURE);
+}
+
+#endif /* UTIL_LINUX_CLOSESTREAM_H */