diff options
author | Junio C Hamano <gitster@pobox.com> | 2016-10-31 10:41:41 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-11-02 19:34:16 -0700 |
commit | 1e3001a8e2386a1433d1769a5a78007596bbc04d (patch) | |
tree | 96d4e4d5211721c894221b1bb53955a8660b603a /sha1_file.c | |
parent | 1b8ac5ead520146802debd52cb38e5c27b3483a2 (diff) | |
download | git-1e3001a8e2386a1433d1769a5a78007596bbc04d.tar.gz |
git_open_cloexec(): use fcntl(2) w/ FD_CLOEXEC fallback
A platform might not support open(2) with O_CLOEXEC but may support
telling the same with fcntl(2) to flip FD_CLOEXEC bit on on an open
file descriptor. It is a fallback that is inherently racy and this
may not be worth doing, though.
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'sha1_file.c')
-rw-r--r-- | sha1_file.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/sha1_file.c b/sha1_file.c index dfbf398183..64e1a21fc6 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1561,14 +1561,28 @@ int check_sha1_signature(const unsigned char *sha1, void *map, int git_open_cloexec(const char *name, int flags) { - static int cloexec = O_CLOEXEC; - int fd = open(name, flags | cloexec); + int fd; + static int o_cloexec = O_CLOEXEC; - if ((cloexec & O_CLOEXEC) && fd < 0 && errno == EINVAL) { + fd = open(name, flags | o_cloexec); + if ((o_cloexec & O_CLOEXEC) && fd < 0 && errno == EINVAL) { /* Try again w/o O_CLOEXEC: the kernel might not support it */ - cloexec &= ~O_CLOEXEC; - fd = open(name, flags | cloexec); + o_cloexec &= ~O_CLOEXEC; + fd = open(name, flags | o_cloexec); } + +#if defined(F_GETFL) && defined(F_SETFL) && defined(FD_CLOEXEC) + { + static int fd_cloexec = FD_CLOEXEC; + + if (!o_cloexec && 0 <= fd && fd_cloexec) { + /* Opened w/o O_CLOEXEC? try with fcntl(2) to add it */ + int flags = fcntl(fd, F_GETFL); + if (fcntl(fd, F_SETFL, flags | fd_cloexec)) + fd_cloexec = 0; + } + } +#endif return fd; } |