object-file: move `git_open_cloexec()` to "compat/open.c"

The `git_open_cloexec()` wrapper function provides the ability to open a file with `O_CLOEXEC` in a platform-agnostic way. This function is provided by "object-file.c" even though it is not specific to the object subsystem at all. Move the file into "compat/open.c". This file already exists before this commit, but has only been compiled conditionally depending on whether or not open(3p) may return EINTR. With this change we now unconditionally compile the object, but wrap `git_open_with_retry()` in an ifdef. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Apr 15, 2025 at 11:38 UTC 97dc141fd676e7079c2fd51e3bea2681a5b9f824
11 files changed +34 -36
Makefile
+1 -1
@@ -994,6 +994,7 @@ LIB_OBJS += common-exit.o
994 LIB_OBJS += common-init.o
995 LIB_OBJS += compat/nonblock.o
996 LIB_OBJS += compat/obstack.o
997 +LIB_OBJS += compat/open.o
998 LIB_OBJS += compat/terminal.o
999 LIB_OBJS += compiler-tricks/not-constant.o
1000 LIB_OBJS += config.o
@@ -1812,7 +1813,6 @@ ifdef FREAD_READS_DIRECTORIES
1813 endif
1814 ifdef OPEN_RETURNS_EINTR
1815 COMPAT_CFLAGS += -DOPEN_RETURNS_EINTR
1815 - COMPAT_OBJS += compat/open.o
1816 endif
1817 ifdef NO_SYMLINK_HEAD
1818 BASIC_CFLAGS += -DNO_SYMLINK_HEAD
commit-graph.c
-1
@@ -13,7 +13,6 @@
13 #include "refs.h"
14 #include "hash-lookup.h"
15 #include "commit-graph.h"
16 -#include "object-file.h"
16 #include "object-store-ll.h"
17 #include "oid-array.h"
18 #include "path.h"
compat/open.c
+29
@@ -1,5 +1,6 @@
1 #include "git-compat-util.h"
2
3 +#ifdef OPEN_RETURNS_EINTR
4 #undef open
5 int git_open_with_retry(const char *path, int flags, ...)
6 {
@@ -23,3 +24,31 @@ int git_open_with_retry(const char *path, int flags, ...)
24
25 return ret;
26 }
27 +#endif
28 +
29 +int git_open_cloexec(const char *name, int flags)
30 +{
31 + int fd;
32 + static int o_cloexec = O_CLOEXEC;
33 +
34 + fd = open(name, flags | o_cloexec);
35 + if ((o_cloexec & O_CLOEXEC) && fd < 0 && errno == EINVAL) {
36 + /* Try again w/o O_CLOEXEC: the kernel might not support it */
37 + o_cloexec &= ~O_CLOEXEC;
38 + fd = open(name, flags | o_cloexec);
39 + }
40 +
41 +#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
42 + {
43 + static int fd_cloexec = FD_CLOEXEC;
44 +
45 + if (!o_cloexec && 0 <= fd && fd_cloexec) {
46 + /* Opened w/o O_CLOEXEC? try with fcntl(2) to add it */
47 + int flags = fcntl(fd, F_GETFD);
48 + if (fcntl(fd, F_SETFD, flags | fd_cloexec))
49 + fd_cloexec = 0;
50 + }
51 + }
52 +#endif
53 + return fd;
54 +}
git-compat-util.h
+3
@@ -1000,6 +1000,9 @@ int git_vsnprintf(char *str, size_t maxsize,
1000 int git_open_with_retry(const char *path, int flag, ...);
1001 #endif
1002
1003 +int git_open_cloexec(const char *name, int flags);
1004 +#define git_open(name) git_open_cloexec(name, O_RDONLY)
1005 +
1006 #ifdef __GLIBC_PREREQ
1007 #if __GLIBC_PREREQ(2, 1)
1008 #define HAVE_STRCHRNUL
meson.build
+1
@@ -263,6 +263,7 @@ libgit_sources = [
263 'common-init.c',
264 'compat/nonblock.c',
265 'compat/obstack.c',
266 + 'compat/open.c',
267 'compat/terminal.c',
268 'compiler-tricks/not-constant.c',
269 'config.c',
midx.c
-1
@@ -5,7 +5,6 @@
5 #include "dir.h"
6 #include "hex.h"
7 #include "packfile.h"
8 -#include "object-file.h"
8 #include "hash-lookup.h"
9 #include "midx.h"
10 #include "progress.h"
object-file.c
-27
@@ -833,33 +833,6 @@ int stream_object_signature(struct repository *r, const struct object_id *oid)
833 return !oideq(oid, &real_oid) ? -1 : 0;
834 }
835
836 -int git_open_cloexec(const char *name, int flags)
837 -{
838 - int fd;
839 - static int o_cloexec = O_CLOEXEC;
840 -
841 - fd = open(name, flags | o_cloexec);
842 - if ((o_cloexec & O_CLOEXEC) && fd < 0 && errno == EINVAL) {
843 - /* Try again w/o O_CLOEXEC: the kernel might not support it */
844 - o_cloexec &= ~O_CLOEXEC;
845 - fd = open(name, flags | o_cloexec);
846 - }
847 -
848 -#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
849 - {
850 - static int fd_cloexec = FD_CLOEXEC;
851 -
852 - if (!o_cloexec && 0 <= fd && fd_cloexec) {
853 - /* Opened w/o O_CLOEXEC? try with fcntl(2) to add it */
854 - int flags = fcntl(fd, F_GETFD);
855 - if (fcntl(fd, F_SETFD, flags | fd_cloexec))
856 - fd_cloexec = 0;
857 - }
858 - }
859 -#endif
860 - return fd;
861 -}
862 -
836 /*
837 * Find "oid" as a loose object in the local repository or in an alternate.
838 * Returns 0 on success, negative on failure.
object-file.h
-3
@@ -21,9 +21,6 @@ extern int fetch_if_missing;
21 int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
22 int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
23
24 -int git_open_cloexec(const char *name, int flags);
25 -#define git_open(name) git_open_cloexec(name, O_RDONLY)
26 -
24 /**
25 * unpack_loose_header() initializes the data stream needed to unpack
26 * a loose object header.
pack-bitmap.c
-1
@@ -17,7 +17,6 @@
17 #include "packfile.h"
18 #include "repository.h"
19 #include "trace2.h"
20 -#include "object-file.h"
20 #include "object-store-ll.h"
21 #include "list-objects-filter-options.h"
22 #include "midx.h"
pack-mtimes.c
-1
@@ -1,7 +1,6 @@
1 #include "git-compat-util.h"
2 #include "gettext.h"
3 #include "pack-mtimes.h"
4 -#include "object-file.h"
4 #include "object-store-ll.h"
5 #include "packfile.h"
6 #include "strbuf.h"
pack-revindex.c
-1
@@ -1,7 +1,6 @@
1 #include "git-compat-util.h"
2 #include "gettext.h"
3 #include "pack-revindex.h"
4 -#include "object-file.h"
4 #include "object-store-ll.h"
5 #include "packfile.h"
6 #include "strbuf.h"