Upcoming patches will be setting FD_CLOEXEC and/or O_NONBLOCK on more
files; the correct way to do this requires a read-modify-write, which
is enough lines of code to be worth a helper function. I chose the
semantics of close()ing the fd on (unlikely) failure, on the grounds
that these functions will likely be used only immediately after the fd
is created.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
common/utils/utils.h | 2 ++
common/utils/utils.c | 46 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 48 insertions(+)
diff --git a/common/utils/utils.h b/common/utils/utils.h
index 3f10cdc0..ebd5f66b 100644
--- a/common/utils/utils.h
+++ b/common/utils/utils.h
@@ -36,5 +36,7 @@
extern void shell_quote (const char *str, FILE *fp);
extern void uri_quote (const char *str, FILE *fp);
extern int exit_status_to_nbd_error (int status, const char *cmd);
+extern int set_cloexec (int fd);
+extern int set_nonblock (int fd);
#endif /* NBDKIT_UTILS_H */
diff --git a/common/utils/utils.c b/common/utils/utils.c
index 7534a13d..37c81871 100644
--- a/common/utils/utils.c
+++ b/common/utils/utils.c
@@ -32,11 +32,13 @@
#include <config.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <unistd.h>
#include <nbdkit-plugin.h>
@@ -126,3 +128,47 @@ exit_status_to_nbd_error (int status, const char *cmd)
return 0;
}
+
+/* Set the FD_CLOEXEC flag on the given fd, if it is non-negative.
+ * On failure, close fd and return -1; on success, return fd.
+ */
+int
+set_cloexec (int fd) {
+ int f;
+ int err;
+
+ if (fd == -1)
+ return -1;
+
+ f = fcntl (fd, F_GETFD);
+ if (f == -1 || fcntl (fd, F_SETFD, f | FD_CLOEXEC) == -1) {
+ err = errno;
+ nbdkit_error ("fcntl: %m");
+ close (fd);
+ errno = err;
+ return -1;
+ }
+ return fd;
+}
+
+/* Set the O_NONBLOCK flag on the given fd, if it is non-negative.
+ * On failure, close fd and return -1; on success, return fd.
+ */
+int
+set_nonblock (int fd) {
+ int f;
+ int err;
+
+ if (fd == -1)
+ return -1;
+
+ f = fcntl (fd, F_GETFL);
+ if (f == -1 || fcntl (fd, F_SETFL, f | O_NONBLOCK) == -1) {
+ err = errno;
+ nbdkit_error ("fcntl: %m");
+ close (fd);
+ errno = err;
+ return -1;
+ }
+ return fd;
+}
--
2.20.1