summaryrefslogtreecommitdiff
path: root/goo
diff options
context:
space:
mode:
authorChristian Persch <chpe@src.gnome.org>2019-01-03 21:11:49 +0100
committerChristian Persch <chpe@src.gnome.org>2019-01-03 21:11:49 +0100
commitd5625de8ce3fc31608248fe14b12c4c7d1a43593 (patch)
tree0360c9f11b9f9e4655d3de321decc5feb56a4642 /goo
parent4a3eef323d72b06780c318f58917f884eecc812e (diff)
gfile: Open files with CLOEXEC flag set
First try to atomically open the file using O_CLOEXEC for open() and the "e" mode for fopen(), and if that doesn't work or O_CLOEXEC isn't defined, fall back to opening the file first and applying the FD_CLOEXEC flag afterwards.
Diffstat (limited to 'goo')
-rw-r--r--goo/gfile.cc47
1 files changed, 45 insertions, 2 deletions
diff --git a/goo/gfile.cc b/goo/gfile.cc
index c2973416..c33b580a 100644
--- a/goo/gfile.cc
+++ b/goo/gfile.cc
@@ -66,6 +66,8 @@
#ifndef _WIN32
+using namespace std::string_literals;
+
namespace {
template< typename... >
@@ -270,8 +272,33 @@ GooString *appendToPath(GooString *path, const char *fileName) {
#endif
}
+static bool makeFileDescriptorCloexec(int fd) {
+#ifdef FD_CLOEXEC
+ int flags = fcntl(fd, F_GETFD);
+ if (flags >= 0 && !(flags & FD_CLOEXEC))
+ flags = fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+
+ return flags >= 0;
+#else
+ return true;
+#endif
+}
+
int openFileDescriptor(const char *path, int flags) {
- return open(path, flags);
+#ifdef O_CLOEXEC
+ return open(path, flags | O_CLOEXEC);
+#else
+ int fd = open(path, flags);
+ if (fd == -1)
+ return fd;
+
+ if (!makeFileDescriptorCloexec(fd)) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+#endif
}
FILE *openFile(const char *path, const char *mode) {
@@ -333,7 +360,23 @@ FILE *openFile(const char *path, const char *mode) {
return fopen(nPath, mode);
}
#else
- return fopen(path, mode);
+ // First try to atomically open the file with CLOEXEC
+ const std::string modeStr = mode + "e"s;
+ FILE *file = fopen(path, modeStr.c_str());
+ if (file != nullptr)
+ return file;
+
+ // Fall back to the provided mode and apply CLOEXEC afterwards
+ file = fopen(path, mode);
+ if (file == nullptr)
+ return nullptr;
+
+ if (!makeFileDescriptorCloexec(fileno(file))) {
+ fclose(file);
+ return nullptr;
+ }
+
+ return file;
#endif
}