From 6eb539486f89e8f43bf48c92b1ceeaf4a72f0d84 Mon Sep 17 00:00:00 2001 From: Collin Funk Date: Mon, 17 Mar 2025 21:16:22 -0700 Subject: [PATCH] utimensat: Work around a GNU/Hurd bug. * lib/utimensat.c (rpl_utimensat) [__gnu_hurd__]: Check for out of range tv_nsec values. * m4/utimensat.m4 (gl_FUNC_UTIMENSAT): Likewise. Guess that utimensat doesn't work on GNU/Hurd. * doc/posix-functions/utimensat.texi: Mention the bug. --- ChangeLog | 9 ++++++++ doc/posix-functions/utimensat.texi | 3 ++- lib/utimensat.c | 9 +++++--- m4/utimensat.m4 | 34 ++++++++++++++++++++++++------ 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index fa88455eb5..e22981469f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2025-03-17 Collin Funk + + utimensat: Work around a GNU/Hurd bug. + * lib/utimensat.c (rpl_utimensat) [__gnu_hurd__]: Check for out of range + tv_nsec values. + * m4/utimensat.m4 (gl_FUNC_UTIMENSAT): Likewise. Guess that utimensat + doesn't work on GNU/Hurd. + * doc/posix-functions/utimensat.texi: Mention the bug. + 2025-03-13 Collin Funk vma-iter: Detect executable memory segments on Haiku (regr. 2011-01-25). diff --git a/doc/posix-functions/utimensat.texi b/doc/posix-functions/utimensat.texi index 41b30768ae..6547a80b6c 100644 --- a/doc/posix-functions/utimensat.texi +++ b/doc/posix-functions/utimensat.texi @@ -35,7 +35,8 @@ Linux kernel 2.6.32, macOS 14, NetBSD 10.0, Solaris 11.1. @item Out-of-range values of @code{tv_nsec} do not lead to a failure on some platforms: -Linux kernel 2.6.22.19 on hppa, NetBSD 10.0. +@c https://sourceware.org/bugzilla/show_bug.cgi?id=32802 +Linux kernel 2.6.22.19 on hppa, NetBSD 10.0, GNU/Hurd. @item On some platforms, this function mis-handles a trailing slash: AIX 7.2. diff --git a/lib/utimensat.c b/lib/utimensat.c index b44207b4be..ca1d39e590 100644 --- a/lib/utimensat.c +++ b/lib/utimensat.c @@ -1,5 +1,5 @@ /* Set the access and modification time of a file relative to directory fd. - Copyright (C) 2009-2024 Free Software Foundation, Inc. + Copyright (C) 2009-2025 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -136,8 +136,9 @@ rpl_utimensat (int fd, char const *file, struct timespec const times[2], } # endif # endif -# if defined __APPLE__ && defined __MACH__ - /* macOS 10.13 does not reject invalid tv_nsec values either. */ +# if (defined __APPLE__ && defined __MACH__) || defined __gnu_hurd__ + /* macOS 10.13 and GNU Hurd do not reject invalid tv_nsec values + either. */ if (times && ((times[0].tv_nsec != UTIME_OMIT && times[0].tv_nsec != UTIME_NOW @@ -151,6 +152,7 @@ rpl_utimensat (int fd, char const *file, struct timespec const times[2], errno = EINVAL; return -1; } +# if defined __APPLE__ && defined __MACH__ size_t len = strlen (file); if (len > 0 && file[len - 1] == '/') { @@ -163,6 +165,7 @@ rpl_utimensat (int fd, char const *file, struct timespec const times[2], return -1; } } +# endif # endif result = utimensat (fd, file, times, flag); /* Linux kernel 2.6.25 has a bug where it returns EINVAL for diff --git a/m4/utimensat.m4 b/m4/utimensat.m4 index a583f37668..ec7fde7bb2 100644 --- a/m4/utimensat.m4 +++ b/m4/utimensat.m4 @@ -1,6 +1,6 @@ # utimensat.m4 -# serial 12 -dnl Copyright (C) 2009-2024 Free Software Foundation, Inc. +# 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. @@ -66,11 +66,30 @@ AC_DEFUN([gl_FUNC_UTIMENSAT], ts[1].tv_sec = 1; ts[1].tv_nsec = UTIME_OMIT; if (utimensat (AT_FDCWD, f, ts, 0)) - result |= 16; + result |= 8; if (stat (f, &st)) - result |= 32; + result |= 8; else if (st.st_ctime < st.st_atime) - result |= 64; + 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; ]])], @@ -82,8 +101,11 @@ AC_DEFUN([gl_FUNC_UTIMENSAT], ], [case "$host_os" in # Guess yes on Linux or glibc systems. - linux-* | linux | *-gnu* | gnu*) + 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" ;; -- 2.39.5