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@

Reply via email to