Hello! CentOS 5.11 (glibc 2.5) does not have utimensat function, so there is no nanosecond precision of file times available. Currently, the test fails with:
/tmp/cc36u3o7.o: In function `_D3std4file17__T8setTimesTAyaZ8setTimesFAyaS3std8datetime7systime7SysTimeS3std8datetime7systime7SysTimeZ16trustedUtimensatFNbNiNeiPxaKxG2S4core3sys5posix6signal8timespeciZi': /home/uros/git/gcc/libphobos/testsuite/../src/std/file.d:1272: undefined reference to `utimensat' collect2: error: ld returned 1 exit status compiler exited with status 1 Attached patch detects utimensat function during configure time and falls back to utimes in case utimensat is not available. 2019-05-08 Uroš Bizjak <ubiz...@gmail.com> PR d/90261 * m4/druntime/libraries.m4 (DRUNTIME_LIBRARIES_CLIB): Check for utimensat function. * configure: Regenerate * Makefile.in: Regenerate * libdruntime/gcc/config.d.in: Add Have_Utimensat. * libdruntime/Makefile.in: Regenerate. * libdruntime/core/sys/posix/sys/stat.d [version (CRuntime_Glibc)]: Declare utimensat and futimens only with Have_Utimensat. * src/Makefile.in: Regenerate. * src/std/file.d: Call testTimes with non-zero argument only when utimensat is defined. * testsuite/Makefile.in: Regenerate. BTW: The same fix as applied to CRuntime_Glibc can also be applied to FreeBSD version, which currently reads: // Since FreeBSD 11: version (none) { int utimensat(int dirfd, const char *pathname, ref const(timespec)[2] times, int flags); int futimens(int fd, ref const(timespec)[2] times); } BTW2: The testcase now fails in another place in src/std/file.d on CentOS 5.11 (and probably other non-modern systems): // Tests sub-second precision of querying file times. // Should pass on most modern systems running on modern filesystems. // Exceptions: // - FreeBSD, where one would need to first set the // vfs.timestamp_precision sysctl to a value greater than zero. // - OS X, where the native filesystem (HFS+) stores filesystem // timestamps with 1-second precision. This test should check the availability of utimensat on linux, otherwise the resolution is only in seconds range. Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32} with CentOS 5.11 and Fedora 30. Uros.
diff --git a/libphobos/Makefile.in b/libphobos/Makefile.in index 58368c92b492..de5c7d04fee3 100644 --- a/libphobos/Makefile.in +++ b/libphobos/Makefile.in @@ -215,6 +215,7 @@ DCFG_HAVE_64BIT_ATOMICS = @DCFG_HAVE_64BIT_ATOMICS@ DCFG_HAVE_ATOMIC_BUILTINS = @DCFG_HAVE_ATOMIC_BUILTINS@ DCFG_HAVE_LIBATOMIC = @DCFG_HAVE_LIBATOMIC@ DCFG_HAVE_QSORT_R = @DCFG_HAVE_QSORT_R@ +DCFG_HAVE_UTIMENSAT = @DCFG_HAVE_UTIMENSAT@ DCFG_MINFO_BRACKETING = @DCFG_MINFO_BRACKETING@ DCFG_THREAD_MODEL = @DCFG_THREAD_MODEL@ DEFS = @DEFS@ diff --git a/libphobos/configure b/libphobos/configure index 95a2b4232187..a33debdd97b0 100755 --- a/libphobos/configure +++ b/libphobos/configure @@ -651,6 +651,7 @@ LIBATOMIC DCFG_HAVE_LIBATOMIC DCFG_HAVE_64BIT_ATOMICS DCFG_HAVE_ATOMIC_BUILTINS +DCFG_HAVE_UTIMENSAT DCFG_HAVE_QSORT_R OS_LINK_SPEC DCFG_DLPI_TLS_MODID @@ -11635,7 +11636,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11638 "configure" +#line 11639 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11741,7 +11742,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11744 "configure" +#line 11745 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -14393,6 +14394,13 @@ if test "x$ac_cv_func_qsort_r" = xyes; then : fi + DCFG_HAVE_UTIMENSAT=false + ac_fn_c_check_func "$LINENO" "utimensat" "ac_cv_func_utimensat" +if test "x$ac_cv_func_utimensat" = xyes; then : + DCFG_HAVE_UTIMENSAT=true +fi + + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in index 19ee94fc370d..bdcc1979046f 100644 --- a/libphobos/libdruntime/Makefile.in +++ b/libphobos/libdruntime/Makefile.in @@ -547,6 +547,7 @@ DCFG_HAVE_64BIT_ATOMICS = @DCFG_HAVE_64BIT_ATOMICS@ DCFG_HAVE_ATOMIC_BUILTINS = @DCFG_HAVE_ATOMIC_BUILTINS@ DCFG_HAVE_LIBATOMIC = @DCFG_HAVE_LIBATOMIC@ DCFG_HAVE_QSORT_R = @DCFG_HAVE_QSORT_R@ +DCFG_HAVE_UTIMENSAT = @DCFG_HAVE_UTIMENSAT@ DCFG_MINFO_BRACKETING = @DCFG_MINFO_BRACKETING@ DCFG_THREAD_MODEL = @DCFG_THREAD_MODEL@ DEFS = @DEFS@ diff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d index 76e4460550df..9161912b8cb9 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/stat.d +++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d @@ -975,9 +975,14 @@ version (CRuntime_Glibc) enum UTIME_NOW = 0x3fffffff; enum UTIME_OMIT = 0x3ffffffe; - int utimensat(int dirfd, const char *pathname, - ref const(timespec)[2] times, int flags); - int futimens(int fd, ref const(timespec)[2] times); + // utimensat was added in glibc in 2.6. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90261 + import gcc.config : Have_Utimensat; + static if (Have_Utimensat) + { + int utimensat(int dirfd, const char *pathname, + ref const(timespec)[2] times, int flags); + int futimens(int fd, ref const(timespec)[2] times); + } } else version (Darwin) { diff --git a/libphobos/libdruntime/gcc/config.d.in b/libphobos/libdruntime/gcc/config.d.in index 9c58af0e4f65..0a3782ff2b47 100644 --- a/libphobos/libdruntime/gcc/config.d.in +++ b/libphobos/libdruntime/gcc/config.d.in @@ -49,3 +49,6 @@ enum GNU_Have_LibAtomic = @DCFG_HAVE_LIBATOMIC@; // Do we have qsort_r function enum Have_Qsort_R = @DCFG_HAVE_QSORT_R@; + +// Do we have utimensat function +enum Have_Utimensat = @DCFG_HAVE_UTIMENSAT@; diff --git a/libphobos/m4/druntime/libraries.m4 b/libphobos/m4/druntime/libraries.m4 index a7aab4dd88be..74f9f040cdf2 100644 --- a/libphobos/m4/druntime/libraries.m4 +++ b/libphobos/m4/druntime/libraries.m4 @@ -236,5 +236,8 @@ AC_DEFUN([DRUNTIME_LIBRARIES_CLIB], DCFG_HAVE_QSORT_R=false AC_CHECK_FUNC(qsort_r, [DCFG_HAVE_QSORT_R=true]) AC_SUBST(DCFG_HAVE_QSORT_R) + DCFG_HAVE_UTIMENSAT=false + AC_CHECK_FUNC(utimensat, [DCFG_HAVE_UTIMENSAT=true]) + AC_SUBST(DCFG_HAVE_UTIMENSAT) AC_LANG_POP([C]) ]) diff --git a/libphobos/src/Makefile.in b/libphobos/src/Makefile.in index 5a46cb9c4bde..27c1391f6103 100644 --- a/libphobos/src/Makefile.in +++ b/libphobos/src/Makefile.in @@ -286,6 +286,7 @@ DCFG_HAVE_64BIT_ATOMICS = @DCFG_HAVE_64BIT_ATOMICS@ DCFG_HAVE_ATOMIC_BUILTINS = @DCFG_HAVE_ATOMIC_BUILTINS@ DCFG_HAVE_LIBATOMIC = @DCFG_HAVE_LIBATOMIC@ DCFG_HAVE_QSORT_R = @DCFG_HAVE_QSORT_R@ +DCFG_HAVE_UTIMENSAT = @DCFG_HAVE_UTIMENSAT@ DCFG_MINFO_BRACKETING = @DCFG_MINFO_BRACKETING@ DCFG_THREAD_MODEL = @DCFG_THREAD_MODEL@ DEFS = @DEFS@ diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d index 9ba992944ebd..8c0c85da35ed 100644 --- a/libphobos/src/std/file.d +++ b/libphobos/src/std/file.d @@ -1344,7 +1344,7 @@ if (isConvertibleToString!R) } testTimes(0); - version (linux) + static if (is(typeof(&utimensat))) testTimes(123_456_7); rmdirRecurse(newdir); diff --git a/libphobos/testsuite/Makefile.in b/libphobos/testsuite/Makefile.in index efbd884d7ae7..735a36e426a4 100644 --- a/libphobos/testsuite/Makefile.in +++ b/libphobos/testsuite/Makefile.in @@ -159,6 +159,7 @@ DCFG_HAVE_64BIT_ATOMICS = @DCFG_HAVE_64BIT_ATOMICS@ DCFG_HAVE_ATOMIC_BUILTINS = @DCFG_HAVE_ATOMIC_BUILTINS@ DCFG_HAVE_LIBATOMIC = @DCFG_HAVE_LIBATOMIC@ DCFG_HAVE_QSORT_R = @DCFG_HAVE_QSORT_R@ +DCFG_HAVE_UTIMENSAT = @DCFG_HAVE_UTIMENSAT@ DCFG_MINFO_BRACKETING = @DCFG_MINFO_BRACKETING@ DCFG_THREAD_MODEL = @DCFG_THREAD_MODEL@ DEFS = @DEFS@