diff options
author | Nobuyoshi Nakada <[email protected]> | 2022-06-27 13:17:36 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <[email protected]> | 2022-06-27 17:52:13 +0900 |
commit | b6b9a6190def53aa53ac816a51034fa1c96ed70b (patch) | |
tree | 42512ff6c911c0f54a89200662c75d76010764e3 /file.c | |
parent | 6ba52647c3d2b3a0060e0b0edc95f46c77a11944 (diff) |
Check availability of `utimensat` on macOS
Diffstat (limited to 'file.c')
-rw-r--r-- | file.c | 51 |
1 files changed, 42 insertions, 9 deletions
@@ -2833,6 +2833,31 @@ utime_failed(struct apply_arg *aa) #if defined(HAVE_UTIMES) +# if defined(__APPLE__) && \ + (!defined(MAC_OS_X_VERSION_13_0) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_13_0)) + +# if defined(__has_attribute) && __has_attribute(availability) +typedef int utimensat_func(int, const char *, const struct timespec [2], int); + +RBIMPL_WARNING_PUSH(); +RBIMPL_WARNING_IGNORED(-Wunguarded-availability-new); +static inline utimensat_func * +rb_utimensat(void) +{ + return &utimensat; +} +RBIMPL_WARNING_POP(); + +# define utimensat rb_utimensat() +# else /* __API_AVAILABLE macro does nothing on gcc */ +__attribute__((weak)) int utimensat(int, const char *, const struct timespec [2], int); +# endif + +# define utimensat_available_p() (utimensat != NULL) +# else +# define utimensat_available_p() 1 +# endif + static int utime_internal(const char *path, void *arg) { @@ -2841,12 +2866,18 @@ utime_internal(const char *path, void *arg) struct timeval tvbuf[2], *tvp = NULL; #if defined(HAVE_UTIMENSAT) +# if defined(__APPLE__) + const int try_utimensat = utimensat != NULL; + const int try_utimensat_follow = utimensat != NULL; +# else +# define TRY_UTIMENSAT 1 static int try_utimensat = 1; # ifdef AT_SYMLINK_NOFOLLOW static int try_utimensat_follow = 1; # else const int try_utimensat_follow = 0; # endif +# endif int flags = 0; if (v->follow ? try_utimensat_follow : try_utimensat) { @@ -2856,20 +2887,22 @@ utime_internal(const char *path, void *arg) } # endif - if (utimensat(AT_FDCWD, path, tsp, flags) < 0) { - if (errno == ENOSYS) { + int result = utimensat(AT_FDCWD, path, tsp, flags); +# ifdef TRY_UTIMENSAT + if (result < 0 && errno == ENOSYS) { # ifdef AT_SYMLINK_NOFOLLOW - try_utimensat_follow = 0; + try_utimensat_follow = 0; # endif - if (!v->follow) - try_utimensat = 0; - goto no_utimensat; - } - return -1; /* calls utime_failed */ + if (!v->follow) + try_utimensat = 0; } - return 0; + else +# endif + return result; } +# ifdef TRY_UTIMENSAT no_utimensat: +# endif #endif if (tsp) { |