From 2b5f5b65faf5fe77d4d13a22b12cfc90572b1bec Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Thu, 20 Jan 2022 14:18:14 +0900 Subject: [PATCH] Imported Upstream version 2.7.5 --- .tarball-version | 2 +- ChangeLog | 183 ++++++++ Makefile.in | 11 +- NEWS | 6 + TODO | 5 - aclocal.m4 | 458 +++++++++++++++++++ build-aux/config.guess | 27 +- build-aux/config.sub | 10 +- build-aux/texinfo.tex | 59 ++- config.hin | 46 ++ configure | 819 +++++++++++++++++++++++++++++++--- lib/Makefile.in | 50 ++- lib/diffseq.h | 4 +- lib/dirent--.h | 1 + lib/dirent.in.h | 2 + lib/euidaccess.c | 221 +++++++++ lib/faccessat.c | 45 ++ lib/getdtablesize.c | 42 +- lib/getgroups.c | 131 ++++++ lib/getopt.c | 52 ++- lib/gnulib.mk | 45 +- lib/group-member.c | 119 +++++ lib/root-uid.h | 30 ++ lib/signal.in.h | 8 +- lib/symlinkat.c | 3 + lib/tempname.c | 118 ++--- lib/tempname.h | 15 + lib/vasnprintf.c | 8 +- lib/xalloc.h | 1 + m4/dup2.m4 | 84 ++-- m4/euidaccess.m4 | 52 +++ m4/faccessat.m4 | 28 ++ m4/fcntl.m4 | 58 ++- m4/getdtablesize.m4 | 6 +- m4/getgroups.m4 | 107 +++++ m4/gnulib-comp.m4 | 38 ++ m4/group-member.m4 | 29 ++ m4/printf.m4 | 47 +- src/Makefile.am | 5 +- src/Makefile.in | 20 +- src/inp.c | 2 + src/list.h | 55 +++ src/patch.c | 36 +- src/pch.c | 7 +- src/safe.c | 420 +++++++++++++---- src/util.c | 62 +-- tests/Makefile.in | 11 +- tests/copy-rename | 24 + tests/deep-directories | 2 +- tests/no-mode-change-git-diff | 4 +- tests/read-only-files | 2 +- tests/symlinks | 170 ++++++- 52 files changed, 3333 insertions(+), 457 deletions(-) create mode 100644 lib/euidaccess.c create mode 100644 lib/faccessat.c create mode 100644 lib/getgroups.c create mode 100644 lib/group-member.c create mode 100644 lib/root-uid.h create mode 100644 m4/euidaccess.m4 create mode 100644 m4/faccessat.m4 create mode 100644 m4/getgroups.m4 create mode 100644 m4/group-member.m4 create mode 100644 src/list.h diff --git a/.tarball-version b/.tarball-version index a4dd9db..a603bb5 100644 --- a/.tarball-version +++ b/.tarball-version @@ -1 +1 @@ -2.7.4 +2.7.5 diff --git a/ChangeLog b/ChangeLog index 21e051e..84eefd5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,186 @@ +2015-03-07 Andreas Gruenbacher + + Version 2.7.5 + * NEWS: Update. + + build: update gnulib submodule to latest + + Allow absolute symlinks that lead back into the working directory + * src/safe.c (cwd_stat_errno, cwd_stat): stat() result of ".". + (read_symlink): When a symlink is absolute, check if it leads back into the + working directory. If it does, strip off the prefix above the working + directory. If the symlink points to the working directory, return an empty + path. + (traverse_another_path): Recognize empty paths from read_symlink(). + * tests/symlinks: Absolute symlink test cases. + +2015-03-05 Andreas Gruenbacher + + Describe better how the dirfd cache works + + Use overflow safe arithmetic for counting cache misses + * src/safe.c: We don't need a long counter if we use overflow-safe arithmetic + here. + + Also cache resolved symlinks + When resolving a symlink in a pathname, we traverse each path component in the + symlink and cache all of them. At the end, add an additional cache entry for + the symlink itself so that we don't have to resolve the symlink again (even + though this will usually be cached). Skip that if the symlink's parent isn't + in the cache anymore, though. + * src/safe.c (free_cached_dirfd): Remove from parent here instead of in + callers. Move close() to remove_cached_dirfd() instead. + (insert_cached_dirfd): Only insert if the entry's parent still exists; entries + without parent are invalid (see compare_cached_dirfds()); "top-level" entries + have cwd as their parent. + (new_cached_dirfd): New function split off from openat_cached(). + (openat_cached): Use new_cached_dirfd() here. + (traverse_another_path): When starting to resolve a symlink, create an unhashed + dirfd cache entry for the symlink lookup result. When the symlink is completely + resolved, add that entry to the cache. + + Invalidate child dirfd cache entries when their parent goes away + If we don't do that, a directory could be removed from the cache, a new + directory with the same dirfd could be created, and the entries from the old + directory would appear in the new directory. + * src/safe.c (struct cached_dirfd): Keep track of the children of each dirfd + cache entry. + (remove_cached_dirfd): Remove all the entry's children from the lookup hash, + take them off the list of children, and initialize the children's + children_link. Then, remove the entry itself from its parent. This has no + effect if the entry doesn't have a parent because then, children_link is empty. + (openat_cached): Add new dirfd cache entries to their parent's list of children + and initialize the entry's list of children. + (traverse_another_path): Also initialize cwd's list of children. + + Convert lru list into a list_head list + * src/safe.c (struct cached_dirfd): Replace prev and next with a lru_link + list_head. + (lru_list): Turn into a list_head. + (lru_list_add, lru_list_del, lru_list_del_init): Replace by list_add(), + list_del(), list_del_init(). + (insert_cached_dirfd): Get to the list entry from the embedded list_head with + the list_entry() macro. + + Add list_head based double linked list + * src/list.h: New data structure. + src/Makefile.am (patch_SOURCES): Add list.h. + + Invalidate dirfd less aggressively + src/safe.c (safe_rename, safe_rmdir): Only invalidate cache entries when the + underlying sycall succeeds and the entry actually goes away. This keeps the + cache filled upon speculative rmdir when the directory may not be empty, for + example. + +2015-03-05 Tim Waugh + + Add more path traversal test cases + * tests/symlinks: Add more path traversal test cases. + +2015-03-05 Andreas Gruenbacher + + Move path traversal error reporting into main() + * src/safe.c (traverse_another_path): Don't report errors here. + * src/patch.c (main): Instead, recognize and report them here. Detect when an + output file name is invalid; it doesn't make sense to try creating a + reject file based on the same outbut file name in that case. + + Limit the number of path components + src/safe.c (MAX_PATH_COMPONENTS): The maximum number of path components + allowed. + (count_path_components): New function. + (traverse_another_path): Fail if the number of path components gets too high. + + Follow directory symlinks within the working directory + * src/safe.c (struct symlink): A symlink to resolve. + (push_symlink, pop_symlink): New functions. + (read_symlink): Create a new symlink stack entry. + (traverse_next): Follow ".." components within the working directory. When + hitting symlinks, "follow" them by reading and returning them. + (traverse_another_path): Recursively traverse symlinks. + + Keep track of the directory hierarchy + * src/safe.c (struct cached_dirfd): Add parent pointer. Now that we know our + parent, we no longer need to duplicate its directory file descriptor. + (lookup_cached_dirfd): Don't update the lru list here. + (insert_cached_dirfd): The lru list may now be empty even if the cache is not. + (put_path): New function to put a path back into the lru list. + (openat_cached): Take cached entried off the lru list. They are added back + in put_path(). + (traverse_another_path): Put lookup result back into the lru list with + put_path(). + +2015-02-28 Andreas Gruenbacher + + Refactor traverse_another_path() and helpers + Prepare for keeping track of the directory hierarchy: + * src/safe.c (traverse_another_path): Pass struct cached_dirfd to + traverse_next(). + (traverse_next, openat_cached): Pass through struct cached_dirfd. + + Move error reporting out of make_tempfile() + * src/util.c (make_tempfile): Remove error reporting here. + * src/inp.c (plan_b): Readd error reporting here. + * src/patch.c (main): Likewise. + * src/pch.c (open_patch_file): Likewise. + + Minor cosmetic changes + * src/safe.c: Minor cosmetic changes + +2015-02-22 Andreas Gruenbacher + + Fix handling of renamed files + When a file has already been renamed, make sure it is not renamed back to its + old name. Reported by Guido Draheim. + * src/patch.c (main): Make sure we never rename a file back to its previous + name. Report when a file was renamed already. + * tests/copy-rename: Add "already renamed" test cases. + +2015-02-10 Andreas Gruenbacher + + Fix symlinks test case on some architectures + * src/safe.c: Include util.h for say(). Define EFTYPE if it isn't defined + already. + (traverse_another_path): When openat fails, also check for EMLINK, EFTYPE, and + ENOTDIR. Change the error message to "file ... is not a directory" and only + skip the rest of the patch instead of aborting. + * tests/symlinks: Update. + +2015-02-04 Andreas Gruenbacher + + Test suite portability fixes + Reported and fixed (mostly) by Christian Weisgerber : + * tests/deep-directories: Avoid the bash >& redirection operator. + * tests/no-mode-change-git-diff: Instead of "stat -c", use "ls -l sed". + * tests/read-only-files: A redirection failure for a special built-in causes + some shells (FreeBSD sh, OpenBSD sh (pdksh), some bash --posix) to exit, and + the colon command is a special built-in. Perform the redirection in a subshell. + + Switch from gen_tempname() to try_tempname() + * Update gnulib submodule to latest. + * src/util.c (try_safe_open_args, try_safe_open): Arguments and callback for + try_tempname(). + (make_tempfile): Switch from gen_tempname() to try_tempname(). + +2015-02-02 Andreas Gruenbacher + + Check the result of the --follow-symlinks option + * tests/symlinks: Check the result of treating a symlink as a file with + --follow-symlinks. + +2015-02-01 Andreas Gruenbacher + + Link patch with LIB_EACCESS where needed + * src/Makefile.am (patch_LDADD): Add LIB_EACCESS here. At least on Solaris, + faccessat() is implemented through eaccess() which is in the "gen" library. + + Fix minor signedness warning + * src/pch.c (intuit_diff_type): Don't assign signed dummy value to unsigned + variable. + + Use gnulib faccessat module + * bootstrap.conf (gnulib_modules): Add faccessat. + 2015-01-31 Andreas Gruenbacher Upate NEWS diff --git a/Makefile.in b/Makefile.in index bc6329c..f480e32 100644 --- a/Makefile.in +++ b/Makefile.in @@ -121,17 +121,21 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \ $(top_srcdir)/m4/double-slash-root.m4 $(top_srcdir)/m4/dup2.m4 \ $(top_srcdir)/m4/eealloc.m4 $(top_srcdir)/m4/environ.m4 \ $(top_srcdir)/m4/errno_h.m4 $(top_srcdir)/m4/error.m4 \ - $(top_srcdir)/m4/exponentd.m4 $(top_srcdir)/m4/extensions.m4 \ - $(top_srcdir)/m4/extern-inline.m4 $(top_srcdir)/m4/fchdir.m4 \ + $(top_srcdir)/m4/euidaccess.m4 $(top_srcdir)/m4/exponentd.m4 \ + $(top_srcdir)/m4/extensions.m4 \ + $(top_srcdir)/m4/extern-inline.m4 \ + $(top_srcdir)/m4/faccessat.m4 $(top_srcdir)/m4/fchdir.m4 \ $(top_srcdir)/m4/fchmodat.m4 $(top_srcdir)/m4/fchownat.m4 \ $(top_srcdir)/m4/fcntl-o.m4 $(top_srcdir)/m4/fcntl.m4 \ $(top_srcdir)/m4/fcntl_h.m4 $(top_srcdir)/m4/filenamecat.m4 \ $(top_srcdir)/m4/float_h.m4 $(top_srcdir)/m4/fstat.m4 \ $(top_srcdir)/m4/fstatat.m4 $(top_srcdir)/m4/getcwd.m4 \ - $(top_srcdir)/m4/getdtablesize.m4 $(top_srcdir)/m4/getopt.m4 \ + $(top_srcdir)/m4/getdtablesize.m4 \ + $(top_srcdir)/m4/getgroups.m4 $(top_srcdir)/m4/getopt.m4 \ $(top_srcdir)/m4/gettime.m4 $(top_srcdir)/m4/gettimeofday.m4 \ $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnulib-common.m4 \ $(top_srcdir)/m4/gnulib-comp.m4 \ + $(top_srcdir)/m4/group-member.m4 \ $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/intmax_t.m4 \ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/largefile.m4 \ $(top_srcdir)/m4/lchown.m4 $(top_srcdir)/m4/localcharset.m4 \ @@ -846,6 +850,7 @@ LIBPATCH_LIBDEPS = @LIBPATCH_LIBDEPS@ LIBPATCH_LTLIBDEPS = @LIBPATCH_LTLIBDEPS@ LIBS = @LIBS@ LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ +LIB_EACCESS = @LIB_EACCESS@ LIB_XATTR = @LIB_XATTR@ LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@ LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@ diff --git a/NEWS b/NEWS index 9fafde4..d9e1cf2 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +Changes in version 2.7.5: + +* There are users which expect patch to follow symbolic links in the working + directory, so patch now again follows symbolic links as long as they do not + leave the working directory. + Changes until version 2.7.4: * When a file isn't being deleted because the file contents don't match the diff --git a/TODO b/TODO index 41324ab..55e65a0 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,3 @@ -* Add instrumentation code for the path traversal functions !!! - -access() !!! -Apply the mode fix! -Alpha release ?! Announcement ... * Fix Savannah patches. diff --git a/aclocal.m4 b/aclocal.m4 index e2807fb..788c0f8 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -20,6 +20,460 @@ You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) +# po.m4 serial 24 (gettext-0.19) +dnl Copyright (C) 1995-2014 Free Software 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. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.60]) + +dnl Checks for all prerequisites of the po subdirectory. +AC_DEFUN([AM_PO_SUBDIRS], +[ + AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AC_PROG_MKDIR_P])dnl + AC_REQUIRE([AC_PROG_SED])dnl + AC_REQUIRE([AM_NLS])dnl + + dnl Release version of the gettext macros. This is used to ensure that + dnl the gettext macros and po/Makefile.in.in are in sync. + AC_SUBST([GETTEXT_MACRO_VERSION], [0.19]) + + dnl Perform the following tests also if --disable-nls has been given, + dnl because they are needed for "make dist" to work. + + dnl Search for GNU msgfmt in the PATH. + dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. + dnl The second test excludes FreeBSD msgfmt. + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT]) + + dnl Test whether it is GNU msgfmt >= 0.15. +changequote(,)dnl + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([MSGFMT_015]) +changequote(,)dnl + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([GMSGFMT_015]) + + dnl Search for GNU xgettext 0.12 or newer in the PATH. + dnl The first test excludes Solaris xgettext and early GNU xgettext versions. + dnl The second test excludes FreeBSD xgettext. + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + + dnl Test whether it is GNU xgettext >= 0.15. +changequote(,)dnl + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac +changequote([,])dnl + AC_SUBST([XGETTEXT_015]) + + dnl Search for GNU msgmerge 0.11 or newer in the PATH. + AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, + [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) + + dnl Installation directories. + dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we + dnl have to define it here, so that it can be used in po/Makefile. + test -n "$localedir" || localedir='${datadir}/locale' + AC_SUBST([localedir]) + + dnl Support for AM_XGETTEXT_OPTION. + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) + + AC_CONFIG_COMMANDS([po-directories], [[ + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + gt_tab=`printf '\t'` + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done]], + [# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + ]) +]) + +dnl Postprocesses a Makefile in a directory containing PO files. +AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], +[ + # When this code is run, in config.status, two variables have already been + # set: + # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, + # - LINGUAS is the value of the environment variable LINGUAS at configure + # time. + +changequote(,)dnl + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + # Find a way to echo strings without interpreting backslash. + if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='echo' + else + if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='printf %s\n' + else + echo_func () { + cat < "$ac_file.tmp" + tab=`printf '\t'` + if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + cat >> "$ac_file.tmp" < /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` + cat >> "$ac_file.tmp" <> "$ac_file.tmp" </dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) + arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ @@ -197,6 +204,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in os=netbsd ;; esac + # Determine ABI tags. + case "${UNAME_MACHINE_ARCH}" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + ;; + esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need @@ -213,7 +227,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "${machine}-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` @@ -933,6 +947,9 @@ EOF crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; + e2k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; diff --git a/build-aux/config.sub b/build-aux/config.sub index 6d2e94c..60e3590 100755 --- a/build-aux/config.sub +++ b/build-aux/config.sub @@ -2,7 +2,7 @@ # Configuration validation subroutine script. # Copyright 1992-2015 Free Software Foundation, Inc. -timestamp='2015-01-01' +timestamp='2015-03-06' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -117,7 +117,7 @@ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os @@ -259,7 +259,7 @@ case $basic_machine in | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ - | epiphany \ + | e2k | epiphany \ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ @@ -381,7 +381,7 @@ case $basic_machine in | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ + | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ @@ -1373,7 +1373,7 @@ case $os in | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ + | -aos* | -aros* | -cloudabi* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ diff --git a/build-aux/texinfo.tex b/build-aux/texinfo.tex index 7f5f357..8236d7d 100644 --- a/build-aux/texinfo.tex +++ b/build-aux/texinfo.tex @@ -3,7 +3,7 @@ % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2015-01-30.16} +\def\texinfoversion{2015-02-05.16} % % Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, % 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, @@ -4489,7 +4489,6 @@ end % Called from \indexdummies and \atdummies. % \def\commondummies{% - % % \definedummyword defines \#1 as \string\#1\space, thus effectively % preventing its expansion. This is used only for control words, % not control letters, because the \space would be incorrect for @@ -4566,6 +4565,7 @@ end \definedummyword\guilsinglright \definedummyword\lbracechar \definedummyword\leq + \definedummyword\mathopsup \definedummyword\minus \definedummyword\ogonek \definedummyword\pounds @@ -4579,6 +4579,8 @@ end \definedummyword\quotesinglbase \definedummyword\rbracechar \definedummyword\result + \definedummyword\sub + \definedummyword\sup \definedummyword\textdegree % % We want to disable all macros so that they are not expanded by \write. @@ -4653,6 +4655,7 @@ end \definedummyword\samp \definedummyword\strong \definedummyword\tie + \definedummyword\U \definedummyword\uref \definedummyword\url \definedummyword\var @@ -8335,14 +8338,7 @@ end \catcode`\\=\other % % Make the characters 128-255 be printing characters. - {% - \count1=128 - \def\loop{% - \catcode\count1=\other - \advance\count1 by 1 - \ifnum \count1<256 \loop \fi - }% - }% + {\setnonasciicharscatcodenonglobal\other}% % % @ is our escape character in .aux files, and we need braces. \catcode`\{=1 @@ -8988,7 +8984,9 @@ directory should work if nowhere else does.} % \else \ifx \declaredencoding \utfeight \setnonasciicharscatcode\active - \utfeightchardefs + % since we already invoked \utfeightchardefs at the top level + % (below), do not re-invoke it, then our check for duplicated + % definitions triggers. Making non-ascii chars active is enough. % \else \message{Ignoring unknown document encoding: #1.}% @@ -9829,15 +9827,51 @@ directory should work if nowhere else does.} \DeclareUnicodeCharacter{2261}{\equiv} }% end of \utfeightchardefs - % US-ASCII character definitions. \def\asciichardefs{% nothing need be done \relax } +% Latin1 (ISO-8859-1) character definitions. +\def\nonasciistringdefs{% + \setnonasciicharscatcode\active + \def\defstringchar##1{\def##1{\string##1}}% + \defstringchar^^a0\defstringchar^^a1\defstringchar^^a2\defstringchar^^a3% + \defstringchar^^a4\defstringchar^^a5\defstringchar^^a6\defstringchar^^a7% + \defstringchar^^a8\defstringchar^^a9\defstringchar^^aa\defstringchar^^ab% + \defstringchar^^ac\defstringchar^^ad\defstringchar^^ae\defstringchar^^af% + % + \defstringchar^^b0\defstringchar^^b1\defstringchar^^b2\defstringchar^^b3% + \defstringchar^^b4\defstringchar^^b5\defstringchar^^b6\defstringchar^^b7% + \defstringchar^^b8\defstringchar^^b9\defstringchar^^ba\defstringchar^^bb% + \defstringchar^^bc\defstringchar^^bd\defstringchar^^be\defstringchar^^bf% + % + \defstringchar^^c0\defstringchar^^c1\defstringchar^^c2\defstringchar^^c3% + \defstringchar^^c4\defstringchar^^c5\defstringchar^^c6\defstringchar^^c7% + \defstringchar^^c8\defstringchar^^c9\defstringchar^^ca\defstringchar^^cb% + \defstringchar^^cc\defstringchar^^cd\defstringchar^^ce\defstringchar^^cf% + % + \defstringchar^^d0\defstringchar^^d1\defstringchar^^d2\defstringchar^^d3% + \defstringchar^^d4\defstringchar^^d5\defstringchar^^d6\defstringchar^^d7% + \defstringchar^^d8\defstringchar^^d9\defstringchar^^da\defstringchar^^db% + \defstringchar^^dc\defstringchar^^dd\defstringchar^^de\defstringchar^^df% + % + \defstringchar^^e0\defstringchar^^e1\defstringchar^^e2\defstringchar^^e3% + \defstringchar^^e4\defstringchar^^e5\defstringchar^^e6\defstringchar^^e7% + \defstringchar^^e8\defstringchar^^e9\defstringchar^^ea\defstringchar^^eb% + \defstringchar^^ec\defstringchar^^ed\defstringchar^^ee\defstringchar^^ef% + % + \defstringchar^^f0\defstringchar^^f1\defstringchar^^f2\defstringchar^^f3% + \defstringchar^^f4\defstringchar^^f5\defstringchar^^f6\defstringchar^^f7% + \defstringchar^^f8\defstringchar^^f9\defstringchar^^fa\defstringchar^^fb% + \defstringchar^^fc\defstringchar^^fd\defstringchar^^fe\defstringchar^^ff% +} + + % define all the unicode characters we know about, for the sake of @U. \utfeightchardefs + % Make non-ASCII characters printable again for compatibility with % existing Texinfo documents that may use them, even without declaring a % document encoding. @@ -10191,6 +10225,7 @@ directory should work if nowhere else does.} % {@catcode`- = @active @gdef@normalturnoffactive{% + @nonasciistringdefs @let-=@normaldash @let"=@normaldoublequote @let$=@normaldollar %$ font-lock fix diff --git a/config.hin b/config.hin index f15a9cd..1663bf4 100644 --- a/config.hin +++ b/config.hin @@ -87,6 +87,14 @@ /* Define to 1 if futimesat mishandles a NULL file name. */ #undef FUTIMESAT_NULL_BUG +/* Define to the type of elements in the array set by `getgroups'. Usually + this is either `int' or `gid_t'. */ +#undef GETGROUPS_T + +/* Define this to 1 if getgroups(0,NULL) does not return the number of groups. + */ +#undef GETGROUPS_ZERO_BUG + /* Define if gettimeofday clobbers the localtime buffer. */ #undef GETTIMEOFDAY_CLOBBERS_LOCALTIME @@ -106,6 +114,10 @@ whether the gnulib module dirname shall be considered present. */ #undef GNULIB_DIRNAME +/* Define to a C preprocessor expression that evaluates to 1 or 0, depending + whether the gnulib module faccessat shall be considered present. */ +#undef GNULIB_FACCESSAT + /* Define to a C preprocessor expression that evaluates to 1 or 0, depending whether the gnulib module fchmodat shall be considered present. */ #undef GNULIB_FCHMODAT @@ -177,6 +189,12 @@ /* Define to 1 when the gnulib module environ should be tested. */ #undef GNULIB_TEST_ENVIRON +/* Define to 1 when the gnulib module euidaccess should be tested. */ +#undef GNULIB_TEST_EUIDACCESS + +/* Define to 1 when the gnulib module faccessat should be tested. */ +#undef GNULIB_TEST_FACCESSAT + /* Define to 1 when the gnulib module fchdir should be tested. */ #undef GNULIB_TEST_FCHDIR @@ -201,12 +219,18 @@ /* Define to 1 when the gnulib module getdtablesize should be tested. */ #undef GNULIB_TEST_GETDTABLESIZE +/* Define to 1 when the gnulib module getgroups should be tested. */ +#undef GNULIB_TEST_GETGROUPS + /* Define to 1 when the gnulib module getopt-gnu should be tested. */ #undef GNULIB_TEST_GETOPT_GNU /* Define to 1 when the gnulib module gettimeofday should be tested. */ #undef GNULIB_TEST_GETTIMEOFDAY +/* Define to 1 when the gnulib module group-member should be tested. */ +#undef GNULIB_TEST_GROUP_MEMBER + /* Define to 1 when the gnulib module lchown should be tested. */ #undef GNULIB_TEST_LCHOWN @@ -321,6 +345,9 @@ /* Define to 1 when the gnulib module write should be tested. */ #undef GNULIB_TEST_WRITE +/* Define to 1 if you have the `access' function. */ +#undef HAVE_ACCESS + /* Define to 1 if you have 'alloca' after including , a header that may be supplied by this distribution. */ #undef HAVE_ALLOCA @@ -378,6 +405,10 @@ don't. */ #undef HAVE_DECL_GETC_UNLOCKED +/* Define to 1 if you have the declaration of `getdtablesize', and to 0 if you + don't. */ +#undef HAVE_DECL_GETDTABLESIZE + /* Define to 1 if you have the declaration of `getenv', and to 0 if you don't. */ #undef HAVE_DECL_GETENV @@ -451,9 +482,18 @@ /* Define to 1 if you have the 'dup2' function. */ #undef HAVE_DUP2 +/* Define to 1 if you have the `eaccess' function. */ +#undef HAVE_EACCESS + /* Define if you have the declaration of environ. */ #undef HAVE_ENVIRON_DECL +/* Define to 1 if you have the `euidaccess' function. */ +#undef HAVE_EUIDACCESS + +/* Define to 1 if you have the `faccessat' function. */ +#undef HAVE_FACCESSAT + /* Define to 1 if you have the `fchdir' function. */ #undef HAVE_FCHDIR @@ -496,6 +536,9 @@ /* Define to 1 if you have the `geteuid' function. */ #undef HAVE_GETEUID +/* Define to 1 if your system has a working `getgroups' function. */ +#undef HAVE_GETGROUPS + /* Define to 1 if you have the header file. */ #undef HAVE_GETOPT_H @@ -533,6 +576,9 @@ /* Define to 1 if you have the `lchown' function. */ #undef HAVE_LCHOWN +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBGEN_H + /* Define to 1 if you have the `link' function. */ #undef HAVE_LINK diff --git a/configure b/configure index 1e1aedc..222934a 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for GNU patch 2.7.4. +# Generated by GNU Autoconf 2.69 for GNU patch 2.7.5. # # Report bugs to . # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='GNU patch' PACKAGE_TARNAME='patch' -PACKAGE_VERSION='2.7.4' -PACKAGE_STRING='GNU patch 2.7.4' +PACKAGE_VERSION='2.7.5' +PACKAGE_STRING='GNU patch 2.7.5' PACKAGE_BUGREPORT='bug-patch@gnu.org' PACKAGE_URL='http://www.gnu.org/software/patch/' @@ -1100,6 +1100,7 @@ GNULIB_FUTIMENS GNULIB_FSTATAT GNULIB_FSTAT GNULIB_FCHMODAT +LIB_EACCESS EOVERFLOW_VALUE EOVERFLOW_HIDDEN ENOLINK_VALUE @@ -2013,7 +2014,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures GNU patch 2.7.4 to adapt to many kinds of systems. +\`configure' configures GNU patch 2.7.5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -2083,7 +2084,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of GNU patch 2.7.4:";; + short | recursive ) echo "Configuration of GNU patch 2.7.5:";; esac cat <<\_ACEOF @@ -2187,7 +2188,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -GNU patch configure 2.7.4 +GNU patch configure 2.7.5 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2896,7 +2897,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by GNU patch $as_me 2.7.4, which was +It was created by GNU patch $as_me 2.7.5, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3190,7 +3191,7 @@ as_fn_append ac_header_list " sys/socket.h" as_fn_append ac_func_list " fchdir" as_fn_append ac_header_list " dirent.h" as_fn_append ac_func_list " fdopendir" -as_fn_append ac_func_list " getdtablesize" +as_fn_append ac_func_list " faccessat" as_fn_append ac_func_list " fchmodat" as_fn_append ac_func_list " lchmod" as_fn_append ac_func_list " fcntl" @@ -3198,6 +3199,7 @@ as_fn_append ac_func_list " symlink" as_fn_append ac_func_list " mempcpy" as_fn_append ac_header_list " sys/stat.h" as_fn_append ac_func_list " fstatat" +as_fn_append ac_func_list " getdtablesize" gl_getopt_required=GNU as_fn_append ac_header_list " getopt.h" as_fn_append ac_func_list " gettimeofday" @@ -3843,7 +3845,7 @@ fi # Define the identity of the package. PACKAGE='patch' - VERSION='2.7.4' + VERSION='2.7.5' cat >>confdefs.h <<_ACEOF @@ -6303,10 +6305,12 @@ fi # Code from module environ: # Code from module errno: # Code from module error: + # Code from module euidaccess: # Code from module exitfail: # Code from module extensions: # Code from module extern-inline: + # Code from module faccessat: # Code from module fchdir: # Code from module fchmodat: # Code from module fchownat: @@ -6322,6 +6326,7 @@ fi # Code from module getcwd-lgpl: # Code from module getdate: # Code from module getdtablesize: + # Code from module getgroups: # Code from module getopt-gnu: # Code from module getopt-posix: # Code from module gettext-h: @@ -6330,6 +6335,7 @@ fi # Code from module git-version-gen: # Code from module gitlog-to-changelog: # Code from module gnumakefile: + # Code from module group-member: # Code from module hash: # Code from module ignore-value: # Code from module include_next: @@ -6381,6 +6387,7 @@ fi # Code from module rename: # Code from module renameat: # Code from module rmdir: + # Code from module root-uid: # Code from module safe-write: # Code from module same-inode: # Code from module save-cwd: @@ -7914,8 +7921,6 @@ $as_echo "$gl_cv_pragma_columns" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if environ is properly declared" >&5 $as_echo_n "checking if environ is properly declared... " >&6; } if ${gt_cv_var_environ_declaration+:} false; then : @@ -8429,6 +8434,78 @@ $as_echo "#define STRERROR_R_CHAR_P 1" >>confdefs.h fi + XGETTEXT_EXTRA_OPTIONS= + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking type of array argument to getgroups" >&5 +$as_echo_n "checking type of array argument to getgroups... " >&6; } +if ${ac_cv_type_getgroups+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_type_getgroups=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Thanks to Mike Rendell for this test. */ +$ac_includes_default +#define NGID 256 +#undef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +int +main () +{ + gid_t gidset[NGID]; + int i, n; + union { gid_t gval; long int lval; } val; + + val.lval = -1; + for (i = 0; i < NGID; i++) + gidset[i] = val.gval; + n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1, + gidset); + /* Exit non-zero if getgroups seems to require an array of ints. This + happens when gid_t is short int but getgroups modifies an array + of ints. */ + return n > 0 && gidset[n] != val.gval; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_type_getgroups=gid_t +else + ac_cv_type_getgroups=int +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +if test $ac_cv_type_getgroups = cross; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "getgroups.*int.*gid_t" >/dev/null 2>&1; then : + ac_cv_type_getgroups=gid_t +else + ac_cv_type_getgroups=int +fi +rm -f conftest* + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_getgroups" >&5 +$as_echo "$ac_cv_type_getgroups" >&6; } + +cat >>confdefs.h <<_ACEOF +#define GETGROUPS_T $ac_cv_type_getgroups +_ACEOF + + + ac_fn_c_check_decl "$LINENO" "fchdir" "ac_cv_have_decl_fchdir" "$ac_includes_default" @@ -9075,6 +9152,19 @@ $as_echo "$gl_cv_func_getcwd_posix_signature" >&6; } +ac_fn_c_check_decl "$LINENO" "getdtablesize" "ac_cv_have_decl_getdtablesize" "$ac_includes_default" +if test "x$ac_cv_have_decl_getdtablesize" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GETDTABLESIZE $ac_have_decl +_ACEOF + + + @@ -14972,7 +15062,6 @@ $as_echo "#define DOUBLE_SLASH_IS_DISTINCT_ROOT 1" >>confdefs.h - $as_echo "#define HAVE_DUP2 1" >>confdefs.h @@ -14988,56 +15077,66 @@ else gl_cv_func_dup2_works="guessing no" ;; cygwin*) # on cygwin 1.5.x, dup2(1,1) returns 0 gl_cv_func_dup2_works="guessing no" ;; - linux*) # On linux between 2008-07-27 and 2009-05-11, dup2 of a - # closed fd may yield -EBADF instead of -1 / errno=EBADF. - gl_cv_func_dup2_works="guessing no" ;; aix* | freebsd*) # on AIX 7.1 and FreeBSD 6.1, dup2 (1,toobig) gives EMFILE, # not EBADF. gl_cv_func_dup2_works="guessing no" ;; haiku*) # on Haiku alpha 2, dup2(1, 1) resets FD_CLOEXEC. gl_cv_func_dup2_works="guessing no" ;; + *-android*) # implemented using dup3(), which fails if oldfd == newfd + gl_cv_func_dup2_works="guessing no" ;; *) gl_cv_func_dup2_works="guessing yes" ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include -#include -#include + #include + #include + #include + #include + #include + #ifndef RLIM_SAVED_CUR + # define RLIM_SAVED_CUR RLIM_INFINITY + #endif + #ifndef RLIM_SAVED_MAX + # define RLIM_SAVED_MAX RLIM_INFINITY + #endif + int main () { int result = 0; -#ifdef HAVE_GETDTABLESIZE - int bad_fd = getdtablesize (); -#else - int bad_fd = 1000000; -#endif -#ifdef FD_CLOEXEC - if (fcntl (1, F_SETFD, FD_CLOEXEC) == -1) - result |= 1; -#endif - if (dup2 (1, 1) == 0) - result |= 2; -#ifdef FD_CLOEXEC - if (fcntl (1, F_GETFD) != FD_CLOEXEC) - result |= 4; -#endif - close (0); - if (dup2 (0, 0) != -1) - result |= 8; - /* Many gnulib modules require POSIX conformance of EBADF. */ - if (dup2 (2, bad_fd) == -1 && errno != EBADF) - result |= 16; - /* Flush out some cygwin core dumps. */ - if (dup2 (2, -1) != -1 || errno != EBADF) - result |= 32; - dup2 (2, 255); - dup2 (2, 256); - return result; - + int bad_fd = INT_MAX; + struct rlimit rlim; + if (getrlimit (RLIMIT_NOFILE, &rlim) == 0 + && 0 <= rlim.rlim_cur && rlim.rlim_cur <= INT_MAX + && rlim.rlim_cur != RLIM_INFINITY + && rlim.rlim_cur != RLIM_SAVED_MAX + && rlim.rlim_cur != RLIM_SAVED_CUR) + bad_fd = rlim.rlim_cur; + #ifdef FD_CLOEXEC + if (fcntl (1, F_SETFD, FD_CLOEXEC) == -1) + result |= 1; + #endif + if (dup2 (1, 1) != 1) + result |= 2; + #ifdef FD_CLOEXEC + if (fcntl (1, F_GETFD) != FD_CLOEXEC) + result |= 4; + #endif + close (0); + if (dup2 (0, 0) != -1) + result |= 8; + /* Many gnulib modules require POSIX conformance of EBADF. */ + if (dup2 (2, bad_fd) == -1 && errno != EBADF) + result |= 16; + /* Flush out some cygwin core dumps. */ + if (dup2 (2, -1) != -1 || errno != EBADF) + result |= 32; + dup2 (2, 255); + dup2 (2, 256); + return result; ; return 0; } @@ -15180,6 +15279,317 @@ $as_echo "$ac_cv_lib_error_at_line" >&6; } fi + XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS --flag=error:3:c-format" + + + + XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS --flag=error_at_line:5:c-format" + + + + + + + for ac_func in euidaccess +do : + ac_fn_c_check_func "$LINENO" "euidaccess" "ac_cv_func_euidaccess" +if test "x$ac_cv_func_euidaccess" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EUIDACCESS 1 +_ACEOF + +fi +done + + if test $ac_cv_func_euidaccess = no; then + HAVE_EUIDACCESS=0 + fi + + if test $HAVE_EUIDACCESS = 0; then + + + + + + + + + gl_LIBOBJS="$gl_LIBOBJS euidaccess.$ac_objext" + + + + for ac_header in libgen.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "libgen.h" "ac_cv_header_libgen_h" "$ac_includes_default" +if test "x$ac_cv_header_libgen_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGEN_H 1 +_ACEOF + +fi + +done + + + ac_fn_c_check_func "$LINENO" "getgroups" "ac_cv_func_getgroups" +if test "x$ac_cv_func_getgroups" = xyes; then : + +fi + + + # If we don't yet have getgroups, see if it's in -lbsd. + # This is reported to be necessary on an ITOS 3000WS running SEIUX 3.1. + ac_save_LIBS=$LIBS + if test $ac_cv_func_getgroups = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgroups in -lbsd" >&5 +$as_echo_n "checking for getgroups in -lbsd... " >&6; } +if ${ac_cv_lib_bsd_getgroups+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getgroups (); +int +main () +{ +return getgroups (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bsd_getgroups=yes +else + ac_cv_lib_bsd_getgroups=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_getgroups" >&5 +$as_echo "$ac_cv_lib_bsd_getgroups" >&6; } +if test "x$ac_cv_lib_bsd_getgroups" = xyes; then : + GETGROUPS_LIB=-lbsd +fi + + fi + + # Run the program to test the functionality of the system-supplied + # getgroups function only if there is such a function. + if test $ac_cv_func_getgroups = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working getgroups" >&5 +$as_echo_n "checking for working getgroups... " >&6; } +if ${ac_cv_func_getgroups_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + case "$host_os" in # (( + # Guess yes on glibc systems. + *-gnu*) ac_cv_func_getgroups_works="guessing yes" ;; + # If we don't know, assume the worst. + *) ac_cv_func_getgroups_works="guessing no" ;; + esac + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +/* On Ultrix 4.3, getgroups (0, 0) always fails. */ + return getgroups (0, 0) == -1; + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_getgroups_works=yes +else + ac_cv_func_getgroups_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getgroups_works" >&5 +$as_echo "$ac_cv_func_getgroups_works" >&6; } + else + ac_cv_func_getgroups_works=no + fi + case "$ac_cv_func_getgroups_works" in + *yes) + +$as_echo "#define HAVE_GETGROUPS 1" >>confdefs.h + + ;; + esac + LIBS=$ac_save_LIBS + + + # Solaris 9 and 10 need -lgen to get the eaccess function. + # Save and restore LIBS so -lgen isn't added to it. Otherwise, *all* + # programs in the package would end up linked with that potentially-shared + # library, inducing unnecessary run-time overhead. + LIB_EACCESS= + + gl_saved_libs=$LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing eaccess" >&5 +$as_echo_n "checking for library containing eaccess... " >&6; } +if ${ac_cv_search_eaccess+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char eaccess (); +int +main () +{ +return eaccess (); + ; + return 0; +} +_ACEOF +for ac_lib in '' gen; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_eaccess=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_eaccess+:} false; then : + break +fi +done +if ${ac_cv_search_eaccess+:} false; then : + +else + ac_cv_search_eaccess=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_eaccess" >&5 +$as_echo "$ac_cv_search_eaccess" >&6; } +ac_res=$ac_cv_search_eaccess +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + test "$ac_cv_search_eaccess" = "none required" || + LIB_EACCESS=$ac_cv_search_eaccess +fi + + for ac_func in eaccess +do : + ac_fn_c_check_func "$LINENO" "eaccess" "ac_cv_func_eaccess" +if test "x$ac_cv_func_eaccess" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EACCESS 1 +_ACEOF + +fi +done + + LIBS=$gl_saved_libs + + fi + + + + + + GNULIB_EUIDACCESS=1 + + + + + +$as_echo "#define GNULIB_TEST_EUIDACCESS 1" >>confdefs.h + + + + + + + + + + + if test $ac_cv_func_faccessat = no; then + HAVE_FACCESSAT=0 + fi + + if test $HAVE_FACCESSAT = 0; then + + + + + + + + + gl_LIBOBJS="$gl_LIBOBJS faccessat.$ac_objext" + + + for ac_func in access +do : + ac_fn_c_check_func "$LINENO" "access" "ac_cv_func_access" +if test "x$ac_cv_func_access" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ACCESS 1 +_ACEOF + +fi +done + + + fi + + +cat >>confdefs.h <<_ACEOF +#define GNULIB_FACCESSAT 1 +_ACEOF + + + + + + + + GNULIB_FACCESSAT=1 + + + + + +$as_echo "#define GNULIB_TEST_FACCESSAT 1" >>confdefs.h + + + @@ -15490,36 +15900,43 @@ if ${gl_cv_func_fcntl_f_dupfd_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : - # Guess that it works on glibc systems - case $host_os in #(( - *-gnu*) gl_cv_func_fcntl_f_dupfd_works="guessing yes";; - *) gl_cv_func_fcntl_f_dupfd_works="guessing no";; + case $host_os in + aix* | cygwin* | haiku*) + gl_cv_func_fcntl_f_dupfd_works="guessing no" ;; + *) gl_cv_func_fcntl_f_dupfd_works="guessing yes" ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - -#ifdef HAVE_GETDTABLESIZE -# include -#endif -#include #include + #include + #include + #include + #include + #ifndef RLIM_SAVED_CUR + # define RLIM_SAVED_CUR RLIM_INFINITY + #endif + #ifndef RLIM_SAVED_MAX + # define RLIM_SAVED_MAX RLIM_INFINITY + #endif int main () { int result = 0; -#ifdef HAVE_GETDTABLESIZE - int bad_fd = getdtablesize (); -#else - int bad_fd = 1000000; -#endif - if (fcntl (0, F_DUPFD, -1) != -1) result |= 1; - if (errno != EINVAL) result |= 2; - if (fcntl (0, F_DUPFD, bad_fd) != -1) result |= 4; - if (errno != EINVAL) result |= 8; - return result; - + int bad_fd = INT_MAX; + struct rlimit rlim; + if (getrlimit (RLIMIT_NOFILE, &rlim) == 0 + && 0 <= rlim.rlim_cur && rlim.rlim_cur <= INT_MAX + && rlim.rlim_cur != RLIM_INFINITY + && rlim.rlim_cur != RLIM_SAVED_MAX + && rlim.rlim_cur != RLIM_SAVED_CUR) + bad_fd = rlim.rlim_cur; + if (fcntl (0, F_DUPFD, -1) != -1) result |= 1; + if (errno != EINVAL) result |= 2; + if (fcntl (0, F_DUPFD, bad_fd) != -1) result |= 4; + if (errno != EINVAL) result |= 8; + return result; ; return 0; } @@ -16198,7 +16615,9 @@ $as_echo "#define GNULIB_TEST_GETCWD 1" >>confdefs.h - if test $ac_cv_func_getdtablesize = yes; then + + if test $ac_cv_func_getdtablesize = yes && + test $ac_cv_have_decl_getdtablesize = yes; then # Cygwin 1.7.25 automatically increases the RLIMIT_NOFILE soft limit # up to an unchangeable hard limit; all other platforms correctly # require setrlimit before getdtablesize() can report a larger value. @@ -16285,6 +16704,206 @@ $as_echo "#define GNULIB_TEST_GETDTABLESIZE 1" >>confdefs.h + ac_fn_c_check_func "$LINENO" "getgroups" "ac_cv_func_getgroups" +if test "x$ac_cv_func_getgroups" = xyes; then : + +fi + + + # If we don't yet have getgroups, see if it's in -lbsd. + # This is reported to be necessary on an ITOS 3000WS running SEIUX 3.1. + ac_save_LIBS=$LIBS + if test $ac_cv_func_getgroups = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgroups in -lbsd" >&5 +$as_echo_n "checking for getgroups in -lbsd... " >&6; } +if ${ac_cv_lib_bsd_getgroups+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getgroups (); +int +main () +{ +return getgroups (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bsd_getgroups=yes +else + ac_cv_lib_bsd_getgroups=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_getgroups" >&5 +$as_echo "$ac_cv_lib_bsd_getgroups" >&6; } +if test "x$ac_cv_lib_bsd_getgroups" = xyes; then : + GETGROUPS_LIB=-lbsd +fi + + fi + + # Run the program to test the functionality of the system-supplied + # getgroups function only if there is such a function. + if test $ac_cv_func_getgroups = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working getgroups" >&5 +$as_echo_n "checking for working getgroups... " >&6; } +if ${ac_cv_func_getgroups_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + case "$host_os" in # (( + # Guess yes on glibc systems. + *-gnu*) ac_cv_func_getgroups_works="guessing yes" ;; + # If we don't know, assume the worst. + *) ac_cv_func_getgroups_works="guessing no" ;; + esac + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +/* On Ultrix 4.3, getgroups (0, 0) always fails. */ + return getgroups (0, 0) == -1; + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_getgroups_works=yes +else + ac_cv_func_getgroups_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getgroups_works" >&5 +$as_echo "$ac_cv_func_getgroups_works" >&6; } + else + ac_cv_func_getgroups_works=no + fi + case "$ac_cv_func_getgroups_works" in + *yes) + +$as_echo "#define HAVE_GETGROUPS 1" >>confdefs.h + + ;; + esac + LIBS=$ac_save_LIBS + + if test $ac_cv_func_getgroups != yes; then + HAVE_GETGROUPS=0 + else + if test "$ac_cv_type_getgroups" != gid_t \ + || { case "$ac_cv_func_getgroups_works" in + *yes) false;; + *) true;; + esac + }; then + REPLACE_GETGROUPS=1 + +$as_echo "#define GETGROUPS_ZERO_BUG 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether getgroups handles negative values" >&5 +$as_echo_n "checking whether getgroups handles negative values... " >&6; } +if ${gl_cv_func_getgroups_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_getgroups_works="guessing yes" ;; + # If we don't know, assume the worst. + *) gl_cv_func_getgroups_works="guessing no" ;; + esac + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +int size = getgroups (0, 0); + gid_t *list = malloc (size * sizeof *list); + return getgroups (-1, list) != -1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + gl_cv_func_getgroups_works=yes +else + gl_cv_func_getgroups_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_func_getgroups_works" >&5 +$as_echo "$gl_cv_func_getgroups_works" >&6; } + case "$gl_cv_func_getgroups_works" in + *yes) ;; + *) REPLACE_GETGROUPS=1 ;; + esac + fi + fi + test -n "$GETGROUPS_LIB" && LIBS="$GETGROUPS_LIB $LIBS" + + if test $HAVE_GETGROUPS = 0 || test $REPLACE_GETGROUPS = 1; then + + + + + + + + + gl_LIBOBJS="$gl_LIBOBJS getgroups.$ac_objext" + + fi + + + + + + GNULIB_GETGROUPS=1 + + + + + +$as_echo "#define GNULIB_TEST_GETGROUPS 1" >>confdefs.h + + + + + + + + if test $REPLACE_GETOPT = 1; then @@ -16585,6 +17204,51 @@ $as_echo "#define GNULIB_TEST_GETTIMEOFDAY 1" >>confdefs.h + ac_fn_c_check_func "$LINENO" "group_member" "ac_cv_func_group_member" +if test "x$ac_cv_func_group_member" = xyes; then : + +else + + HAVE_GROUP_MEMBER=0 + +fi + + + if test $HAVE_GROUP_MEMBER = 0; then + + + + + + + + + gl_LIBOBJS="$gl_LIBOBJS group-member.$ac_objext" + + + + + fi + + + + + + GNULIB_GROUP_MEMBER=1 + + + + + +$as_echo "#define GNULIB_TEST_GROUP_MEMBER 1" >>confdefs.h + + + + + + + + for ac_func in lchown do : ac_fn_c_check_func "$LINENO" "lchown" "ac_cv_func_lchown" @@ -22574,6 +23238,20 @@ $as_echo "#define GNULIB_TEST_VASPRINTF 1" >>confdefs.h + XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS --flag=asprintf:2:c-format" + + + + XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS --flag=vasprintf:2:c-format" + + + + XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS --flag=verror:3:c-format" + + + + XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS --flag=verror_at_line:5:c-format" + @@ -23154,6 +23832,9 @@ done : + + XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS --flag=xasprintf:1:c-format" + # End of code from modules @@ -24991,7 +25672,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by GNU patch $as_me 2.7.4, which was +This file was extended by GNU patch $as_me 2.7.5, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -25063,7 +25744,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -GNU patch config.status 2.7.4 +GNU patch config.status 2.7.5 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/lib/Makefile.in b/lib/Makefile.in index bc3e544..9487d28 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -35,7 +35,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl --lib=libpatch --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --makefile-name=gnulib.mk --no-conditional-dependencies --no-libtool --macro-prefix=gl argmatch backupfile clock-time diffseq dirname dup2 errno exitfail extensions fchmodat fchownat fcntl-h fstatat full-write getdate getopt-gnu gettime git-version-gen gitlog-to-changelog hash ignore-value intprops largefile linked-list maintainer-makefile malloc manywarnings memchr minmax mkdirat openat progname quotearg readlinkat realloc renameat setenv signal ssize_t stat-time stdbool stdlib symlinkat sys_stat tempname time unistd unlinkat update-copyright utimensat verror xalloc xlist xmemdup0 +# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl --lib=libpatch --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --makefile-name=gnulib.mk --no-conditional-dependencies --no-libtool --macro-prefix=gl argmatch backupfile clock-time diffseq dirname dup2 errno exitfail extensions faccessat fchmodat fchownat fcntl-h fstatat full-write getdate getopt-gnu gettime git-version-gen gitlog-to-changelog hash ignore-value intprops largefile linked-list maintainer-makefile malloc manywarnings memchr minmax mkdirat openat progname quotearg readlinkat realloc renameat setenv signal ssize_t stat-time stdbool stdlib symlinkat sys_stat tempname time unistd unlinkat update-copyright utimensat verror xalloc xlist xmemdup0 VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' @@ -118,17 +118,21 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \ $(top_srcdir)/m4/double-slash-root.m4 $(top_srcdir)/m4/dup2.m4 \ $(top_srcdir)/m4/eealloc.m4 $(top_srcdir)/m4/environ.m4 \ $(top_srcdir)/m4/errno_h.m4 $(top_srcdir)/m4/error.m4 \ - $(top_srcdir)/m4/exponentd.m4 $(top_srcdir)/m4/extensions.m4 \ - $(top_srcdir)/m4/extern-inline.m4 $(top_srcdir)/m4/fchdir.m4 \ + $(top_srcdir)/m4/euidaccess.m4 $(top_srcdir)/m4/exponentd.m4 \ + $(top_srcdir)/m4/extensions.m4 \ + $(top_srcdir)/m4/extern-inline.m4 \ + $(top_srcdir)/m4/faccessat.m4 $(top_srcdir)/m4/fchdir.m4 \ $(top_srcdir)/m4/fchmodat.m4 $(top_srcdir)/m4/fchownat.m4 \ $(top_srcdir)/m4/fcntl-o.m4 $(top_srcdir)/m4/fcntl.m4 \ $(top_srcdir)/m4/fcntl_h.m4 $(top_srcdir)/m4/filenamecat.m4 \ $(top_srcdir)/m4/float_h.m4 $(top_srcdir)/m4/fstat.m4 \ $(top_srcdir)/m4/fstatat.m4 $(top_srcdir)/m4/getcwd.m4 \ - $(top_srcdir)/m4/getdtablesize.m4 $(top_srcdir)/m4/getopt.m4 \ + $(top_srcdir)/m4/getdtablesize.m4 \ + $(top_srcdir)/m4/getgroups.m4 $(top_srcdir)/m4/getopt.m4 \ $(top_srcdir)/m4/gettime.m4 $(top_srcdir)/m4/gettimeofday.m4 \ $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnulib-common.m4 \ $(top_srcdir)/m4/gnulib-comp.m4 \ + $(top_srcdir)/m4/group-member.m4 \ $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/intmax_t.m4 \ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/largefile.m4 \ $(top_srcdir)/m4/lchown.m4 $(top_srcdir)/m4/localcharset.m4 \ @@ -800,6 +804,7 @@ LIBPATCH_LIBDEPS = @LIBPATCH_LIBDEPS@ LIBPATCH_LTLIBDEPS = @LIBPATCH_LTLIBDEPS@ LIBS = @LIBS@ LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ +LIB_EACCESS = @LIB_EACCESS@ LIB_XATTR = @LIB_XATTR@ LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@ LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@ @@ -1105,16 +1110,17 @@ EXTRA_DIST = alloca.in.h argmatch.h assure.h openat-priv.h \ chdir-long.c chdir-long.h chown.c fchown-stub.c cloexec.h \ close.c closedir.c dirent-private.h dirent.in.h dirent--.h \ dirent-safer.h dirfd.c stripslash.c dirname.h dosname.h dup2.c \ - errno.in.h error.c error.h exitfail.h fchdir.c at-func.c \ - fchmodat.c at-func.c fchownat.c fcntl.c fcntl.in.h fd-hook.h \ - filename.h filenamecat.h float.c float.in.h itold.c fstat.c \ - at-func.c fstatat.c getcwd-lgpl.c getdate.h getdtablesize.c \ - getopt.c getopt.in.h getopt1.c getopt_int.h gettimeofday.c \ + errno.in.h error.c error.h euidaccess.c exitfail.h at-func.c \ + faccessat.c fchdir.c at-func.c fchmodat.c at-func.c fchownat.c \ + fcntl.c fcntl.in.h fd-hook.h filename.h filenamecat.h float.c \ + float.in.h itold.c fstat.c at-func.c fstatat.c getcwd-lgpl.c \ + getdate.h getdtablesize.c getgroups.c getopt.c getopt.in.h \ + getopt1.c getopt_int.h gettimeofday.c \ $(top_srcdir)/build-aux/git-version-gen \ $(top_srcdir)/build-aux/gitlog-to-changelog \ - $(top_srcdir)/GNUmakefile hash.h ignore-value.h intprops.h \ - lchown.c config.charset ref-add.sin ref-del.sin lstat.c \ - $(top_srcdir)/maint.mk malloc.c malloc.c malloca.h \ + $(top_srcdir)/GNUmakefile group-member.c hash.h ignore-value.h \ + intprops.h lchown.c config.charset ref-add.sin ref-del.sin \ + lstat.c $(top_srcdir)/maint.mk malloc.c malloc.c malloca.h \ malloca.valgrind mbrtowc.c mbsinit.c memchr.c memchr.valgrind \ mempcpy.c memrchr.c mkdir.c at-func.c mkdirat.c \ mktime-internal.h mktime.c msvc-inval.c msvc-inval.h \ @@ -1122,9 +1128,10 @@ EXTRA_DIST = alloca.in.h argmatch.h assure.h openat-priv.h \ dirent-private.h opendir.c parse-datetime.c parse-datetime.h \ pathmax.h quote.h quote.h quotearg.h raise.c dirent-private.h \ readdir.c readlink.c at-func.c readlinkat.c realloc.c \ - realloc.c rename.c at-func2.c renameat.c rmdir.c safe-read.c \ - safe-write.h same-inode.h save-cwd.h secure_getenv.c setenv.c \ - signal.in.h $(top_srcdir)/build-aux/snippet/_Noreturn.h \ + realloc.c rename.c at-func2.c renameat.c rmdir.c root-uid.h \ + safe-read.c safe-write.h same-inode.h save-cwd.h \ + secure_getenv.c setenv.c signal.in.h \ + $(top_srcdir)/build-aux/snippet/_Noreturn.h \ $(top_srcdir)/build-aux/snippet/arg-nonnull.h \ $(top_srcdir)/build-aux/snippet/c++defs.h \ $(top_srcdir)/build-aux/snippet/warn-on-use.h stat.c \ @@ -1175,10 +1182,11 @@ libpatch_a_LIBADD = $(gl_LIBOBJS) libpatch_a_DEPENDENCIES = $(gl_LIBOBJS) EXTRA_libpatch_a_SOURCES = openat-proc.c canonicalize-lgpl.c \ chdir-long.c chown.c fchown-stub.c close.c closedir.c dirfd.c \ - stripslash.c dup2.c error.c fchdir.c at-func.c fchmodat.c \ - at-func.c fchownat.c fcntl.c float.c itold.c fstat.c at-func.c \ - fstatat.c getcwd-lgpl.c getdtablesize.c getopt.c getopt1.c \ - gettimeofday.c lchown.c lstat.c malloc.c malloc.c mbrtowc.c \ + stripslash.c dup2.c error.c euidaccess.c at-func.c faccessat.c \ + fchdir.c at-func.c fchmodat.c at-func.c fchownat.c fcntl.c \ + float.c itold.c fstat.c at-func.c fstatat.c getcwd-lgpl.c \ + getdtablesize.c getgroups.c getopt.c getopt1.c gettimeofday.c \ + group-member.c lchown.c lstat.c malloc.c malloc.c mbrtowc.c \ mbsinit.c memchr.c mempcpy.c memrchr.c mkdir.c at-func.c \ mkdirat.c mktime.c msvc-inval.c msvc-nothrow.c open.c openat.c \ opendir.c raise.c readdir.c readlink.c at-func.c readlinkat.c \ @@ -1281,7 +1289,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dup-safer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dup2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/euidaccess.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exitfail.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/faccessat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fchdir.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fchmodat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fchown-stub.Po@am__quote@ @@ -1296,6 +1306,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/full-write.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getcwd-lgpl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getdtablesize.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getgroups.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettime.Po@am__quote@ @@ -1303,6 +1314,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gl_linked_list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gl_list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gl_xlist.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/group-member.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/itold.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lchown.Po@am__quote@ diff --git a/lib/diffseq.h b/lib/diffseq.h index b418830..a4f389a 100644 --- a/lib/diffseq.h +++ b/lib/diffseq.h @@ -41,8 +41,8 @@ EQUAL A two-argument macro that tests two elements for equality. OFFSET A signed integer type sufficient to hold the - difference between two indices. Usually - something like ssize_t. + difference between two indices. Usually + something like ptrdiff_t. EXTRA_CONTEXT_FIELDS Declarations of fields for 'struct context'. NOTE_DELETE(ctxt, xoff) Record the removal of the object xvec[xoff]. NOTE_INSERT(ctxt, yoff) Record the insertion of the object yvec[yoff]. diff --git a/lib/dirent--.h b/lib/dirent--.h index 17a8853..aa3f492 100644 --- a/lib/dirent--.h +++ b/lib/dirent--.h @@ -21,3 +21,4 @@ #undef opendir #define opendir opendir_safer +#define GNULIB_defined_opendir 1 diff --git a/lib/dirent.in.h b/lib/dirent.in.h index ddd3b84..154d268 100644 --- a/lib/dirent.in.h +++ b/lib/dirent.in.h @@ -77,6 +77,7 @@ typedef struct gl_directory DIR; # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef opendir # define opendir rpl_opendir +# define GNULIB_defined_opendir 1 # endif _GL_FUNCDECL_RPL (opendir, DIR *, (const char *dir_name) _GL_ARG_NONNULL ((1))); _GL_CXXALIAS_RPL (opendir, DIR *, (const char *dir_name)); @@ -128,6 +129,7 @@ _GL_WARN_ON_USE (rewinddir, "rewinddir is not portable - " # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef closedir # define closedir rpl_closedir +# define GNULIB_defined_closedir 1 # endif _GL_FUNCDECL_RPL (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1))); _GL_CXXALIAS_RPL (closedir, int, (DIR *dirp)); diff --git a/lib/euidaccess.c b/lib/euidaccess.c new file mode 100644 index 0000000..c7e6cfb --- /dev/null +++ b/lib/euidaccess.c @@ -0,0 +1,221 @@ +/* euidaccess -- check if effective user id can access file + + Copyright (C) 1990-1991, 1995, 1998, 2000, 2003-2006, 2008-2015 Free + Software Foundation, Inc. + + This file is part of the GNU C Library. + + 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 David MacKenzie and Torbjorn Granlund. + Adapted for GNU C library by Roland McGrath. */ + +#ifndef _LIBC +# include +#endif + +#include +#include +#include +#include + +#include "root-uid.h" + +#if HAVE_LIBGEN_H +# include +#endif + +#include +#ifndef __set_errno +# define __set_errno(val) errno = (val) +#endif + +#if defined EACCES && !defined EACCESS +# define EACCESS EACCES +#endif + +#ifndef F_OK +# define F_OK 0 +# define X_OK 1 +# define W_OK 2 +# define R_OK 4 +#endif + + +#ifdef _LIBC + +# define access __access +# define getuid __getuid +# define getgid __getgid +# define geteuid __geteuid +# define getegid __getegid +# define group_member __group_member +# define euidaccess __euidaccess +# undef stat +# define stat stat64 + +#endif + +/* Return 0 if the user has permission of type MODE on FILE; + otherwise, return -1 and set 'errno'. + Like access, except that it uses the effective user and group + id's instead of the real ones, and it does not always check for read-only + file system, text busy, etc. */ + +int +euidaccess (const char *file, int mode) +{ +#if HAVE_FACCESSAT /* glibc, AIX 7, Solaris 11, Cygwin 1.7 */ + return faccessat (AT_FDCWD, file, mode, AT_EACCESS); +#elif defined EFF_ONLY_OK /* IRIX, OSF/1, Interix */ + return access (file, mode | EFF_ONLY_OK); +#elif defined ACC_SELF /* AIX */ + return accessx (file, mode, ACC_SELF); +#elif HAVE_EACCESS /* FreeBSD */ + return eaccess (file, mode); +#else /* Mac OS X, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, mingw, BeOS */ + + uid_t uid = getuid (); + gid_t gid = getgid (); + uid_t euid = geteuid (); + gid_t egid = getegid (); + struct stat stats; + +# if HAVE_DECL_SETREGID && PREFER_NONREENTRANT_EUIDACCESS + + /* Define PREFER_NONREENTRANT_EUIDACCESS if you prefer euidaccess to + return the correct result even if this would make it + nonreentrant. Define this only if your entire application is + safe even if the uid or gid might temporarily change. If your + application uses signal handlers or threads it is probably not + safe. */ + + if (mode == F_OK) + return stat (file, &stats); + else + { + int result; + int saved_errno; + + if (uid != euid) + setreuid (euid, uid); + if (gid != egid) + setregid (egid, gid); + + result = access (file, mode); + saved_errno = errno; + + /* Restore them. */ + if (uid != euid) + setreuid (uid, euid); + if (gid != egid) + setregid (gid, egid); + + errno = saved_errno; + return result; + } + +# else + + /* The following code assumes the traditional Unix model, and is not + correct on systems that have ACLs or the like. However, it's + better than nothing, and it is reentrant. */ + + unsigned int granted; + if (uid == euid && gid == egid) + /* If we are not set-uid or set-gid, access does the same. */ + return access (file, mode); + + if (stat (file, &stats) != 0) + return -1; + + /* The super-user can read and write any file, and execute any file + that anyone can execute. */ + if (euid == ROOT_UID + && ((mode & X_OK) == 0 + || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))) + return 0; + + /* Convert the mode to traditional form, clearing any bogus bits. */ + if (R_OK == 4 && W_OK == 2 && X_OK == 1 && F_OK == 0) + mode &= 7; + else + mode = ((mode & R_OK ? 4 : 0) + + (mode & W_OK ? 2 : 0) + + (mode & X_OK ? 1 : 0)); + + if (mode == 0) + return 0; /* The file exists. */ + + /* Convert the file's permission bits to traditional form. */ + if (S_IRUSR == (4 << 6) && S_IWUSR == (2 << 6) && S_IXUSR == (1 << 6) + && S_IRGRP == (4 << 3) && S_IWGRP == (2 << 3) && S_IXGRP == (1 << 3) + && S_IROTH == (4 << 0) && S_IWOTH == (2 << 0) && S_IXOTH == (1 << 0)) + granted = stats.st_mode; + else + granted = ((stats.st_mode & S_IRUSR ? 4 << 6 : 0) + + (stats.st_mode & S_IWUSR ? 2 << 6 : 0) + + (stats.st_mode & S_IXUSR ? 1 << 6 : 0) + + (stats.st_mode & S_IRGRP ? 4 << 3 : 0) + + (stats.st_mode & S_IWGRP ? 2 << 3 : 0) + + (stats.st_mode & S_IXGRP ? 1 << 3 : 0) + + (stats.st_mode & S_IROTH ? 4 << 0 : 0) + + (stats.st_mode & S_IWOTH ? 2 << 0 : 0) + + (stats.st_mode & S_IXOTH ? 1 << 0 : 0)); + + if (euid == stats.st_uid) + granted >>= 6; + else if (egid == stats.st_gid || group_member (stats.st_gid)) + granted >>= 3; + + if ((mode & ~granted) == 0) + return 0; + __set_errno (EACCESS); + return -1; + +# endif +#endif +} +#undef euidaccess +#ifdef weak_alias +weak_alias (__euidaccess, euidaccess) +#endif + +#ifdef TEST +# include +# include +# include + +char *program_name; + +int +main (int argc, char **argv) +{ + char *file; + int mode; + int err; + + program_name = argv[0]; + if (argc < 3) + abort (); + file = argv[1]; + mode = atoi (argv[2]); + + err = euidaccess (file, mode); + printf ("%d\n", err); + if (err != 0) + error (0, errno, "%s", file); + exit (0); +} +#endif diff --git a/lib/faccessat.c b/lib/faccessat.c new file mode 100644 index 0000000..5bd7ecf --- /dev/null +++ b/lib/faccessat.c @@ -0,0 +1,45 @@ +/* Check the access rights of a file relative to an open directory. + Copyright (C) 2009-2015 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 Eric Blake */ + +#include + +#include +#include + +#ifndef HAVE_ACCESS +/* Mingw lacks access, but it also lacks real vs. effective ids, so + the gnulib euidaccess module is good enough. */ +# undef access +# define access euidaccess +#endif + +/* Invoke access or euidaccess on file, FILE, using mode MODE, in the directory + open on descriptor FD. If possible, do it without changing the + working directory. Otherwise, resort to using save_cwd/fchdir, then + (access|euidaccess)/restore_cwd. If either the save_cwd or the + restore_cwd fails, then give a diagnostic and exit nonzero. + Note that this implementation only supports AT_EACCESS, although some + native versions also support AT_SYMLINK_NOFOLLOW. */ + +#define AT_FUNC_NAME faccessat +#define AT_FUNC_F1 euidaccess +#define AT_FUNC_F2 access +#define AT_FUNC_USE_F1_COND AT_EACCESS +#define AT_FUNC_POST_FILE_PARAM_DECLS , int mode, int flag +#define AT_FUNC_POST_FILE_ARGS , mode +#include "at-func.c" diff --git a/lib/getdtablesize.c b/lib/getdtablesize.c index 59b9736..03eb7ef 100644 --- a/lib/getdtablesize.c +++ b/lib/getdtablesize.c @@ -84,32 +84,38 @@ getdtablesize (void) return dtablesize; } -#elif HAVE_GETDTABLESIZE +#else +# include # include -# undef getdtablesize -int -rpl_getdtablesize(void) -{ - /* To date, this replacement is only compiled for Cygwin 1.7.25, - which auto-increased the RLIMIT_NOFILE soft limit until it - hits the compile-time constant hard limit of 3200. Although - that version of cygwin supported a child process inheriting - a smaller soft limit, the smaller limit is not enforced, so - we might as well just report the hard limit. */ - struct rlimit lim; - if (!getrlimit (RLIMIT_NOFILE, &lim) && lim.rlim_max != RLIM_INFINITY) - return lim.rlim_max; - return getdtablesize (); -} +# ifndef RLIM_SAVED_CUR +# define RLIM_SAVED_CUR RLIM_INFINITY +# endif +# ifndef RLIM_SAVED_MAX +# define RLIM_SAVED_MAX RLIM_INFINITY +# endif -#elif defined _SC_OPEN_MAX +# ifdef __CYGWIN__ + /* Cygwin 1.7.25 auto-increases the RLIMIT_NOFILE soft limit until it + hits the compile-time constant hard limit of 3200. We might as + well just report the hard limit. */ +# define rlim_cur rlim_max +# endif int getdtablesize (void) { - return sysconf (_SC_OPEN_MAX); + struct rlimit lim; + + if (getrlimit (RLIMIT_NOFILE, &lim) == 0 + && 0 <= lim.rlim_cur && lim.rlim_cur <= INT_MAX + && lim.rlim_cur != RLIM_INFINITY + && lim.rlim_cur != RLIM_SAVED_CUR + && lim.rlim_cur != RLIM_SAVED_MAX) + return lim.rlim_cur; + + return INT_MAX; } #endif diff --git a/lib/getgroups.c b/lib/getgroups.c new file mode 100644 index 0000000..5563dfb --- /dev/null +++ b/lib/getgroups.c @@ -0,0 +1,131 @@ +/* provide consistent interface to getgroups for systems that don't allow N==0 + + Copyright (C) 1996, 1999, 2003, 2006-2015 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 + +#include + +#include +#include +#include + +#if !HAVE_GETGROUPS + +/* Provide a stub that fails with ENOSYS, since there is no group + information available on mingw. */ +int +getgroups (int n _GL_UNUSED, GETGROUPS_T *groups _GL_UNUSED) +{ + errno = ENOSYS; + return -1; +} + +#else /* HAVE_GETGROUPS */ + +# undef getgroups +# ifndef GETGROUPS_ZERO_BUG +# define GETGROUPS_ZERO_BUG 0 +# endif + +/* On OS X 10.6 and later, use the usual getgroups, not the one + supplied when _DARWIN_C_SOURCE is defined. _DARWIN_C_SOURCE is + normally defined, since it means "conform to POSIX, but add + non-POSIX extensions even if that violates the POSIX namespace + rules", which is what we normally want. But with getgroups there + is an inconsistency, and _DARWIN_C_SOURCE means "change getgroups() + so that it no longer works right". The BUGS section of compat(5) + says that the behavior is dubious if you compile different sections + of a program with different _DARWIN_C_SOURCE settings, so fix only + the offending symbol. */ +# ifdef __APPLE__ +int posix_getgroups (int, gid_t []) __asm ("_getgroups"); +# define getgroups posix_getgroups +# endif + +/* On at least Ultrix 4.3 and NextStep 3.2, getgroups (0, NULL) always + fails. On other systems, it returns the number of supplemental + groups for the process. This function handles that special case + and lets the system-provided function handle all others. However, + it can fail with ENOMEM if memory is tight. It is unspecified + whether the effective group id is included in the list. */ + +int +rpl_getgroups (int n, gid_t *group) +{ + int n_groups; + GETGROUPS_T *gbuf; + int saved_errno; + + if (n < 0) + { + errno = EINVAL; + return -1; + } + + if (n != 0 || !GETGROUPS_ZERO_BUG) + { + int result; + if (sizeof *group == sizeof *gbuf) + return getgroups (n, (GETGROUPS_T *) group); + + if (SIZE_MAX / sizeof *gbuf <= n) + { + errno = ENOMEM; + return -1; + } + gbuf = malloc (n * sizeof *gbuf); + if (!gbuf) + return -1; + result = getgroups (n, gbuf); + if (0 <= result) + { + n = result; + while (n--) + group[n] = gbuf[n]; + } + saved_errno = errno; + free (gbuf); + errno = saved_errno; + return result; + } + + n = 20; + while (1) + { + /* No need to worry about address arithmetic overflow here, + since the ancient systems that we're running on have low + limits on the number of secondary groups. */ + gbuf = malloc (n * sizeof *gbuf); + if (!gbuf) + return -1; + n_groups = getgroups (n, gbuf); + if (n_groups == -1 ? errno != EINVAL : n_groups < n) + break; + free (gbuf); + n *= 2; + } + + saved_errno = errno; + free (gbuf); + errno = saved_errno; + + return n_groups; +} + +#endif /* HAVE_GETGROUPS */ diff --git a/lib/getopt.c b/lib/getopt.c index 3b9c585..212cbf7 100644 --- a/lib/getopt.c +++ b/lib/getopt.c @@ -487,7 +487,20 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, const struct option *p; struct option_list *next; } *ambig_list = NULL; +#ifdef _LIBC +/* malloc() not used for _LIBC to simplify failure messages. */ +# define free_option_list(l) +#else +# define free_option_list(l) \ + while (l != NULL) \ + { \ + struct option_list *pn = l->next; \ + free (l); \ + l = pn; \ + } +#endif int exact = 0; + int ambig = 0; int indfound = -1; int option_index; @@ -514,22 +527,37 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, pfound = p; indfound = option_index; } + else if (ambig) + ; /* Taking simpler path to handling ambiguities. */ else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) { /* Second or later nonexact match found. */ +#ifdef _LIBC + struct option_list *newp = alloca (sizeof (*newp)); +#else struct option_list *newp = malloc (sizeof (*newp)); - newp->p = p; - newp->next = ambig_list; - ambig_list = newp; + if (newp == NULL) + { + free_option_list (ambig_list); + ambig_list = NULL; + ambig = 1; /* Use simpler fallback message. */ + } + else +#endif + { + newp->p = p; + newp->next = ambig_list; + ambig_list = newp; + } } } - if (ambig_list != NULL && !exact) + if ((ambig || ambig_list) && !exact) { - if (print_errors) + if (print_errors && ambig_list) { struct option_list first; first.p = pfound; @@ -585,18 +613,20 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, fputc ('\n', stderr); #endif } + else if (print_errors && ambig) + { + fprintf (stderr, + _("%s: option '%s' is ambiguous\n"), + argv[0], argv[d->optind]); + } d->__nextchar += strlen (d->__nextchar); d->optind++; d->optopt = 0; + free_option_list (ambig_list); return '?'; } - while (ambig_list != NULL) - { - struct option_list *pn = ambig_list->next; - free (ambig_list); - ambig_list = pn; - } + free_option_list (ambig_list); if (pfound != NULL) { diff --git a/lib/gnulib.mk b/lib/gnulib.mk index 9d80d74..e7d245a 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk @@ -21,7 +21,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl --lib=libpatch --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --makefile-name=gnulib.mk --no-conditional-dependencies --no-libtool --macro-prefix=gl argmatch backupfile clock-time diffseq dirname dup2 errno exitfail extensions fchmodat fchownat fcntl-h fstatat full-write getdate getopt-gnu gettime git-version-gen gitlog-to-changelog hash ignore-value intprops largefile linked-list maintainer-makefile malloc manywarnings memchr minmax mkdirat openat progname quotearg readlinkat realloc renameat setenv signal ssize_t stat-time stdbool stdlib symlinkat sys_stat tempname time unistd unlinkat update-copyright utimensat verror xalloc xlist xmemdup0 +# Reproduce by: gnulib-tool --import --dir=. --local-dir=gl --lib=libpatch --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --makefile-name=gnulib.mk --no-conditional-dependencies --no-libtool --macro-prefix=gl argmatch backupfile clock-time diffseq dirname dup2 errno exitfail extensions faccessat fchmodat fchownat fcntl-h fstatat full-write getdate getopt-gnu gettime git-version-gen gitlog-to-changelog hash ignore-value intprops largefile linked-list maintainer-makefile malloc manywarnings memchr minmax mkdirat openat progname quotearg readlinkat realloc renameat setenv signal ssize_t stat-time stdbool stdlib symlinkat sys_stat tempname time unistd unlinkat update-copyright utimensat verror xalloc xlist xmemdup0 MOSTLYCLEANFILES += core *.stackdump @@ -368,6 +368,15 @@ EXTRA_libpatch_a_SOURCES += error.c ## end gnulib module error +## begin gnulib module euidaccess + + +EXTRA_DIST += euidaccess.c + +EXTRA_libpatch_a_SOURCES += euidaccess.c + +## end gnulib module euidaccess + ## begin gnulib module exitfail libpatch_a_SOURCES += exitfail.c @@ -376,6 +385,15 @@ EXTRA_DIST += exitfail.h ## end gnulib module exitfail +## begin gnulib module faccessat + + +EXTRA_DIST += at-func.c faccessat.c + +EXTRA_libpatch_a_SOURCES += at-func.c faccessat.c + +## end gnulib module faccessat + ## begin gnulib module fchdir @@ -552,6 +570,15 @@ EXTRA_libpatch_a_SOURCES += getdtablesize.c ## end gnulib module getdtablesize +## begin gnulib module getgroups + + +EXTRA_DIST += getgroups.c + +EXTRA_libpatch_a_SOURCES += getgroups.c + +## end gnulib module getgroups + ## begin gnulib module getopt-posix BUILT_SOURCES += $(GETOPT_H) @@ -624,6 +651,15 @@ EXTRA_DIST += $(top_srcdir)/GNUmakefile ## end gnulib module gnumakefile +## begin gnulib module group-member + + +EXTRA_DIST += group-member.c + +EXTRA_libpatch_a_SOURCES += group-member.c + +## end gnulib module group-member + ## begin gnulib module hash libpatch_a_SOURCES += hash.c @@ -1050,6 +1086,13 @@ EXTRA_libpatch_a_SOURCES += rmdir.c ## end gnulib module rmdir +## begin gnulib module root-uid + + +EXTRA_DIST += root-uid.h + +## end gnulib module root-uid + ## begin gnulib module safe-write libpatch_a_SOURCES += safe-write.c diff --git a/lib/group-member.c b/lib/group-member.c new file mode 100644 index 0000000..23074e4 --- /dev/null +++ b/lib/group-member.c @@ -0,0 +1,119 @@ +/* group-member.c -- determine whether group id is in calling user's group list + + Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2015 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 . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include + +#include "xalloc-oversized.h" + +/* Most processes have no more than this many groups, and for these + processes we can avoid using malloc. */ +enum { GROUPBUF_SIZE = 100 }; + +struct group_info + { + gid_t *group; + gid_t groupbuf[GROUPBUF_SIZE]; + }; + +static void +free_group_info (struct group_info const *g) +{ + if (g->group != g->groupbuf) + free (g->group); +} + +static int +get_group_info (struct group_info *gi) +{ + int n_groups = getgroups (GROUPBUF_SIZE, gi->groupbuf); + gi->group = gi->groupbuf; + + if (n_groups < 0) + { + int n_group_slots = getgroups (0, NULL); + if (0 <= n_group_slots + && ! xalloc_oversized (n_group_slots, sizeof *gi->group)) + { + gi->group = malloc (n_group_slots * sizeof *gi->group); + if (gi->group) + n_groups = getgroups (n_group_slots, gi->group); + } + } + + /* In case of error, the user loses. */ + return n_groups; +} + +/* Return non-zero if GID is one that we have in our groups list. + Note that the groups list is not guaranteed to contain the current + or effective group ID, so they should generally be checked + separately. */ + +int +group_member (gid_t gid) +{ + int i; + int found; + struct group_info gi; + int n_groups = get_group_info (&gi); + + /* Search through the list looking for GID. */ + found = 0; + for (i = 0; i < n_groups; i++) + { + if (gid == gi.group[i]) + { + found = 1; + break; + } + } + + free_group_info (&gi); + + return found; +} + +#ifdef TEST + +char *program_name; + +int +main (int argc, char **argv) +{ + int i; + + program_name = argv[0]; + + for (i = 1; i < argc; i++) + { + gid_t gid; + + gid = atoi (argv[i]); + printf ("%d: %s\n", gid, group_member (gid) ? "yes" : "no"); + } + exit (0); +} + +#endif /* TEST */ diff --git a/lib/root-uid.h b/lib/root-uid.h new file mode 100644 index 0000000..d263f4d --- /dev/null +++ b/lib/root-uid.h @@ -0,0 +1,30 @@ +/* The user ID that always has appropriate privileges in the POSIX sense. + + Copyright 2012-2015 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. */ + +#ifndef ROOT_UID_H_ +#define ROOT_UID_H_ + +/* The user ID that always has appropriate privileges in the POSIX sense. */ +#ifdef __TANDEM +# define ROOT_UID 65535 +#else +# define ROOT_UID 0 +#endif + +#endif diff --git a/lib/signal.in.h b/lib/signal.in.h index 0f2ff5a..265b72a 100644 --- a/lib/signal.in.h +++ b/lib/signal.in.h @@ -55,11 +55,13 @@ #ifndef _@GUARD_PREFIX@_SIGNAL_H #define _@GUARD_PREFIX@_SIGNAL_H -/* Mac OS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6 declare - pthread_sigmask in , not in . +/* Mac OS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6, Android + declare pthread_sigmask in , not in . But avoid namespace pollution on glibc systems.*/ #if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \ - && ((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || defined __OpenBSD__ || defined __osf__ || defined __sun) \ + && ((defined __APPLE__ && defined __MACH__) \ + || defined __FreeBSD__ || defined __OpenBSD__ || defined __osf__ \ + || defined __sun || defined __ANDROID__) \ && ! defined __GLIBC__ # include #endif diff --git a/lib/symlinkat.c b/lib/symlinkat.c index ce10d94..84d5584 100644 --- a/lib/symlinkat.c +++ b/lib/symlinkat.c @@ -24,6 +24,9 @@ #if HAVE_SYMLINKAT # undef symlinkat +#include +#include + /* Create a symlink, but reject trailing slash. */ int rpl_symlinkat (char const *contents, int fd, char const *name) diff --git a/lib/tempname.c b/lib/tempname.c index 088b224..8e6d26c 100644 --- a/lib/tempname.c +++ b/lib/tempname.c @@ -62,6 +62,7 @@ # define struct_stat64 struct stat64 #else # define struct_stat64 struct stat +# define __try_tempname try_tempname # define __gen_tempname gen_tempname # define __getpid getpid # define __gettimeofday gettimeofday @@ -176,21 +177,9 @@ __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; -/* Generate a temporary file name based on TMPL. TMPL must match the - rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix). - The name constructed does not exist at the time of the call to - __gen_tempname. TMPL is overwritten with the result. - - KIND may be one of: - __GT_NOCREATE: simply verify that the name does not exist - at the time of the call. - __GT_FILE: create the file using open(O_CREAT|O_EXCL) - and return a read-write fd. The file is mode 0600. - __GT_DIR: create a directory, which will be mode 0700. - - We use a clever algorithm to get hard-to-predict names. */ int -__gen_tempname (char *tmpl, int suffixlen, int flags, int kind) +__try_tempname (char *tmpl, int suffixlen, void *args, + int (*tryfunc) (char *, void *)) { int len; char *XXXXXX; @@ -199,7 +188,6 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind) unsigned int count; int fd = -1; int save_errno = errno; - struct_stat64 st; /* A lower bound on the number of temporary files to attempt to generate. The maximum total number of temporary file names that @@ -256,41 +244,7 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind) v /= 62; XXXXXX[5] = letters[v % 62]; - switch (kind) - { - case __GT_FILE: - fd = __open (tmpl, - (flags & ~O_ACCMODE) - | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); - break; - - case __GT_DIR: - fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); - break; - - case __GT_NOCREATE: - /* This case is backward from the other three. __gen_tempname - succeeds if __xstat fails because the name does not exist. - Note the continue to bypass the common logic at the bottom - of the loop. */ - if (__lxstat64 (_STAT_VER, tmpl, &st) < 0) - { - if (errno == ENOENT) - { - __set_errno (save_errno); - return 0; - } - else - /* Give up now. */ - return -1; - } - continue; - - default: - assert (! "invalid KIND in __gen_tempname"); - abort (); - } - + fd = tryfunc (tmpl, args); if (fd >= 0) { __set_errno (save_errno); @@ -304,3 +258,67 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind) __set_errno (EEXIST); return -1; } + +static int +try_file (char *tmpl, void *flags) +{ + int *openflags = flags; + return __open (tmpl, + (*openflags & ~O_ACCMODE) + | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); +} + +static int +try_dir (char *tmpl, void *flags) +{ + return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); +} + +static int +try_nocreate (char *tmpl, void *flags) +{ + struct_stat64 st; + + if (__lxstat64 (_STAT_VER, tmpl, &st) == 0) + __set_errno (EEXIST); + return errno == ENOENT ? 0 : -1; +} + +/* Generate a temporary file name based on TMPL. TMPL must match the + rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix). + The name constructed does not exist at the time of the call to + __gen_tempname. TMPL is overwritten with the result. + + KIND may be one of: + __GT_NOCREATE: simply verify that the name does not exist + at the time of the call. + __GT_FILE: create the file using open(O_CREAT|O_EXCL) + and return a read-write fd. The file is mode 0600. + __GT_DIR: create a directory, which will be mode 0700. + + We use a clever algorithm to get hard-to-predict names. */ +int +__gen_tempname (char *tmpl, int suffixlen, int flags, int kind) +{ + int (*tryfunc) (char *, void *); + + switch (kind) + { + case __GT_FILE: + tryfunc = try_file; + break; + + case __GT_DIR: + tryfunc = try_dir; + break; + + case __GT_NOCREATE: + tryfunc = try_nocreate; + break; + + default: + assert (! "invalid KIND in __gen_tempname"); + abort (); + } + return __try_tempname (tmpl, suffixlen, &flags, tryfunc); +} diff --git a/lib/tempname.h b/lib/tempname.h index b560ee5..e609360 100644 --- a/lib/tempname.h +++ b/lib/tempname.h @@ -32,6 +32,10 @@ # define GT_NOCREATE 2 # endif +#ifdef __cplusplus +extern "C" { +#endif + /* Generate a temporary file name based on TMPL. TMPL must match the rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix). The name constructed does not exist at the time of the call to @@ -47,4 +51,15 @@ We use a clever algorithm to get hard-to-predict names. */ extern int gen_tempname (char *tmpl, int suffixlen, int flags, int kind); +/* Similar to gen_tempname, but TRYFUNC is called for each temporary + name to try. If TRYFUNC returns a non-negative number, TRY_GEN_TEMPNAME + returns with this value. Otherwise, if errno is set to EEXIST, another + name is tried, or else TRY_GEN_TEMPNAME returns -1. */ +extern int try_tempname (char *tmpl, int suffixlen, void *args, + int (*tryfunc) (char *, void *)); + +#ifdef __cplusplus +} +#endif + #endif /* GL_TEMPNAME_H */ diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 246831f..88332f0 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -1886,7 +1886,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, else { do - result[length++] = (unsigned char) *cp++; + result[length++] = *cp++; while (--n > 0); } } @@ -4793,7 +4793,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, { const FCHAR_T *mp = dp->width_start; do - *fbp++ = (unsigned char) *mp++; + *fbp++ = *mp++; while (--n > 0); } } @@ -4814,7 +4814,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, { const FCHAR_T *mp = dp->precision_start; do - *fbp++ = (unsigned char) *mp++; + *fbp++ = *mp++; while (--n > 0); } } @@ -5382,7 +5382,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, tmpsrc += count; tmpdst += count; for (n = count; n > 0; n--) - *--tmpdst = (unsigned char) *--tmpsrc; + *--tmpdst = *--tmpsrc; } } #endif diff --git a/lib/xalloc.h b/lib/xalloc.h index 3dfaa87..68f847a 100644 --- a/lib/xalloc.h +++ b/lib/xalloc.h @@ -258,5 +258,6 @@ xmemdup (T const *p, size_t s) #endif +_GL_INLINE_HEADER_END #endif /* !XALLOC_H_ */ diff --git a/m4/dup2.m4 b/m4/dup2.m4 index 0354c6a..59028e0 100644 --- a/m4/dup2.m4 +++ b/m4/dup2.m4 @@ -1,4 +1,4 @@ -#serial 20 +#serial 24 dnl Copyright (C) 2002, 2005, 2007, 2009-2015 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,7 +8,6 @@ AC_DEFUN([gl_FUNC_DUP2], [ AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) AC_REQUIRE([AC_CANONICAL_HOST]) - AC_CHECK_FUNCS_ONCE([getdtablesize]) m4_ifdef([gl_FUNC_DUP2_OBSOLETE], [ AC_CHECK_FUNCS_ONCE([dup2]) if test $ac_cv_func_dup2 = no; then @@ -20,38 +19,50 @@ AC_DEFUN([gl_FUNC_DUP2], if test $HAVE_DUP2 = 1; then AC_CACHE_CHECK([whether dup2 works], [gl_cv_func_dup2_works], [AC_RUN_IFELSE([ - AC_LANG_PROGRAM([[#include -#include -#include ]], - [int result = 0; -#ifdef HAVE_GETDTABLESIZE - int bad_fd = getdtablesize (); -#else - int bad_fd = 1000000; -#endif -#ifdef FD_CLOEXEC - if (fcntl (1, F_SETFD, FD_CLOEXEC) == -1) - result |= 1; -#endif - if (dup2 (1, 1) == 0) - result |= 2; -#ifdef FD_CLOEXEC - if (fcntl (1, F_GETFD) != FD_CLOEXEC) - result |= 4; -#endif - close (0); - if (dup2 (0, 0) != -1) - result |= 8; - /* Many gnulib modules require POSIX conformance of EBADF. */ - if (dup2 (2, bad_fd) == -1 && errno != EBADF) - result |= 16; - /* Flush out some cygwin core dumps. */ - if (dup2 (2, -1) != -1 || errno != EBADF) - result |= 32; - dup2 (2, 255); - dup2 (2, 256); - return result; - ]) + AC_LANG_PROGRAM( + [[#include + #include + #include + #include + #include + #ifndef RLIM_SAVED_CUR + # define RLIM_SAVED_CUR RLIM_INFINITY + #endif + #ifndef RLIM_SAVED_MAX + # define RLIM_SAVED_MAX RLIM_INFINITY + #endif + ]], + [[int result = 0; + int bad_fd = INT_MAX; + struct rlimit rlim; + if (getrlimit (RLIMIT_NOFILE, &rlim) == 0 + && 0 <= rlim.rlim_cur && rlim.rlim_cur <= INT_MAX + && rlim.rlim_cur != RLIM_INFINITY + && rlim.rlim_cur != RLIM_SAVED_MAX + && rlim.rlim_cur != RLIM_SAVED_CUR) + bad_fd = rlim.rlim_cur; + #ifdef FD_CLOEXEC + if (fcntl (1, F_SETFD, FD_CLOEXEC) == -1) + result |= 1; + #endif + if (dup2 (1, 1) != 1) + result |= 2; + #ifdef FD_CLOEXEC + if (fcntl (1, F_GETFD) != FD_CLOEXEC) + result |= 4; + #endif + close (0); + if (dup2 (0, 0) != -1) + result |= 8; + /* Many gnulib modules require POSIX conformance of EBADF. */ + if (dup2 (2, bad_fd) == -1 && errno != EBADF) + result |= 16; + /* Flush out some cygwin core dumps. */ + if (dup2 (2, -1) != -1 || errno != EBADF) + result |= 32; + dup2 (2, 255); + dup2 (2, 256); + return result;]]) ], [gl_cv_func_dup2_works=yes], [gl_cv_func_dup2_works=no], [case "$host_os" in @@ -59,15 +70,14 @@ AC_DEFUN([gl_FUNC_DUP2], gl_cv_func_dup2_works="guessing no" ;; cygwin*) # on cygwin 1.5.x, dup2(1,1) returns 0 gl_cv_func_dup2_works="guessing no" ;; - linux*) # On linux between 2008-07-27 and 2009-05-11, dup2 of a - # closed fd may yield -EBADF instead of -1 / errno=EBADF. - gl_cv_func_dup2_works="guessing no" ;; aix* | freebsd*) # on AIX 7.1 and FreeBSD 6.1, dup2 (1,toobig) gives EMFILE, # not EBADF. gl_cv_func_dup2_works="guessing no" ;; haiku*) # on Haiku alpha 2, dup2(1, 1) resets FD_CLOEXEC. gl_cv_func_dup2_works="guessing no" ;; + *-android*) # implemented using dup3(), which fails if oldfd == newfd + gl_cv_func_dup2_works="guessing no" ;; *) gl_cv_func_dup2_works="guessing yes" ;; esac]) ]) diff --git a/m4/euidaccess.m4 b/m4/euidaccess.m4 new file mode 100644 index 0000000..e23e9c3 --- /dev/null +++ b/m4/euidaccess.m4 @@ -0,0 +1,52 @@ +# euidaccess.m4 serial 15 +dnl Copyright (C) 2002-2015 Free Software 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. + +AC_DEFUN([gl_FUNC_NONREENTRANT_EUIDACCESS], +[ + AC_REQUIRE([gl_FUNC_EUIDACCESS]) + AC_CHECK_DECLS([setregid]) + AC_DEFINE([PREFER_NONREENTRANT_EUIDACCESS], [1], + [Define this if you prefer euidaccess to return the correct result + even if this would make it nonreentrant. Define this only if your + entire application is safe even if the uid or gid might temporarily + change. If your application uses signal handlers or threads it + is probably not safe.]) +]) + +AC_DEFUN([gl_FUNC_EUIDACCESS], +[ + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + + dnl Persuade glibc to declare euidaccess(). + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + AC_CHECK_FUNCS([euidaccess]) + if test $ac_cv_func_euidaccess = no; then + HAVE_EUIDACCESS=0 + fi +]) + +# Prerequisites of lib/euidaccess.c. +AC_DEFUN([gl_PREREQ_EUIDACCESS], [ + dnl Prefer POSIX faccessat over non-standard euidaccess. + AC_CHECK_FUNCS_ONCE([faccessat]) + dnl Try various other non-standard fallbacks. + AC_CHECK_HEADERS([libgen.h]) + AC_FUNC_GETGROUPS + + # Solaris 9 and 10 need -lgen to get the eaccess function. + # Save and restore LIBS so -lgen isn't added to it. Otherwise, *all* + # programs in the package would end up linked with that potentially-shared + # library, inducing unnecessary run-time overhead. + LIB_EACCESS= + AC_SUBST([LIB_EACCESS]) + gl_saved_libs=$LIBS + AC_SEARCH_LIBS([eaccess], [gen], + [test "$ac_cv_search_eaccess" = "none required" || + LIB_EACCESS=$ac_cv_search_eaccess]) + AC_CHECK_FUNCS([eaccess]) + LIBS=$gl_saved_libs +]) diff --git a/m4/faccessat.m4 b/m4/faccessat.m4 new file mode 100644 index 0000000..941cb02 --- /dev/null +++ b/m4/faccessat.m4 @@ -0,0 +1,28 @@ +# serial 6 +# See if we need to provide faccessat replacement. + +dnl Copyright (C) 2009-2015 Free Software 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. + +# Written by Eric Blake. + +AC_DEFUN([gl_FUNC_FACCESSAT], +[ + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + + dnl Persuade glibc to declare faccessat(). + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + + AC_CHECK_FUNCS_ONCE([faccessat]) + if test $ac_cv_func_faccessat = no; then + HAVE_FACCESSAT=0 + fi +]) + +# Prerequisites of lib/faccessat.m4. +AC_DEFUN([gl_PREREQ_FACCESSAT], +[ + AC_CHECK_FUNCS([access]) +]) diff --git a/m4/fcntl.m4 b/m4/fcntl.m4 index 733cd2d..76dd867 100644 --- a/m4/fcntl.m4 +++ b/m4/fcntl.m4 @@ -1,4 +1,4 @@ -# fcntl.m4 serial 5 +# fcntl.m4 serial 8 dnl Copyright (C) 2009-2015 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -19,7 +19,7 @@ AC_DEFUN([gl_FUNC_FCNTL], AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) AC_REQUIRE([gl_FCNTL_H_DEFAULTS]) AC_REQUIRE([AC_CANONICAL_HOST]) - AC_CHECK_FUNCS_ONCE([fcntl getdtablesize]) + AC_CHECK_FUNCS_ONCE([fcntl]) if test $ac_cv_func_fcntl = no; then gl_REPLACE_FCNTL else @@ -27,30 +27,40 @@ AC_DEFUN([gl_FUNC_FCNTL], dnl haiku alpha 2 F_DUPFD has wrong errno AC_CACHE_CHECK([whether fcntl handles F_DUPFD correctly], [gl_cv_func_fcntl_f_dupfd_works], - [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ -#ifdef HAVE_GETDTABLESIZE -# include -#endif -#include -#include -]], [[int result = 0; -#ifdef HAVE_GETDTABLESIZE - int bad_fd = getdtablesize (); -#else - int bad_fd = 1000000; -#endif - if (fcntl (0, F_DUPFD, -1) != -1) result |= 1; - if (errno != EINVAL) result |= 2; - if (fcntl (0, F_DUPFD, bad_fd) != -1) result |= 4; - if (errno != EINVAL) result |= 8; - return result; - ]])], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + #include + #include + #include + #ifndef RLIM_SAVED_CUR + # define RLIM_SAVED_CUR RLIM_INFINITY + #endif + #ifndef RLIM_SAVED_MAX + # define RLIM_SAVED_MAX RLIM_INFINITY + #endif + ]], + [[int result = 0; + int bad_fd = INT_MAX; + struct rlimit rlim; + if (getrlimit (RLIMIT_NOFILE, &rlim) == 0 + && 0 <= rlim.rlim_cur && rlim.rlim_cur <= INT_MAX + && rlim.rlim_cur != RLIM_INFINITY + && rlim.rlim_cur != RLIM_SAVED_MAX + && rlim.rlim_cur != RLIM_SAVED_CUR) + bad_fd = rlim.rlim_cur; + if (fcntl (0, F_DUPFD, -1) != -1) result |= 1; + if (errno != EINVAL) result |= 2; + if (fcntl (0, F_DUPFD, bad_fd) != -1) result |= 4; + if (errno != EINVAL) result |= 8; + return result;]])], [gl_cv_func_fcntl_f_dupfd_works=yes], [gl_cv_func_fcntl_f_dupfd_works=no], - [# Guess that it works on glibc systems - case $host_os in #(( - *-gnu*) gl_cv_func_fcntl_f_dupfd_works="guessing yes";; - *) gl_cv_func_fcntl_f_dupfd_works="guessing no";; + [case $host_os in + aix* | cygwin* | haiku*) + gl_cv_func_fcntl_f_dupfd_works="guessing no" ;; + *) gl_cv_func_fcntl_f_dupfd_works="guessing yes" ;; esac])]) case $gl_cv_func_fcntl_f_dupfd_works in *yes) ;; diff --git a/m4/getdtablesize.m4 b/m4/getdtablesize.m4 index a6b6c1b..25e9968 100644 --- a/m4/getdtablesize.m4 +++ b/m4/getdtablesize.m4 @@ -1,4 +1,4 @@ -# getdtablesize.m4 serial 5 +# getdtablesize.m4 serial 6 dnl Copyright (C) 2008-2015 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -9,7 +9,9 @@ AC_DEFUN([gl_FUNC_GETDTABLESIZE], AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_CHECK_FUNCS_ONCE([getdtablesize]) - if test $ac_cv_func_getdtablesize = yes; then + AC_CHECK_DECLS_ONCE([getdtablesize]) + if test $ac_cv_func_getdtablesize = yes && + test $ac_cv_have_decl_getdtablesize = yes; then # Cygwin 1.7.25 automatically increases the RLIMIT_NOFILE soft limit # up to an unchangeable hard limit; all other platforms correctly # require setrlimit before getdtablesize() can report a larger value. diff --git a/m4/getgroups.m4 b/m4/getgroups.m4 new file mode 100644 index 0000000..16e72c7 --- /dev/null +++ b/m4/getgroups.m4 @@ -0,0 +1,107 @@ +# serial 18 + +dnl From Jim Meyering. +dnl A wrapper around AC_FUNC_GETGROUPS. + +# Copyright (C) 1996-1997, 1999-2004, 2008-2015 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +m4_version_prereq([2.70], [] ,[ + +# This is taken from the following Autoconf patch: +# http://git.savannah.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=7fbb553727ed7e0e689a17594b58559ecf3ea6e9 +AC_DEFUN([AC_FUNC_GETGROUPS], +[ + AC_REQUIRE([AC_TYPE_GETGROUPS])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl for cross-compiles + AC_CHECK_FUNC([getgroups]) + + # If we don't yet have getgroups, see if it's in -lbsd. + # This is reported to be necessary on an ITOS 3000WS running SEIUX 3.1. + ac_save_LIBS=$LIBS + if test $ac_cv_func_getgroups = no; then + AC_CHECK_LIB(bsd, getgroups, [GETGROUPS_LIB=-lbsd]) + fi + + # Run the program to test the functionality of the system-supplied + # getgroups function only if there is such a function. + if test $ac_cv_func_getgroups = yes; then + AC_CACHE_CHECK([for working getgroups], [ac_cv_func_getgroups_works], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [AC_INCLUDES_DEFAULT], + [[/* On Ultrix 4.3, getgroups (0, 0) always fails. */ + return getgroups (0, 0) == -1;]]) + ], + [ac_cv_func_getgroups_works=yes], + [ac_cv_func_getgroups_works=no], + [case "$host_os" in # (( + # Guess yes on glibc systems. + *-gnu*) ac_cv_func_getgroups_works="guessing yes" ;; + # If we don't know, assume the worst. + *) ac_cv_func_getgroups_works="guessing no" ;; + esac + ]) + ]) + else + ac_cv_func_getgroups_works=no + fi + case "$ac_cv_func_getgroups_works" in + *yes) + AC_DEFINE([HAVE_GETGROUPS], [1], + [Define to 1 if your system has a working `getgroups' function.]) + ;; + esac + LIBS=$ac_save_LIBS +])# AC_FUNC_GETGROUPS + +]) + +AC_DEFUN([gl_FUNC_GETGROUPS], +[ + AC_REQUIRE([AC_TYPE_GETGROUPS]) + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + AC_FUNC_GETGROUPS + if test $ac_cv_func_getgroups != yes; then + HAVE_GETGROUPS=0 + else + if test "$ac_cv_type_getgroups" != gid_t \ + || { case "$ac_cv_func_getgroups_works" in + *yes) false;; + *) true;; + esac + }; then + REPLACE_GETGROUPS=1 + AC_DEFINE([GETGROUPS_ZERO_BUG], [1], [Define this to 1 if + getgroups(0,NULL) does not return the number of groups.]) + else + dnl Detect FreeBSD bug; POSIX requires getgroups(-1,ptr) to fail. + AC_CACHE_CHECK([whether getgroups handles negative values], + [gl_cv_func_getgroups_works], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT], + [[int size = getgroups (0, 0); + gid_t *list = malloc (size * sizeof *list); + return getgroups (-1, list) != -1;]])], + [gl_cv_func_getgroups_works=yes], + [gl_cv_func_getgroups_works=no], + [case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_getgroups_works="guessing yes" ;; + # If we don't know, assume the worst. + *) gl_cv_func_getgroups_works="guessing no" ;; + esac + ])]) + case "$gl_cv_func_getgroups_works" in + *yes) ;; + *) REPLACE_GETGROUPS=1 ;; + esac + fi + fi + test -n "$GETGROUPS_LIB" && LIBS="$GETGROUPS_LIB $LIBS" +]) diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 00de6ad..ae855f5 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -70,10 +70,12 @@ AC_DEFUN([gl_EARLY], # Code from module environ: # Code from module errno: # Code from module error: + # Code from module euidaccess: # Code from module exitfail: # Code from module extensions: AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) # Code from module extern-inline: + # Code from module faccessat: # Code from module fchdir: # Code from module fchmodat: # Code from module fchownat: @@ -89,6 +91,7 @@ AC_DEFUN([gl_EARLY], # Code from module getcwd-lgpl: # Code from module getdate: # Code from module getdtablesize: + # Code from module getgroups: # Code from module getopt-gnu: # Code from module getopt-posix: # Code from module gettext-h: @@ -97,6 +100,7 @@ AC_DEFUN([gl_EARLY], # Code from module git-version-gen: # Code from module gitlog-to-changelog: # Code from module gnumakefile: + # Code from module group-member: # Code from module hash: # Code from module ignore-value: # Code from module include_next: @@ -148,6 +152,7 @@ AC_DEFUN([gl_EARLY], # Code from module rename: # Code from module renameat: # Code from module rmdir: + # Code from module root-uid: # Code from module safe-write: # Code from module same-inode: # Code from module save-cwd: @@ -303,7 +308,20 @@ AC_DEFUN([gl_INIT], m4_ifdef([AM_XGETTEXT_OPTION], [AM_][XGETTEXT_OPTION([--flag=error:3:c-format]) AM_][XGETTEXT_OPTION([--flag=error_at_line:5:c-format])]) + gl_FUNC_EUIDACCESS + if test $HAVE_EUIDACCESS = 0; then + AC_LIBOBJ([euidaccess]) + gl_PREREQ_EUIDACCESS + fi + gl_UNISTD_MODULE_INDICATOR([euidaccess]) AC_REQUIRE([gl_EXTERN_INLINE]) + gl_FUNC_FACCESSAT + if test $HAVE_FACCESSAT = 0; then + AC_LIBOBJ([faccessat]) + gl_PREREQ_FACCESSAT + fi + gl_MODULE_INDICATOR([faccessat]) + gl_UNISTD_MODULE_INDICATOR([faccessat]) gl_FUNC_FCHDIR gl_UNISTD_MODULE_INDICATOR([fchdir]) gl_FUNC_FCHMODAT @@ -354,6 +372,11 @@ AC_DEFUN([gl_INIT], gl_PREREQ_GETDTABLESIZE fi gl_UNISTD_MODULE_INDICATOR([getdtablesize]) + gl_FUNC_GETGROUPS + if test $HAVE_GETGROUPS = 0 || test $REPLACE_GETGROUPS = 1; then + AC_LIBOBJ([getgroups]) + fi + gl_UNISTD_MODULE_INDICATOR([getgroups]) gl_FUNC_GETOPT_GNU if test $REPLACE_GETOPT = 1; then AC_LIBOBJ([getopt]) @@ -392,6 +415,12 @@ AC_DEFUN([gl_INIT], m4_defn([m4_PACKAGE_VERSION])), [1], [], [AC_CONFIG_LINKS([$GNUmakefile:$GNUmakefile], [], [GNUmakefile=$GNUmakefile])]) + gl_FUNC_GROUP_MEMBER + if test $HAVE_GROUP_MEMBER = 0; then + AC_LIBOBJ([group-member]) + gl_PREREQ_GROUP_MEMBER + fi + gl_UNISTD_MODULE_INDICATOR([group-member]) AC_REQUIRE([gl_LARGEFILE]) gl_FUNC_LCHOWN if test $HAVE_LCHOWN = 0 || test $REPLACE_LCHOWN = 1; then @@ -882,8 +911,10 @@ AC_DEFUN([gl_FILE_LIST], [ lib/errno.in.h lib/error.c lib/error.h + lib/euidaccess.c lib/exitfail.c lib/exitfail.h + lib/faccessat.c lib/fchdir.c lib/fchmodat.c lib/fchown-stub.c @@ -906,6 +937,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/getcwd-lgpl.c lib/getdate.h lib/getdtablesize.c + lib/getgroups.c lib/getopt.c lib/getopt.in.h lib/getopt1.c @@ -921,6 +953,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/gl_list.h lib/gl_xlist.c lib/gl_xlist.h + lib/group-member.c lib/hash.c lib/hash.h lib/ignore-value.h @@ -980,6 +1013,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/rename.c lib/renameat.c lib/rmdir.c + lib/root-uid.h lib/safe-read.c lib/safe-write.c lib/safe-write.h @@ -1077,9 +1111,11 @@ AC_DEFUN([gl_FILE_LIST], [ m4/environ.m4 m4/errno_h.m4 m4/error.m4 + m4/euidaccess.m4 m4/exponentd.m4 m4/extensions.m4 m4/extern-inline.m4 + m4/faccessat.m4 m4/fchdir.m4 m4/fchmodat.m4 m4/fchownat.m4 @@ -1092,11 +1128,13 @@ AC_DEFUN([gl_FILE_LIST], [ m4/fstatat.m4 m4/getcwd.m4 m4/getdtablesize.m4 + m4/getgroups.m4 m4/getopt.m4 m4/gettime.m4 m4/gettimeofday.m4 m4/glibc21.m4 m4/gnulib-common.m4 + m4/group-member.m4 m4/include_next.m4 m4/intmax_t.m4 m4/inttypes_h.m4 diff --git a/m4/group-member.m4 b/m4/group-member.m4 new file mode 100644 index 0000000..526a67a --- /dev/null +++ b/m4/group-member.m4 @@ -0,0 +1,29 @@ +# serial 14 + +# Copyright (C) 1999-2001, 2003-2007, 2009-2015 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +dnl Written by Jim Meyering + +AC_DEFUN([gl_FUNC_GROUP_MEMBER], +[ + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + + dnl Persuade glibc to declare group_member(). + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + dnl Do this replacement check manually because I want the hyphen + dnl (not the underscore) in the filename. + AC_CHECK_FUNC([group_member], , [ + HAVE_GROUP_MEMBER=0 + ]) +]) + +# Prerequisites of lib/group-member.c. +AC_DEFUN([gl_PREREQ_GROUP_MEMBER], +[ + AC_REQUIRE([AC_FUNC_GETGROUPS]) +]) diff --git a/m4/printf.m4 b/m4/printf.m4 index ffbb235..d06746a 100644 --- a/m4/printf.m4 +++ b/m4/printf.m4 @@ -1,4 +1,4 @@ -# printf.m4 serial 51 +# printf.m4 serial 52 dnl Copyright (C) 2003, 2007-2015 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -365,66 +365,51 @@ int main () { /* Pseudo-NaN. */ static union { unsigned int word[4]; long double value; } x = { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) }; - if (sprintf (buf, "%Lf", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Lf", x.value) <= 0) result |= 4; - if (sprintf (buf, "%Le", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Le", x.value) <= 0) result |= 4; - if (sprintf (buf, "%Lg", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Lg", x.value) <= 0) result |= 4; } { /* Pseudo-Infinity. */ static union { unsigned int word[4]; long double value; } x = { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) }; - if (sprintf (buf, "%Lf", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Lf", x.value) <= 0) result |= 8; - if (sprintf (buf, "%Le", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Le", x.value) <= 0) result |= 8; - if (sprintf (buf, "%Lg", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Lg", x.value) <= 0) result |= 8; } { /* Pseudo-Zero. */ static union { unsigned int word[4]; long double value; } x = { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) }; - if (sprintf (buf, "%Lf", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Lf", x.value) <= 0) result |= 16; - if (sprintf (buf, "%Le", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Le", x.value) <= 0) result |= 16; - if (sprintf (buf, "%Lg", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Lg", x.value) <= 0) result |= 16; } { /* Unnormalized number. */ static union { unsigned int word[4]; long double value; } x = { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) }; - if (sprintf (buf, "%Lf", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Lf", x.value) <= 0) result |= 32; - if (sprintf (buf, "%Le", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Le", x.value) <= 0) result |= 32; - if (sprintf (buf, "%Lg", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Lg", x.value) <= 0) result |= 32; } { /* Pseudo-Denormal. */ static union { unsigned int word[4]; long double value; } x = { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) }; - if (sprintf (buf, "%Lf", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Lf", x.value) <= 0) result |= 64; - if (sprintf (buf, "%Le", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Le", x.value) <= 0) result |= 64; - if (sprintf (buf, "%Lg", x.value) < 0 - || !strisnan (buf, 0, strlen (buf))) + if (sprintf (buf, "%Lg", x.value) <= 0) result |= 64; } #endif diff --git a/src/Makefile.am b/src/Makefile.am index 7690760..4fe71d2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -32,11 +32,12 @@ patch_SOURCES = \ util.c \ util.h \ version.c \ - version.h + version.h \ + list.h AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib patch_LDADD = $(LDADD) $(top_builddir)/lib/libpatch.a $(LIB_CLOCK_GETTIME) \ - $(LIB_XATTR) + $(LIB_XATTR) $(LIB_EACCESS) if ENABLE_MERGE patch_SOURCES += merge.c diff --git a/src/Makefile.in b/src/Makefile.in index 2104c86..d21ed19 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -113,17 +113,21 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \ $(top_srcdir)/m4/double-slash-root.m4 $(top_srcdir)/m4/dup2.m4 \ $(top_srcdir)/m4/eealloc.m4 $(top_srcdir)/m4/environ.m4 \ $(top_srcdir)/m4/errno_h.m4 $(top_srcdir)/m4/error.m4 \ - $(top_srcdir)/m4/exponentd.m4 $(top_srcdir)/m4/extensions.m4 \ - $(top_srcdir)/m4/extern-inline.m4 $(top_srcdir)/m4/fchdir.m4 \ + $(top_srcdir)/m4/euidaccess.m4 $(top_srcdir)/m4/exponentd.m4 \ + $(top_srcdir)/m4/extensions.m4 \ + $(top_srcdir)/m4/extern-inline.m4 \ + $(top_srcdir)/m4/faccessat.m4 $(top_srcdir)/m4/fchdir.m4 \ $(top_srcdir)/m4/fchmodat.m4 $(top_srcdir)/m4/fchownat.m4 \ $(top_srcdir)/m4/fcntl-o.m4 $(top_srcdir)/m4/fcntl.m4 \ $(top_srcdir)/m4/fcntl_h.m4 $(top_srcdir)/m4/filenamecat.m4 \ $(top_srcdir)/m4/float_h.m4 $(top_srcdir)/m4/fstat.m4 \ $(top_srcdir)/m4/fstatat.m4 $(top_srcdir)/m4/getcwd.m4 \ - $(top_srcdir)/m4/getdtablesize.m4 $(top_srcdir)/m4/getopt.m4 \ + $(top_srcdir)/m4/getdtablesize.m4 \ + $(top_srcdir)/m4/getgroups.m4 $(top_srcdir)/m4/getopt.m4 \ $(top_srcdir)/m4/gettime.m4 $(top_srcdir)/m4/gettimeofday.m4 \ $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnulib-common.m4 \ $(top_srcdir)/m4/gnulib-comp.m4 \ + $(top_srcdir)/m4/group-member.m4 \ $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/intmax_t.m4 \ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/largefile.m4 \ $(top_srcdir)/m4/lchown.m4 $(top_srcdir)/m4/localcharset.m4 \ @@ -187,7 +191,7 @@ am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am__patch_SOURCES_DIST = bestmatch.h common.h inp.c inp.h patch.c \ pch.c pch.h safe.c safe.h util.c util.h version.c version.h \ - merge.c + list.h merge.c @ENABLE_MERGE_TRUE@am__objects_1 = merge.$(OBJEXT) am_patch_OBJECTS = inp.$(OBJEXT) patch.$(OBJEXT) pch.$(OBJEXT) \ safe.$(OBJEXT) util.$(OBJEXT) version.$(OBJEXT) \ @@ -195,7 +199,8 @@ am_patch_OBJECTS = inp.$(OBJEXT) patch.$(OBJEXT) pch.$(OBJEXT) \ patch_OBJECTS = $(am_patch_OBJECTS) am__DEPENDENCIES_1 = patch_DEPENDENCIES = $(top_builddir)/lib/libpatch.a \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -774,6 +779,7 @@ LIBPATCH_LIBDEPS = @LIBPATCH_LIBDEPS@ LIBPATCH_LTLIBDEPS = @LIBPATCH_LTLIBDEPS@ LIBS = @LIBS@ LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ +LIB_EACCESS = @LIB_EACCESS@ LIB_XATTR = @LIB_XATTR@ LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@ LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@ @@ -1057,12 +1063,12 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS) patch_SOURCES = bestmatch.h common.h inp.c inp.h patch.c pch.c pch.h \ - safe.c safe.h util.c util.h version.c version.h \ + safe.c safe.h util.c util.h version.c version.h list.h \ $(am__append_1) AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib \ $(am__append_2) patch_LDADD = $(LDADD) $(top_builddir)/lib/libpatch.a $(LIB_CLOCK_GETTIME) \ - $(LIB_XATTR) + $(LIB_XATTR) $(LIB_EACCESS) all: all-am diff --git a/src/inp.c b/src/inp.c index 4969837..32d0919 100644 --- a/src/inp.c +++ b/src/inp.c @@ -365,6 +365,8 @@ plan_b (char const *filename) { tifd = make_tempfile (&TMPINNAME, 'i', NULL, O_RDWR | O_BINARY, S_IRUSR | S_IWUSR); + if (tifd == -1) + pfatal ("Can't create temporary file %s", TMPINNAME); TMPINNAME_needs_removal = true; } i = 0; diff --git a/src/list.h b/src/list.h new file mode 100644 index 0000000..11d1184 --- /dev/null +++ b/src/list.h @@ -0,0 +1,55 @@ +#ifndef __LIST_H +#define __LIST_H + +#include + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +static inline void +list_add (struct list_head *entry, struct list_head *head) +{ + struct list_head *next = head->next; + entry->prev = head; + entry->next = next; + next->prev = head->next = entry; +} + +static inline void +list_del (struct list_head *entry) +{ + struct list_head *next = entry->next; + struct list_head *prev = entry->prev; + next->prev = prev; + prev->next = next; +} + +static inline void +list_del_init (struct list_head *entry) +{ + list_del(entry); + INIT_LIST_HEAD(entry); +} + +static inline bool +list_empty (const struct list_head *head) +{ + return head->next == head; +} + +#define list_entry(ptr, type, member) \ + (type *)( (char *)(ptr) - offsetof(type, member) ) + +#endif /* __LIST_H */ diff --git a/src/patch.c b/src/patch.c index 2c51f44..a60e631 100644 --- a/src/patch.c +++ b/src/patch.c @@ -115,6 +115,7 @@ main (int argc, char **argv) struct stat tmpoutst; char numbuf[LINENUM_LENGTH_BOUND + 1]; bool written_to_rejname = false; + bool skip_reject_file = false; bool apply_empty_patch = false; mode_t file_type; int outfd = -1; @@ -190,6 +191,7 @@ main (int argc, char **argv) there_is_another_patch (! (inname || posixly_correct), &file_type) || apply_empty_patch; reinitialize_almost_everything(), + skip_reject_file = false, apply_empty_patch = false ) { /* for each patch in patch file */ int hunk = 0; @@ -244,7 +246,7 @@ main (int argc, char **argv) if (outfile) outname = outfile; else if (pch_copy () || pch_rename ()) - outname = pch_name (! strcmp (inname, pch_name (OLD))); + outname = pch_name (! reverse); else outname = inname; } @@ -309,7 +311,20 @@ main (int argc, char **argv) outfd = make_tempfile (&TMPOUTNAME, 'o', outname, O_WRONLY | binary_transput, instat.st_mode & S_IRWXUGO); - TMPOUTNAME_needs_removal = true; + if (outfd == -1) + { + if (errno == ELOOP || errno == EXDEV) + { + say ("Invalid file name %s -- skipping patch\n", quotearg (outname)); + skip_rest_of_patch = true; + skip_reject_file = true; + somefailed = true; + } + else + pfatal ("Can't create temporary file %s", TMPOUTNAME); + } + else + TMPOUTNAME_needs_removal = true; if (diff_type == ED_DIFF) { outstate.zero_output = false; somefailed |= skip_rest_of_patch; @@ -351,16 +366,18 @@ main (int argc, char **argv) if (verbosity != SILENT) { bool renamed = strcmp (inname, outname); + bool skip_rename = ! renamed && pch_rename (); say ("%s %s %s%c", dry_run ? "checking" : "patching", S_ISLNK (file_type) ? "symbolic link" : "file", - quotearg (outname), renamed ? ' ' : '\n'); - if (renamed) - say ("(%s from %s)\n", + quotearg (outname), renamed || skip_rename ? ' ' : '\n'); + if (renamed || skip_rename) + say ("(%s%s from %s)\n", + skip_rename ? "already " : "", pch_copy () ? "copied" : (pch_rename () ? "renamed" : "read"), - inname); + ! skip_rename ? inname : pch_name (! strcmp (inname, pch_name (OLD)))); if (verbosity == VERBOSE) say ("Using Plan %s...\n", using_plan_a ? "A" : "B"); } @@ -450,7 +467,8 @@ main (int argc, char **argv) || ! where || ! apply_hunk (&outstate, where)))) { - abort_hunk (outname, ! failed, reverse); + if (! skip_reject_file) + abort_hunk (outname, ! failed, reverse); failed++; if (verbosity == VERBOSE || (! skip_rest_of_patch && verbosity != SILENT)) @@ -591,7 +609,7 @@ main (int argc, char **argv) if (diff_type != ED_DIFF) { struct stat rejst; - if (failed) { + if (failed && ! skip_reject_file) { if (fstat (fileno (rejfp), &rejst) != 0 || fclose (rejfp) != 0) write_fatal (); rejfp = NULL; @@ -1584,6 +1602,8 @@ init_reject (char const *outname) int fd; fd = make_tempfile (&TMPREJNAME, 'r', outname, O_WRONLY | binary_transput, 0666); + if (fd == -1) + pfatal ("Can't create temporary file %s", TMPREJNAME); TMPREJNAME_needs_removal = true; rejfp = fdopen (fd, binary_transput ? "wb" : "w"); if (! rejfp) diff --git a/src/pch.c b/src/pch.c index fd8885e..9d74471 100644 --- a/src/pch.c +++ b/src/pch.c @@ -138,8 +138,11 @@ open_patch_file (char const *filename) else { size_t charsread; - int fd = make_tempfile (&TMPPATNAME, 'p', NULL, O_RDWR | O_BINARY, 0); + int fd; FILE *read_pfp = pfp; + fd = make_tempfile (&TMPPATNAME, 'p', NULL, O_RDWR | O_BINARY, 0); + if (fd == -1) + pfatal ("Can't create temporary file %s", TMPPATNAME); TMPPATNAME_needs_removal = true; pfp = fdopen (fd, "w+b"); if (! pfp) @@ -434,7 +437,7 @@ intuit_diff_type (bool need_header, mode_t *p_file_type) int version_controlled[3]; enum diff retval; mode_t file_type; - size_t indent = -1; + size_t indent = 0; for (i = OLD; i <= INDEX; i++) if (p_name[i]) { diff --git a/src/safe.c b/src/safe.c index eec6ce5..cdf9f74 100644 --- a/src/safe.c +++ b/src/safe.c @@ -39,35 +39,38 @@ #define XTERN extern #include "common.h" +#include "util.h" +#include "list.h" + +#ifndef EFTYPE +# define EFTYPE 0 +#endif + +static const unsigned int MAX_PATH_COMPONENTS = 1024; + /* Path lookup results are cached in a hash table + LRU list. When the cache is full, the oldest entries are removed. */ -unsigned long dirfd_cache_misses; +unsigned int dirfd_cache_misses; struct cached_dirfd { - /* lru list */ - struct cached_dirfd *prev, *next; + struct list_head lru_link; + struct list_head children_link, children; + struct cached_dirfd *parent; - /* key (openat arguments) */ - int dirfd; char *name; - - /* value (openat result) */ int fd; }; static Hash_table *cached_dirfds = NULL; static size_t max_cached_fds; -static struct cached_dirfd lru_list = { - .prev = &lru_list, - .next = &lru_list, -}; +LIST_HEAD (lru_list); static size_t hash_cached_dirfd (const void *entry, size_t table_size) { const struct cached_dirfd *d = entry; size_t strhash = hash_string (d->name, table_size); - return (strhash * 31 + d->dirfd) % table_size; + return (strhash * 31 + d->parent->fd) % table_size; } static bool compare_cached_dirfds (const void *_a, @@ -76,15 +79,15 @@ static bool compare_cached_dirfds (const void *_a, const struct cached_dirfd *a = _a; const struct cached_dirfd *b = _b; - return (a->dirfd == b->dirfd && + return (a->parent->fd == b->parent->fd && !strcmp (a->name, b->name)); } -static void free_cached_dirfd (struct cached_dirfd *d) +static void free_cached_dirfd (struct cached_dirfd *entry) { - close (d->fd); - free (d->name); - free (d); + list_del (&entry->children_link); + free (entry->name); + free (entry); } static void init_dirfd_cache (void) @@ -105,38 +108,16 @@ static void init_dirfd_cache (void) xalloc_die (); } -static void lru_list_add (struct cached_dirfd *entry, struct cached_dirfd *head) -{ - struct cached_dirfd *next = head->next; - entry->prev = head; - entry->next = next; - head->next = next->prev = entry; -} - -static void lru_list_del (struct cached_dirfd *entry) -{ - struct cached_dirfd *prev = entry->prev; - struct cached_dirfd *next = entry->next; - prev->next = next; - next->prev = prev; -} - -static struct cached_dirfd *lookup_cached_dirfd (int dirfd, const char *name) +static struct cached_dirfd *lookup_cached_dirfd (struct cached_dirfd *dir, const char *name) { struct cached_dirfd *entry = NULL; if (cached_dirfds) { struct cached_dirfd key; - key.dirfd = dirfd; + key.parent = dir; key.name = (char *) name; entry = hash_lookup (cached_dirfds, &key); - if (entry) - { - /* Move this most recently used entry to the head of the lru list */ - lru_list_del (entry); - lru_list_add (entry, &lru_list); - } } return entry; @@ -144,8 +125,17 @@ static struct cached_dirfd *lookup_cached_dirfd (int dirfd, const char *name) static void remove_cached_dirfd (struct cached_dirfd *entry) { - lru_list_del (entry); - hash_delete (cached_dirfds, entry); + while (! list_empty (&entry->children)) + { + struct cached_dirfd *child = + list_entry (entry->children.next, struct cached_dirfd, children_link); + list_del_init (&child->children_link); + /* assert (list_empty (&child->children_link)); */ + hash_delete (cached_dirfds, child); /* noop when not hashed */ + } + list_del (&entry->lru_link); + hash_delete (cached_dirfds, entry); /* noop when not hashed */ + close (entry->fd); free_cached_dirfd (entry); } @@ -157,100 +147,295 @@ static void insert_cached_dirfd (struct cached_dirfd *entry, int keepfd) /* Trim off the least recently used entries */ while (hash_get_n_entries (cached_dirfds) >= max_cached_fds) { - struct cached_dirfd *last = lru_list.prev; - assert (last != &lru_list); + struct cached_dirfd *last = + list_entry (lru_list.prev, struct cached_dirfd, lru_link); + if (&last->lru_link == &lru_list) + break; if (last->fd == keepfd) { - last = last->prev; - assert (last != &lru_list); + last = list_entry (last->lru_link.prev, struct cached_dirfd, lru_link); + if (&last->lru_link == &lru_list) + break; } remove_cached_dirfd (last); } - assert (hash_insert (cached_dirfds, entry) == entry); - lru_list_add (entry, &lru_list); + /* Only insert if the parent still exists. */ + if (! list_empty (&entry->children_link)) + assert (hash_insert (cached_dirfds, entry) == entry); } static void invalidate_cached_dirfd (int dirfd, const char *name) { - struct cached_dirfd key, *entry; + struct cached_dirfd dir, key, *entry; if (!cached_dirfds) return; - key.dirfd = dirfd; + dir.fd = dirfd; + key.parent = &dir; key.name = (char *) name; entry = hash_lookup (cached_dirfds, &key); if (entry) remove_cached_dirfd (entry); } -static int openat_cached (int dirfd, const char *name, int keepfd) +/* Put the looked up path back onto the lru list. Return the file descriptor + of the top entry. */ +static int put_path (struct cached_dirfd *entry) +{ + int fd = entry->fd; + + while (entry) + { + struct cached_dirfd *parent = entry->parent; + if (! parent) + break; + list_add (&entry->lru_link, &lru_list); + entry = parent; + } + + return fd; +} + +static struct cached_dirfd *new_cached_dirfd (struct cached_dirfd *dir, const char *name, int fd) +{ + struct cached_dirfd *entry = xmalloc (sizeof (struct cached_dirfd)); + + INIT_LIST_HEAD (&entry->lru_link); + list_add (&entry->children_link, &dir->children); + INIT_LIST_HEAD (&entry->children); + entry->parent = dir; + entry->name = xstrdup (name); + entry->fd = fd; + return entry; +} + +static struct cached_dirfd *openat_cached (struct cached_dirfd *dir, const char *name, int keepfd) { int fd; - struct cached_dirfd *entry = lookup_cached_dirfd (dirfd, name); + struct cached_dirfd *entry = lookup_cached_dirfd (dir, name); if (entry) - return entry->fd; + { + list_del_init (&entry->lru_link); + /* assert (list_empty (&entry->lru_link)); */ + goto out; + } dirfd_cache_misses++; /* Actually get the new directory file descriptor. Don't follow symbolic links. */ - fd = openat (dirfd, name, O_DIRECTORY | O_NOFOLLOW); + fd = openat (dir->fd, name, O_DIRECTORY | O_NOFOLLOW); /* Don't cache errors. */ if (fd < 0) - return fd; + return NULL; /* Store new cache entry */ - entry = xmalloc (sizeof (struct cached_dirfd)); - entry->dirfd = dirfd; - entry->name = xstrdup (name); - entry->fd = fd; + entry = new_cached_dirfd (dir, name, fd); insert_cached_dirfd (entry, keepfd); - return fd; +out: + return entry; +} + +static unsigned int count_path_components (const char *path) +{ + unsigned int components; + + while (ISSLASH (*path)) + path++; + if (! *path) + return 1; + for (components = 0; *path; components++) + { + while (*path && ! ISSLASH (*path)) + path++; + while (ISSLASH (*path)) + path++; + } + return components; } -/* Resolve the next path component in PATH inside DIRFD. */ -static int traverse_next (int dirfd, const char **path, int keepfd) +/* A symlink to resolve. */ +struct symlink { + struct symlink *prev; + const char *path; + char buffer[0]; +}; + +static void push_symlink (struct symlink **stack, struct symlink *symlink) +{ + symlink->prev = *stack; + *stack = symlink; +} + +static void pop_symlink (struct symlink **stack) +{ + struct symlink *top = *stack; + *stack = top->prev; + free (top); +} + +int cwd_stat_errno = -1; +struct stat cwd_stat; + +static struct symlink *read_symlink(int dirfd, const char *name) +{ + int saved_errno = errno; + struct stat st; + struct symlink *symlink; + ssize_t ret; + + if (fstatat (dirfd, name, &st, AT_SYMLINK_NOFOLLOW) + || ! S_ISLNK (st.st_mode)) + { + errno = saved_errno; + return NULL; + } + symlink = xmalloc (sizeof (*symlink) + st.st_size + 1); + ret = readlinkat (dirfd, name, symlink->buffer, st.st_size); + if (ret <= 0) + goto fail; + symlink->buffer[ret] = 0; + symlink->path = symlink->buffer; + if (ISSLASH (*symlink->path)) + { + char *end; + + if (cwd_stat_errno == -1) + { + cwd_stat_errno = stat (".", &cwd_stat) == 0 ? 0 : errno; + if (cwd_stat_errno) + goto fail_exdev; + } + end = symlink->buffer + ret; + for (;;) + { + char slash; + int rv; + + slash = *end; *end = 0; + rv = stat (symlink->path, &st); + *end = slash; + + if (rv == 0 + && st.st_dev == cwd_stat.st_dev + && st.st_ino == cwd_stat.st_ino) + { + while (ISSLASH (*end)) + end++; + symlink->path = end; + return symlink; + } + end--; + if (end == symlink->path) + break; + while (end != symlink->path + 1 && ! ISSLASH (*end)) + end--; + while (end != symlink->path + 1 && ISSLASH (*(end - 1))) + end--; + } + goto fail_exdev; + } + return symlink; + +fail_exdev: + errno = EXDEV; +fail: + free (symlink); + return NULL; +} + +/* Resolve the next path component in PATH inside DIR. If it is a symlink, + read it and returned it in TOP. */ +static struct cached_dirfd * +traverse_next (struct cached_dirfd *dir, const char **path, int keepfd, + struct symlink **symlink) { const char *p = *path; + struct cached_dirfd *entry = dir; char *name; while (*p && ! ISSLASH (*p)) p++; if (**path == '.' && *path + 1 == p) goto skip; + if (**path == '.' && *(*path + 1) == '.' && *path + 2 == p) + { + entry = dir->parent; + if (! entry) + { + /* Must not leave the working tree. */ + errno = EXDEV; + goto out; + } + assert (list_empty (&dir->lru_link)); + list_add (&dir->lru_link, &lru_list); + goto skip; + } name = alloca (p - *path + 1); memcpy(name, *path, p - *path); name[p - *path] = 0; - dirfd = openat_cached (dirfd, name, keepfd); - if (dirfd < 0 && dirfd != AT_FDCWD) + entry = openat_cached (dir, name, keepfd); + if (! entry) { - *path = p; - return -1; + if (errno == ELOOP + || errno == EMLINK /* FreeBSD 10.1: Too many links */ + || errno == EFTYPE /* NetBSD 6.1: Inappropriate file type or format */ + || errno == ENOTDIR) + { + if ((*symlink = read_symlink (dir->fd, name))) + { + entry = dir; + goto skip; + } + errno = ELOOP; + } + goto out; } skip: while (ISSLASH (*p)) p++; +out: *path = p; - return dirfd; + return entry; } /* Traverse PATHNAME. Updates PATHNAME to point to the last path component and returns a file descriptor to its parent directory (which can be AT_FDCWD). When KEEPFD is given, make sure that the cache entry for DIRFD is not - removed from the cache (and KEEPFD remains open) even if the cache grows - beyond MAX_CACHED_FDS entries. */ + removed from the cache (and KEEPFD remains open). + + When this function is not running, all cache entries are on the lru list, + and all cache entries which still have a parent are also in the hash table. + While this function is running, all cache entries on the path being looked + up are off the lru list but in the hash table. + */ static int traverse_another_path (const char **pathname, int keepfd) { - unsigned long misses = dirfd_cache_misses; + static struct cached_dirfd cwd = { + .fd = AT_FDCWD, + }; + + unsigned int misses = dirfd_cache_misses; const char *path = *pathname, *last; - int dirfd = AT_FDCWD; + struct cached_dirfd *dir = &cwd; + struct symlink *stack = NULL; + unsigned int steps = count_path_components (path); + struct cached_dirfd *traversed_symlink = NULL; + + INIT_LIST_HEAD (&cwd.children); + + if (steps > MAX_PATH_COMPONENTS) + { + errno = ELOOP; + return -1; + } if (! *path || IS_ABSOLUTE_FILE_NAME (path)) - return dirfd; + return AT_FDCWD; /* Find the last pathname component */ last = strrchr (path, 0) - 1; @@ -263,41 +448,88 @@ static int traverse_another_path (const char **pathname, int keepfd) while (last != path && ! ISSLASH (*(last - 1))) last--; if (last == path) - return dirfd; + return AT_FDCWD; if (debug & 32) printf ("Resolving path \"%.*s\"", (int) (last - path), path); - while (path != last) + while (stack || path != last) { - dirfd = traverse_next (dirfd, &path, keepfd); - if (dirfd < 0 && dirfd != AT_FDCWD) + struct cached_dirfd *entry; + struct symlink *symlink = NULL; + const char *prev = path; + + entry = traverse_next (dir, stack ? &stack->path : &path, keepfd, &symlink); + if (! entry) { if (debug & 32) { printf (" (failed)\n"); fflush (stdout); } - if (errno == ELOOP) + goto fail; + } + dir = entry; + if (! stack && symlink) + { + const char *p = prev; + char *name; + + while (*p && ! ISSLASH (*p)) + p++; + name = alloca (p - prev + 1); + memcpy (name, prev, p - prev); + name[p - prev] = 0; + + traversed_symlink = new_cached_dirfd (dir, name, -1); + } + if (stack && ! *stack->path) + pop_symlink (&stack); + if (symlink && *symlink->path) + { + push_symlink (&stack, symlink); + steps += count_path_components (symlink->path); + if (steps > MAX_PATH_COMPONENTS) { - fprintf (stderr, "Refusing to follow symbolic link %.*s\n", - (int) (path - *pathname), *pathname); - fatal_exit (0); + errno = ELOOP; + goto fail; } - return dirfd; + } + else if (symlink) + pop_symlink (&symlink); + if (traversed_symlink && ! stack) + { + traversed_symlink->fd = + entry->fd == AT_FDCWD ? AT_FDCWD : dup (entry->fd); + if (traversed_symlink->fd != -1) + { + insert_cached_dirfd (traversed_symlink, keepfd); + list_add (&traversed_symlink->lru_link, &lru_list); + } + else + free_cached_dirfd (traversed_symlink); + traversed_symlink = NULL; } } *pathname = last; if (debug & 32) { - misses = dirfd_cache_misses - misses; + misses = (signed int) dirfd_cache_misses - (signed int) misses; if (! misses) printf(" (cached)\n"); else - printf (" (%lu miss%s)\n", misses, misses == 1 ? "" : "es"); + printf (" (%u miss%s)\n", misses, misses == 1 ? "" : "es"); fflush (stdout); } - return dirfd; + return put_path (dir); + +fail: + if (traversed_symlink) + free_cached_dirfd (traversed_symlink); + put_path (dir); + while (stack) + pop_symlink (&stack); + return -1; } /* Just traverse PATHNAME; see traverse_another_path(). */ @@ -346,16 +578,19 @@ int safe_rename (const char *oldpath, const char *newpath) int ret; olddirfd = traverse_path (&oldpath); - if (olddirfd != AT_FDCWD && olddirfd < 0) + if (olddirfd < 0 && olddirfd != AT_FDCWD) return olddirfd; newdirfd = traverse_another_path (&newpath, olddirfd); - if (newdirfd != AT_FDCWD && newdirfd < 0) + if (newdirfd < 0 && newdirfd != AT_FDCWD) return newdirfd; ret = renameat (olddirfd, oldpath, newdirfd, newpath); - invalidate_cached_dirfd (olddirfd, oldpath); - invalidate_cached_dirfd (newdirfd, newpath); + if (! ret) + { + invalidate_cached_dirfd (olddirfd, oldpath); + invalidate_cached_dirfd (newdirfd, newpath); + } return ret; } @@ -381,7 +616,8 @@ int safe_rmdir (const char *pathname) return dirfd; ret = unlinkat (dirfd, pathname, AT_REMOVEDIR); - invalidate_cached_dirfd (dirfd, pathname); + if (! ret) + invalidate_cached_dirfd (dirfd, pathname); return ret; } @@ -441,7 +677,7 @@ int safe_lutimens (const char *pathname, struct timespec const times[2]) } /* Replacement for readlink() */ -ssize_t safe_readlink(const char *pathname, char *buf, size_t bufsiz) +ssize_t safe_readlink (const char *pathname, char *buf, size_t bufsiz) { int dirfd; @@ -452,7 +688,7 @@ ssize_t safe_readlink(const char *pathname, char *buf, size_t bufsiz) } /* Replacement for access() */ -int safe_access(const char *pathname, int mode) +int safe_access (const char *pathname, int mode) { int dirfd; diff --git a/src/util.c b/src/util.c index fae628a..82a7e37 100644 --- a/src/util.c +++ b/src/util.c @@ -1598,12 +1598,39 @@ Fseek (FILE *stream, file_offset offset, int ptrname) #define TMPDIR "/tmp" #endif +struct try_safe_open_args + { + int flags; + mode_t mode; + }; + +static int try_safe_open (char *template, void *__args) +{ + struct try_safe_open_args *args = __args; + int try_makedirs_errno = ENOENT; + int fd; + +repeat: + fd = safe_open (template, O_CREAT | O_EXCL | args->flags, args->mode); + if (fd < 0 && errno == try_makedirs_errno) + { + makedirs (template); + try_makedirs_errno = 0; + goto repeat; + } + return fd; +} + int make_tempfile (char const **name, char letter, char const *real_name, int flags, mode_t mode) { - int try_makedirs_errno = ENOENT; char *template; + struct try_safe_open_args args = { + .flags = flags, + .mode = mode, + }; + int fd; if (real_name && ! dry_run) { @@ -1632,36 +1659,9 @@ make_tempfile (char const **name, char letter, char const *real_name, template = xmalloc (strlen (tmpdir) + 10); sprintf (template, "%s/p%cXXXXXX", tmpdir, letter); } - for(;;) - { - int fd; - - /* gen_tempname(..., GT_NOCREATE) calls lstat() to check if a file - already exists. In the worst case, this leads to a template that - follows a symbolic link and that we cannot use; safe_open() will - detect that. */ - - if (gen_tempname (template, 0, flags, GT_NOCREATE)) - pfatal ("Can't create temporary file %s", template); - retry: - fd = safe_open (template, O_CREAT | O_EXCL | flags, mode); - if (fd == -1) - { - if (errno == try_makedirs_errno) - { - makedirs (template); - /* FIXME: When patch fails, this may leave around empty - directories. */ - try_makedirs_errno = 0; - goto retry; - } - if (errno == EEXIST) - continue; - pfatal ("Can't create temporary file %s", template); - } - *name = template; - return fd; - } + fd = try_tempname(template, 0, &args, try_safe_open); + *name = template; + return fd; } int stat_file (char const *filename, struct stat *st) diff --git a/tests/Makefile.in b/tests/Makefile.in index 838b98e..9b144ea 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -109,17 +109,21 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \ $(top_srcdir)/m4/double-slash-root.m4 $(top_srcdir)/m4/dup2.m4 \ $(top_srcdir)/m4/eealloc.m4 $(top_srcdir)/m4/environ.m4 \ $(top_srcdir)/m4/errno_h.m4 $(top_srcdir)/m4/error.m4 \ - $(top_srcdir)/m4/exponentd.m4 $(top_srcdir)/m4/extensions.m4 \ - $(top_srcdir)/m4/extern-inline.m4 $(top_srcdir)/m4/fchdir.m4 \ + $(top_srcdir)/m4/euidaccess.m4 $(top_srcdir)/m4/exponentd.m4 \ + $(top_srcdir)/m4/extensions.m4 \ + $(top_srcdir)/m4/extern-inline.m4 \ + $(top_srcdir)/m4/faccessat.m4 $(top_srcdir)/m4/fchdir.m4 \ $(top_srcdir)/m4/fchmodat.m4 $(top_srcdir)/m4/fchownat.m4 \ $(top_srcdir)/m4/fcntl-o.m4 $(top_srcdir)/m4/fcntl.m4 \ $(top_srcdir)/m4/fcntl_h.m4 $(top_srcdir)/m4/filenamecat.m4 \ $(top_srcdir)/m4/float_h.m4 $(top_srcdir)/m4/fstat.m4 \ $(top_srcdir)/m4/fstatat.m4 $(top_srcdir)/m4/getcwd.m4 \ - $(top_srcdir)/m4/getdtablesize.m4 $(top_srcdir)/m4/getopt.m4 \ + $(top_srcdir)/m4/getdtablesize.m4 \ + $(top_srcdir)/m4/getgroups.m4 $(top_srcdir)/m4/getopt.m4 \ $(top_srcdir)/m4/gettime.m4 $(top_srcdir)/m4/gettimeofday.m4 \ $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnulib-common.m4 \ $(top_srcdir)/m4/gnulib-comp.m4 \ + $(top_srcdir)/m4/group-member.m4 \ $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/intmax_t.m4 \ $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/largefile.m4 \ $(top_srcdir)/m4/lchown.m4 $(top_srcdir)/m4/localcharset.m4 \ @@ -927,6 +931,7 @@ LIBPATCH_LIBDEPS = @LIBPATCH_LIBDEPS@ LIBPATCH_LTLIBDEPS = @LIBPATCH_LTLIBDEPS@ LIBS = @LIBS@ LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ +LIB_EACCESS = @LIB_EACCESS@ LIB_XATTR = @LIB_XATTR@ LOCALCHARSET_TESTS_ENVIRONMENT = @LOCALCHARSET_TESTS_ENVIRONMENT@ LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@ diff --git a/tests/copy-rename b/tests/copy-rename index fd5fd64..ef9bc8e 100644 --- a/tests/copy-rename +++ b/tests/copy-rename @@ -63,6 +63,30 @@ check 'cat h' < h + +check 'patch -p1 < rename.diff || echo "Status: $?"' <& /dev/null || exit 77 +ulimit -n 32 > /dev/null 2>&1 || exit 77 cat > ab.diff < read-only chmod a-w read-only -if : 2> /dev/null > read-only; then +if ( : 2> /dev/null > read-only ); then echo "Files with read-only permissions are writable" \ "(probably running as superuser)" >&2 exit 77 diff --git a/tests/symlinks b/tests/symlinks index 36fbb1e..518e446 100644 --- a/tests/symlinks +++ b/tests/symlinks @@ -59,6 +59,14 @@ check 'patch --follow-symlinks < modify.diff || echo "Status: $?"' < f.diff < retraverse.diff < d/f +ln -s d ld + +cat > ld.diff < eld.diff < follow-bad-symlink.diff < symlink-target.diff < bad-symlink-target1.diff < good-absolute.diff <