зеркало из https://github.com/github/ruby.git
Check availability of `utimensat` on macOS
This commit is contained in:
Родитель
6ba52647c3
Коммит
b6b9a6190d
45
file.c
45
file.c
|
@ -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,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;
|
||||
|
||||
|
@ -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;
|
||||
# endif
|
||||
if (!v->follow)
|
||||
try_utimensat = 0;
|
||||
goto no_utimensat;
|
||||
}
|
||||
return -1; /* calls utime_failed */
|
||||
}
|
||||
return 0;
|
||||
else
|
||||
# endif
|
||||
return result;
|
||||
}
|
||||
# ifdef TRY_UTIMENSAT
|
||||
no_utimensat:
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if (tsp) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче