Browse Source

Add fclose_noerr()

Rusty Russell 17 years ago
parent
commit
b2def1c863
3 changed files with 39 additions and 1 deletions
  1. 13 0
      ccan/noerr/noerr.c
  2. 10 0
      ccan/noerr/noerr.h
  3. 16 1
      ccan/noerr/test/run.c

+ 13 - 0
ccan/noerr/noerr.c

@@ -15,6 +15,19 @@ int close_noerr(int fd)
 	return ret;
 }
 
+int fclose_noerr(FILE *fp)
+{
+	int saved_errno = errno, ret;
+
+	if (fclose(fp) != 0)
+		ret = errno;
+	else
+		ret = 0;
+
+	errno = saved_errno;
+	return ret;
+}
+
 int unlink_noerr(const char *pathname)
 {
 	int saved_errno = errno, ret;

+ 10 - 0
ccan/noerr/noerr.h

@@ -1,5 +1,6 @@
 #ifndef NOERR_H
 #define NOERR_H
+#include <stdio.h>
 
 /**
  * close_noerr - close without stomping errno.
@@ -10,6 +11,15 @@
  */
 int close_noerr(int fd);
 
+/**
+ * fclose_noerr - close without stomping errno.
+ * @fp: the FILE pointer.
+ *
+ * errno is saved and restored across the call to fclose: if an error occurs,
+ * the resulting (non-zero) errno is returned.
+ */
+int fclose_noerr(FILE *fp);
+
 /**
  * unlink_noerr - unlink a file without stomping errno.
  * @pathname: the path to unlink.

+ 16 - 1
ccan/noerr/test/run.c

@@ -12,8 +12,9 @@ int main(int argc, char *argv[])
 	/* tempnam(3) is generally a bad idea, but OK here. */
 	char *name = tempnam(NULL, "noerr");
 	int fd;
+	FILE *fp;
 
-	plan_tests(12);
+	plan_tests(15);
 	/* Should fail to unlink. */
 	ok1(unlink(name) != 0);
 	ok1(errno == ENOENT);
@@ -44,5 +45,19 @@ int main(int argc, char *argv[])
 	ok1(unlink_noerr(name) == 0);
 	ok1(errno == 100);
 
+	/* Test failing fclose */
+	fp = fopen(name, "wb");
+	assert(fp);
+	close(fileno(fp));
+	ok1(fclose_noerr(fp) == EBADF);
+
+	/* Test successful fclose */
+	fp = fopen(name, "wb");
+	assert(fp);
+
+	errno = 100;
+	ok1(fclose_noerr(fp) == 0);
+	ok1(errno == 100);
+
 	return exit_status();
 }