summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ccan/noerr/noerr.c13
-rw-r--r--ccan/noerr/noerr.h10
-rw-r--r--ccan/noerr/test/run.c17
3 files changed, 39 insertions, 1 deletions
diff --git a/ccan/noerr/noerr.c b/ccan/noerr/noerr.c
index d6df81f7..439ac7e8 100644
--- a/ccan/noerr/noerr.c
+++ b/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;
diff --git a/ccan/noerr/noerr.h b/ccan/noerr/noerr.h
index 559ba613..191b3d3c 100644
--- a/ccan/noerr/noerr.h
+++ b/ccan/noerr/noerr.h
@@ -1,5 +1,6 @@
#ifndef NOERR_H
#define NOERR_H
+#include <stdio.h>
/**
* close_noerr - close without stomping errno.
@@ -11,6 +12,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.
*
diff --git a/ccan/noerr/test/run.c b/ccan/noerr/test/run.c
index 6d3c6837..6f1361ce 100644
--- a/ccan/noerr/test/run.c
+++ b/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();
}