]> granicus.if.org Git - procps-ng/commitdiff
lib: add fileutils file with stream error checking facility
authorSami Kerola <kerolasa@iki.fi>
Fri, 23 Mar 2012 10:10:04 +0000 (11:10 +0100)
committerSami Kerola <kerolasa@iki.fi>
Fri, 23 Mar 2012 14:57:41 +0000 (15:57 +0100)
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/fileutils.h [new file with mode: 0644]
lib/.gitignore
lib/Makefile.am
lib/fileutils.c [new file with mode: 0644]
testsuite/Makefile.am
testsuite/lib.test/fileutils.exp [new file with mode: 0644]
testsuite/lib.test/fileutils_badfd.sh [new file with mode: 0755]
testsuite/lib.test/fileutils_full.sh [new file with mode: 0755]

diff --git a/include/fileutils.h b/include/fileutils.h
new file mode 100644 (file)
index 0000000..cfab570
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef PROCPS_NG_FILEUTILS
+#define PROCPS_NG_FILEUTILS
+
+int close_stream(FILE * stream);
+void close_stdout(void);
+
+#endif
index f4208e7aed1bbeaec9a5be77ef01764f49b4d0db..6b7ce835ae515e08e6baeac8795e16cee9b2227c 100644 (file)
@@ -1,2 +1,3 @@
 .dirstamp
+test_fileutils
 test_strutils
index 4216a252d09d3ca1b337390b280d4d390e0c1a62..9430de2e4d020935f5fc001e42e23cc4b32e7fee 100644 (file)
@@ -2,6 +2,7 @@ AM_CPPFLAGS = -include $(top_builddir)/config.h -I$(top_srcdir)/include
 
 AM_CPPFLAGS += -DTEST_PROGRAM
 
-noinst_PROGRAMS = test_strutils
+noinst_PROGRAMS = test_strutils test_fileutils
 
 test_strutils_SOURCES = strutils.c
+test_fileutils_SOURCES = fileutils.c
diff --git a/lib/fileutils.c b/lib/fileutils.c
new file mode 100644 (file)
index 0000000..b47a9cf
--- /dev/null
@@ -0,0 +1,43 @@
+#include <errno.h>
+#include <error.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "nls.h"
+
+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;
+}
+
+/* Use atexit(); */
+void close_stdout(void)
+{
+       if (close_stream(stdout) != 0 && !(errno == EPIPE)) {
+               char const *write_error = _("write error");
+               error(0, errno, "%s", write_error);
+               _exit(EXIT_FAILURE);
+       }
+
+       if (close_stream(stderr) != 0)
+               _exit(EXIT_FAILURE);
+}
+
+#ifdef TEST_PROGRAM
+#include <stdio.h>
+int main(int argc, char *argv[])
+{
+       atexit(close_stdout);
+       printf("Hello, World!\n");
+       return EXIT_SUCCESS;
+}
+#endif                         /* TEST_PROGRAM */
index 62acfa647f01229dc96fcbfd42d609370dd2bec4..0bb7fb9ff94602856374b21a1989b78396ed91d2 100644 (file)
@@ -34,6 +34,7 @@ EXTRA_DIST = \
        global-conf.exp \
     free.test/free.exp \
     kill.test/kill.exp \
+    lib.test/fileutils.exp \
     lib.test/strutils.exp \
     pgrep.test/pgrep.exp \
     pkill.test/pkill.exp \
diff --git a/testsuite/lib.test/fileutils.exp b/testsuite/lib.test/fileutils.exp
new file mode 100644 (file)
index 0000000..3fab11e
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# Testsuite for lib/fileutils program
+#
+
+set noarg "${topdir}lib/test_fileutils"
+
+set test "without argument"
+spawn $noarg
+expect_pass "$test" "Hello, World!"
+
+set badfd "${topdir}testsuite/lib.test/fileutils_badfd.sh"
+set test "test bad file descriptor"
+spawn $badfd
+expect_pass "$test" "test_fileutils: write error: Bad file descriptor"
+
+set full "${topdir}testsuite/lib.test/fileutils_full.sh"
+set test "test no space left on device"
+spawn $full
+expect_pass "$test" "test_fileutils: write error: No space left on device"
diff --git a/testsuite/lib.test/fileutils_badfd.sh b/testsuite/lib.test/fileutils_badfd.sh
new file mode 100755 (executable)
index 0000000..4a0d5c6
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+BASEDIR=$(dirname ${0})
+${BASEDIR}/../../lib/test_fileutils >&-
diff --git a/testsuite/lib.test/fileutils_full.sh b/testsuite/lib.test/fileutils_full.sh
new file mode 100755 (executable)
index 0000000..0d96a0d
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+BASEDIR=$(dirname ${0})
+${BASEDIR}/../../lib/test_fileutils > /dev/full