From: Bruno Haible Date: Tue, 3 Oct 2023 13:59:57 +0000 (+0200) Subject: access: Work around trailing slash bug on Mac OS X 10.5. X-Git-Tag: v1.0~747 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=acdf80a46a09656214cbbf518125bf94db087ae8;p=gnulib.git access: Work around trailing slash bug on Mac OS X 10.5. * m4/access.m4 (gl_FUNC_ACCESS): Test whether access honors a trailing slash. Set REPLACE_ACCESS to 1 and define ACCESS_TRAILING_SLASH_BUG if not. * lib/access.c (access): Add an implementation for Unix-like platforms. * tests/test-access.c (main): Test for result if the argument has a trailing slash. * modules/access-tests (Depends-on): Add 'symlink'. * doc/posix-functions/access.texi: Mention the Mac OS X bug. --- diff --git a/ChangeLog b/ChangeLog index b9ced8b4aa..0c8d28f113 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2023-10-03 Bruno Haible + + access: Work around trailing slash bug on Mac OS X 10.5. + * m4/access.m4 (gl_FUNC_ACCESS): Test whether access honors a trailing + slash. Set REPLACE_ACCESS to 1 and define ACCESS_TRAILING_SLASH_BUG if + not. + * lib/access.c (access): Add an implementation for Unix-like platforms. + * tests/test-access.c (main): Test for result if the argument has a + trailing slash. + * modules/access-tests (Depends-on): Add 'symlink'. + * doc/posix-functions/access.texi: Mention the Mac OS X bug. + 2023-10-03 Bruno Haible update-copyright tests: Fix test failure (regression 2023-06-18). diff --git a/doc/posix-functions/access.texi b/doc/posix-functions/access.texi index 8bfa2c1a67..fd114d300f 100644 --- a/doc/posix-functions/access.texi +++ b/doc/posix-functions/access.texi @@ -11,6 +11,10 @@ Portability problems fixed by Gnulib: @item This function does not support the @code{X_OK} mode on some platforms: MSVC 14. +@item +This function does not reject trailing slashes on symlinks to non-directories +on some platforms: +Mac OS X 10.5. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/access.c b/lib/access.c index e2c12b1f19..75d2148453 100644 --- a/lib/access.c +++ b/lib/access.c @@ -20,7 +20,10 @@ #include #include -#include + +#if defined _WIN32 && ! defined __CYGWIN__ + +# include int access (const char *file, int mode) @@ -29,3 +32,35 @@ access (const char *file, int mode) mode = (mode & ~X_OK) | R_OK; return _access (file, mode); } + +#else + +# include +# include +# include +# include + +int +access (const char *file, int mode) +# undef access +{ + int ret = access (file, mode); +# if ACCESS_TRAILING_SLASH_BUG + if (ret == 0) + { + size_t file_len = strlen (file); + if (file_len > 0 && file[file_len - 1] == '/') + { + struct stat st; + if (stat (file, &st) == 0 && ! S_ISDIR (st.st_mode)) + { + errno = ENOTDIR; + return -1; + } + } + } +# endif + return ret; +} + +#endif diff --git a/m4/access.m4 b/m4/access.m4 index 259e2221fa..9fb9ee145e 100644 --- a/m4/access.m4 +++ b/m4/access.m4 @@ -1,4 +1,4 @@ -# access.m4 serial 2 +# access.m4 serial 3 dnl Copyright (C) 2019-2023 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -11,6 +11,55 @@ AC_DEFUN([gl_FUNC_ACCESS], dnl On native Windows, access (= _access) does not support the X_OK mode. dnl It works by chance on some versions of mingw. case "$host_os" in - mingw* | windows*) REPLACE_ACCESS=1 ;; + mingw* | windows*) + REPLACE_ACCESS=1 + ;; + *) + dnl Mac OS X 10.5 mistakenly allows access("link-to-file/",amode). + AC_CHECK_FUNCS_ONCE([lstat]) + AC_CACHE_CHECK([whether access honors trailing slash], + [gl_cv_func_access_slash_works], + [# Assume that if we have lstat, we can also check symlinks. + if test $ac_cv_func_lstat = yes; then + rm -rf conftest.f conftest.lnk + touch conftest.f || AC_MSG_ERROR([cannot create temporary files]) + ln -s conftest.f conftest.lnk + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ + #include + ]], + [[int result = 0; + if (access ("conftest.lnk/", R_OK) == 0) + result |= 1; + return result; + ]])], + [gl_cv_func_access_slash_works=yes], + [gl_cv_func_access_slash_works=no], + dnl When crosscompiling, assume access is broken. + [case "$host_os" in + # Guess yes on Linux systems. + linux-* | linux) gl_cv_func_access_slash_works="guessing yes" ;; + # Guess yes on systems that emulate the Linux system calls. + midipix*) gl_cv_func_access_slash_works="guessing yes" ;; + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_access_slash_works="guessing yes" ;; + # If we don't know, obey --enable-cross-guesses. + *) gl_cv_func_access_slash_works="$gl_cross_guess_normal" ;; + esac + ]) + rm -rf conftest.f conftest.lnk + else + gl_cv_func_access_slash_works="guessing yes" + fi + ]) + case "$gl_cv_func_access_slash_works" in + *yes) ;; + *) + REPLACE_ACCESS=1 + AC_DEFINE([ACCESS_TRAILING_SLASH_BUG], [1], + [Define if access does not correctly handle trailing slashes.]) + ;; + esac + ;; esac ]) diff --git a/modules/access-tests b/modules/access-tests index 4b35c21150..78344887cd 100644 --- a/modules/access-tests +++ b/modules/access-tests @@ -6,6 +6,7 @@ tests/macros.h Depends-on: creat root-uid +symlink configure.ac: AC_CHECK_FUNCS_ONCE([geteuid]) diff --git a/tests/test-access.c b/tests/test-access.c index 5f9a4ad216..771678f0f7 100644 --- a/tests/test-access.c +++ b/tests/test-access.c @@ -42,6 +42,7 @@ main () unlink (BASE "f1"); chmod (BASE "f2", 0600); unlink (BASE "f2"); + unlink (BASE "sl"); { errno = 0; @@ -59,9 +60,31 @@ main () { ASSERT (close (creat (BASE "f1", 0700)) == 0); + ASSERT (access (BASE "f1", F_OK) == 0); ASSERT (access (BASE "f1", R_OK) == 0); ASSERT (access (BASE "f1", W_OK) == 0); ASSERT (access (BASE "f1", X_OK) == 0); + + ASSERT (access (BASE "f1/", F_OK) == -1); + ASSERT (errno == ENOTDIR); + ASSERT (access (BASE "f1/", R_OK) == -1); + ASSERT (errno == ENOTDIR); + ASSERT (access (BASE "f1/", W_OK) == -1); + ASSERT (errno == ENOTDIR); + ASSERT (access (BASE "f1/", X_OK) == -1); + ASSERT (errno == ENOTDIR); + + if (symlink (BASE "f1", BASE "sl") == 0) + { + ASSERT (access (BASE "sl/", F_OK) == -1); + ASSERT (errno == ENOTDIR); + ASSERT (access (BASE "sl/", R_OK) == -1); + ASSERT (errno == ENOTDIR); + ASSERT (access (BASE "sl/", W_OK) == -1); + ASSERT (errno == ENOTDIR); + ASSERT (access (BASE "sl/", X_OK) == -1); + ASSERT (errno == ENOTDIR); + } } { ASSERT (close (creat (BASE "f2", 0600)) == 0); @@ -90,6 +113,7 @@ main () ASSERT (unlink (BASE "f1") == 0); ASSERT (chmod (BASE "f2", 0600) == 0); ASSERT (unlink (BASE "f2") == 0); + unlink (BASE "sl"); return 0; }