bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
From: Bruno Haible <bruno@clisp.org>
To: bug-gnulib@gnu.org
Cc: "Martin Storsjö" <martin@martin.st>
Subject: Re: utime on macOS
Date: Sat, 05 Dec 2020 00:24:00 +0100	[thread overview]
Message-ID: <12658255.5VkcuPUL5K@omega> (raw)
In-Reply-To: <alpine.DEB.2.23.453.2012011509530.4295@cone.martin.st>

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



  parent reply	other threads:[~2020-12-04 23:24 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-01 13:14 Issues with posix functions on modern macOS/Xcode Martin Storsjö
2020-12-01 13:50 ` Martin Storsjö
2020-12-01 18:58 ` Bruno Haible
2020-12-02 18:56 ` Bruno Haible
2021-01-02 20:43   ` Bruno Haible
2021-03-21  2:57     ` Bruno Haible
2021-03-21 13:58       ` Bruno Haible
2020-12-02 21:52 ` strsignal on macOS Bruno Haible
2020-12-03 20:59 ` fprintf-posix " Bruno Haible
2020-12-04 23:24 ` Bruno Haible [this message]
2021-01-02 16:03 ` renameatu: Fix test failures " Bruno Haible
2021-01-02 18:06 ` utimens: " Bruno Haible

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://lists.gnu.org/mailman/listinfo/bug-gnulib

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=12658255.5VkcuPUL5K@omega \
    --to=bruno@clisp.org \
    --cc=bug-gnulib@gnu.org \
    --cc=martin@martin.st \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).