From 64c2e4a530837b13f987f5de386c49bac90aef43 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 29 May 2021 12:10:38 -0400 Subject: gnulib: import chown A few sims use this to emulate chown syscalls. --- gnulib/import/Makefile.am | 10 ++ gnulib/import/Makefile.in | 31 +++--- gnulib/import/chown.c | 151 +++++++++++++++++++++++++++ gnulib/import/fchown-stub.c | 34 ++++++ gnulib/import/m4/chown.m4 | 218 +++++++++++++++++++++++++++++++++++++++ gnulib/import/m4/gnulib-cache.m4 | 2 + gnulib/import/m4/gnulib-comp.m4 | 12 +++ 7 files changed, 445 insertions(+), 13 deletions(-) create mode 100644 gnulib/import/chown.c create mode 100644 gnulib/import/fchown-stub.c create mode 100644 gnulib/import/m4/chown.m4 (limited to 'gnulib/import') diff --git a/gnulib/import/Makefile.am b/gnulib/import/Makefile.am index e99adab..30b8afd 100644 --- a/gnulib/import/Makefile.am +++ b/gnulib/import/Makefile.am @@ -35,6 +35,7 @@ # --no-vc-files \ # alloca \ # canonicalize-lgpl \ +# chown \ # count-one-bits \ # dirent \ # dirfd \ @@ -237,6 +238,15 @@ EXTRA_libgnu_a_SOURCES += chdir-long.c ## end gnulib module chdir-long +## begin gnulib module chown + + +EXTRA_DIST += chown.c fchown-stub.c + +EXTRA_libgnu_a_SOURCES += chown.c fchown-stub.c + +## end gnulib module chown + ## begin gnulib module cloexec libgnu_a_SOURCES += cloexec.c diff --git a/gnulib/import/Makefile.in b/gnulib/import/Makefile.in index e02adc6..d8a31f8 100644 --- a/gnulib/import/Makefile.in +++ b/gnulib/import/Makefile.in @@ -49,6 +49,7 @@ # --no-vc-files \ # alloca \ # canonicalize-lgpl \ +# chown \ # count-one-bits \ # dirent \ # dirfd \ @@ -182,6 +183,7 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/import/m4/builtin-expect.m4 \ $(top_srcdir)/import/m4/canonicalize.m4 \ $(top_srcdir)/import/m4/chdir-long.m4 \ + $(top_srcdir)/import/m4/chown.m4 \ $(top_srcdir)/import/m4/clock_time.m4 \ $(top_srcdir)/import/m4/close.m4 \ $(top_srcdir)/import/m4/closedir.m4 \ @@ -1787,12 +1789,12 @@ noinst_LTLIBRARIES = # No GNU Make output. EXTRA_DIST = m4/gnulib-cache.m4 alloca.c alloca.in.h arpa_inet.in.h \ assure.h attribute.h basename-lgpl.h btowc.c \ - canonicalize-lgpl.c chdir-long.c chdir-long.h cloexec.h \ - close.c closedir.c dirent-private.h count-one-bits.h \ - ctype.in.h dirent.in.h dirfd.c dirname.h dup.c dup2.c \ - eloop-threshold.h errno.in.h error.c error.h exitfail.h \ - fchdir.c fcntl.c fcntl.in.h fd-hook.h fdopendir.c ffs.c \ - filename.h filenamecat.h flexmember.h float.c float.in.h \ + canonicalize-lgpl.c chdir-long.c chdir-long.h chown.c \ + fchown-stub.c cloexec.h close.c closedir.c dirent-private.h \ + count-one-bits.h ctype.in.h dirent.in.h dirfd.c dirname.h \ + dup.c dup2.c eloop-threshold.h errno.in.h error.c error.h \ + exitfail.h fchdir.c fcntl.c fcntl.in.h fd-hook.h fdopendir.c \ + ffs.c filename.h filenamecat.h flexmember.h float.c float.in.h \ itold.c fnmatch.c fnmatch_loop.c fnmatch.c fnmatch.in.h \ fpucw.h free.c frexp.c frexp.c frexpl.c fstat.c stat-w32.c \ stat-w32.h at-func.c fstatat.c \ @@ -1876,13 +1878,14 @@ libgnu_a_SOURCES = openat-priv.h openat-proc.c basename-lgpl.c \ libgnu_a_LIBADD = $(gl_LIBOBJS) @ALLOCA@ libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) @ALLOCA@ EXTRA_libgnu_a_SOURCES = alloca.c btowc.c canonicalize-lgpl.c \ - chdir-long.c close.c closedir.c dirfd.c dup.c dup2.c error.c \ - fchdir.c fcntl.c fdopendir.c ffs.c float.c itold.c fnmatch.c \ - fnmatch_loop.c fnmatch.c free.c frexp.c frexp.c frexpl.c \ - fstat.c stat-w32.c at-func.c fstatat.c getcwd.c getcwd-lgpl.c \ - getdelim.c getdtablesize.c getline.c getlogin_r.c getrandom.c \ - gettimeofday.c glob.c glob_pattern_p.c globfree.c inet_ntop.c \ - isblank.c isnan.c isnand.c isnan.c isnanl.c lstat.c malloc.c \ + chdir-long.c chown.c fchown-stub.c close.c closedir.c dirfd.c \ + dup.c dup2.c error.c fchdir.c fcntl.c fdopendir.c ffs.c \ + float.c itold.c fnmatch.c fnmatch_loop.c fnmatch.c free.c \ + frexp.c frexp.c frexpl.c fstat.c stat-w32.c at-func.c \ + fstatat.c getcwd.c getcwd-lgpl.c getdelim.c getdtablesize.c \ + getline.c getlogin_r.c getrandom.c gettimeofday.c glob.c \ + glob_pattern_p.c globfree.c inet_ntop.c isblank.c isnan.c \ + isnand.c isnan.c isnanl.c lstat.c malloc.c \ lc-charset-dispatch.c mbrtowc.c mbtowc-lock.c mbsinit.c \ mbsrtowcs-state.c mbsrtowcs.c mbtowc.c memchr.c memmem.c \ memmem.c mempcpy.c memrchr.c mkdir.c mkdtemp.c mkostemp.c \ @@ -2010,6 +2013,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/btowc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/canonicalize-lgpl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chdir-long.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chown.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cloexec.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/close.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/closedir.Po@am__quote@ @@ -2023,6 +2027,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exitfail.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fchdir.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fchown-stub.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcntl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fd-hook.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fd-safer-flag.Po@am__quote@ diff --git a/gnulib/import/chown.c b/gnulib/import/chown.c new file mode 100644 index 0000000..9b8b361 --- /dev/null +++ b/gnulib/import/chown.c @@ -0,0 +1,151 @@ +/* provide consistent interface to chown for systems that don't interpret + an ID of -1 as meaning "don't change the corresponding ID". + + Copyright (C) 1997, 2004-2007, 2009-2021 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* written by Jim Meyering */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include +#include + +#if !HAVE_CHOWN + +/* Simple stub that always fails with ENOSYS, for mingw. */ +int +chown (const char *file _GL_UNUSED, uid_t uid _GL_UNUSED, + gid_t gid _GL_UNUSED) +{ + errno = ENOSYS; + return -1; +} + +#else /* HAVE_CHOWN */ + +/* Below we refer to the system's chown(). */ +# undef chown + +/* Provide a more-closely POSIX-conforming version of chown on + systems with one or both of the following problems: + - chown doesn't treat an ID of -1 as meaning + "don't change the corresponding ID". + - chown doesn't dereference symlinks. */ + +int +rpl_chown (const char *file, uid_t uid, gid_t gid) +{ + struct stat st; + bool stat_valid = false; + int result; + +# if CHOWN_CHANGE_TIME_BUG + if (gid != (gid_t) -1 || uid != (uid_t) -1) + { + if (stat (file, &st)) + return -1; + stat_valid = true; + } +# endif + +# if CHOWN_FAILS_TO_HONOR_ID_OF_NEGATIVE_ONE + if (gid == (gid_t) -1 || uid == (uid_t) -1) + { + /* Stat file to get id(s) that should remain unchanged. */ + if (!stat_valid && stat (file, &st)) + return -1; + if (gid == (gid_t) -1) + gid = st.st_gid; + if (uid == (uid_t) -1) + uid = st.st_uid; + } +# endif + +# if CHOWN_MODIFIES_SYMLINK + { + /* Handle the case in which the system-supplied chown function + does *not* follow symlinks. Instead, it changes permissions + on the symlink itself. To work around that, we open the + file (but this can fail due to lack of read or write permission) and + use fchown on the resulting descriptor. */ + int open_flags = O_NONBLOCK | O_NOCTTY | O_CLOEXEC; + int fd = open (file, O_RDONLY | open_flags); + if (0 <= fd + || (errno == EACCES + && 0 <= (fd = open (file, O_WRONLY | open_flags)))) + { + int saved_errno; + bool fchown_socket_failure; + + result = fchown (fd, uid, gid); + saved_errno = errno; + + /* POSIX says fchown can fail with errno == EINVAL on sockets + and pipes, so fall back on chown in that case. */ + fchown_socket_failure = + (result != 0 && saved_errno == EINVAL + && fstat (fd, &st) == 0 + && (S_ISFIFO (st.st_mode) || S_ISSOCK (st.st_mode))); + + close (fd); + + if (! fchown_socket_failure) + { + errno = saved_errno; + return result; + } + } + else if (errno != EACCES) + return -1; + } +# endif + +# if CHOWN_TRAILING_SLASH_BUG + if (!stat_valid) + { + size_t len = strlen (file); + if (len && file[len - 1] == '/' && stat (file, &st)) + return -1; + } +# endif + + result = chown (file, uid, gid); + +# if CHOWN_CHANGE_TIME_BUG + if (result == 0 && stat_valid + && (uid == st.st_uid || uid == (uid_t) -1) + && (gid == st.st_gid || gid == (gid_t) -1)) + { + /* No change in ownership, but at least one argument was not -1, + so we are required to update ctime. Since chown succeeded, + we assume that chmod will do likewise. Fortunately, on all + known systems where a 'no-op' chown skips the ctime update, a + 'no-op' chmod still does the trick. */ + result = chmod (file, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO + | S_ISUID | S_ISGID | S_ISVTX)); + } +# endif + + return result; +} + +#endif /* HAVE_CHOWN */ diff --git a/gnulib/import/fchown-stub.c b/gnulib/import/fchown-stub.c new file mode 100644 index 0000000..f549ff3 --- /dev/null +++ b/gnulib/import/fchown-stub.c @@ -0,0 +1,34 @@ +/* Change ownership of a file. + Copyright (C) 2004-2021 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert, 2004. */ + +#include + +#include +#include + +/* A trivial substitute for 'fchown'. + + DJGPP 2.03 and earlier (and perhaps later) don't have 'fchown', + so we pretend no-one has permission for this operation. */ + +int +fchown (int fd, uid_t uid, gid_t gid) +{ + errno = EPERM; + return -1; +} diff --git a/gnulib/import/m4/chown.m4 b/gnulib/import/m4/chown.m4 new file mode 100644 index 0000000..d1c0831 --- /dev/null +++ b/gnulib/import/m4/chown.m4 @@ -0,0 +1,218 @@ +# serial 35 +# Determine whether we need the chown wrapper. + +dnl Copyright (C) 1997-2001, 2003-2005, 2007, 2009-2021 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 + ]GL_MDA_DEFINES], + [[ + 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 +#include +#include +]GL_MDA_DEFINES], + [[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 +#include +#include +#include +#include +]GL_MDA_DEFINES], + [[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 +#include +#include +]GL_MDA_DEFINES[ + 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 +]) diff --git a/gnulib/import/m4/gnulib-cache.m4 b/gnulib/import/m4/gnulib-cache.m4 index ad7db9a..d21f542 100644 --- a/gnulib/import/m4/gnulib-cache.m4 +++ b/gnulib/import/m4/gnulib-cache.m4 @@ -40,6 +40,7 @@ # --no-vc-files \ # alloca \ # canonicalize-lgpl \ +# chown \ # count-one-bits \ # dirent \ # dirfd \ @@ -85,6 +86,7 @@ gl_LOCAL_DIR([]) gl_MODULES([ alloca canonicalize-lgpl + chown count-one-bits dirent dirfd diff --git a/gnulib/import/m4/gnulib-comp.m4 b/gnulib/import/m4/gnulib-comp.m4 index 75fe076..d473485 100644 --- a/gnulib/import/m4/gnulib-comp.m4 +++ b/gnulib/import/m4/gnulib-comp.m4 @@ -57,6 +57,7 @@ AC_DEFUN([gl_EARLY], # Code from module canonicalize-lgpl: # Code from module chdir: # Code from module chdir-long: + # Code from module chown: # Code from module clock-time: # Code from module cloexec: # Code from module close: @@ -268,6 +269,14 @@ AC_DEFUN([gl_INIT], AC_LIBOBJ([chdir-long]) gl_PREREQ_CHDIR_LONG fi + gl_FUNC_CHOWN + if test $HAVE_CHOWN = 0 || test $REPLACE_CHOWN = 1; then + AC_LIBOBJ([chown]) + fi + if test $REPLACE_CHOWN = 1 && test $ac_cv_func_fchown = no; then + AC_LIBOBJ([fchown-stub]) + fi + gl_UNISTD_MODULE_INDICATOR([chown]) gl_CLOCK_TIME gl_MODULE_INDICATOR_FOR_TESTS([cloexec]) gl_FUNC_CLOSE @@ -968,6 +977,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/cdefs.h lib/chdir-long.c lib/chdir-long.h + lib/chown.c lib/cloexec.c lib/cloexec.h lib/close.c @@ -991,6 +1001,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/exitfail.c lib/exitfail.h lib/fchdir.c + lib/fchown-stub.c lib/fcntl.c lib/fcntl.in.h lib/fd-hook.c @@ -1189,6 +1200,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/builtin-expect.m4 m4/canonicalize.m4 m4/chdir-long.m4 + m4/chown.m4 m4/clock_time.m4 m4/close.m4 m4/closedir.m4 -- cgit v1.1