зеркало из https://github.com/github/ruby.git
Check availability of `utimensat` on macOS
This commit is contained in:
Родитель
6ba52647c3
Коммит
b6b9a6190d
51
file.c
51
file.c
|
@ -2833,6 +2833,31 @@ utime_failed(struct apply_arg *aa)
|
||||||
|
|
||||||
#if defined(HAVE_UTIMES)
|
#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
|
static int
|
||||||
utime_internal(const char *path, void *arg)
|
utime_internal(const char *path, void *arg)
|
||||||
{
|
{
|
||||||
|
@ -2841,11 +2866,17 @@ utime_internal(const char *path, void *arg)
|
||||||
struct timeval tvbuf[2], *tvp = NULL;
|
struct timeval tvbuf[2], *tvp = NULL;
|
||||||
|
|
||||||
#if defined(HAVE_UTIMENSAT)
|
#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;
|
static int try_utimensat = 1;
|
||||||
# ifdef AT_SYMLINK_NOFOLLOW
|
# ifdef AT_SYMLINK_NOFOLLOW
|
||||||
static int try_utimensat_follow = 1;
|
static int try_utimensat_follow = 1;
|
||||||
# else
|
# else
|
||||||
const int try_utimensat_follow = 0;
|
const int try_utimensat_follow = 0;
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
|
@ -2856,20 +2887,22 @@ utime_internal(const char *path, void *arg)
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
if (utimensat(AT_FDCWD, path, tsp, flags) < 0) {
|
int result = utimensat(AT_FDCWD, path, tsp, flags);
|
||||||
if (errno == ENOSYS) {
|
# ifdef TRY_UTIMENSAT
|
||||||
|
if (result < 0 && errno == ENOSYS) {
|
||||||
# ifdef AT_SYMLINK_NOFOLLOW
|
# ifdef AT_SYMLINK_NOFOLLOW
|
||||||
try_utimensat_follow = 0;
|
try_utimensat_follow = 0;
|
||||||
# endif
|
# endif
|
||||||
if (!v->follow)
|
if (!v->follow)
|
||||||
try_utimensat = 0;
|
try_utimensat = 0;
|
||||||
goto no_utimensat;
|
|
||||||
}
|
|
||||||
return -1; /* calls utime_failed */
|
|
||||||
}
|
}
|
||||||
return 0;
|
else
|
||||||
|
# endif
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
# ifdef TRY_UTIMENSAT
|
||||||
no_utimensat:
|
no_utimensat:
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (tsp) {
|
if (tsp) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче