bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: utime on macOS


From: Bruno Haible
Subject: Re: utime on macOS
Date: Sat, 05 Dec 2020 00:24:00 +0100
User-agent: KMail/5.1.3 (Linux/4.4.0-193-generic; KDE/5.18.0; x86_64; ; )

Martin Storsjö wrote:
> FAIL: test-utime

When I add an autoconf test for the trailing slash handling in utime(), I get:
  checking whether utime handles trailing slashes on files... no
along with
  checking whether lstat correctly handles trailing slash... no
  checking whether stat handles trailing slashes on files... no
  checking whether open recognizes a trailing slash... no
  checking whether symlink handles trailing slash correctly... no

This patch fixes it. Since utime() has side effects, we have to check for
the trailing slash before invoking utime().


2020-12-04  Bruno Haible  <bruno@clisp.org>

        utime: Fix a test failure on macOS 10.13.
        Reported by Martin Storsjö <martin@martin.st> in
        <https://lists.gnu.org/archive/html/bug-gnulib/2020-12/msg00003.html>.
        * m4/utime.m4 (gl_FUNC_UTIME): Test whether utime handles trailing
        slashes on files.
        * lib/utime.c (utime): Add alternative implementation for Unix
        platforms.
        * modules/utime (Depends-on): Add stat.
        * doc/posix-functions/utime.texi: Mention the macOS 10.13 bug.
        * doc/posix-functions/lstat.texi: Mention that macOS 10.13 also has the
        trailing-slash bug.
        * doc/posix-functions/open.texi: Likewise.
        * doc/posix-functions/stat.texi: Likewise.
        * doc/posix-functions/symlink.texi: Likewise.

diff --git a/doc/posix-functions/lstat.texi b/doc/posix-functions/lstat.texi
index 1b1aff6..1a1ffb4 100644
--- a/doc/posix-functions/lstat.texi
+++ b/doc/posix-functions/lstat.texi
@@ -24,7 +24,7 @@ Solaris 9.
 @item
 On some platforms, @code{lstat("file/",buf)} succeeds instead of
 failing with @code{ENOTDIR}.
-Solaris 9.
+Mac OS X 10.13, Solaris 9.
 @item
 On Solaris 11.4, when this function yields a timestamp with a
 nonpositive @code{tv_sec} value, @code{tv_nsec} might be in the range
diff --git a/doc/posix-functions/open.texi b/doc/posix-functions/open.texi
index d4767d9..7e4f187 100644
--- a/doc/posix-functions/open.texi
+++ b/doc/posix-functions/open.texi
@@ -19,7 +19,7 @@ correctly with files larger than 2 GB@.  (Cf. 
@code{AC_SYS_LARGEFILE}.)
 This function does not fail when the file name argument ends in a slash
 and (without the slash) names a nonexistent file or a file that is not a
 directory, on some platforms:
-FreeBSD 7.2, AIX 7.1, HP-UX 11.00, Solaris 9.
+Mac OS X 10.13, FreeBSD 7.2, AIX 7.1, HP-UX 11.00, Solaris 9.
 @item
 This function does not support the @code{O_NONBLOCK} flag when it is defined
 by the gnulib module @code{nonblocking} on some platforms:
diff --git a/doc/posix-functions/stat.texi b/doc/posix-functions/stat.texi
index 27fbe27..1d1f927 100644
--- a/doc/posix-functions/stat.texi
+++ b/doc/posix-functions/stat.texi
@@ -29,7 +29,7 @@ on directories such as @samp{C:\System Volume Information}.
 @item
 On some platforms, @code{stat("link-to-file/",buf)} succeeds instead
 of failing with @code{ENOTDIR}.
-FreeBSD 7.2, AIX 7.1, Solaris 9, mingw64.
+Mac OS X 10.13, FreeBSD 7.2, AIX 7.1, Solaris 9, mingw64.
 @item
 On some platforms, @code{stat(".",buf)} and @code{stat("./",buf)} give
 different results:
diff --git a/doc/posix-functions/symlink.texi b/doc/posix-functions/symlink.texi
index 88d1c77..3826ccf 100644
--- a/doc/posix-functions/symlink.texi
+++ b/doc/posix-functions/symlink.texi
@@ -11,7 +11,7 @@ Portability problems fixed by Gnulib:
 @item
 On some systems, @code{symlink(value,"name/")} mistakenly creates a
 symlink:
-FreeBSD 7.2, AIX 7.1, Solaris 9.
+Mac OS X 10.13, FreeBSD 7.2, AIX 7.1, Solaris 9.
 @item
 This function is missing on some platforms; however, the replacement
 always fails with @code{EPERM}:
diff --git a/doc/posix-functions/utime.texi b/doc/posix-functions/utime.texi
index d019c4a..4e41e5d 100644
--- a/doc/posix-functions/utime.texi
+++ b/doc/posix-functions/utime.texi
@@ -16,6 +16,10 @@ mingw, MSVC 14 (when the environment variable @code{TZ} is 
set).
 On some platforms, the prototype for @code{utime} omits @code{const}
 for the second argument:
 mingw, MSVC 14.
+@item
+On some platforms, @code{utime("link-to-file/",buf)} succeeds instead
+of failing with @code{ENOTDIR}.
+Mac OS X 10.13.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/lib/utime.c b/lib/utime.c
index c35eb16..f6465a3 100644
--- a/lib/utime.c
+++ b/lib/utime.c
@@ -259,4 +259,29 @@ utime (const char *name, const struct utimbuf *ts)
     }
 }
 
+#else
+
+# include <sys/stat.h>
+# include "filename.h"
+
+int
+utime (const char *name, const struct utimbuf *ts)
+#undef utime
+{
+# if REPLACE_FUNC_UTIME_FILE
+  /* macOS 10.13 mistakenly succeeds when given a symbolic link to a
+     non-directory with a trailing slash.  */
+  size_t len = strlen (name);
+  if (ISSLASH (name[len - 1]))
+    {
+      struct stat buf;
+
+      if (stat (name, &buf) < 0)
+        return -1;
+    }
+# endif /* REPLACE_FUNC_UTIME_FILE */
+
+  return utime (name, ts);
+}
+
 #endif
diff --git a/m4/utime.m4 b/m4/utime.m4
index f0a8235..3d2e13c 100644
--- a/m4/utime.m4
+++ b/m4/utime.m4
@@ -1,4 +1,4 @@
-# utime.m4 serial 2
+# utime.m4 serial 3
 dnl Copyright (C) 2017-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -8,6 +8,7 @@ AC_DEFUN([gl_FUNC_UTIME],
 [
   AC_REQUIRE([gl_UTIME_H_DEFAULTS])
   AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_CHECK_FUNCS_ONCE([lstat])
   case "$host_os" in
     mingw*)
       dnl On this platform, the original utime() or _utime() produces
@@ -21,6 +22,51 @@ AC_DEFUN([gl_FUNC_UTIME],
       AC_CHECK_FUNCS([utime])
       if test $ac_cv_func_utime = no; then
         HAVE_UTIME=0
+      else
+        dnl On macOS 10.13, utime("link-to-file/", NULL) mistakenly succeeds.
+        AC_CACHE_CHECK([whether utime handles trailing slashes on files],
+          [gl_cv_func_utime_file_slash],
+          [touch conftest.tmp
+           # Assume that if we have lstat, we can also check symlinks.
+           if test $ac_cv_func_lstat = yes; then
+             ln -s conftest.tmp conftest.lnk
+           fi
+           AC_RUN_IFELSE(
+             [AC_LANG_PROGRAM(
+               [[#include <stddef.h>
+                 #include <time.h>
+               ]],
+               [[int result = 0;
+                 if (!utime ("conftest.tmp/", NULL))
+                   result |= 1;
+                 #if HAVE_LSTAT
+                 if (!utime ("conftest.lnk/", NULL))
+                   result |= 2;
+                 #endif
+                 return result;
+               ]])],
+             [gl_cv_func_utime_file_slash=yes],
+             [gl_cv_func_utime_file_slash=no],
+             [case "$host_os" in
+                                 # Guess yes on Linux systems.
+                linux-* | linux) gl_cv_func_utime_file_slash="guessing yes" ;;
+                                 # Guess yes on glibc systems.
+                *-gnu* | gnu*)   gl_cv_func_utime_file_slash="guessing yes" ;;
+                                 # Guess no on macOS.
+                darwin*)         gl_cv_func_utime_file_slash="guessing no" ;;
+                                 # If we don't know, obey 
--enable-cross-guesses.
+                *)               
gl_cv_func_utime_file_slash="$gl_cross_guess_normal" ;;
+              esac
+             ])
+           rm -f conftest.tmp conftest.lnk
+          ])
+        case $gl_cv_func_stat_file_slash in
+          *no)
+            REPLACE_UTIME=1
+            AC_DEFINE([REPLACE_FUNC_UTIME_FILE], [1],
+              [Define to 1 if utime needs help when passed a file name with a 
trailing slash])
+            ;;
+        esac
       fi
       ;;
   esac
diff --git a/modules/utime b/modules/utime
index 0fc34eb..d1975f4 100644
--- a/modules/utime
+++ b/modules/utime
@@ -10,6 +10,7 @@ utime-h
 time
 filename        [test $HAVE_UTIME = 0 || test $REPLACE_UTIME = 1]
 malloca         [test $HAVE_UTIME = 0 || test $REPLACE_UTIME = 1]
+stat            [test $HAVE_UTIME = 0 || test $REPLACE_UTIME = 1]
 
 configure.ac:
 gl_FUNC_UTIME




reply via email to

[Prev in Thread] Current Thread [Next in Thread]