Skip to content

Commit

Permalink
Check availability of utimensat on macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
nobu committed Jun 27, 2022
1 parent 6ba5264 commit b6b9a61
Showing 1 changed file with 42 additions and 9 deletions.
51 changes: 42 additions & 9 deletions file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -2841,11 +2866,17 @@ 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;

Expand All @@ -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) {
Expand Down

0 comments on commit b6b9a61

Please sign in to comment.