Imported Upstream version 2.7.5 upstream/2.7.5
authorDongHun Kwak <dh0128.kwak@samsung.com>
Thu, 20 Jan 2022 05:18:14 +0000 (14:18 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Thu, 20 Jan 2022 05:18:14 +0000 (14:18 +0900)
52 files changed:
.tarball-version
ChangeLog
Makefile.in
NEWS
TODO
aclocal.m4
build-aux/config.guess
build-aux/config.sub
build-aux/texinfo.tex
config.hin
configure
lib/Makefile.in
lib/diffseq.h
lib/dirent--.h
lib/dirent.in.h
lib/euidaccess.c [new file with mode: 0644]
lib/faccessat.c [new file with mode: 0644]
lib/getdtablesize.c
lib/getgroups.c [new file with mode: 0644]
lib/getopt.c
lib/gnulib.mk
lib/group-member.c [new file with mode: 0644]
lib/root-uid.h [new file with mode: 0644]
lib/signal.in.h
lib/symlinkat.c
lib/tempname.c
lib/tempname.h
lib/vasnprintf.c
lib/xalloc.h
m4/dup2.m4
m4/euidaccess.m4 [new file with mode: 0644]
m4/faccessat.m4 [new file with mode: 0644]
m4/fcntl.m4
m4/getdtablesize.m4
m4/getgroups.m4 [new file with mode: 0644]
m4/gnulib-comp.m4
m4/group-member.m4 [new file with mode: 0644]
m4/printf.m4
src/Makefile.am
src/Makefile.in
src/inp.c
src/list.h [new file with mode: 0644]
src/patch.c
src/pch.c
src/safe.c
src/util.c
tests/Makefile.in
tests/copy-rename
tests/deep-directories
tests/no-mode-change-git-diff
tests/read-only-files
tests/symlinks

index a4dd9dba4fbfc56b9de647bc31ed848d9f65885f..a603bb50a29e354cfdf452850141fcb013b0a71a 100644 (file)
@@ -1 +1 @@
-2.7.4
+2.7.5
index 21e051e3d98b4196d37e87d45ba7c4f53306ec96..84eefd5d9dcbef7affc72fdad0092e32b03cf229 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,186 @@
+2015-03-07  Andreas Gruenbacher  <agruen@gnu.org>
+
+       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  <agruen@gnu.org>
+
+       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  <twaugh@redhat.com>
+
+       Add more path traversal test cases
+       * tests/symlinks: Add more path traversal test cases.
+
+2015-03-05  Andreas Gruenbacher  <agruen@gnu.org>
+
+       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  <agruen@gnu.org>
+
+       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  <agruen@gnu.org>
+
+       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  <agruen@gnu.org>
+
+       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  <agruen@gnu.org>
+
+       Test suite portability fixes
+       Reported and fixed (mostly) by Christian Weisgerber <naddy@mips.inka.de>:
+       * 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  <agruen@gnu.org>
+
+       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  <agruen@gnu.org>
+
+       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  <agruen@gnu.org>
 
        Upate NEWS
index bc6329c82a4397df425275f6b3a7d454ce1bfcf8..f480e3214055bd80a43295a109cc12fdf7821445 100644 (file)
@@ -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 9fafde479eff5f6c5271da1a8d657890580b78e9..d9e1cf266002dbad1adcf835a1cfc27eeefb1b9d 100644 (file)
--- 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 41324ab55174d1b1562866927b72404b04c5cee1..55e65a05d5ba5ef7af79e0406c2679179955371a 100644 (file)
--- 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.
index e2807fb1a8f614db8877c7ff072bf7e86339ad10..788c0f8aafc23e0d316c1b3f5612bf45b0568111 100644 (file)
@@ -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 <drepper@cygnus.com>, 1995-2000.
+dnl   Bruno Haible <haible@clisp.cons.org>, 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 <<EOT
+$*
+EOT
+      }
+      gt_echo='echo_func'
+    fi
+  fi
+
+  # A sed script that extracts the value of VARIABLE from a Makefile.
+  tab=`printf '\t'`
+  sed_x_variable='
+# Test if the hold space is empty.
+x
+s/P/P/
+x
+ta
+# Yes it was empty. Look if we have the expected variable definition.
+/^['"${tab}"' ]*VARIABLE['"${tab}"' ]*=/{
+  # Seen the first line of the variable definition.
+  s/^['"${tab}"' ]*VARIABLE['"${tab}"' ]*=//
+  ba
+}
+bd
+:a
+# Here we are processing a line from the variable definition.
+# Remove comment, more precisely replace it with a space.
+s/#.*$/ /
+# See if the line ends in a backslash.
+tb
+:b
+s/\\$//
+# Print the line, without the trailing backslash.
+p
+tc
+# There was no trailing backslash. The end of the variable definition is
+# reached. Clear the hold space.
+s/^.*$//
+x
+bd
+:c
+# A trailing backslash means that the variable definition continues in the
+# next line. Put a nonempty string into the hold space to indicate this.
+s/^.*$/P/
+x
+:d
+'
+changequote([,])dnl
+
+  # Set POTFILES to the value of the Makefile variable POTFILES.
+  sed_x_POTFILES=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/POTFILES/g'`
+  POTFILES=`sed -n -e "$sed_x_POTFILES" < "$ac_file"`
+  # Compute POTFILES_DEPS as
+  #   $(foreach file, $(POTFILES), $(top_srcdir)/$(file))
+  POTFILES_DEPS=
+  for file in $POTFILES; do
+    POTFILES_DEPS="$POTFILES_DEPS "'$(top_srcdir)/'"$file"
+  done
+  POMAKEFILEDEPS=""
+
+  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
+  if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
+    # The LINGUAS file contains the set of available languages.
+    ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"`
+    POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS"
+  else
+    # Set ALL_LINGUAS to the value of the Makefile variable LINGUAS.
+    sed_x_LINGUAS=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/LINGUAS/g'`
+    ALL_LINGUAS_=`sed -n -e "$sed_x_LINGUAS" < "$ac_file"`
+  fi
+  # Hide the ALL_LINGUAS assignment from automake < 1.5.
+  eval 'ALL_LINGUAS''=$ALL_LINGUAS_'
+  # 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)
+  # Compute PROPERTIESFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).properties)
+  # Compute CLASSFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).class)
+  # Compute QMFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).qm)
+  # Compute MSGFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang)).msg)
+  # Compute RESOURCESDLLFILES
+  # as      $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang))/$(DOMAIN).resources.dll)
+  case "$ac_given_srcdir" in
+    .) srcdirpre= ;;
+    *) srcdirpre='$(srcdir)/' ;;
+  esac
+  POFILES=
+  UPDATEPOFILES=
+  DUMMYPOFILES=
+  GMOFILES=
+  PROPERTIESFILES=
+  CLASSFILES=
+  QMFILES=
+  MSGFILES=
+  RESOURCESDLLFILES=
+  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"
+    PROPERTIESFILES="$PROPERTIESFILES \$(top_srcdir)/\$(DOMAIN)_$lang.properties"
+    CLASSFILES="$CLASSFILES \$(top_srcdir)/\$(DOMAIN)_$lang.class"
+    QMFILES="$QMFILES $srcdirpre$lang.qm"
+    frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
+    MSGFILES="$MSGFILES $srcdirpre$frobbedlang.msg"
+    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/'`
+    RESOURCESDLLFILES="$RESOURCESDLLFILES $srcdirpre$frobbedlang/\$(DOMAIN).resources.dll"
+  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=
+  JAVACATALOGS=
+  QTCATALOGS=
+  TCLCATALOGS=
+  CSHARPCATALOGS=
+  if test -n "$INST_LINGUAS"; then
+    for lang in $INST_LINGUAS; do
+      CATALOGS="$CATALOGS $lang.gmo"
+      JAVACATALOGS="$JAVACATALOGS \$(DOMAIN)_$lang.properties"
+      QTCATALOGS="$QTCATALOGS $lang.qm"
+      frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
+      TCLCATALOGS="$TCLCATALOGS $frobbedlang.msg"
+      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/'`
+      CSHARPCATALOGS="$CSHARPCATALOGS $frobbedlang/\$(DOMAIN).resources.dll"
+    done
+  fi
+
+  sed -e "s|@POTFILES_DEPS@|$POTFILES_DEPS|g" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@PROPERTIESFILES@|$PROPERTIESFILES|g" -e "s|@CLASSFILES@|$CLASSFILES|g" -e "s|@QMFILES@|$QMFILES|g" -e "s|@MSGFILES@|$MSGFILES|g" -e "s|@RESOURCESDLLFILES@|$RESOURCESDLLFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@JAVACATALOGS@|$JAVACATALOGS|g" -e "s|@QTCATALOGS@|$QTCATALOGS|g" -e "s|@TCLCATALOGS@|$TCLCATALOGS|g" -e "s|@CSHARPCATALOGS@|$CSHARPCATALOGS|g" -e 's,^#distdir:,distdir:,' < "$ac_file" > "$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" <<EOF
+$frobbedlang.msg: $lang.po
+${tab}@echo "\$(MSGFMT) -c --tcl -d \$(srcdir) -l $lang $srcdirpre$lang.po"; \
+${tab}\$(MSGFMT) -c --tcl -d "\$(srcdir)" -l $lang $srcdirpre$lang.po || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; }
+EOF
+    done
+  fi
+  if grep -l '@CSHARPCATALOGS@' "$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/_/-/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" <<EOF
+$frobbedlang/\$(DOMAIN).resources.dll: $lang.po
+${tab}@echo "\$(MSGFMT) -c --csharp -d \$(srcdir) -l $lang $srcdirpre$lang.po -r \$(DOMAIN)"; \
+${tab}\$(MSGFMT) -c --csharp -d "\$(srcdir)" -l $lang $srcdirpre$lang.po -r "\$(DOMAIN)" || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; }
+EOF
+    done
+  fi
+  if test -n "$POMAKEFILEDEPS"; then
+    cat >> "$ac_file.tmp" <<EOF
+Makefile: $POMAKEFILEDEPS
+EOF
+  fi
+  mv "$ac_file.tmp" "$ac_file"
+])
+
+dnl Initializes the accumulator used by AM_XGETTEXT_OPTION.
+AC_DEFUN([AM_XGETTEXT_OPTION_INIT],
+[
+  XGETTEXT_EXTRA_OPTIONS=
+])
+
+dnl Registers an option to be passed to xgettext in the po subdirectory.
+AC_DEFUN([AM_XGETTEXT_OPTION],
+[
+  AC_REQUIRE([AM_XGETTEXT_OPTION_INIT])
+  XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS $1"
+])
+
 # Copyright (C) 2002-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
@@ -1231,9 +1685,11 @@ m4_include([m4/eealloc.m4])
 m4_include([m4/environ.m4])
 m4_include([m4/errno_h.m4])
 m4_include([m4/error.m4])
+m4_include([m4/euidaccess.m4])
 m4_include([m4/exponentd.m4])
 m4_include([m4/extensions.m4])
 m4_include([m4/extern-inline.m4])
+m4_include([m4/faccessat.m4])
 m4_include([m4/fchdir.m4])
 m4_include([m4/fchmodat.m4])
 m4_include([m4/fchownat.m4])
@@ -1246,12 +1702,14 @@ m4_include([m4/fstat.m4])
 m4_include([m4/fstatat.m4])
 m4_include([m4/getcwd.m4])
 m4_include([m4/getdtablesize.m4])
+m4_include([m4/getgroups.m4])
 m4_include([m4/getopt.m4])
 m4_include([m4/gettime.m4])
 m4_include([m4/gettimeofday.m4])
 m4_include([m4/glibc21.m4])
 m4_include([m4/gnulib-common.m4])
 m4_include([m4/gnulib-comp.m4])
+m4_include([m4/group-member.m4])
 m4_include([m4/include_next.m4])
 m4_include([m4/intmax_t.m4])
 m4_include([m4/inttypes_h.m4])
index dbfb9786cb6f9b8003367505d49dcadb2145610a..f7eb141e75a921f7b87b97983ac1bd8949995716 100755 (executable)
@@ -2,7 +2,7 @@
 # Attempt to guess a canonical system name.
 #   Copyright 1992-2015 Free Software Foundation, Inc.
 
-timestamp='2015-01-01'
+timestamp='2015-03-04'
 
 # 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
@@ -168,20 +168,27 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
        # Note: NetBSD doesn't particularly care about the vendor
        # portion of the name.  We always set it to "unknown".
        sysctl="sysctl -n hw.machine_arch"
-       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/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 ;;
index 6d2e94c8bf9ea6925b96846aade1fd64074985d3..60e3590b4739f0a405d4f38cb07345cbe2272ce0 100755 (executable)
@@ -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* \
index 7f5f357549119e11f27ab51427df15f4bb4a9446..8236d7d2f8258f08874bb9240a537bb803259358 100644 (file)
@@ -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
index f15a9cdbe59cfabce4cba50022777a90fad9fd88..1663bf43f1b0da95c617233cf017a4c0139760d4 100644 (file)
 /* 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
 
    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
 /* 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
 
 /* 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
 
 /* 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 <alloca.h>, a header that
    may be supplied by this distribution. */
 #undef HAVE_ALLOCA
    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
 /* 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
 
 /* 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 <getopt.h> header file. */
 #undef HAVE_GETOPT_H
 
 /* Define to 1 if you have the `lchown' function. */
 #undef HAVE_LCHOWN
 
+/* Define to 1 if you have the <libgen.h> header file. */
+#undef HAVE_LIBGEN_H
+
 /* Define to 1 if you have the `link' function. */
 #undef HAVE_LINK
 
index 1e1aedcc78e9a16a3f9d16b343e46c5c5e941a5b..222934a0d275665d4c17f5264556edd4d1190d96 100755 (executable)
--- 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 <bug-patch@gnu.org>.
 #
@@ -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 <unistd.h>
+
+_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 <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
+         #include <errno.h>
+             #include <fcntl.h>
+             #include <limits.h>
+             #include <sys/resource.h>
+             #include <unistd.h>
+             #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 <unistd.h>
-#endif
-#include <fcntl.h>
 #include <errno.h>
+              #include <fcntl.h>
+              #include <limits.h>
+              #include <sys/resource.h>
+              #include <unistd.h>
+              #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\\"
 
index bc3e54481545228ffdafd5728aac840bdfec6050..9487d28b28e7ae9c8e5ecce09b94e2f01dc40ca7 100644 (file)
@@ -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@
index b4188300c022197cb9f4a6c471e104e912d62357..a4f389adca24f71b572d42aedf32d652d9b7f3cb 100644 (file)
@@ -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].
index 17a88538795ec3ef8da4d34c20cd14d7563b5b38..aa3f4929cb2ced584b43cf2232a80427fb75a695 100644 (file)
@@ -21,3 +21,4 @@
 
 #undef opendir
 #define opendir opendir_safer
+#define GNULIB_defined_opendir 1
index ddd3b84fbb289fefd16d89e6a95f26da1dffbd4b..154d2689e3da7cc1330f1063f61e098f7fe3dc87 100644 (file)
@@ -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 (file)
index 0000000..c7e6cfb
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.  */
+
+/* Written by David MacKenzie and Torbjorn Granlund.
+   Adapted for GNU C library by Roland McGrath.  */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "root-uid.h"
+
+#if HAVE_LIBGEN_H
+# include <libgen.h>
+#endif
+
+#include <errno.h>
+#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
+\f
+#ifdef TEST
+# include <error.h>
+# include <stdio.h>
+# include <stdlib.h>
+
+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 (file)
index 0000000..5bd7ecf
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.  */
+
+/* written by Eric Blake */
+
+#include <config.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#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"
index 59b97360bc576dce3b5c8f79a1d5b369670c34f1..03eb7ef1bffd1e793a5b802eb6f2ab4d6dc4b9cf 100644 (file)
@@ -84,32 +84,38 @@ getdtablesize (void)
   return dtablesize;
 }
 
-#elif HAVE_GETDTABLESIZE
+#else
 
+# include <limits.h>
 # include <sys/resource.h>
-# 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 (file)
index 0000000..5563dfb
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.  */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#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 */
index 3b9c585a28c3abf20d6214ac62acc639d6cba001..212cbf7341074627ef9fa7440783aaab8643d9e2 100644 (file)
@@ -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)
         {
index 9d80d74349de1dbc71561636553c3a59d2501b54..e7d245a1ed345f7a6c75ecd6e97b0828a107a9f7 100644 (file)
@@ -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 (file)
index 0000000..23074e4
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+#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 (file)
index 0000000..d263f4d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+   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
index 0f2ff5af8435a9a8928f4070a64a8148435fad6d..265b72ab0ec5fbff87cd210dc89fe8ff570cc8f5 100644 (file)
 #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 <pthread.h>, not in <signal.h>.
+/* Mac OS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6, Android
+   declare pthread_sigmask in <pthread.h>, not in <signal.h>.
    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 <pthread.h>
 #endif
index ce10d94a47b5105ad51529d23e0f22a8814db225..84d55847696fe59dcb59a13b9dd7c7ac4e407775 100644 (file)
@@ -24,6 +24,9 @@
 #if HAVE_SYMLINKAT
 # undef symlinkat
 
+#include <sys/stat.h>
+#include <string.h>
+
 /* Create a symlink, but reject trailing slash.  */
 int
 rpl_symlinkat (char const *contents, int fd, char const *name)
index 088b224ab96784c2d6f856aeb7eebba4f219642e..8e6d26cc4859c83aa5a44534f41bdb7b9713d4df 100644 (file)
@@ -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);
+}
index b560ee5cb147dcea2d6dd36748ce4b01f5af128f..e6093607463c113edbafa52d19b86ce47d825f28 100644 (file)
 #  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
    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 */
index 246831f8d235474a22a76e2d777bc2a614569b24..88332f0bcae4555d54a93101348311d0af52a7a4 100644 (file)
@@ -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
index 3dfaa87fe408a46b8e06a52122db9c4591c99df3..68f847a2c4ee877948d3584b23c7f83193245bdb 100644 (file)
@@ -258,5 +258,6 @@ xmemdup (T const *p, size_t s)
 
 #endif
 
+_GL_INLINE_HEADER_END
 
 #endif /* !XALLOC_H_ */
index 0354c6ad478fc65dcc3222a72ef739374cfc4a5c..59028e0982cc2990cabf2e71d565906b4337d7f4 100644 (file)
@@ -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 <unistd.h>
-#include <fcntl.h>
-#include <errno.h>]],
-           [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 <errno.h>
+             #include <fcntl.h>
+             #include <limits.h>
+             #include <sys/resource.h>
+             #include <unistd.h>
+             #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 (file)
index 0000000..e23e9c3
--- /dev/null
@@ -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 <unistd.h> 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 (file)
index 0000000..941cb02
--- /dev/null
@@ -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 <unistd.h> 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])
+])
index 733cd2d701b2d1ee54271dad658b2d544861e515..76dd86711b224814c592fb73ce8a04ef8484aaaf 100644 (file)
@@ -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 <unistd.h>
-#endif
-#include <fcntl.h>
-#include <errno.h>
-]], [[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 <errno.h>
+              #include <fcntl.h>
+              #include <limits.h>
+              #include <sys/resource.h>
+              #include <unistd.h>
+              #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) ;;
index a6b6c1b6c52c671e18619b555a6ced64767bb7ed..25e9968947d0cf3703f60a4b86e67151c2846f1d 100644 (file)
@@ -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 (file)
index 0000000..16e72c7
--- /dev/null
@@ -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"
+])
index 00de6add3aeb2a8ce779d504bd6f2775d943b189..ae855f5ac596be3165e1a47af843d1146bdfd494 100644 (file)
@@ -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 (file)
index 0000000..526a67a
--- /dev/null
@@ -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 <unistd.h> 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])
+])
index ffbb235c6a0800597e3a824c7bff5b7eecc5d201..d06746aae78f872a63d5c1dbfed3a4ac996ef92a 100644 (file)
@@ -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
index 7690760ac8ada44a39abf70628520c98257e320e..4fe71d2887941d86e80fe52fe5f51d765a9e2ee6 100644 (file)
@@ -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
index 2104c86eebc3e910b74379e6186d049c2b41c457..d21ed19ad6335de93307ad5b3bca9b741cf20a0c 100644 (file)
@@ -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
 
index 49698373c4aded2bbc78ba488bf81a764271a00b..32d0919c1d1108b63c639a593108a560b9ae79f0 100644 (file)
--- 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 (file)
index 0000000..11d1184
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef __LIST_H
+#define __LIST_H
+
+#include <stdbool.h>
+
+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 */
index 2c51f446c18ec198bbef6a16bc2345669438b885..a60e6317144bac675b3f84cef44750abf2c5415b 100644 (file)
@@ -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)
index fd8885ea3493c5793fd5f8c66e36c65da12a5c24..9d74471304502d04433079f65082274af635eef2 100644 (file)
--- 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]) {
index eec6ce5cee175ab1f5a8421941aa56f2113f0590..cdf9f74265c6ea4e499a9929eebb14c95f7b8ef5 100644 (file)
 #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;
 
index fae628a0e9ed286f90db064a2d4036636e63efb6..82a7e3793c511bfb2857c05ecaf877968e17086f 100644 (file)
@@ -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)
index 838b98e89d457e8561a0776ad20b51fdab1cc799..9b144ea5a4450979e06dc79b17a52bcf5b6a7c6c 100644 (file)
@@ -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@
index fd5fd6446be4a84e830aa7a3ce0be1df61d4588c..ef9bc8e32c051fae02bc8f66db832938b9e09ed6 100644 (file)
@@ -63,6 +63,30 @@ check 'cat h' <<EOF
 new
 EOF
 
+echo old > h
+
+check 'patch -p1 < rename.diff || echo "Status: $?"' <<EOF
+patching file h (already renamed from f)
+EOF
+
+ncheck 'test ! -e f'
+
+check 'cat h' <<EOF
+new
+EOF
+
+mv h f
+
+check 'patch -p1 -R < rename.diff || echo "Status: $?"' <<EOF
+patching file f (already renamed from h)
+EOF
+
+ncheck 'test ! -e h'
+
+check 'cat f' <<EOF
+old
+EOF
+
 # --------------------------------------------------------------
 # Patches with no hunks
 
index d6a41a66be5224831a2c3ee1eb34b5e5a862d206..4698842631ed683472ed8b6371d9b58f1aa07042 100755 (executable)
@@ -14,7 +14,7 @@ use_tmpdir
 # Exercise the directory file descriptor cache
 
 # Artificially limit to 8 cache entries
-ulimit -n 32 >& /dev/null || exit 77
+ulimit -n 32 > /dev/null 2>&1 || exit 77
 
 cat > ab.diff <<EOF
 --- /dev/null
index 2f9bc36d91b1000fb025e920580397fd395cb758..b8f33c14177759f19a8c09950481a82801854c9c 100644 (file)
@@ -29,6 +29,6 @@ check 'patch -p1 < simple.diff || echo "Status:  $?"' <<EOF
 patching file f
 EOF
 
-check 'stat -c "%a" f'<<EOF
-755
+check 'ls -l f | sed "s,\(..........\).*,\1,"' <<EOF
+-rwxr-xr-x
 EOF
index bcc11a49e719012cb08d244d94ef36318ebfebec..febaeb855ea8386ae8875323c67e0dd05a8408e8 100644 (file)
@@ -16,7 +16,7 @@ use_tmpdir
 
 : > 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
index 36fbb1efc1a2054a6d0e4d0896fbe4b7e7b8ce42..518e446cf15275af370d01a39128b88cfc60cdba 100644 (file)
@@ -59,6 +59,14 @@ check 'patch --follow-symlinks < modify.diff || echo "Status: $?"' <<EOF
 patching file l
 EOF
 
+check 'cat f' <<EOF
+one
+EOF
+
+check 'cat l' <<EOF
+two
+EOF
+
 # --------------------------------------------------------------
 
 rm -f f l
@@ -146,12 +154,113 @@ ncheck 'test ! -L symlink'
 
 # --------------------------------------------------------------
 
+# Recursive symlinks
+
+ln -s l1 l2
+ln -s l2 l1
+
+cat > f.diff <<EOF
+--- l1/f
++++ l1/f
+@@ -0,0 +1 @@
++new
+EOF
+
+check 'patch -p0 < f.diff || echo "Status: $?"' <<EOF
+Invalid file name l1/f -- skipping patch
+Status: 1
+EOF
+
+rm -f l1 l2
+
+# --------------------------------------------------------------
+
+cat > retraverse.diff <<EOF
+--- abc/def/ghi/jkl
++++ abc/def/ghi/jkl
+@@ -0,0 +1 @@
++Parent directory traversal
+EOF
+
+ncheck 'mkdir abc'
+ncheck 'mkdir abc/def'
+ln -sf ../../abc/def abc/def/ghi
+check 'patch -p0 < retraverse.diff || echo "Status: $?"' << EOF
+patching file abc/def/ghi/jkl
+EOF
+
+# --------------------------------------------------------------
+
 # Patch should not create symlinks which point outside the working directory.
 
-# We cannot even ensure that symlinks with ".." components are safe: we cannot
-# guarantee that they won't end up higher up in the working tree than we think;
-# the path to the symlink may follow symlinks itself.
-#
+mkdir d
+echo one > d/f
+ln -s d ld
+
+cat > ld.diff <<EOF
+--- ld/f
++++ ld/f
+@@ -1 +1 @@
+-one
++two
+EOF
+
+check 'patch -p0 < ld.diff' <<EOF
+patching file ld/f
+EOF
+
+mkdir e
+ln -s ../d e/ld
+
+cat > eld.diff <<EOF
+--- e/ld/f
++++ e/ld/f
+@@ -1 +1 @@
+-two
++three
+EOF
+
+check 'patch -p0 < eld.diff' <<EOF
+patching file e/ld/f
+EOF
+
+rm -f e/ld
+ln -sf ../ld e/ld
+
+check 'patch -p0 -R < eld.diff' <<EOF
+patching file e/ld/f
+EOF
+
+mkdir g
+ln -sf ../../z g/bad-rel
+ln -sf .. bad-rel-step2
+ln -sf ../bad-rel-step2/z g/bad-rel-step1
+ln -sf /z g/bad-abs
+
+cat > follow-bad-symlink.diff <<EOF
+--- g/bad-rel/x
++++ g/bad-rel/x
+@@ -0,0 +1 @@
++relative
+--- g/bad-rel-step1/x
++++ g/bad-rel-step1/x
+@@ -0,0 +1 @@
++relative, 2 steps
+--- g/bad-abs/x
++++ g/bad-abs/x
+@@ -0,0 +1 @@
++absolute
+EOF
+
+check 'patch -p0 < follow-bad-symlink.diff || echo "Status: $?"' <<EOF
+Invalid file name g/bad-rel/x -- skipping patch
+Invalid file name g/bad-rel-step1/x -- skipping patch
+Invalid file name g/bad-abs/x -- skipping patch
+Status: 1
+EOF
+
+rm -rf ld d e g
+
 cat > symlink-target.diff <<EOF
 diff --git a/dir/foo b/dir/foo
 new file mode 120000
@@ -184,14 +293,37 @@ index 0000000..2ab772d
 +++ b/dir/foo/bar
 @@ -0,0 +1 @@
 +created in ..
+diff --git a/dir/bad b/dir/bad
+new file mode 120000
+index 0000000..cad2309
+--- /dev/null
++++ b/dir/bad
+@@ -0,0 +1 @@
++../..
+\ No newline at end of file
+diff --git a/dir/bad/baz b/dir/bad/baz
+new file mode 100644
+index 0000000..2ab772d
+--- /dev/null
++++ b/dir/bad/baz
+@@ -0,0 +1 @@
++created in ../..
 EOF
 
 check 'patch -f -p1 < follow-symlink.diff || echo "Status: $?"' <<EOF
 patching symbolic link dir/foo
-Refusing to follow symbolic link dir/foo
-Status: 2
+patching file dir/foo/bar
+patching symbolic link dir/bad
+Invalid file name dir/bad/baz -- skipping patch
+Status: 1
 EOF
 
+check 'cat bar' <<EOF
+created in ..
+EOF
+
+rm -f bar
+
 cat > bad-symlink-target1.diff <<EOF
 diff --git a/bar b/bar
 new file mode 120000
@@ -224,6 +356,32 @@ EOF
 
 # --------------------------------------------------------------
 
+# Absolute symlinks that point back into the working directory
+
+mkdir d
+ln -s $PWD here
+ln -s $PWD/here/d here_d
+
+cat > good-absolute.diff <<EOF
+--- /dev/null
++++ here/d/foo
+@@ -0,0 +1 @@
++foo
+--- /dev/null
++++ here_d/bar
+@@ -0,0 +1 @@
++bar
+EOF
+
+check 'patch -p0 < good-absolute.diff' <<EOF
+patching file here/d/foo
+patching file here_d/bar
+EOF
+
+rm -rf d
+
+# --------------------------------------------------------------
+
 # The backup file of a new symlink is an empty regular file.
 
 check 'patch -p1 --backup < create-symlink.diff || echo "Status: $?"' <<EOF