diff options
Diffstat (limited to '')
-rw-r--r-- | gl/m4/chown.m4 | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/gl/m4/chown.m4 b/gl/m4/chown.m4 new file mode 100644 index 0000000..3638187 --- /dev/null +++ b/gl/m4/chown.m4 @@ -0,0 +1,216 @@ +# serial 34 +# Determine whether we need the chown wrapper. + +dnl Copyright (C) 1997-2001, 2003-2005, 2007, 2009-2020 Free Software +dnl 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. + +# chown should accept arguments of -1 for uid and gid, and it should +# dereference symlinks. If it doesn't, arrange to use the replacement +# function. + +# From Jim Meyering. + +# This is taken from the following Autoconf patch: +# https://git.savannah.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=7fbb553727ed7e0e689a17594b58559ecf3ea6e9 +AC_DEFUN([AC_FUNC_CHOWN], +[ + AC_REQUIRE([AC_TYPE_UID_T])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl for cross-compiles + AC_CHECK_HEADERS([unistd.h]) + AC_CACHE_CHECK([for working chown], + [ac_cv_func_chown_works], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [AC_INCLUDES_DEFAULT + [#include <fcntl.h> + ]], + [[ + char *f = "conftest.chown"; + struct stat before, after; + + if (creat (f, 0600) < 0) + return 1; + if (stat (f, &before) < 0) + return 1; + if (chown (f, (uid_t) -1, (gid_t) -1) == -1) + return 1; + if (stat (f, &after) < 0) + return 1; + return ! (before.st_uid == after.st_uid && before.st_gid == after.st_gid); + ]]) + ], + [ac_cv_func_chown_works=yes], + [ac_cv_func_chown_works=no], + [case "$host_os" in # (( + # Guess yes on Linux systems. + linux-* | linux) ac_cv_func_chown_works="guessing yes" ;; + # Guess yes on glibc systems. + *-gnu* | gnu*) ac_cv_func_chown_works="guessing yes" ;; + # Guess no on native Windows. + mingw*) ac_cv_func_chown_works="guessing no" ;; + # If we don't know, obey --enable-cross-guesses. + *) ac_cv_func_chown_works="$gl_cross_guess_normal" ;; + esac + ]) + rm -f conftest.chown + ]) + case "$ac_cv_func_chown_works" in + *yes) + AC_DEFINE([HAVE_CHOWN], [1], + [Define to 1 if your system has a working `chown' function.]) + ;; + esac +])# AC_FUNC_CHOWN + +AC_DEFUN_ONCE([gl_FUNC_CHOWN], +[ + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + AC_REQUIRE([AC_TYPE_UID_T]) + AC_REQUIRE([AC_FUNC_CHOWN]) + AC_REQUIRE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CHECK_FUNCS_ONCE([chown fchown]) + + dnl mingw lacks chown altogether. + if test $ac_cv_func_chown = no; then + HAVE_CHOWN=0 + else + dnl Some old systems treated chown like lchown. + case "$gl_cv_func_chown_follows_symlink" in + *yes) ;; + *) REPLACE_CHOWN=1 ;; + esac + + dnl Some old systems tried to use uid/gid -1 literally. + case "$ac_cv_func_chown_works" in + *no) + AC_DEFINE([CHOWN_FAILS_TO_HONOR_ID_OF_NEGATIVE_ONE], [1], + [Define if chown is not POSIX compliant regarding IDs of -1.]) + REPLACE_CHOWN=1 + ;; + esac + + dnl Solaris 9 ignores trailing slash. + dnl FreeBSD 7.2 mishandles trailing slash on symlinks. + dnl Likewise for AIX 7.1. + AC_CACHE_CHECK([whether chown honors trailing slash], + [gl_cv_func_chown_slash_works], + [touch conftest.file && rm -f conftest.link + AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +]], [[ if (symlink ("conftest.file", "conftest.link")) return 1; + if (chown ("conftest.link/", getuid (), getgid ()) == 0) return 2; + ]])], + [gl_cv_func_chown_slash_works=yes], + [gl_cv_func_chown_slash_works=no], + [case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_chown_slash_works="guessing yes" ;; + # Guess yes on musl systems. + *-musl*) gl_cv_func_chown_slash_works="guessing yes" ;; + # If we don't know, obey --enable-cross-guesses. + *) gl_cv_func_chown_slash_works="$gl_cross_guess_normal" ;; + esac + ]) + rm -f conftest.link conftest.file]) + case "$gl_cv_func_chown_slash_works" in + *yes) ;; + *) + AC_DEFINE([CHOWN_TRAILING_SLASH_BUG], [1], + [Define to 1 if chown mishandles trailing slash.]) + REPLACE_CHOWN=1 + ;; + esac + + dnl OpenBSD fails to update ctime if ownership does not change. + AC_CACHE_CHECK([whether chown always updates ctime], + [gl_cv_func_chown_ctime_works], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +]], [[ struct stat st1, st2; + if (close (creat ("conftest.file", 0600))) return 1; + if (stat ("conftest.file", &st1)) return 2; + sleep (1); + if (chown ("conftest.file", st1.st_uid, st1.st_gid)) return 3; + if (stat ("conftest.file", &st2)) return 4; + if (st2.st_ctime <= st1.st_ctime) return 5; + ]])], + [gl_cv_func_chown_ctime_works=yes], + [gl_cv_func_chown_ctime_works=no], + [case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_chown_ctime_works="guessing yes" ;; + # Guess yes on musl systems. + *-musl*) gl_cv_func_chown_ctime_works="guessing yes" ;; + # If we don't know, obey --enable-cross-guesses. + *) gl_cv_func_chown_ctime_works="$gl_cross_guess_normal" ;; + esac + ]) + rm -f conftest.file]) + case "$gl_cv_func_chown_ctime_works" in + *yes) ;; + *) + AC_DEFINE([CHOWN_CHANGE_TIME_BUG], [1], [Define to 1 if chown fails + to change ctime when at least one argument was not -1.]) + REPLACE_CHOWN=1 + ;; + esac + fi +]) + +# Determine whether chown follows symlinks (it should). +AC_DEFUN_ONCE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK], +[ + AC_CACHE_CHECK( + [whether chown dereferences symlinks], + [gl_cv_func_chown_follows_symlink], + [ + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> + + int + main () + { + int result = 0; + char const *dangling_symlink = "conftest.dangle"; + + unlink (dangling_symlink); + if (symlink ("conftest.no-such", dangling_symlink)) + abort (); + + /* Exit successfully on a conforming system, + i.e., where chown must fail with ENOENT. */ + if (chown (dangling_symlink, getuid (), getgid ()) == 0) + result |= 1; + if (errno != ENOENT) + result |= 2; + return result; + } + ]])], + [gl_cv_func_chown_follows_symlink=yes], + [gl_cv_func_chown_follows_symlink=no], + [gl_cv_func_chown_follows_symlink="guessing yes"] + ) + ] + ) + + case "$gl_cv_func_chown_follows_symlink" in + *yes) ;; + *) + AC_DEFINE([CHOWN_MODIFIES_SYMLINK], [1], + [Define if chown modifies symlinks.]) + ;; + esac +]) |