Skip to content

Commit 2f17ecb

Browse files
committed
Merge branch 'dm/compat-s-ifmt-for-zos'
Long overdue departure from the assumption that S_IFMT is shared by everybody made in 2005. * dm/compat-s-ifmt-for-zos: compat: convert modes to use portable file type values
2 parents 0b5ae7b + d543d9c commit 2f17ecb

File tree

5 files changed

+113
-7
lines changed

5 files changed

+113
-7
lines changed

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ all::
191191
# Define NO_TRUSTABLE_FILEMODE if your filesystem may claim to support
192192
# the executable mode bit, but doesn't really do so.
193193
#
194+
# Define NEEDS_MODE_TRANSLATION if your OS strays from the typical file type
195+
# bits in mode values (e.g. z/OS defines I_SFMT to 0xFF000000 as opposed to the
196+
# usual 0xF000).
197+
#
194198
# Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
195199
#
196200
# Define NO_UNIX_SOCKETS if your system does not offer unix sockets.
@@ -1230,6 +1234,10 @@ endif
12301234
ifdef NO_TRUSTABLE_FILEMODE
12311235
BASIC_CFLAGS += -DNO_TRUSTABLE_FILEMODE
12321236
endif
1237+
ifdef NEEDS_MODE_TRANSLATION
1238+
COMPAT_CFLAGS += -DNEEDS_MODE_TRANSLATION
1239+
COMPAT_OBJS += compat/stat.o
1240+
endif
12331241
ifdef NO_IPV6
12341242
BASIC_CFLAGS += -DNO_IPV6
12351243
endif

cache.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,6 @@ unsigned long git_deflate_bound(git_zstream *, unsigned long);
6565
*
6666
* The value 0160000 is not normally a valid mode, and
6767
* also just happens to be S_IFDIR + S_IFLNK
68-
*
69-
* NOTE! We *really* shouldn't depend on the S_IFxxx macros
70-
* always having the same values everywhere. We should use
71-
* our internal git values for these things, and then we can
72-
* translate that to the OS-specific value. It just so
73-
* happens that everybody shares the same bit representation
74-
* in the UNIX world (and apparently wider too..)
7568
*/
7669
#define S_IFGITLINK 0160000
7770
#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK)

compat/stat.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#define _POSIX_C_SOURCE 200112L
2+
#include <sys/stat.h> /* *stat, S_IS* */
3+
#include <sys/types.h> /* mode_t */
4+
5+
static inline mode_t mode_native_to_git(mode_t native_mode)
6+
{
7+
mode_t perm_bits = native_mode & 07777;
8+
if (S_ISREG(native_mode))
9+
return 0100000 | perm_bits;
10+
if (S_ISDIR(native_mode))
11+
return 0040000 | perm_bits;
12+
if (S_ISLNK(native_mode))
13+
return 0120000 | perm_bits;
14+
if (S_ISBLK(native_mode))
15+
return 0060000 | perm_bits;
16+
if (S_ISCHR(native_mode))
17+
return 0020000 | perm_bits;
18+
if (S_ISFIFO(native_mode))
19+
return 0010000 | perm_bits;
20+
if (S_ISSOCK(native_mode))
21+
return 0140000 | perm_bits;
22+
/* Non-standard type bits were given. */
23+
return perm_bits;
24+
}
25+
26+
int git_stat(const char *path, struct stat *buf)
27+
{
28+
int rc = stat(path, buf);
29+
if (rc == 0)
30+
buf->st_mode = mode_native_to_git(buf->st_mode);
31+
return rc;
32+
}
33+
34+
int git_fstat(int fd, struct stat *buf)
35+
{
36+
int rc = fstat(fd, buf);
37+
if (rc == 0)
38+
buf->st_mode = mode_native_to_git(buf->st_mode);
39+
return rc;
40+
}
41+
42+
int git_lstat(const char *path, struct stat *buf)
43+
{
44+
int rc = lstat(path, buf);
45+
if (rc == 0)
46+
buf->st_mode = mode_native_to_git(buf->st_mode);
47+
return rc;
48+
}

configure.ac

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,29 @@ else
873873
SNPRINTF_RETURNS_BOGUS=
874874
fi
875875
GIT_CONF_SUBST([SNPRINTF_RETURNS_BOGUS])
876+
#
877+
# Define NEEDS_MODE_TRANSLATION if your OS strays from the typical file type
878+
# bits in mode values.
879+
AC_CACHE_CHECK([whether the platform uses typical file type bits],
880+
[ac_cv_sane_mode_bits], [
881+
AC_EGREP_CPP(yippeeyeswehaveit,
882+
AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
883+
[#if S_IFMT == 0170000 && \
884+
S_IFREG == 0100000 && S_IFDIR == 0040000 && S_IFLNK == 0120000 && \
885+
S_IFBLK == 0060000 && S_IFCHR == 0020000 && \
886+
S_IFIFO == 0010000 && S_IFSOCK == 0140000
887+
yippeeyeswehaveit
888+
#endif
889+
]),
890+
[ac_cv_sane_mode_bits=yes],
891+
[ac_cv_sane_mode_bits=no])
892+
])
893+
if test $ac_cv_sane_mode_bits = yes; then
894+
NEEDS_MODE_TRANSLATION=
895+
else
896+
NEEDS_MODE_TRANSLATION=UnfortunatelyYes
897+
fi
898+
GIT_CONF_SUBST([NEEDS_MODE_TRANSLATION])
876899

877900

878901
## Checks for library functions.

git-compat-util.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,40 @@ extern int git_munmap(void *start, size_t length);
475475
#define on_disk_bytes(st) ((st).st_blocks * 512)
476476
#endif
477477

478+
#ifdef NEEDS_MODE_TRANSLATION
479+
#undef S_IFMT
480+
#undef S_IFREG
481+
#undef S_IFDIR
482+
#undef S_IFLNK
483+
#undef S_IFBLK
484+
#undef S_IFCHR
485+
#undef S_IFIFO
486+
#undef S_IFSOCK
487+
#define S_IFMT 0170000
488+
#define S_IFREG 0100000
489+
#define S_IFDIR 0040000
490+
#define S_IFLNK 0120000
491+
#define S_IFBLK 0060000
492+
#define S_IFCHR 0020000
493+
#define S_IFIFO 0010000
494+
#define S_IFSOCK 0140000
495+
#ifdef stat
496+
#undef stat
497+
#endif
498+
#define stat(path, buf) git_stat(path, buf)
499+
extern int git_stat(const char *, struct stat *);
500+
#ifdef fstat
501+
#undef fstat
502+
#endif
503+
#define fstat(fd, buf) git_fstat(fd, buf)
504+
extern int git_fstat(int, struct stat *);
505+
#ifdef lstat
506+
#undef lstat
507+
#endif
508+
#define lstat(path, buf) git_lstat(path, buf)
509+
extern int git_lstat(const char *, struct stat *);
510+
#endif
511+
478512
#define DEFAULT_PACKED_GIT_LIMIT \
479513
((1024L * 1024L) * (sizeof(void*) >= 8 ? 8192 : 256))
480514

0 commit comments

Comments
 (0)