diff options
author | Christian Persch <chpe@src.gnome.org> | 2019-01-03 21:11:49 +0100 |
---|---|---|
committer | Christian Persch <chpe@src.gnome.org> | 2019-01-03 21:11:49 +0100 |
commit | d5625de8ce3fc31608248fe14b12c4c7d1a43593 (patch) | |
tree | 0360c9f11b9f9e4655d3de321decc5feb56a4642 /goo | |
parent | 4a3eef323d72b06780c318f58917f884eecc812e (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.cc | 47 |
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 } |