Branch
Hash :
579debda
Author :
Date :
2025-03-18T18:12:39
utimensat: Make sure exit status in configure check doesn't exceed 127. Reported by Bruno Haible in <https://lists.gnu.org/archive/html/bug-gnulib/2025-03/msg00061.html>. * m4/utimensat.m4 (gl_FUNC_UTIMENSAT): Merge bits for tests to match expectations on current platforms.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
# utimensat.m4
# serial 14
dnl Copyright (C) 2009-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl This file is offered as-is, without any warranty.
# See if we need to provide utimensat replacement.
# Written by Eric Blake.
AC_DEFUN([gl_FUNC_UTIMENSAT],
[
AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
gl_CHECK_FUNCS_ANDROID([utimensat], [[#include <sys/stat.h>]])
if test $ac_cv_func_utimensat = no; then
HAVE_UTIMENSAT=0
case "$gl_cv_onwards_func_utimensat" in
future*) REPLACE_UTIMENSAT=1 ;;
esac
else
AC_CACHE_CHECK([whether utimensat works],
[gl_cv_func_utimensat_works],
[AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
]GL_MDA_DEFINES],
[[int result = 0;
const char *f = "conftest.file";
if (close (creat (f, 0600)))
return 1;
/* Test whether a trailing slash is handled correctly.
This fails on AIX 7.2. */
{
struct timespec ts[2];
ts[0].tv_sec = 345183300; ts[0].tv_nsec = 0;
ts[1] = ts[0];
if (utimensat (AT_FDCWD, "conftest.file/", ts, 0) == 0)
result |= 2;
}
/* Test whether the AT_SYMLINK_NOFOLLOW flag is supported. */
{
if (utimensat (AT_FDCWD, f, NULL, AT_SYMLINK_NOFOLLOW))
result |= 4;
}
/* Test whether UTIME_NOW and UTIME_OMIT work. */
{
struct timespec ts[2];
ts[0].tv_sec = 1;
ts[0].tv_nsec = UTIME_OMIT;
ts[1].tv_sec = 1;
ts[1].tv_nsec = UTIME_NOW;
if (utimensat (AT_FDCWD, f, ts, 0))
result |= 8;
}
sleep (1);
{
struct stat st;
struct timespec ts[2];
ts[0].tv_sec = 1;
ts[0].tv_nsec = UTIME_NOW;
ts[1].tv_sec = 1;
ts[1].tv_nsec = UTIME_OMIT;
if (utimensat (AT_FDCWD, f, ts, 0))
result |= 8;
if (stat (f, &st))
result |= 8;
else if (st.st_ctime < st.st_atime)
result |= 16;
}
enum
{
BILLION = 1000 * 1000 * 1000,
/* Bogus positive and negative tv_nsec values closest to valid
range, but without colliding with UTIME_NOW or UTIME_OMIT. */
UTIME_BOGUS_POS = BILLION + ((UTIME_NOW == BILLION || UTIME_OMIT == BILLION)
? (1 + (UTIME_NOW == BILLION + 1)
+ (UTIME_OMIT == BILLION + 1))
: 0)
};
{
struct timespec ts[2];
ts[0].tv_sec = 1;
ts[0].tv_nsec = UTIME_BOGUS_POS;
ts[1].tv_sec = 1;
ts[1].tv_nsec = 0;
if (utimensat (AT_FDCWD, f, ts, 0) == 0)
result |= 32;
}
return result;
]])],
[gl_cv_func_utimensat_works=yes],
[case $? in
2) gl_cv_func_utimensat_works='nearly' ;;
*) gl_cv_func_utimensat_works=no ;;
esac
],
[case "$host_os" in
# Guess yes on Linux or glibc systems.
linux*)
gl_cv_func_utimensat_works="guessing yes" ;;
# Guess no on GNU/Hurd.
gnu*)
gl_cv_func_utimensat_works="guessing no" ;;
# Guess yes on systems that emulate the Linux system calls.
midipix*)
gl_cv_func_utimensat_works="guessing yes" ;;
# Guess 'nearly' on AIX.
aix*)
gl_cv_func_utimensat_works="guessing nearly" ;;
# If we don't know, obey --enable-cross-guesses.
*)
gl_cv_func_utimensat_works="$gl_cross_guess_normal" ;;
esac
])
])
case "$gl_cv_func_utimensat_works" in
*yes)
;;
*nearly)
AC_DEFINE([HAVE_NEARLY_WORKING_UTIMENSAT], [1],
[Define to 1 if utimensat works, except for the trailing slash handling.])
REPLACE_UTIMENSAT=1
;;
*)
REPLACE_UTIMENSAT=1
;;
esac
fi
])