diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5806cd4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/tar-1.26.tar.xz
diff --git a/.tar.metadata b/.tar.metadata
new file mode 100644
index 0000000..230f038
--- /dev/null
+++ b/.tar.metadata
@@ -0,0 +1 @@
+996ac2937d426c5a0b3be2a00fc6ae05c16f71d8 SOURCES/tar-1.26.tar.xz
diff --git a/README.md b/README.md
deleted file mode 100644
index 0e7897f..0000000
--- a/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-The master branch has no content
- 
-Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6
- 
-If you find this file in a distro specific branch, it means that no content has been checked in yet
diff --git a/SOURCES/tar-1.14-loneZeroWarning.patch b/SOURCES/tar-1.14-loneZeroWarning.patch
new file mode 100644
index 0000000..70b20d3
--- /dev/null
+++ b/SOURCES/tar-1.14-loneZeroWarning.patch
@@ -0,0 +1,29 @@
+diff --git a/src/list.c b/src/list.c
+index cf2de09..f4e6e0a 100644
+--- a/src/list.c
++++ b/src/list.c
+@@ -212,6 +212,14 @@ read_and (void (*do_something) (void))
+ 
+ 	  if (!ignore_zeros_option)
+ 	    {
++             /*
++              * According to POSIX tar specs, this is wrong, but on the web
++              * there are some tar specs that can trigger this, and some tar
++              * implementations create tars according to that spec.  For now,
++              * let's not be pedantic about issuing the warning.
++              */
++#if 0
++
+ 	      char buf[UINTMAX_STRSIZE_BOUND];
+ 
+ 	      status = read_header (&current_header, &current_stat_info,
+@@ -221,6 +229,9 @@ read_and (void (*do_something) (void))
+ 	      WARNOPT (WARN_ALONE_ZERO_BLOCK,
+ 		       (0, 0, _("A lone zero block at %s"),
+ 			STRINGIFY_BIGINT (current_block_ordinal (), buf)));
++#endif
++	      status = read_header (&current_header, &current_stat_info,
++	                            read_header_auto);
+ 	      break;
+ 	    }
+ 	  status = prev_status;
diff --git a/SOURCES/tar-1.15.1-vfatTruncate.patch b/SOURCES/tar-1.15.1-vfatTruncate.patch
new file mode 100644
index 0000000..a61684e
--- /dev/null
+++ b/SOURCES/tar-1.15.1-vfatTruncate.patch
@@ -0,0 +1,31 @@
+diff --git a/src/system.c b/src/system.c
+index ba4ac2d..ea88cd6 100644
+--- a/src/system.c
++++ b/src/system.c
+@@ -231,8 +231,25 @@ sys_compare_links (struct stat *link_data, struct stat *stat_data)
+ int
+ sys_truncate (int fd)
+ {
++  struct stat st;
+   off_t pos = lseek (fd, (off_t) 0, SEEK_CUR);
+-  return pos < 0 ? -1 : ftruncate (fd, pos);
++
++  if ( pos < 0) 
++    return -1;
++
++  if ( ftruncate(fd, pos) && errno == EPERM ) {
++    /* wrapper around ftruncate:
++     * ftruncate may fail to grow the size of a file with some OS and filesystem
++     * combinations. Linux and vfat/fat is one example. If this is the case do
++     * a write to grow the file to the desired length.
++     */
++    if( (fstat( fd, &st ) == -1) || 
++        (st.st_size >= pos)  ||
++        (lseek( fd, pos - 1, SEEK_SET) == (off_t)-1) ||
++        (write( fd, "\0", 1) == -1) )
++	return -1;
++  }
++  return 0;
+ }
+ 
+ /* Return nonzero if NAME is the name of a regular file, or if the file
diff --git a/SOURCES/tar-1.17-wildcards.patch b/SOURCES/tar-1.17-wildcards.patch
new file mode 100644
index 0000000..62919d1
--- /dev/null
+++ b/SOURCES/tar-1.17-wildcards.patch
@@ -0,0 +1,92 @@
+diff --git a/doc/tar.texi b/doc/tar.texi
+index db8f986..d70d113 100644
+--- a/doc/tar.texi
++++ b/doc/tar.texi
+@@ -7597,7 +7597,7 @@ The following table summarizes pattern-matching default values:
+ 
+ @multitable @columnfractions .3 .7
+ @headitem Members @tab Default settings
+-@item Inclusion @tab @option{--no-wildcards --anchored --no-wildcards-match-slash}
++@item Inclusion @tab @option{--wildcards --anchored --wildcards-match-slash}
+ @item Exclusion @tab @option{--wildcards --no-anchored --wildcards-match-slash}
+ @end multitable
+ 
+@@ -12038,6 +12038,9 @@ version of this document is available at
+ @table @asis
+ @item Use of globbing patterns when listing and extracting.
+ 
++Note: Following is true for original unpatched GNU tar.
++For compatibility reasons, the old behavior was preserved.
++
+ Previous versions of GNU tar assumed shell-style globbing when
+ extracting from or listing an archive.  For example:
+ 
+diff --git a/src/names.c b/src/names.c
+index ba4d509..3911f8c 100644
+--- a/src/names.c
++++ b/src/names.c
+@@ -966,10 +966,7 @@ collect_and_sort_names (void)
+ 
+       if (name->found_count || name->directory)
+ 	continue;
+-      if (name->matching_flags & EXCLUDE_WILDCARDS)
+-	/* NOTE: EXCLUDE_ANCHORED is not relevant here */
+-	/* FIXME: just skip regexps for now */
+-	continue;
++
+       chdir_do (name->change_dir);
+ 
+       if (name->name[0] == 0)
+diff --git a/src/tar.c b/src/tar.c
+index 928cfdd..22d3db1 100644
+--- a/src/tar.c
++++ b/src/tar.c
+@@ -722,7 +722,7 @@ static struct argp_option options[] = {
+   {"no-ignore-case", NO_IGNORE_CASE_OPTION, 0, 0,
+    N_("case sensitive matching (default)"), GRID+1 },
+   {"wildcards", WILDCARDS_OPTION, 0, 0,
+-   N_("use wildcards (default for exclusion)"), GRID+1 },
++   N_("use wildcards (default)"), GRID+1 },
+   {"no-wildcards", NO_WILDCARDS_OPTION, 0, 0,
+    N_("verbatim string matching"), GRID+1 },
+   {"no-wildcards-match-slash", NO_WILDCARDS_MATCH_SLASH_OPTION, 0, 0,
+@@ -815,8 +815,7 @@ ARGMATCH_VERIFY (atime_preserve_args, atime_preserve_types);
+ /* Wildcard matching settings */
+ enum wildcards
+   {
+-    default_wildcards, /* For exclusion == enable_wildcards,
+-			  for inclusion == disable_wildcards */
++    default_wildcards, /* enable_wildcards */
+     disable_wildcards,
+     enable_wildcards
+   };
+@@ -847,7 +846,7 @@ struct tar_args        /* Variables used during option parsing */
+   | recursion_option)
+ 
+ #define MAKE_INCL_OPTIONS(args) \
+- ((((args)->wildcards == enable_wildcards) ? EXCLUDE_WILDCARDS : 0) \
++ ((((args)->wildcards != disable_wildcards) ? EXCLUDE_WILDCARDS : 0) \
+   | (args)->include_anchored \
+   | (args)->matching_flags \
+   | recursion_option)
+@@ -2347,7 +2346,7 @@ decode_options (int argc, char **argv)
+ 
+   /* Warn about implicit use of the wildcards in command line arguments.
+      See TODO */
+-  warn_regex_usage = args.wildcards == default_wildcards;
++  warn_regex_usage = 0; /* args.wildcards == default_wildcards; */
+ 
+   /* Derive option values and check option consistency.  */
+ 
+diff --git a/tests/exclude01.at b/tests/exclude01.at
+index 778a7fc..bd65ae0 100644
+--- a/tests/exclude01.at
++++ b/tests/exclude01.at
+@@ -59,6 +59,7 @@ testdir/dir2/file2
+ testdir/dir3/
+ NEXT
+ testdir/dir1/*
++testdir/dir1/file1
+ NEXT
+ testdir/dir1/*
+ NEXT
diff --git a/SOURCES/tar-1.22-atime-rofs.patch b/SOURCES/tar-1.22-atime-rofs.patch
new file mode 100644
index 0000000..c61cbc4
--- /dev/null
+++ b/SOURCES/tar-1.22-atime-rofs.patch
@@ -0,0 +1,14 @@
+diff --git a/src/create.c b/src/create.c
+index 43b5a4c..f98cbb5 100644
+--- a/src/create.c
++++ b/src/create.c
+@@ -1798,7 +1798,8 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
+ 	    }
+ 	  else if (atime_preserve_option == replace_atime_preserve
+ 		   && fd && (is_dir || original_size != 0)
+-		   && set_file_atime (fd, parentfd, name, st->atime) != 0)
++		   && set_file_atime (fd, parentfd, name, st->atime) != 0
++		   && errno != EROFS )
+ 	    utime_error (p);
+ 	}
+ 
diff --git a/SOURCES/tar-1.23-oldarchive.patch b/SOURCES/tar-1.23-oldarchive.patch
new file mode 100644
index 0000000..6163916
--- /dev/null
+++ b/SOURCES/tar-1.23-oldarchive.patch
@@ -0,0 +1,14 @@
+diff -urNp tar-1.23-orig/src/tar.c tar-1.23/src/tar.c
+--- tar-1.23-orig/src/tar.c	2010-06-01 13:55:03.792173060 +0200
++++ tar-1.23/src/tar.c	2010-06-01 14:01:40.494172986 +0200
+@@ -1911,6 +1911,10 @@ parse_opt (int key, char *arg, struct ar
+ 			  _("Invalid number")));
+ 	}
+       break;
++
++    case OLD_ARCHIVE_OPTION:
++      set_archive_format ("v7");
++      break;
+ 
+     case OVERWRITE_DIR_OPTION:
+       old_files_option = DEFAULT_OLD_FILES;
diff --git a/SOURCES/tar-1.26-add-skip-old-files-option.patch b/SOURCES/tar-1.26-add-skip-old-files-option.patch
new file mode 100644
index 0000000..00d632d
--- /dev/null
+++ b/SOURCES/tar-1.26-add-skip-old-files-option.patch
@@ -0,0 +1,370 @@
+diff --git a/doc/tar.texi b/doc/tar.texi
+index d70d113..a0e3d5f 100644
+--- a/doc/tar.texi
++++ b/doc/tar.texi
+@@ -1881,6 +1881,7 @@ The other operations of @command{tar} (@option{--list},
+ @option{--extract}, @option{--compare}, and @option{--update})
+ will act on the entire contents of the archive.
+ 
++@anchor{exit status}
+ @cindex exit status
+ @cindex return status
+ Besides successful exits, @GNUTAR{} may fail for
+@@ -2815,7 +2816,10 @@ when extracting files from an archive.
+ @item --keep-old-files
+ @itemx -k
+ 
+-Do not overwrite existing files when extracting files from an archive.
++Do not overwrite existing files when extracting files from an
++archive.  Return error if such files exist.  See also
++@ref{--skip-old-files}.
++
+ @xref{Keep Old Files}.
+ 
+ @opsummary{label}
+@@ -3268,6 +3272,20 @@ the archive creation operations it instructs @command{tar} to list the
+ member names stored in the archive, as opposed to the actual file
+ names.  @xref{listing member and file names}.
+ 
++@opsummary{skip-old-files}
++@item --skip-old-files
++
++Do not overwrite existing files when extracting files from an
++archive.  @xref{Keep Old Files}.
++
++This option differs from @option{--keep-old-files} in that it does not
++treat such files as an error, instead it just silently avoids
++overwriting them.
++
++The @option{--warning=existing-file} option can be used together with
++this option to produce warning messages about existing old files
++(@pxref{warnings}).
++
+ @opsummary{sparse}
+ @item --sparse
+ @itemx -S
+@@ -4443,11 +4461,11 @@ in the archive; the most recently archived members will be extracted
+ last.  Additionally, an extracted member will @emph{replace} a file of
+ the same name which existed in the directory already, and @command{tar}
+ will not prompt you about this@footnote{Unless you give it
+-@option{--keep-old-files} option, or the disk copy is newer than
+-the one in the archive and you invoke @command{tar} with
+-@option{--keep-newer-files} option.}.  Thus, only the most recently archived
+-member will end up being extracted, as it will replace the one
+-extracted before it, and so on.
++@option{--keep-old-files} (or @option{--skip-old-files}) option, or
++the disk copy is newer than the one in the archive and you invoke
++@command{tar} with @option{--keep-newer-files} option.}.  Thus, only
++the most recently archived member will end up being extracted, as it
++will replace the one extracted before it, and so on.
+ 
+ @cindex extracting @var{n}th copy of the file
+ @xopindex{occurrence, described}
+@@ -5123,10 +5141,25 @@ such a directory, use the @option{--no-overwrite-dir} option.
+ @cindex Overwriting old files, prevention
+ @xopindex{keep-old-files, introduced}
+ To be even more cautious and prevent existing files from being replaced, use
+-the @option{--keep-old-files} (@option{-k}) option.  It causes @command{tar} to refuse
+-to replace or update a file that already exists, i.e., a file with the
+-same name as an archive member prevents extraction of that archive
+-member.  Instead, it reports an error.
++the @option{--keep-old-files} (@option{-k}) option.  It causes
++@command{tar} to refuse to replace or update a file that already
++exists, i.e., a file with the same name as an archive member prevents
++extraction of that archive member.  Instead, it reports an error.  For
++example:
++
++@example
++$ @kbd{ls}
++blues
++$ @kbd{tar -x -k -f archive.tar}
++tar: blues: Cannot open: File exists
++tar: Exiting with failure status due to previous errors
++@end example
++
++@xopindex{skip-old-files, introduced}
++If you wish to preserve old files untouched, but don't want
++@command{tar} to treat them as errors, use the
++@option{--skip-old-files} option.  This option causes @command{tar} to
++silently skip extracting over existing files.
+ 
+ @xopindex{overwrite, introduced}
+ To be more aggressive about altering existing files, use the
+@@ -5192,16 +5225,24 @@ archive, but remove other files before extracting.
+ @node Keep Old Files
+ @unnumberedsubsubsec Keep Old Files
+ 
++@GNUTAR{} provides two options to control its actions in a situation
++when it is about to extract a file which already exists on disk.
++
+ @table @option
+ @opindex keep-old-files
+ @item --keep-old-files
+ @itemx -k
+-Do not replace existing files from archive.  The
+-@option{--keep-old-files} (@option{-k}) option prevents @command{tar}
+-from replacing existing files with files with the same name from the
+-archive. The @option{--keep-old-files} option is meaningless with
+-@option{--list} (@option{-t}).  Prevents @command{tar} from replacing
+-files in the file system during extraction.
++Do not replace existing files from archive.  When such a file is
++encountered, @command{tar} issues an error message.  Upon end of
++extraction, @command{tar} exits with code 2 (@pxref{exit status}).
++
++@item --skip-old-files
++Do not replace existing files from archive, but do not treat that
++as error.  Such files are silently skipped and do not affect
++@command{tar} exit status.
++
++Additional verbosity can be obtained using @option{--warning=existing-file}
++together with that option (@pxref{warnings}).
+ @end table
+ 
+ @node Keep Newer Files
+diff --git a/src/common.h b/src/common.h
+index 0b9bd7a..2409413 100644
+--- a/src/common.h
++++ b/src/common.h
+@@ -182,6 +182,7 @@ enum old_files
+   OVERWRITE_OLD_FILES,        /* --overwrite */
+   UNLINK_FIRST_OLD_FILES,     /* --unlink-first */
+   KEEP_OLD_FILES,             /* --keep-old-files */
++  SKIP_OLD_FILES,             /* --skip-old-files */
+   KEEP_NEWER_FILES	      /* --keep-newer-files */
+ };
+ GLOBAL enum old_files old_files_option;
+@@ -807,11 +808,12 @@ void checkpoint_run (bool do_write);
+ #define WARN_UNKNOWN_KEYWORD     0x00020000
+ #define WARN_XDEV                0x00040000
+ #define WARN_DECOMPRESS_PROGRAM  0x00080000
++#define WARN_EXISTING_FILE       0x00100000
+ 
+ /* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default
+    in verbose mode */
+ #define WARN_VERBOSE_WARNINGS    (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY|\
+-				  WARN_DECOMPRESS_PROGRAM)
++				  WARN_DECOMPRESS_PROGRAM|WARN_EXISTING_FILE)
+ #define WARN_ALL                 (~WARN_VERBOSE_WARNINGS)
+ 
+ void set_warning_option (const char *arg);
+diff --git a/src/extract.c b/src/extract.c
+index aaea56e..662ea0b 100644
+--- a/src/extract.c
++++ b/src/extract.c
+@@ -639,9 +639,14 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
+ 
+       switch (old_files_option)
+ 	{
+-	case KEEP_OLD_FILES:
++	case SKIP_OLD_FILES:
++	  WARNOPT (WARN_EXISTING_FILE,
++		   (0, 0, _("%s: skipping existing file"), file_name));
+ 	  return RECOVER_SKIP;
+ 
++	case KEEP_OLD_FILES:
++	  return RECOVER_NO;
++
+ 	case KEEP_NEWER_FILES:
+ 	  if (file_newer_p (file_name, stp, &current_stat_info))
+ 	    break;
+diff --git a/src/tar.c b/src/tar.c
+index 7b62996..7a673e0 100644
+--- a/src/tar.c
++++ b/src/tar.c
+@@ -328,6 +328,7 @@ enum
+   SHOW_DEFAULTS_OPTION,
+   SHOW_OMITTED_DIRS_OPTION,
+   SHOW_TRANSFORMED_NAMES_OPTION,
++  SKIP_OLD_FILES_OPTION,
+   SPARSE_VERSION_OPTION,
+   STRIP_COMPONENTS_OPTION,
+   SUFFIX_OPTION,
+@@ -452,7 +453,11 @@ static struct argp_option options[] = {
+   {"remove-files", REMOVE_FILES_OPTION, 0, 0,
+    N_("remove files after adding them to the archive"), GRID+1 },
+   {"keep-old-files", 'k', 0, 0,
+-   N_("don't replace existing files when extracting"), GRID+1 },
++   N_("don't replace existing files when extracting, "
++      "treat them as errors"), GRID+1 },
++  {"skip-old-files", SKIP_OLD_FILES_OPTION, 0, 0,
++   N_("don't replace existing files when extracting, silently skip over them"),
++   GRID+1 },
+   {"keep-newer-files", KEEP_NEWER_FILES_OPTION, 0, 0,
+    N_("don't replace existing files that are newer than their archive copies"), GRID+1 },
+   {"overwrite", OVERWRITE_OPTION, 0, 0,
+@@ -1618,6 +1623,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
+       sparse_option = true;
+       break;
+ 
++    case SKIP_OLD_FILES_OPTION:
++      old_files_option = SKIP_OLD_FILES;
++      break;
++
+     case SPARSE_VERSION_OPTION:
+       sparse_option = true;
+       {
+diff --git a/src/warning.c b/src/warning.c
+index 5d1bcab..ee9d684 100644
+--- a/src/warning.c
++++ b/src/warning.c
+@@ -42,6 +42,7 @@ static char const *const warning_args[] = {
+   "unknown-keyword",
+   "xdev",
+   "decompress-program",
++  "existing-file",
+   NULL
+ };
+ 
+@@ -66,7 +67,8 @@ static int warning_types[] = {
+   WARN_UNKNOWN_CAST,
+   WARN_UNKNOWN_KEYWORD,
+   WARN_XDEV,
+-  WARN_DECOMPRESS_PROGRAM
++  WARN_DECOMPRESS_PROGRAM,
++  WARN_EXISTING_FILE,
+ };
+ 
+ ARGMATCH_VERIFY (warning_args, warning_types);
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 119f1f3..3d78ea2 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -77,6 +77,8 @@ TESTSUITE_AT = \
+  extrac07.at\
+  extrac08.at\
+  extrac09.at\
++ extrac18.at\
++ extrac19.at\
+  extrac10.at\
+  extrac11.at\
+  extrac12.at\
+diff --git a/tests/extrac18.at b/tests/extrac18.at
+new file mode 100644
+index 0000000..8b42ef7
+--- /dev/null
++++ b/tests/extrac18.at
+@@ -0,0 +1,60 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2011 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, 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/>.
++
++# Description: Check the functionality of the --keep-old-files option.
++# It should report an error and cause tar to exit with status 2.
++#
++# There was a regression in versions 1.23 to 1.26 inclusive, where
++# this option silently skipped such files.
++# Reported by: Doug McLaren <dougmc@frenzied.us>,
++#              Gary Partis <gary@partis.co.uk>,
++#              Jim Meyering <jim@meyering.net>
++#              
++# References: <20111117045433.GA8245@algol.frenzied.us>,
++#             <4F3D824717847C4487F77228F83329A3514CBB@server.Partis.local>,
++#             <87wrar6zzz.fsf@rho.meyering.net>
++
++AT_SETUP([keep-old-files])
++AT_KEYWORDS([extract extrac18 old-files keep-old-files])
++
++AT_TAR_CHECK([
++mkdir dir
++cd dir
++echo 'Old file a' > a
++echo 'Old file b' > b
++
++tar cf ../archive .
++
++rm b
++echo 'File a' > a
++
++tar -x -k -f ../archive
++echo status=$?
++
++cat a
++],
++[0],
++[status=2
++File a
++],
++[tar: ./a: Cannot open: File exists
++tar: Exiting with failure status due to previous errors
++])
++
++AT_CLEANUP
++
+diff --git a/tests/extrac19.at b/tests/extrac19.at
+new file mode 100644
+index 0000000..43c4c50
+--- /dev/null
++++ b/tests/extrac19.at
+@@ -0,0 +1,44 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2011 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, 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/>.
++
++AT_SETUP([skip-old-files])
++AT_KEYWORDS([extract extrac19 old-files skip-old-files])
++
++AT_TAR_CHECK([
++mkdir dir
++cd dir
++echo 'Old file a' > a
++echo 'Old file b' > b
++
++tar cf ../archive .
++
++rm b
++echo 'File a' > a
++
++tar -x --skip-old-files -f ../archive
++echo status=$?
++
++cat a
++],
++[0],
++[status=0
++File a
++])
++
++AT_CLEANUP
++
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index d1dab36..e43653e 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -166,6 +166,9 @@ m4_include([extrac15.at])
+ m4_include([extrac16.at])
+ m4_include([extrac17.at])
+ 
++m4_include([extrac18.at])
++m4_include([extrac19.at])
++
+ m4_include([label01.at])
+ m4_include([label02.at])
+ m4_include([label03.at])
diff --git a/SOURCES/tar-1.26-allow-extract-single-volume.patch b/SOURCES/tar-1.26-allow-extract-single-volume.patch
new file mode 100644
index 0000000..6ec830d
--- /dev/null
+++ b/SOURCES/tar-1.26-allow-extract-single-volume.patch
@@ -0,0 +1,27 @@
+diff --git a/src/extract.c b/src/extract.c
+index 87b383a..340beea 100644
+--- a/src/extract.c
++++ b/src/extract.c
+@@ -1415,6 +1415,13 @@ extract_failure (char *file_name, int typeflag)
+   return 1;
+ }
+ 
++static int
++extract_skip (char *file_name, int typeflag)
++{
++  skip_member ();
++  return 0;
++}
++
+ typedef int (*tar_extractor_t) (char *file_name, int typeflag);
+ 
+ 
+@@ -1495,7 +1502,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
+       ERROR ((0, 0,
+ 	      _("%s: Cannot extract -- file is continued from another volume"),
+ 	      quotearg_colon (current_stat_info.file_name)));
+-      *fun = extract_failure;
++      *fun = extract_skip;
+       break;
+ 
+     case GNUTYPE_LONGNAME:
diff --git a/SOURCES/tar-1.26-default-acls.patch b/SOURCES/tar-1.26-default-acls.patch
new file mode 100644
index 0000000..12c805c
--- /dev/null
+++ b/SOURCES/tar-1.26-default-acls.patch
@@ -0,0 +1,267 @@
+From e3a7b9c8f26ca3b5a9aedd4c1d596a4a8504c812 Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Thu, 4 Jun 2015 09:30:38 +0200
+Subject: [PATCH] acls: don't mistakenly set default ACLs
+
+Upstream commits
+efbf4cce0b93e8c5a5fc93335b917bbeae2f67cb
+9df17e6005e7a333399e3dc21a7afec75565c767
+7fe7adcbb985e78aaf9f78051fa26167779be1f6
+---
+ configure.ac       |   2 +
+ src/xattrs.c       |  37 ++++++++++++---
+ tests/Makefile.am  |   1 +
+ tests/acls03.at    | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ tests/testsuite.at |   1 +
+ 5 files changed, 165 insertions(+), 7 deletions(-)
+ create mode 100644 tests/acls03.at
+
+diff --git a/configure.ac b/configure.ac
+index 9b3e0c8..7ccb579 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -85,6 +85,8 @@ if test "x$with_posix_acls" != "xno"; then
+   AC_SEARCH_LIBS([acl_set_fd],    [acl pacl],, [with_posix_acl=no])
+   AC_SEARCH_LIBS([acl_to_text],   [acl pacl],, [with_posix_acl=no])
+   AC_SEARCH_LIBS([acl_from_text], [acl pacl],, [with_posix_acl=no])
++  AC_SEARCH_LIBS([acl_delete_def_file], [acl pacl],, [with_posix_acl=no])
++  AC_SEARCH_LIBS([acl_free], [acl pacl],, [with_posix_acl=no])
+   if test "x$with_posix_acls" != xno; then
+     AC_DEFINE(HAVE_POSIX_ACLS,,[Define when we have working POSIX acls])
+   fi
+diff --git a/src/xattrs.c b/src/xattrs.c
+index bdf6ba0..5bd4b02 100644
+--- a/src/xattrs.c
++++ b/src/xattrs.c
+@@ -61,6 +61,7 @@ static struct
+ acl_t acl_get_file_at (int dirfd, const char *file, acl_type_t type);
+ int acl_set_file_at (int dirfd, const char *file, acl_type_t type, acl_t acl);
+ int file_has_acl_at (int dirfd, char const *, struct stat const *);
++int acl_delete_def_file_at (int, char const *);
+ 
+ /* acl_get_file_at */
+ #define AT_FUNC_NAME acl_get_file_at
+@@ -88,6 +89,17 @@ int file_has_acl_at (int dirfd, char const *, struct stat const *);
+ #undef AT_FUNC_POST_FILE_PARAM_DECLS
+ #undef AT_FUNC_POST_FILE_ARGS
+ 
++/* acl_delete_def_file_at */
++#define AT_FUNC_NAME acl_delete_def_file_at
++#define AT_FUNC_F1 acl_delete_def_file
++#define AT_FUNC_POST_FILE_PARAM_DECLS
++#define AT_FUNC_POST_FILE_ARGS
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
++
+ /* gnulib file_has_acl_at */
+ #define AT_FUNC_NAME file_has_acl_at
+ #define AT_FUNC_F1 file_has_acl
+@@ -187,7 +199,8 @@ fixup_extra_acl_fields (char *ptr)
+   return ptr;
+ }
+ 
+-/* "system.posix_acl_access" */
++/* Set the "system.posix_acl_access/system.posix_acl_default" extended
++   attribute.  Called only when acls_option > 0. */
+ static void
+ xattrs__acls_set (struct tar_stat_info const *st,
+                   char const *file_name, int type,
+@@ -199,15 +212,25 @@ xattrs__acls_set (struct tar_stat_info const *st,
+     {
+       /* assert (strlen (ptr) == len); */
+       ptr = fixup_extra_acl_fields (ptr);
+-
+       acl = acl_from_text (ptr);
+-      acls_option = 1;
+     }
+-  else if (acls_option > 0)
++  else if (def)
++    {
++      /* No "default" IEEE 1003.1e ACL set for directory.  At this moment,
++         FILE_NAME may already have inherited default acls from parent
++         directory;  clean them up. */
++      if (acl_delete_def_file_at (chdir_fd, file_name))
++        WARNOPT (WARN_XATTR_WRITE,
++                (0, errno,
++                 _("acl_delete_def_file_at: Cannot drop default POSIX ACLs "
++                   "for file '%s'"),
++                 file_name));
++      return;
++    }
++  else
++    /* There is nothing like "acl_delete_def_file" for non-default acls, we
++       need to re-set ACLs based on permission bits */
+     acl = perms2acl (st->stat.st_mode);
+-  else
+-    return;  /* don't call acl functions unless we first hit an ACL, or
+-		--acls was passed explicitly */
+ 
+   if (!acl)
+     {
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index b0da439..228e936 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -179,6 +179,7 @@ TESTSUITE_AT = \
+  xattr05.at\
+  acls01.at\
+  acls02.at\
++ acls03.at\
+  selnx01.at\
+  selacl01.at\
+  capabs_raw01.at
+diff --git a/tests/acls03.at b/tests/acls03.at
+new file mode 100644
+index 0000000..83c5bdc
+--- /dev/null
++++ b/tests/acls03.at
+@@ -0,0 +1,131 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright 2013, 2014 Free Software Foundation, Inc.
++
++# This file is part of GNU tar.
++
++# GNU tar 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.
++
++# GNU tar 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/>.
++#
++# Test description:
++#
++# Check the storing/restoring with/without default ACLs.  When --acls is passed,
++# restored directory tree should always match archive contents (even when the
++# archive does not contain any ACLs).
++#
++# References:
++# http://www.mail-archive.com/bug-tar@gnu.org/msg04355.html
++
++AT_SETUP([acls: default ACLs])
++AT_KEYWORDS([xattrs acls acls03])
++
++m4_define([ACL_LISTDIR], [
++    cd $1
++    $1="$(find d1 | sort | xargs -n 1 getfacl)"
++    cd ..
++])
++
++m4_define([ACL_ASSERT], [
++    echo "$$1" > $1.log
++    echo "$$2" > $2.log
++    if test ! "$$1" "$3" "$$2"; then
++        echo "bad '$1' against '$2' output"
++    fi
++])
++
++AT_TAR_CHECK([
++AT_XATTRS_UTILS_PREREQ
++AT_ACLS_PREREQ
++AT_SORT_PREREQ
++
++MYNAME=$( id -un )
++MYGROUP=$( id -gn )
++
++# Prepare directory structure with default ACLs
++mkdir -p pure/d1/d2
++genfile --file pure/d1/f2a
++genfile --file pure/d1/f2b
++genfile --file pure/d1/d2/f3a
++genfile --file pure/d1/d2/f3b
++setfacl    -m g:$MYGROUP:r-x pure/d1
++setfacl -d -m g:$MYGROUP:rwx pure/d1
++setfacl -d -m u:$MYNAME:rwx  pure/d1
++# "*a" files have "some" additional ACLs
++setfacl    -m u:$MYNAME:--- pure/d1/d2/f3a
++setfacl    -m u:$MYNAME:--- pure/d1/f2a
++
++# use default format (no acls stored)
++tar -cf noacl.tar -C pure d1
++
++# use posix format, acls stored
++tar --acls -cf acl.tar -C pure d1
++
++# Directory names are chosen based on "how the files were extracted from
++# archive".  Equivalent no* tags are used also:
++#   ^sacl_    — extracted archive has stored ACLs
++#   _def_     — target directory (-C) has default ACLs
++#   _optacl$  — extraction was done with --acls option
++
++mkdir sacl_def_optacl
++mkdir sacl_def_optnoacl
++mkdir sacl_nodef_optacl
++mkdir sacl_nodef_optnoacl
++mkdir nosacl_def_optacl
++mkdir nosacl_def_optnoacl
++mkdir nosacl_nodef_optacl
++mkdir nosacl_nodef_optnoacl
++
++setfacl -d -m u:$MYNAME:---  nosacl_def_optnoacl sacl_def_optnoacl sacl_def_optacl nosacl_def_optacl
++setfacl -d -m g:$MYGROUP:--- nosacl_def_optnoacl sacl_def_optnoacl sacl_def_optacl nosacl_def_optacl
++
++tar -xf acl.tar -C sacl_nodef_optnoacl
++tar --acls -xf acl.tar -C sacl_nodef_optacl
++tar -xf acl.tar -C sacl_def_optnoacl
++tar --acls -xf acl.tar -C sacl_def_optacl
++tar -xf noacl.tar -C nosacl_def_optnoacl
++# _NO_ ACLs in output
++tar -xf noacl.tar -C nosacl_nodef_optnoacl
++tar -xf noacl.tar -C nosacl_nodef_optacl
++tar -cf noacl_repackaged.tar -C nosacl_nodef_optnoacl d1
++# _NO_ ACLs in output (even when default ACLs exist)
++tar --acls -xf noacl_repackaged.tar -C nosacl_def_optacl
++
++ACL_LISTDIR(pure)
++
++ACL_LISTDIR(sacl_def_optacl)
++ACL_LISTDIR(sacl_def_optnoacl)
++ACL_LISTDIR(sacl_nodef_optacl)
++ACL_LISTDIR(sacl_nodef_optnoacl)
++ACL_LISTDIR(nosacl_def_optacl)
++ACL_LISTDIR(nosacl_def_optnoacl)
++ACL_LISTDIR(nosacl_nodef_optacl)
++ACL_LISTDIR(nosacl_nodef_optnoacl)
++
++ACL_ASSERT(pure, sacl_def_optacl, =)
++
++ACL_ASSERT(sacl_def_optacl,     sacl_nodef_optacl,      =)
++ACL_ASSERT(sacl_def_optnoacl,   nosacl_def_optnoacl,    =)
++ACL_ASSERT(sacl_nodef_optnoacl, nosacl_nodef_optnoacl,  =)
++ACL_ASSERT(nosacl_def_optacl,   nosacl_nodef_optacl,    =)
++ACL_ASSERT(nosacl_def_optacl,   nosacl_nodef_optnoacl,  =)
++
++ACL_ASSERT(sacl_def_optacl,     sacl_def_optnoacl,      !=)
++ACL_ASSERT(sacl_def_optacl,     nosacl_def_optnoacl,    !=)
++ACL_ASSERT(nosacl_def_optnoacl, nosacl_nodef_optnoacl,  !=)
++],
++[0],
++[],
++[])
++
++AT_CLEANUP
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index d5925b3..10cf26a 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -341,6 +341,7 @@ m4_include([xattr05.at])
+ 
+ m4_include([acls01.at])
+ m4_include([acls02.at])
++m4_include([acls03.at])
+ 
+ m4_include([selnx01.at])
+ m4_include([selacl01.at])
+-- 
+2.1.0
+
diff --git a/SOURCES/tar-1.26-directory_with_remove-files.patch b/SOURCES/tar-1.26-directory_with_remove-files.patch
new file mode 100644
index 0000000..c622792
--- /dev/null
+++ b/SOURCES/tar-1.26-directory_with_remove-files.patch
@@ -0,0 +1,3501 @@
+From 4bf4efe97d25784eb5e56c8ee337af3c7866ec34 Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Tue, 24 Sep 2013 14:01:13 +0300
+Subject: [PATCH 01/11] Fix normalize_filename.
+
+The function did not take into account eventual -C options, which
+in particular led to various problems when using -C and --remove-files
+together.
+
+* src/common.h (namebuf_add_dir,namebuf_finish)
+(tar_getcwd): New prototypes.
+* src/misc.c (namebuf_add_dir,namebuf_finish)
+(tar_getcwd): New functions.
+(normalize_filename): Use tar_getcwd.
+---
+ src/common.h |  4 ++++
+ src/misc.c   | 41 ++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 44 insertions(+), 1 deletion(-)
+
+diff --git a/src/common.h b/src/common.h
+index 16ba401..85a6977 100644
+--- a/src/common.h
++++ b/src/common.h
+@@ -603,6 +603,10 @@ typedef struct namebuf *namebuf_t;
+ namebuf_t namebuf_create (const char *dir);
+ void namebuf_free (namebuf_t buf);
+ char *namebuf_name (namebuf_t buf, const char *name);
++void namebuf_add_dir (namebuf_t buf, const char *name);
++char *namebuf_finish (namebuf_t buf);
++
++char *tar_getcwd (void);
+ 
+ void code_ns_fraction (int ns, char *p);
+ char const *code_timespec (struct timespec ts, char *sbuf);
+diff --git a/src/misc.c b/src/misc.c
+index b75f2ab..f45f79a 100644
+--- a/src/misc.c
++++ b/src/misc.c
+@@ -283,7 +283,7 @@ normalize_filename (const char *name)
+          getcwd is slow, it might fail, and it does not necessarily
+          return a canonical name even when it succeeds.  Perhaps we
+          can use dev+ino pairs instead of names?  */
+-      copy = xgetcwd ();
++      copy = tar_getcwd ();
+       if (copy)
+         {
+           size_t copylen = strlen (copy);
+@@ -777,6 +777,21 @@ chdir_do (int i)
+     }
+ }
+ 
++char *
++tar_getcwd (void)
++{
++  static char *cwd;
++  namebuf_t nbuf;
++  int i;
++
++  if (!cwd)
++    cwd = xgetcwd ();
++  nbuf = namebuf_create (cwd);
++  for (i = 1; i <= chdir_current; i++)
++    namebuf_add_dir (nbuf, wd[i].name);
++  return namebuf_finish (nbuf);
++}
++
+ void
+ close_diag (char const *name)
+ {
+@@ -945,3 +960,27 @@ namebuf_name (namebuf_t buf, const char *name)
+
+   return ret;
+ }
++
++void
++namebuf_add_dir (namebuf_t buf, const char *name)
++{
++  static char dirsep[] = { DIRECTORY_SEPARATOR, 0 };
++  if (!ISSLASH (buf->buffer[buf->dir_length - 1]))
++    {
++      namebuf_name (buf, dirsep);
++      buf->dir_length++;
++    }
++  namebuf_name (buf, name);
++  buf->dir_length += strlen (name);
++}
++
++char *
++namebuf_finish (namebuf_t buf)
++{
++  char *res = buf->buffer;
++
++  if (ISSLASH (buf->buffer[buf->dir_length - 1]))
++    buf->buffer[buf->dir_length] = 0;
++  free (buf);
++  return res;
++}
+-- 
+2.9.3
+
+
+From 272e1c879644b3684031acd62c9adb0adc5133b5 Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Wed, 25 Sep 2013 15:58:43 +0300
+Subject: [PATCH 02/11] Improve tar_getcwd
+
+* src/common.h (tar_getcwd): Return pointer is const.
+* src/misc.c (wd) <cwd>: New member.
+(chdir_arg): Initialize cwd.
+(tar_getcwd): Use cwd member to cache the result.  Take into
+account absolute pathnames,
+(normalize_filename): Don't free the value
+returned from tar_getcwd.
+* src/names.c (name_next_elt): Remove leftover call chdir().
+* tests/Makefile.am: Add new tests.
+* tests/testsuite.at: Likewise.
+
+* tests/incr08.at: New testcase.
+* tests/remfiles04.at: New testcase.
+* tests/remfiles05.at: New testcase.
+* tests/remfiles06.at: New testcase.
+* tests/remfiles07.at: New testcase.
+---
+ src/common.h        |  2 +-
+ src/misc.c          | 57 +++++++++++++++++++++++------------
+ src/names.c         |  3 +-
+ tests/Makefile.am   |  5 ++++
+ tests/incr08.at     | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ tests/remfiles04.at | 53 +++++++++++++++++++++++++++++++++
+ tests/remfiles05.at | 60 +++++++++++++++++++++++++++++++++++++
+ tests/remfiles06.at | 66 ++++++++++++++++++++++++++++++++++++++++
+ tests/remfiles07.at | 63 +++++++++++++++++++++++++++++++++++++++
+ tests/testsuite.at  |  5 ++++
+ 10 files changed, 378 insertions(+), 22 deletions(-)
+ create mode 100644 tests/incr08.at
+ create mode 100644 tests/remfiles04.at
+ create mode 100644 tests/remfiles05.at
+ create mode 100644 tests/remfiles06.at
+ create mode 100644 tests/remfiles07.at
+
+diff --git a/src/common.h b/src/common.h
+index 85a6977..99f8552 100644
+--- a/src/common.h
++++ b/src/common.h
+@@ -606,7 +606,7 @@ char *namebuf_name (namebuf_t buf, const char *name);
+ void namebuf_add_dir (namebuf_t buf, const char *name);
+ char *namebuf_finish (namebuf_t buf);
+ 
+-char *tar_getcwd (void);
++const char *tar_getcwd (void);
+ 
+ void code_ns_fraction (int ns, char *p);
+ char const *code_timespec (struct timespec ts, char *sbuf);
+diff --git a/src/misc.c b/src/misc.c
+index f45f79a..2fd5280 100644
+--- a/src/misc.c
++++ b/src/misc.c
+@@ -283,21 +283,20 @@ normalize_filename (const char *name)
+          getcwd is slow, it might fail, and it does not necessarily
+          return a canonical name even when it succeeds.  Perhaps we
+          can use dev+ino pairs instead of names?  */
+-      copy = tar_getcwd ();
+-      if (copy)
+-        {
+-          size_t copylen = strlen (copy);
+-          bool need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT
+-                                   && copylen == 2 && ISSLASH (copy[1]));
+-          copy = xrealloc (copy, copylen + need_separator + strlen (name) + 1);
+-          copy[copylen] = DIRECTORY_SEPARATOR;
+-          strcpy (copy + copylen + need_separator, name);
+-        }
+-      else
+-        WARN ((0, errno, _("Cannot get working directory")));
++      const char *cwd = tar_getcwd ();
++      size_t copylen;
++      bool need_separator;
++
++      copylen = strlen (cwd);
++      need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT
++			  && copylen == 2 && ISSLASH (cwd[1]));
++      copy = xmalloc (copylen + need_separator + strlen (name) + 1);
++      strcpy (copy, cwd);
++      copy[copylen] = DIRECTORY_SEPARATOR;
++      strcpy (copy + copylen + need_separator, name);
+     }
+ 
+-  if (! copy)
++  if (!copy)
+     copy = xstrdup (name);
+   normalize_filename_x (copy);
+   return copy;
+@@ -632,7 +631,8 @@ struct wd
+ {
+   /* The directory's name.  */
+   char const *name;
+-
++  /* Current working directory; initialized by tar_getcwd */
++  char *cwd;
+   /* If nonzero, the file descriptor of the directory, or AT_FDCWD if
+      the working directory.  If zero, the directory needs to be opened
+      to be used.  */
+@@ -687,6 +687,7 @@ chdir_arg (char const *dir)
+       if (! wd_count)
+ 	{
+ 	  wd[wd_count].name = ".";
++	  wd[wd_count].cwd = NULL;
+ 	  wd[wd_count].fd = AT_FDCWD;
+ 	  wd_count++;
+ 	}
+@@ -704,6 +705,7 @@ chdir_arg (char const *dir)
+     }
+ 
+   wd[wd_count].name = dir;
++  wd[wd_count].cwd = NULL;
+   wd[wd_count].fd = 0;
+   return wd_count++;
+ }
+@@ -777,7 +779,7 @@ chdir_do (int i)
+     }
+ }
+ 
+-char *
++const char *
+ tar_getcwd (void)
+ {
+   static char *cwd;
+@@ -786,10 +788,27 @@ tar_getcwd (void)
+ 
+   if (!cwd)
+     cwd = xgetcwd ();
+-  nbuf = namebuf_create (cwd);
+-  for (i = 1; i <= chdir_current; i++)
+-    namebuf_add_dir (nbuf, wd[i].name);
+-  return namebuf_finish (nbuf);
++  if (!wd)
++    return cwd;
++
++  if (0 == chdir_current || !wd[chdir_current].cwd)
++    {
++      if (IS_ABSOLUTE_FILE_NAME (wd[chdir_current].name))
++	return wd[chdir_current].name;
++
++      if (!wd[0].cwd)
++	wd[0].cwd = cwd;
++
++      for (i = chdir_current - 1; i > 0; i--)
++	if (wd[i].cwd)
++	  break;
++ 
++      nbuf = namebuf_create (wd[i].cwd);
++      for (i++; i <= chdir_current; i++)
++	namebuf_add_dir (nbuf, wd[i].name);
++      wd[chdir_current].cwd = namebuf_finish (nbuf);
++    }
++  return wd[chdir_current].cwd;
+ }
+ 
+ void
+diff --git a/src/names.c b/src/names.c
+index 3911f8c..8c3052f 100644
+--- a/src/names.c
++++ b/src/names.c
+@@ -351,8 +351,7 @@ name_next_elt (int change_dirs)
+ 
+       if (change_dirs && ep->type == NELT_CHDIR)
+ 	{
+-	  if (chdir (name_buffer) < 0)
+-	    chdir_fatal (name_buffer);
++	  chdir_do (chdir_arg (xstrdup (ep->v.name)));
+ 	}
+       else
+ 	{
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 228e936..1d10360 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -99,6 +99,7 @@ TESTSUITE_AT = \
+  incr05.at\
+  incr06.at\
+  incr07.at\
++ incr08.at\
+  indexfile.at\
+  ignfail.at\
+  label01.at\
+@@ -139,6 +140,10 @@ TESTSUITE_AT = \
+  remfiles01.at\
+  remfiles02.at\
+  remfiles03.at\
++ remfiles04.at\
++ remfiles05.at\
++ remfiles06.at\
++ remfiles07.at\
+  same-order01.at\
+  same-order02.at\
+  shortfile.at\
+diff --git a/tests/incr08.at b/tests/incr08.at
+new file mode 100644
+index 0000000..5210d28
+--- /dev/null
++++ b/tests/incr08.at
+@@ -0,0 +1,86 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: In tar 1.26 listed-incremental with -C and absolute path
++# would malfunction under certain conditions due to buggy filename
++# normalization.
++#
++# The value returned by normalize_filename() is used to populate the "caname"
++# field in both the "directory" structure in incremen.c and the "name"
++# structure in names.c, and in both cases that field is then used in the
++# "hash" and "compare" functions for the related hash tables.  Thus, the
++# fact that the returned value doesn't reflect the operation of previous
++# "-C" options means that it's possible for two different directories to
++# be given the same "caname" value in the hashed structure and thus end up
++# being confused with each other.
++#
++# The bug is triggered when dumping both relative paths after -C and
++# absolute paths that match the process' current working directory.
++#
++# Reported by: Nathan Stratton Treadway <nathanst@ontko.com>
++# References: <20130922192135.GJ32256@shire.ontko.com>,
++#             http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00034.html
++
++AT_SETUP([filename normalization])
++AT_KEYWORDS([incremental create incr08])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir tartest
++cd tartest
++mkdir foo
++mkdir foo/subdir
++mkdir foo/subdir/dir1
++mkdir subdir
++mkdir subdir/dir2
++decho A
++find|sort
++
++decho B
++DIR=`pwd`
++tar -cvf ../foo.tar --listed-incremental=../foo.snar -C foo . $DIR 2>../err |\
++  sed "s|$DIR|ABSPATH|"
++sed "s|$DIR|ABSPATH|" ../err >&2
++],
++[0],
++[A
++.
++./foo
++./foo/subdir
++./foo/subdir/dir1
++./subdir
++./subdir/dir2
++B
++./
++./subdir/
++./subdir/dir1/
++ABSPATH/
++ABSPATH/subdir/
++ABSPATH/subdir/dir2/
++],
++[A
++B
++tar: .: Directory is new
++tar: ./subdir: Directory is new
++tar: ./subdir/dir1: Directory is new
++tar: ABSPATH: Directory is new
++tar: ABSPATH/subdir: Directory is new
++tar: ABSPATH/subdir/dir2: Directory is new
++tar: Removing leading `/' from member names
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles04.at b/tests/remfiles04.at
+new file mode 100644
+index 0000000..04df45b
+--- /dev/null
++++ b/tests/remfiles04.at
+@@ -0,0 +1,53 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: Tar 1.26 would remove wrong files when called with
++# --remove-files and -C
++# Reported by: Jörgen Strand <Jorgen.Strand@sonymobile.com>
++# References: <9FC79E5CB90CEC47B9647DCAB7BD327A01AD83B452EE@seldmbx02.corpusers.net>
++#             http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00024.html
++
++AT_SETUP([remove-files with -C])
++AT_KEYWORDS([create remove-files remfiles04])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++echo bar > bar
++echo foobar > foo/bar
++tar -cf foo.tar --remove-files -C foo bar
++echo A
++find . | sort
++echo foobar > foo/bar
++tar -rf foo.tar --remove-files -C foo bar
++echo B
++find . | sort
++],
++[0],
++[A
++.
++./bar
++./foo
++./foo.tar
++B
++.
++./bar
++./foo
++./foo.tar
++],[],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles05.at b/tests/remfiles05.at
+new file mode 100644
+index 0000000..04425a7
+--- /dev/null
++++ b/tests/remfiles05.at
+@@ -0,0 +1,60 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: Tar 1.26 would remove wrong files when invoked with
++# --listed-incremental and -C
++# Reported by: Nathan Stratton Treadway <nathanst@ontko.com>
++# References: <20130921171234.GG32256@shire.ontko.com>,
++#             http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00028.html
++
++AT_SETUP([incremental and -C])
++AT_KEYWORDS([incremental create remove-files remfiles05])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++echo bar > bar
++echo foo/bar > foo/bar
++decho A
++find . | sort
++
++decho B
++tar -cvf foo.tar --listed-incremental=foo.snar --remove-files -C foo bar
++decho C
++find . | sort
++],
++[0],
++[A
++.
++./bar
++./foo
++./foo/bar
++B
++bar
++C
++.
++./bar
++./foo
++./foo.snar
++./foo.tar
++],
++[A
++B
++C
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles06.at b/tests/remfiles06.at
+new file mode 100644
+index 0000000..75ddcfa
+--- /dev/null
++++ b/tests/remfiles06.at
+@@ -0,0 +1,66 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: There was a leftover call to chdir in name_next_elt() in
++# tar 1.26.  After commit e3d28d84 this call would confuse the tar_getcwd
++# function.
++# Reported by: Nathan Stratton Treadway <nathanst@ontko.com>
++# References: <20130924145657.GM32256@shire.ontko.com>,
++#             http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00045.html
++
++AT_SETUP([incremental with two -C])
++AT_KEYWORDS([incremental create remove-files remfiles06])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir tartest
++cd tartest
++mkdir foo
++echo foo/file > foo/file
++mkdir bar
++echo bar/file > bar/file
++decho A
++find|sort
++
++decho B
++tar -cvf ../foo.tar --remove-files -C foo file -C ../bar file
++
++decho C
++find|sort
++],
++[0],
++[A
++.
++./bar
++./bar/file
++./foo
++./foo/file
++B
++file
++file
++C
++.
++./bar
++./foo
++],
++[A
++B
++C
++],[],[],[gnu])
++
++AT_CLEANUP
++
+diff --git a/tests/remfiles07.at b/tests/remfiles07.at
+new file mode 100644
+index 0000000..84ab625
+--- /dev/null
++++ b/tests/remfiles07.at
+@@ -0,0 +1,63 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: See remfiles06.at
++# Reported by: Nathan Stratton Treadway <nathanst@ontko.com>
++# References: <20130924185129.GO32256@shire.ontko.com>
++
++AT_SETUP([incremental with -C to absolute path])
++AT_KEYWORDS([incremental create remove-files remfiles07])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir tartest
++cd tartest
++mkdir foo
++echo foo/file > foo/file
++mkdir bar
++echo bar/file > bar/file
++decho A
++find|sort
++
++DIR=`pwd`
++decho B
++tar -cvf ../foo.tar --remove-files -C foo file -C $DIR/bar file
++
++decho C
++find|sort
++],
++[0],
++[A
++.
++./bar
++./bar/file
++./foo
++./foo/file
++B
++file
++file
++C
++.
++./bar
++./foo
++],
++[A
++B
++C
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index 10cf26a..5c805e7 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -260,6 +260,7 @@ m4_include([incr03.at])
+ m4_include([incr05.at])
+ m4_include([incr06.at])
+ m4_include([incr07.at])
++m4_include([incr08.at])
+ 
+ m4_include([filerem01.at])
+ m4_include([filerem02.at])
+@@ -330,6 +331,10 @@ m4_include([grow.at])
+ m4_include([remfiles01.at])
+ m4_include([remfiles02.at])
+ m4_include([remfiles03.at])
++m4_include([remfiles04.at])
++m4_include([remfiles05.at])
++m4_include([remfiles06.at])
++m4_include([remfiles07.at])
+ 
+ m4_include([sigpipe.at])
+ 
+-- 
+2.9.3
+
+
+From 0c5f95ca80d507a00825c8e3fd05ed5ad993ce17 Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Thu, 26 Sep 2013 15:41:47 +0300
+Subject: [PATCH 03/11] Use relative addressing in deferred unlinks.
+
+* src/common.h (tar_dirname): New function.
+* src/misc.c (normalize_filename_x): Make extern.
+(tar_dirname): New function.
+(tar_getcwd): Take into account absoulte pathnames.
+* src/unlink.c (deferred_unlink) <dir_idx>: New member; keeps the
+value of chdir_current at the moment of structure allocation.
+(flush_deferred_unlinks): Use chdir_do and relative addressing.
+(queue_deferred_unlink): Initialize dir_idx.
+* tests/Makefile.am: Add new tests.
+* tests/testsuite.at: Add new tests.
+* tests/remfiles06.at: Fix description.
+* tests/remfiles07.at: Fix description.
+* tests/remfiles08.at: New test case.
+---
+ src/common.h        |  2 ++
+ src/misc.c          | 28 +++++++++++++++++++---------
+ src/unlink.c        | 27 +++++++++++++++++++++++----
+ tests/Makefile.am   |  1 +
+ tests/remfiles06.at |  4 ++--
+ tests/remfiles07.at |  4 ++--
+ tests/remfiles08.at | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
+ tests/testsuite.at  |  1 +
+ 8 files changed, 98 insertions(+), 17 deletions(-)
+ create mode 100644 tests/remfiles08.at
+
+diff --git a/src/common.h b/src/common.h
+index 99f8552..7d64227 100644
+--- a/src/common.h
++++ b/src/common.h
+@@ -596,6 +596,7 @@ void assign_string (char **dest, const char *src);
+ int unquote_string (char *str);
+ char *zap_slashes (char *name);
+ char *normalize_filename (const char *name);
++void normalize_filename_x (char *name);
+ void replace_prefix (char **pname, const char *samp, size_t slen,
+ 		     const char *repl, size_t rlen);
+ char *tar_savedir (const char *name, int must_exist);
+@@ -607,6 +608,7 @@ void namebuf_add_dir (namebuf_t buf, const char *name);
+ char *namebuf_finish (namebuf_t buf);
+ 
+ const char *tar_getcwd (void);
++const char *tar_dirname (void);
+ 
+ void code_ns_fraction (int ns, char *p);
+ char const *code_timespec (struct timespec ts, char *sbuf);
+diff --git a/src/misc.c b/src/misc.c
+index 2fd5280..c7d51b2 100644
+--- a/src/misc.c
++++ b/src/misc.c
+@@ -229,11 +229,12 @@ zap_slashes (char *name)
+ }
+ 
+ /* Normalize FILE_NAME by removing redundant slashes and "."
+-   components, including redundant trailing slashes.  Leave ".."
+-   alone, as it may be significant in the presence of symlinks and on
+-   platforms where "/.." != "/".  Destructive version: modifies its
+-   argument. */
+-static void
++   components, including redundant trailing slashes.
++   Leave ".." alone, as it may be significant in the presence
++   of symlinks and on platforms where "/.." != "/".
++
++   Destructive version: modifies its argument. */
++void
+ normalize_filename_x (char *file_name)
+ {
+   char *name = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
+@@ -267,8 +268,9 @@ normalize_filename_x (char *file_name)
+ }
+ 
+ /* Normalize NAME by removing redundant slashes and "." components,
+-   including redundant trailing slashes.  Return a normalized
+-   newly-allocated copy.  */
++   including redundant trailing slashes.
++
++   Return a normalized newly-allocated copy.  */
+ 
+ char *
+ normalize_filename (const char *name)
+@@ -780,6 +782,12 @@ chdir_do (int i)
+ }
+ 
+ const char *
++tar_dirname (void)
++{
++  return wd[chdir_current].name;
++}
++
++const char *
+ tar_getcwd (void)
+ {
+   static char *cwd;
+@@ -794,8 +802,10 @@ tar_getcwd (void)
+   if (0 == chdir_current || !wd[chdir_current].cwd)
+     {
+       if (IS_ABSOLUTE_FILE_NAME (wd[chdir_current].name))
+-	return wd[chdir_current].name;
+-
++	{
++	  wd[chdir_current].cwd = xstrdup (wd[chdir_current].name);
++	  return wd[chdir_current].cwd;
++	}
+       if (!wd[0].cwd)
+ 	wd[0].cwd = cwd;
+ 
+diff --git a/src/unlink.c b/src/unlink.c
+index b281636..10e0b41 100644
+--- a/src/unlink.c
++++ b/src/unlink.c
+@@ -22,7 +22,9 @@
+ struct deferred_unlink
+   {
+     struct deferred_unlink *next;   /* Next unlink in the queue */
+-    char *file_name;                /* Absolute name of the file to unlink */
++    int dir_idx;                    /* Directory index in wd */
++    char *file_name;                /* Name of the file to unlink, relative
++				       to dir_idx */
+     bool is_dir;                    /* True if file_name is a directory */
+     off_t records_written;          /* Number of records written when this
+ 				       entry got added to the queue */
+@@ -68,16 +70,30 @@ static void
+ flush_deferred_unlinks (bool force)
+ {
+   struct deferred_unlink *p, *prev = NULL;
++  int saved_chdir = chdir_current;
+ 
+   for (p = dunlink_head; p; )
+     {
+       struct deferred_unlink *next = p->next;
++
+       if (force
+ 	  || records_written > p->records_written + deferred_unlink_delay)
+ 	{
++          chdir_do (p->dir_idx);
+ 	  if (p->is_dir)
+ 	    {
+-	      if (unlinkat (chdir_fd, p->file_name, AT_REMOVEDIR) != 0)
++	      const char *fname;
++
++	      if (p->file_name[0] == 0 ||
++		  strcmp (p->file_name, ".") == 0)
++		{
++		  fname = tar_dirname ();
++		  chdir_do (p->dir_idx - 1);
++		}
++	      else
++		fname = p->file_name;
++
++	      if (unlinkat (chdir_fd, fname, AT_REMOVEDIR) != 0)
+ 		{
+ 		  switch (errno)
+ 		    {
+@@ -95,7 +111,7 @@ flush_deferred_unlinks (bool force)
+ 			}
+ 		      /* fall through */
+ 		    default:
+-		      rmdir_error (p->file_name);
++		      rmdir_error (fname);
+ 		    }
+ 		}
+ 	    }
+@@ -120,6 +136,7 @@ flush_deferred_unlinks (bool force)
+     }
+   if (!dunlink_head)
+     dunlink_tail = NULL;
++  chdir_do (saved_chdir);
+ }
+ 
+ void
+@@ -145,7 +162,9 @@ queue_deferred_unlink (const char *name, bool is_dir)
+ 
+   p = dunlink_alloc ();
+   p->next = NULL;
+-  p->file_name = normalize_filename (name);
++  p->dir_idx = chdir_current;
++  p->file_name = xstrdup (name);
++  normalize_filename_x (p->file_name);
+   p->is_dir = is_dir;
+   p->records_written = records_written;
+ 
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 1d10360..29ebab1 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -144,6 +144,7 @@ TESTSUITE_AT = \
+  remfiles05.at\
+  remfiles06.at\
+  remfiles07.at\
++ remfiles08.at\
+  same-order01.at\
+  same-order02.at\
+  shortfile.at\
+diff --git a/tests/remfiles06.at b/tests/remfiles06.at
+index 75ddcfa..c2d9876 100644
+--- a/tests/remfiles06.at
++++ b/tests/remfiles06.at
+@@ -22,8 +22,8 @@
+ # References: <20130924145657.GM32256@shire.ontko.com>,
+ #             http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00045.html
+ 
+-AT_SETUP([incremental with two -C])
+-AT_KEYWORDS([incremental create remove-files remfiles06])
++AT_SETUP([remove with two -C])
++AT_KEYWORDS([remove-files remfiles06])
+ 
+ AT_TAR_CHECK([
+ AT_SORT_PREREQ
+diff --git a/tests/remfiles07.at b/tests/remfiles07.at
+index 84ab625..742e0a1 100644
+--- a/tests/remfiles07.at
++++ b/tests/remfiles07.at
+@@ -19,8 +19,8 @@
+ # Reported by: Nathan Stratton Treadway <nathanst@ontko.com>
+ # References: <20130924185129.GO32256@shire.ontko.com>
+ 
+-AT_SETUP([incremental with -C to absolute path])
+-AT_KEYWORDS([incremental create remove-files remfiles07])
++AT_SETUP([remove with -C to absolute path])
++AT_KEYWORDS([create remove-files remfiles07])
+ 
+ AT_TAR_CHECK([
+ AT_SORT_PREREQ
+diff --git a/tests/remfiles08.at b/tests/remfiles08.at
+new file mode 100644
+index 0000000..54f5de1
+--- /dev/null
++++ b/tests/remfiles08.at
+@@ -0,0 +1,48 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: See remfiles06.at
++# Reported by: Nathan Stratton Treadway <nathanst@ontko.com>
++# References: <20130926050634.GW32256@shire.ontko.com>
++
++AT_SETUP([remove with -C to absolute and relative paths])
++AT_KEYWORDS([incremental create remove-files remfiles08])
++
++AT_TAR_CHECK([
++mkdir foo
++mkdir bar
++echo foo/foo_file > foo/foo_file
++echo bar/bar_file > bar/bar_file
++decho A
++tar -cvf foo.tar --remove-files -C `pwd`/foo . -C ../bar .
++decho B
++],
++[0],
++[A
++./
++./foo_file
++./
++./bar_file
++B
++.
++./foo.tar
++],
++[A
++B
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index 5c805e7..d468dcf 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -335,6 +335,7 @@ m4_include([remfiles04.at])
+ m4_include([remfiles05.at])
+ m4_include([remfiles06.at])
+ m4_include([remfiles07.at])
++m4_include([remfiles08.at])
+ 
+ m4_include([sigpipe.at])
+ 
+-- 
+2.9.3
+
+
+From 195c6f2b71f49ecc374ae01e20d7287f24501178 Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Fri, 27 Sep 2013 00:59:18 +0300
+Subject: [PATCH 04/11] Bugfix
+
+* tests/remfiles08.at: Restore missing find
+---
+ tests/remfiles08.at | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tests/remfiles08.at b/tests/remfiles08.at
+index 54f5de1..0649e85 100644
+--- a/tests/remfiles08.at
++++ b/tests/remfiles08.at
+@@ -30,6 +30,7 @@ echo bar/bar_file > bar/bar_file
+ decho A
+ tar -cvf foo.tar --remove-files -C `pwd`/foo . -C ../bar .
+ decho B
++find
+ ],
+ [0],
+ [A
+-- 
+2.9.3
+
+
+From 2cce74ec554ec7fca4c3b1d2963beb6a729881fe Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Tue, 1 Oct 2013 21:48:30 +0300
+Subject: [PATCH 05/11] Revamp tar_getcwd/normalize_filename stuff.
+
+The changes are based on the discussion with Nathan.
+
+* src/common.h (normalize_filename): Take two arguments. All
+callers updated.
+(tar_getcwd): Replaced with ..
+(tar_getcdpath): New proto.
+* src/misc.c (normalize_filename): Take two arguments.
+(chdir_arg): Populate cwd along with creating the
+structure.
+(tar_getcwd): Removed.
+(tar_getcdpath): New function.
+
+* tests/incr09.at: New test case.
+* tests/Makefile.am: Add new tests.
+* tests/testsuite.at: Likewise.
+---
+ src/common.h       |  4 ++--
+ src/incremen.c     |  4 ++--
+ src/misc.c         | 48 ++++++++++++++++----------------------------
+ src/names.c        |  6 ++----
+ tests/Makefile.am  |  1 +
+ tests/incr09.at    | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ tests/testsuite.at |  1 +
+ 7 files changed, 84 insertions(+), 39 deletions(-)
+ create mode 100644 tests/incr09.at
+
+diff --git a/src/common.h b/src/common.h
+index 7d64227..16b501b 100644
+--- a/src/common.h
++++ b/src/common.h
+@@ -595,7 +595,7 @@ void skip_member (void);
+ void assign_string (char **dest, const char *src);
+ int unquote_string (char *str);
+ char *zap_slashes (char *name);
+-char *normalize_filename (const char *name);
++char *normalize_filename (int cdidx, const char *name);
+ void normalize_filename_x (char *name);
+ void replace_prefix (char **pname, const char *samp, size_t slen,
+ 		     const char *repl, size_t rlen);
+@@ -607,7 +607,7 @@ char *namebuf_name (namebuf_t buf, const char *name);
+ void namebuf_add_dir (namebuf_t buf, const char *name);
+ char *namebuf_finish (namebuf_t buf);
+ 
+-const char *tar_getcwd (void);
++const char *tar_getcdpath (int);
+ const char *tar_dirname (void);
+ 
+ void code_ns_fraction (int ns, char *p);
+diff --git a/src/incremen.c b/src/incremen.c
+index b2ab5bf..cb12bbc 100644
+--- a/src/incremen.c
++++ b/src/incremen.c
+@@ -279,7 +279,7 @@ free_directory (struct directory *dir)
+ static struct directory *
+ attach_directory (const char *name)
+ {
+-  char *cname = normalize_filename (name);
++  char *cname = normalize_filename (chdir_current, name);
+   struct directory *dir = make_directory (name, cname);
+   if (dirtail)
+     dirtail->next = dir;
+@@ -350,7 +350,7 @@ find_directory (const char *name)
+     return 0;
+   else
+     {
+-      char *caname = normalize_filename (name);
++      char *caname = normalize_filename (chdir_current, name);
+       struct directory *dir = make_directory (name, caname);
+       struct directory *ret = hash_lookup (directory_table, dir);
+       free_directory (dir);
+diff --git a/src/misc.c b/src/misc.c
+index c7d51b2..280f85c 100644
+--- a/src/misc.c
++++ b/src/misc.c
+@@ -273,7 +273,7 @@ normalize_filename_x (char *file_name)
+    Return a normalized newly-allocated copy.  */
+ 
+ char *
+-normalize_filename (const char *name)
++normalize_filename (int cdidx, const char *name)
+ {
+   char *copy = NULL;
+ 
+@@ -285,7 +285,7 @@ normalize_filename (const char *name)
+          getcwd is slow, it might fail, and it does not necessarily
+          return a canonical name even when it succeeds.  Perhaps we
+          can use dev+ino pairs instead of names?  */
+-      const char *cwd = tar_getcwd ();
++      const char *cwd = tar_getcdpath (cdidx);
+       size_t copylen;
+       bool need_separator;
+ 
+@@ -689,7 +689,7 @@ chdir_arg (char const *dir)
+       if (! wd_count)
+ 	{
+ 	  wd[wd_count].name = ".";
+-	  wd[wd_count].cwd = NULL;
++	  wd[wd_count].cwd = xgetcwd ();
+ 	  wd[wd_count].fd = AT_FDCWD;
+ 	  wd_count++;
+ 	}
+@@ -707,7 +707,14 @@ chdir_arg (char const *dir)
+     }
+ 
+   wd[wd_count].name = dir;
+-  wd[wd_count].cwd = NULL;
++  if (IS_ABSOLUTE_FILE_NAME (wd[wd_count].name))
++    wd[wd_count].cwd = xstrdup (wd[wd_count].name);
++  else
++    {
++      namebuf_t nbuf = namebuf_create (wd[wd_count - 1].cwd);
++      namebuf_add_dir (nbuf, wd[wd_count].name);
++      wd[wd_count].cwd = namebuf_finish (nbuf);
++    }
+   wd[wd_count].fd = 0;
+   return wd_count++;
+ }
+@@ -788,37 +795,16 @@ tar_dirname (void)
+ }
+ 
+ const char *
+-tar_getcwd (void)
++tar_getcdpath (int idx)
+ {
+-  static char *cwd;
+-  namebuf_t nbuf;
+-  int i;
+-
+-  if (!cwd)
+-    cwd = xgetcwd ();
+   if (!wd)
+-    return cwd;
+-
+-  if (0 == chdir_current || !wd[chdir_current].cwd)
+     {
+-      if (IS_ABSOLUTE_FILE_NAME (wd[chdir_current].name))
+-	{
+-	  wd[chdir_current].cwd = xstrdup (wd[chdir_current].name);
+-	  return wd[chdir_current].cwd;
+-	}
+-      if (!wd[0].cwd)
+-	wd[0].cwd = cwd;
+-
+-      for (i = chdir_current - 1; i > 0; i--)
+-	if (wd[i].cwd)
+-	  break;
+- 
+-      nbuf = namebuf_create (wd[i].cwd);
+-      for (i++; i <= chdir_current; i++)
+-	namebuf_add_dir (nbuf, wd[i].name);
+-      wd[chdir_current].cwd = namebuf_finish (nbuf);
++      static char *cwd;
++      if (!cwd)
++	cwd = xgetcwd ();
++      return cwd;
+     }
+-  return wd[chdir_current].cwd;
++  return wd[idx].cwd;
+ }
+ 
+ void
+diff --git a/src/names.c b/src/names.c
+index 8c3052f..125f0b5 100644
+--- a/src/names.c
++++ b/src/names.c
+@@ -1004,13 +1004,11 @@ collect_and_sort_names (void)
+   namelist = merge_sort (namelist, num_names, compare_names);
+ 
+   num_names = 0;
+-  nametab = hash_initialize (0, 0,
+-			     name_hash,
+-			     name_compare, NULL);
++  nametab = hash_initialize (0, 0, name_hash, name_compare, NULL);
+   for (name = namelist; name; name = next_name)
+     {
+       next_name = name->next;
+-      name->caname = normalize_filename (name->name);
++      name->caname = normalize_filename (name->change_dir, name->name);
+       if (prev_name)
+ 	{
+ 	  struct name *p = hash_lookup (nametab, name);
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 29ebab1..b05a151 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -99,6 +99,7 @@ TESTSUITE_AT = \
+  incr06.at\
+  incr07.at\
+  incr08.at\
++ incr09.at\
+  indexfile.at\
+  ignfail.at\
+  label01.at\
+diff --git a/tests/incr09.at b/tests/incr09.at
+new file mode 100644
+index 0000000..b6130a6
+--- /dev/null
++++ b/tests/incr09.at
+@@ -0,0 +1,59 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++AT_SETUP([incremental with alternating -C])
++AT_KEYWORDS([incremental create incr09])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo bar middle
++echo foo/foo_file > foo/foo_file
++echo bar/bar_file > bar/bar_file
++echo middle/file > middle/middle_file
++decho A
++tar -cvf foo.tar --incremental -C foo . -C `pwd` middle  -C bar .
++
++rm foo.tar
++>toplevel_file
++decho B
++tar -cvf foo.tar --incremental -C foo . -C `pwd` toplevel_file  -C bar .
++],
++[0],
++[A
++./
++./
++middle/
++./bar_file
++./foo_file
++middle/middle_file
++B
++./
++./
++toplevel_file
++./bar_file
++./foo_file
++],
++[A
++tar: .: Directory is new
++tar: middle: Directory is new
++tar: .: Directory is new
++B
++tar: .: Directory is new
++tar: .: Directory is new
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index d468dcf..a9f2ab6 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -260,6 +260,7 @@ m4_include([incr04.at])
+ m4_include([incr06.at])
+ m4_include([incr07.at])
+ m4_include([incr08.at])
++m4_include([incr09.at])
+ 
+ m4_include([filerem01.at])
+ m4_include([filerem02.at])
+-- 
+2.9.3
+
+
+From 779b02280a9561029d0e459275af3b3a59e521c3 Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Thu, 3 Oct 2013 22:41:04 +0300
+Subject: [PATCH 06/11] Tiny changes.
+
+* src/misc.c: Fix comments, rename wd.cwd to wd.abspath (Nathan Stratton
+Treadway);
+* src/tar.c (options): Reword description of the --starting-file and
+--preserve-order options.
+(decode_options): Both --starting-file and --preserve-order have meaning
+only when used together with an archive reading command. (Pavel Raiskup).
+---
+ src/misc.c | 44 +++++++++++++++++++++++++++++---------------
+ src/tar.c  |  5 +++--
+ 2 files changed, 32 insertions(+), 17 deletions(-)
+
+diff --git a/src/misc.c b/src/misc.c
+index 280f85c..201ed16 100644
+--- a/src/misc.c
++++ b/src/misc.c
+@@ -279,21 +279,23 @@ normalize_filename (int cdidx, const char *name)
+ 
+   if (IS_RELATIVE_FILE_NAME (name))
+     {
+-      /* Set COPY to the absolute file name if possible.
++      /* Set COPY to the absolute path for this name.
+ 
+          FIXME: There should be no need to get the absolute file name.
+-         getcwd is slow, it might fail, and it does not necessarily
+-         return a canonical name even when it succeeds.  Perhaps we
+-         can use dev+ino pairs instead of names?  */
+-      const char *cwd = tar_getcdpath (cdidx);
++         tar_getcdpath does not return a true "canonical" path, so
++         this following approach may lead to situations where the same
++         file or directory is processed twice under different absolute
++         paths without that duplication being detected.  Perhaps we
++         should use dev+ino pairs instead of names?  */
++      const char *cdpath = tar_getcdpath (cdidx);
+       size_t copylen;
+       bool need_separator;
+ 
+-      copylen = strlen (cwd);
++      copylen = strlen (cdpath);
+       need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT
+-			  && copylen == 2 && ISSLASH (cwd[1]));
++			  && copylen == 2 && ISSLASH (cdpath[1]));
+       copy = xmalloc (copylen + need_separator + strlen (name) + 1);
+-      strcpy (copy, cwd);
++      strcpy (copy, cdpath);
+       copy[copylen] = DIRECTORY_SEPARATOR;
+       strcpy (copy + copylen + need_separator, name);
+     }
+@@ -633,8 +635,10 @@ struct wd
+ {
+   /* The directory's name.  */
+   char const *name;
+-  /* Current working directory; initialized by tar_getcwd */
+-  char *cwd;
++  /* "absolute" path representing this directory; in the contrast to
++     the real absolute pathname, it can contain /../ components (see
++     normalize_filename_x for the reason of it). */
++  char *abspath;
+   /* If nonzero, the file descriptor of the directory, or AT_FDCWD if
+      the working directory.  If zero, the directory needs to be opened
+      to be used.  */
+@@ -689,7 +693,7 @@ chdir_arg (char const *dir)
+       if (! wd_count)
+ 	{
+ 	  wd[wd_count].name = ".";
+-	  wd[wd_count].cwd = xgetcwd ();
++	  wd[wd_count].abspath = xgetcwd ();
+ 	  wd[wd_count].fd = AT_FDCWD;
+ 	  wd_count++;
+ 	}
+@@ -707,13 +711,16 @@ chdir_arg (char const *dir)
+     }
+ 
+   wd[wd_count].name = dir;
++  /* if the given name is an absolute path, then use that path
++     to represent this working directory; otherwise, construct
++     a path based on the previous -C option's absolute path */
+   if (IS_ABSOLUTE_FILE_NAME (wd[wd_count].name))
+-    wd[wd_count].cwd = xstrdup (wd[wd_count].name);
++    wd[wd_count].abspath = xstrdup (wd[wd_count].name);
+   else
+     {
+-      namebuf_t nbuf = namebuf_create (wd[wd_count - 1].cwd);
++      namebuf_t nbuf = namebuf_create (wd[wd_count - 1].abspath);
+       namebuf_add_dir (nbuf, wd[wd_count].name);
+-      wd[wd_count].cwd = namebuf_finish (nbuf);
++      wd[wd_count].abspath = namebuf_finish (nbuf);
+     }
+   wd[wd_count].fd = 0;
+   return wd_count++;
+@@ -794,6 +801,13 @@ tar_dirname (void)
+   return wd[chdir_current].name;
+ }
+ 
++/* Return the absolute path that represents the working
++   directory referenced by IDX.
++
++   If wd is empty, then there were no -C options given, and
++   chdir_args() has never been called, so we simply return the
++   process's actual cwd.  (Note that in this case IDX is ignored,
++   since it should always be 0.) */
+ const char *
+ tar_getcdpath (int idx)
+ {
+@@ -804,7 +818,7 @@ tar_getcdpath (int idx)
+ 	cwd = xgetcwd ();
+       return cwd;
+     }
+-  return wd[idx].cwd;
++  return wd[idx].abspath;
+ }
+ 
+ void
+diff --git a/src/tar.c b/src/tar.c
+index 18277e4..d11daa1 100644
+--- a/src/tar.c
++++ b/src/tar.c
+@@ -536,7 +536,8 @@ static struct argp_option options[] = {
+   {"no-same-permissions", NO_SAME_PERMISSIONS_OPTION, 0, 0,
+    N_("apply the user's umask when extracting permissions from the archive (default for ordinary users)"), GRID+1 },
+   {"preserve-order", 's', 0, 0,
+-   N_("sort names to extract to match archive"), GRID+1 },
++   N_("member arguments are listed in the same order as the "
++      "files in the archive"), GRID+1 },
+   {"same-order", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
+   {"preserve", PRESERVE_OPTION, 0, 0,
+    N_("same as both -p and -s"), GRID+1 },
+@@ -730,7 +731,7 @@ static struct argp_option options[] = {
+   {"hard-dereference", HARD_DEREFERENCE_OPTION, 0, 0,
+    N_("follow hard links; archive and dump the files they refer to"), GRID+1 },
+   {"starting-file", 'K', N_("MEMBER-NAME"), 0,
+-   N_("begin at member MEMBER-NAME in the archive"), GRID+1 },
++   N_("begin at member MEMBER-NAME when reading the archive"), GRID+1 },
+   {"newer", 'N', N_("DATE-OR-FILE"), 0,
+    N_("only store files newer than DATE-OR-FILE"), GRID+1 },
+   {"after-date", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
+-- 
+2.9.3
+
+
+From 79f04038e17dec01031113f4ba68f291f22012c3 Mon Sep 17 00:00:00 2001
+From: Nathan Stratton Treadway <nathanst@ontko.com>
+Date: Sat, 5 Oct 2013 08:53:08 +0300
+Subject: [PATCH 07/11] Provide comprehensive testcases for various file
+ removal modes.
+
+* tests/Makefile.am: Add new testcases.
+* tests/testsuite.at: Likewise.
+* tests/incr09.at: Add description.
+* tests/remfiles04a.at: New file.
+* tests/remfiles05.at: Rename to ...
+* tests/remfiles04b.at: ... this.
+* tests/remfiles04.at: Rename to ...
+* tests/remfiles04c.at: ... this.
+* tests/remfiles05a.at: New file.
+* tests/remfiles05b.at: New file.
+* tests/remfiles06.at: Rename to ...
+* tests/remfiles05c.at: ... this.
+* tests/remfiles06a.at: New file.
+* tests/remfiles06b.at: New file.
+* tests/remfiles06c.at: New file.
+* tests/remfiles07a.at: New file.
+* tests/remfiles07b.at: New file.
+* tests/remfiles07c.at: New file.
+* tests/remfiles08a.at: New file.
+* tests/remfiles08b.at: New file.
+* tests/remfiles08c.at: New file.
+* tests/remfiles08.at: Rename to ...
+* tests/remfiles09a.at: ... this.
+* tests/remfiles09b.at: New file.
+* tests/remfiles07.at: Rename to ...
+* tests/remfiles09c.at: ... this.
+---
+ tests/Makefile.am                       | 23 ++++++++---
+ tests/incr09.at                         |  8 ++++
+ tests/remfiles04a.at                    | 45 ++++++++++++++++++++++
+ tests/remfiles04b.at                    | 53 +++++++++++++++++++++++++
+ tests/{remfiles04.at => remfiles04c.at} | 21 +++++++---
+ tests/remfiles05a.at                    | 64 +++++++++++++++++++++++++++++++
+ tests/remfiles05b.at                    | 55 ++++++++++++++++++++++++++
+ tests/{remfiles05.at => remfiles05c.at} | 35 ++++++++++-------
+ tests/remfiles06.at                     | 65 -------------------------------
+ tests/remfiles06a.at                    | 56 +++++++++++++++++++++++++++
+ tests/remfiles06b.at                    | 56 +++++++++++++++++++++++++++
+ tests/remfiles06c.at                    | 68 +++++++++++++++++++++++++++++++++
+ tests/remfiles07a.at                    | 56 +++++++++++++++++++++++++++
+ tests/remfiles07b.at                    | 56 +++++++++++++++++++++++++++
+ tests/remfiles07c.at                    | 68 +++++++++++++++++++++++++++++++++
+ tests/remfiles08a.at                    | 56 +++++++++++++++++++++++++++
+ tests/remfiles08b.at                    | 56 +++++++++++++++++++++++++++
+ tests/remfiles08c.at                    | 68 +++++++++++++++++++++++++++++++++
+ tests/{remfiles08.at => remfiles09a.at} | 27 +++++++------
+ tests/remfiles09b.at                    | 57 +++++++++++++++++++++++++++
+ tests/{remfiles07.at => remfiles09c.at} | 37 ++++++++----------
+ tests/testsuite.at                      | 23 ++++++++---
+ 22 files changed, 923 insertions(+), 130 deletions(-)
+ create mode 100644 tests/remfiles04a.at
+ create mode 100644 tests/remfiles04b.at
+ rename tests/{remfiles04.at => remfiles04c.at} (69%)
+ create mode 100644 tests/remfiles05a.at
+ create mode 100644 tests/remfiles05b.at
+ rename tests/{remfiles05.at => remfiles05c.at} (63%)
+ create mode 100644 tests/remfiles06a.at
+ create mode 100644 tests/remfiles06b.at
+ create mode 100644 tests/remfiles06c.at
+ create mode 100644 tests/remfiles07a.at
+ create mode 100644 tests/remfiles07b.at
+ create mode 100644 tests/remfiles07c.at
+ create mode 100644 tests/remfiles08a.at
+ create mode 100644 tests/remfiles08b.at
+ create mode 100644 tests/remfiles08c.at
+ rename tests/{remfiles08.at => remfiles09a.at} (66%)
+ create mode 100644 tests/remfiles09b.at
+ rename tests/{remfiles07.at => remfiles09c.at} (68%)
+
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index b05a151..cf6f576 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -141,11 +141,24 @@ TESTSUITE_AT = \
+  remfiles01.at\
+  remfiles02.at\
+  remfiles03.at\
+- remfiles04.at\
+- remfiles05.at\
+- remfiles06.at\
+- remfiles07.at\
+- remfiles08.at\
++ remfiles04a.at\
++ remfiles04b.at\
++ remfiles04c.at\
++ remfiles05a.at\
++ remfiles05b.at\
++ remfiles05c.at\
++ remfiles06a.at\
++ remfiles06b.at\
++ remfiles06c.at\
++ remfiles07a.at\
++ remfiles07b.at\
++ remfiles07c.at\
++ remfiles08a.at\
++ remfiles08b.at\
++ remfiles08c.at\
++ remfiles09a.at\
++ remfiles09b.at\
++ remfiles09c.at\
+  same-order01.at\
+  same-order02.at\
+  shortfile.at\
+diff --git a/tests/incr09.at b/tests/incr09.at
+index b6130a6..e91fb5a 100644
+--- a/tests/incr09.at
++++ b/tests/incr09.at
+@@ -15,6 +15,14 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
++# Description: For some intermediate versions of tar 1.26.90,
++# tar would fail to correctly cannonicalize archive member names
++# in incremental mode if there was a -C options with an absolute path
++# on the command line without any archive members specified within that
++# directory. (In that case, the canonical name generated for
++# members specified after later -C options wouldn't correctly reflect the
++# previous absolute path.)
++
+ AT_SETUP([incremental with alternating -C])
+ AT_KEYWORDS([incremental create incr09])
+ 
+diff --git a/tests/remfiles04a.at b/tests/remfiles04a.at
+new file mode 100644
+index 0000000..d1e4614
+--- /dev/null
++++ b/tests/remfiles04a.at
+@@ -0,0 +1,45 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of a single relative-path -C option,
++# in --create/non-incremental mode.
++#
++
++AT_SETUP([remove-files with -C:rel in -c/non-incr. mode])
++AT_KEYWORDS([create remove-files remfiles04 remfiles04a])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++echo bar > bar
++echo foobar > foo/bar
++tar -cf foo.tar --remove-files -C foo bar
++echo A
++find . | sort
++],
++[0],
++[A
++.
++./bar
++./foo
++./foo.tar
++],[],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles04b.at b/tests/remfiles04b.at
+new file mode 100644
+index 0000000..3208557
+--- /dev/null
++++ b/tests/remfiles04b.at
+@@ -0,0 +1,53 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of a single relative-path -C option,
++# in --create/incremental mode.
++#
++# (Tar 1.26 would remove files in original working directory when called in
++# this manner.  [It would follow the -C for archiving the files, but ignore it
++# for removing them afterwards.]
++#
++# Reported by: Nathan Stratton Treadway <nathanst@ontko.com>
++# References: <20130921171234.GG32256@shire.ontko.com>,
++#             http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00028.html
++# )
++
++AT_SETUP([remove-files with -C:rel in -c/incr. mode])
++AT_KEYWORDS([create incremental remove-files remfiles04 remfiles04b])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++echo bar > bar
++echo foobar > foo/bar
++tar -cf foo.tar --incremental --remove-files -C foo bar
++echo A
++find . | sort
++],
++[0],
++[A
++.
++./bar
++./foo
++./foo.tar
++],[],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles04.at b/tests/remfiles04c.at
+similarity index 69%
+rename from tests/remfiles04.at
+rename to tests/remfiles04c.at
+index 04df45b..a1b6d56 100644
+--- a/tests/remfiles04.at
++++ b/tests/remfiles04c.at
+@@ -15,24 +15,32 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
+-# Description: Tar 1.26 would remove wrong files when called with
+-# --remove-files and -C
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of a single relative-path -C option,
++# in --append mode.
++#
++# (Tar 1.26 would remove files in original working directory when called in
++# this manner.  [It would follow the -C for archiving the files, but ignore it
++# for removing them afterwards.]
++#
+ # Reported by: Jörgen Strand <Jorgen.Strand@sonymobile.com>
+ # References: <9FC79E5CB90CEC47B9647DCAB7BD327A01AD83B452EE@seldmbx02.corpusers.net>
+ #             http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00024.html
++# )
+ 
+-AT_SETUP([remove-files with -C])
+-AT_KEYWORDS([create remove-files remfiles04])
++AT_SETUP([remove-files with -C:rel in -r mode])
++AT_KEYWORDS([create append remove-files remfiles04 remfiles04c])
+ 
+ AT_TAR_CHECK([
+ AT_SORT_PREREQ
+ mkdir foo
+ echo bar > bar
+ echo foobar > foo/bar
+-tar -cf foo.tar --remove-files -C foo bar
++tar -cf foo.tar -C foo bar
+ echo A
+ find . | sort
+-echo foobar > foo/bar
+ tar -rf foo.tar --remove-files -C foo bar
+ echo B
+ find . | sort
+@@ -43,6 +51,7 @@ find . | sort
+ ./bar
+ ./foo
+ ./foo.tar
++./foo/bar
+ B
+ .
+ ./bar
+diff --git a/tests/remfiles05a.at b/tests/remfiles05a.at
+new file mode 100644
+index 0000000..4ceec37
+--- /dev/null
++++ b/tests/remfiles05a.at
+@@ -0,0 +1,64 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of two relative-path -C options,
++# in --create/non-incremental mode.
++#
++# (This specific case failed during development of tar 1.26.90:
++# There was a leftover call to chdir in name_next_elt() in
++# tar 1.26.  After commit e3d28d84 this call would confuse the 
++# tar_getcwd function.
++#
++# Reported by: Nathan Stratton Treadway <nathanst@ontko.com>
++# References: <20130924145657.GM32256@shire.ontko.com>,
++#             http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00045.html
++# )
++
++AT_SETUP([remove-files with -C:rel,rel in -c/non-incr. mode])
++AT_KEYWORDS([create remove-files remfiles05 remfiles05a])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++mkdir bar
++echo file > file
++echo foo/file > foo/file
++echo bar/file > bar/file
++decho A
++tar -cvf foo.tar --remove-files -C foo file -C ../bar file
++decho B
++find . | sort
++],
++[0],
++[A
++file
++file
++B
++.
++./bar
++./file
++./foo
++./foo.tar
++],
++[A
++B
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles05b.at b/tests/remfiles05b.at
+new file mode 100644
+index 0000000..d120efd
+--- /dev/null
++++ b/tests/remfiles05b.at
+@@ -0,0 +1,55 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of two relative-path -C options,
++# in --create/incremental mode.
++#
++
++AT_SETUP([remove-files with -C:rel,rel in -c/incr. mode])
++AT_KEYWORDS([create incremental remove-files remfiles05 remfiles05b])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++mkdir bar
++echo file > file
++echo foo/file > foo/file
++echo bar/file > bar/file
++decho A
++tar -cvf foo.tar --incremental --remove-files -C foo file -C ../bar file
++decho B
++find . | sort
++],
++[0],
++[A
++file
++file
++B
++.
++./bar
++./file
++./foo
++./foo.tar
++],
++[A
++B
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles05.at b/tests/remfiles05c.at
+similarity index 63%
+rename from tests/remfiles05.at
+rename to tests/remfiles05c.at
+index 04425a7..a01b092 100644
+--- a/tests/remfiles05.at
++++ b/tests/remfiles05c.at
+@@ -15,25 +15,28 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
+-# Description: Tar 1.26 would remove wrong files when invoked with
+-# --listed-incremental and -C
+-# Reported by: Nathan Stratton Treadway <nathanst@ontko.com>
+-# References: <20130921171234.GG32256@shire.ontko.com>,
+-#             http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00028.html
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of two relative-path -C options,
++# in --append mode.
++#
+ 
+-AT_SETUP([incremental and -C])
+-AT_KEYWORDS([incremental create remove-files remfiles05])
++AT_SETUP([remove-files with -C:rel,rel in -r mode])
++AT_KEYWORDS([create append remove-files remfiles05 remfiles05c])
+ 
+ AT_TAR_CHECK([
+ AT_SORT_PREREQ
+ mkdir foo
+-echo bar > bar
+-echo foo/bar > foo/bar
++mkdir bar
++echo file > file
++echo foo/file > foo/file
++echo bar/file > bar/file
++tar -cf foo.tar -C foo file -C ../bar file
+ decho A
+ find . | sort
+-
+ decho B
+-tar -cvf foo.tar --listed-incremental=foo.snar --remove-files -C foo bar
++tar -rvf foo.tar --remove-files -C foo file -C ../bar file
+ decho C
+ find . | sort
+ ],
+@@ -41,15 +44,19 @@ find . | sort
+ [A
+ .
+ ./bar
++./bar/file
++./file
+ ./foo
+-./foo/bar
++./foo.tar
++./foo/file
+ B
+-bar
++file
++file
+ C
+ .
+ ./bar
++./file
+ ./foo
+-./foo.snar
+ ./foo.tar
+ ],
+ [A
+diff --git a/tests/remfiles06.at b/tests/remfiles06.at
+deleted file mode 100644
+index c2d9876..8b13789
+--- a/tests/remfiles06.at
++++ /dev/null
+@@ -1,66 +0,0 @@
+-# Process this file with autom4te to create testsuite. -*- Autotest -*-
+-# Test suite for GNU tar.
+-# Copyright 2013 Free Software Foundation, Inc.
+-#
+-# GNU tar 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.
+-#
+-# GNU tar 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/>.
+-
+-# Description: There was a leftover call to chdir in name_next_elt() in
+-# tar 1.26.  After commit e3d28d84 this call would confuse the tar_getcwd
+-# function.
+-# Reported by: Nathan Stratton Treadway <nathanst@ontko.com>
+-# References: <20130924145657.GM32256@shire.ontko.com>,
+-#             http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00045.html
+-
+-AT_SETUP([remove with two -C])
+-AT_KEYWORDS([remove-files remfiles06])
+-
+-AT_TAR_CHECK([
+-AT_SORT_PREREQ
+-mkdir tartest
+-cd tartest
+-mkdir foo
+-echo foo/file > foo/file
+-mkdir bar
+-echo bar/file > bar/file
+-decho A
+-find|sort
+-
+-decho B
+-tar -cvf ../foo.tar --remove-files -C foo file -C ../bar file
+-
+-decho C
+-find|sort
+-],
+-[0],
+-[A
+-.
+-./bar
+-./bar/file
+-./foo
+-./foo/file
+-B
+-file
+-file
+-C
+-.
+-./bar
+-./foo
+-],
+-[A
+-B
+-C
+-],[],[],[gnu])
+-
+-AT_CLEANUP
+-
+diff --git a/tests/remfiles06a.at b/tests/remfiles06a.at
+new file mode 100644
+index 0000000..fe762c1
+--- /dev/null
++++ b/tests/remfiles06a.at
+@@ -0,0 +1,56 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of a relative -C option followed by an absolute -C,
++# in --create/non-incremental mode.
++#
++
++AT_SETUP([remove-files with -C:rel,abs in -c/non-incr. mode])
++AT_KEYWORDS([create remove-files remfiles06 remfiles06a])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++mkdir bar
++echo file > file
++echo foo/file > foo/file
++echo bar/file > bar/file
++DIR=`pwd`
++decho A
++tar -cvf foo.tar --remove-files -C foo file -C $DIR/bar file
++decho B
++find . | sort
++],
++[0],
++[A
++file
++file
++B
++.
++./bar
++./file
++./foo
++./foo.tar
++],
++[A
++B
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles06b.at b/tests/remfiles06b.at
+new file mode 100644
+index 0000000..3b867fb
+--- /dev/null
++++ b/tests/remfiles06b.at
+@@ -0,0 +1,56 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of a relative -C option followed by an absolute -C,
++# in --create/incremental mode.
++#
++
++AT_SETUP([remove-files with -C:rel,abs in -c/incr. mode])
++AT_KEYWORDS([create incremental remove-files remfiles06 remfiles06b])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++mkdir bar
++echo file > file
++echo foo/file > foo/file
++echo bar/file > bar/file
++DIR=`pwd`
++decho A
++tar -cvf foo.tar --incremental --remove-files -C foo file -C $DIR/bar file
++decho B
++find . | sort
++],
++[0],
++[A
++file
++file
++B
++.
++./bar
++./file
++./foo
++./foo.tar
++],
++[A
++B
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles06c.at b/tests/remfiles06c.at
+new file mode 100644
+index 0000000..ad9164d
+--- /dev/null
++++ b/tests/remfiles06c.at
+@@ -0,0 +1,68 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of a relative -C option followed by an absolute -C,
++# in --append mode.
++#
++
++AT_SETUP([remove-files with -C:rel,abs in -r mode])
++AT_KEYWORDS([create append remove-files remfiles06 remfiles06c])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++mkdir bar
++echo file > file
++echo foo/file > foo/file
++echo bar/file > bar/file
++DIR=`pwd`
++tar -cf foo.tar -C foo file -C $DIR/bar file
++decho A
++find . | sort
++decho B
++tar -rvf foo.tar --remove-files -C foo file -C ../bar file
++decho C
++find . | sort
++],
++[0],
++[A
++.
++./bar
++./bar/file
++./file
++./foo
++./foo.tar
++./foo/file
++B
++file
++file
++C
++.
++./bar
++./file
++./foo
++./foo.tar
++],
++[A
++B
++C
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles07a.at b/tests/remfiles07a.at
+new file mode 100644
+index 0000000..95f645c
+--- /dev/null
++++ b/tests/remfiles07a.at
+@@ -0,0 +1,56 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of a relative -C option followed by an absolute -C,
++# in --create/non-incremental mode.
++#
++
++AT_SETUP([remove-files with -C:rel,abs in -c/non-incr. mode])
++AT_KEYWORDS([create remove-files remfiles07 remfiles07a])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++mkdir bar
++echo file > file
++echo foo/file > foo/file
++echo bar/file > bar/file
++DIR=`pwd`
++decho A
++tar -cvf foo.tar --remove-files -C foo file -C $DIR/bar file
++decho B
++find . | sort
++],
++[0],
++[A
++file
++file
++B
++.
++./bar
++./file
++./foo
++./foo.tar
++],
++[A
++B
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles07b.at b/tests/remfiles07b.at
+new file mode 100644
+index 0000000..ca67e5d
+--- /dev/null
++++ b/tests/remfiles07b.at
+@@ -0,0 +1,56 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of a relative -C option followed by an absolute -C,
++# in --create/incremental mode.
++#
++
++AT_SETUP([remove-files with -C:rel,abs in -c/incr. mode])
++AT_KEYWORDS([create incremental remove-files remfiles07 remfiles07b])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++mkdir bar
++echo file > file
++echo foo/file > foo/file
++echo bar/file > bar/file
++DIR=`pwd`
++decho A
++tar -cvf foo.tar --incremental --remove-files -C foo file -C $DIR/bar file
++decho B
++find . | sort
++],
++[0],
++[A
++file
++file
++B
++.
++./bar
++./file
++./foo
++./foo.tar
++],
++[A
++B
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles07c.at b/tests/remfiles07c.at
+new file mode 100644
+index 0000000..6a5c870
+--- /dev/null
++++ b/tests/remfiles07c.at
+@@ -0,0 +1,68 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of a relative -C option followed by an absolute -C,
++# in --append mode.
++#
++
++AT_SETUP([remove-files with -C:rel,abs in -r mode])
++AT_KEYWORDS([create append remove-files remfiles07 remfiles07c])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++mkdir bar
++echo file > file
++echo foo/file > foo/file
++echo bar/file > bar/file
++DIR=`pwd`
++tar -cf foo.tar -C foo file -C $DIR/bar file
++decho A
++find . | sort
++decho B
++tar -rvf foo.tar --remove-files -C foo file -C $DIR/bar file
++decho C
++find . | sort
++],
++[0],
++[A
++.
++./bar
++./bar/file
++./file
++./foo
++./foo.tar
++./foo/file
++B
++file
++file
++C
++.
++./bar
++./file
++./foo
++./foo.tar
++],
++[A
++B
++C
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles08a.at b/tests/remfiles08a.at
+new file mode 100644
+index 0000000..eadf149
+--- /dev/null
++++ b/tests/remfiles08a.at
+@@ -0,0 +1,56 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of an absolute -C option followed by a relative -C,
++# in --create/non-incremental mode.
++#
++
++AT_SETUP([remove-files with -C:abs,rel in -c/non-incr. mode])
++AT_KEYWORDS([create remove-files remfiles08 remfiles08a])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++mkdir bar
++echo file > file
++echo foo/file > foo/file
++echo bar/file > bar/file
++DIR=`pwd`
++decho A
++tar -cvf foo.tar --remove-files -C $DIR/foo file -C ../bar file
++decho B
++find . | sort
++],
++[0],
++[A
++file
++file
++B
++.
++./bar
++./file
++./foo
++./foo.tar
++],
++[A
++B
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles08b.at b/tests/remfiles08b.at
+new file mode 100644
+index 0000000..9faf2bb
+--- /dev/null
++++ b/tests/remfiles08b.at
+@@ -0,0 +1,56 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of an absolute -C option followed by a relative -C,
++# in --create/incremental mode.
++#
++
++AT_SETUP([remove-files with -C:abs,rel in -c/incr. mode])
++AT_KEYWORDS([create incremental remove-files remfiles08 remfiles08b])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++mkdir bar
++echo file > file
++echo foo/file > foo/file
++echo bar/file > bar/file
++DIR=`pwd`
++decho A
++tar -cvf foo.tar --incremental --remove-files -C $DIR/foo file -C ../bar file
++decho B
++find . | sort
++],
++[0],
++[A
++file
++file
++B
++.
++./bar
++./file
++./foo
++./foo.tar
++],
++[A
++B
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles08c.at b/tests/remfiles08c.at
+new file mode 100644
+index 0000000..a220f4c
+--- /dev/null
++++ b/tests/remfiles08c.at
+@@ -0,0 +1,68 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: ensure tar correctly respects -C option when deleting
++# files due to the --remove-files option.
++#
++# This case checks the use of an absolute -C option followed by a relative -C,
++# in --append mode.
++#
++
++AT_SETUP([remove-files with -C:abs,rel in -r mode])
++AT_KEYWORDS([create append remove-files remfiles08 remfiles08c])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++mkdir bar
++echo file > file
++echo foo/file > foo/file
++echo bar/file > bar/file
++DIR=`pwd`
++tar -cf foo.tar -C $DIR/foo file -C ../bar file
++decho A
++find . | sort
++decho B
++tar -rvf foo.tar --remove-files -C $DIR/foo file -C ../bar file
++decho C
++find . | sort
++],
++[0],
++[A
++.
++./bar
++./bar/file
++./file
++./foo
++./foo.tar
++./foo/file
++B
++file
++file
++C
++.
++./bar
++./file
++./foo
++./foo.tar
++],
++[A
++B
++C
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles08.at b/tests/remfiles09a.at
+similarity index 66%
+rename from tests/remfiles08.at
+rename to tests/remfiles09a.at
+index 0649e85..fd28b4f 100644
+--- a/tests/remfiles08.at
++++ b/tests/remfiles09a.at
+@@ -15,29 +15,28 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
+-# Description: See remfiles06.at
+-# Reported by: Nathan Stratton Treadway <nathanst@ontko.com>
+-# References: <20130926050634.GW32256@shire.ontko.com>
++# Description: check --remove-files operation when archiving/deleting
++# directory trees.
++#
++# This case checks the operation
++# in --create/non-incremental mode.
++#
+ 
+-AT_SETUP([remove with -C to absolute and relative paths])
+-AT_KEYWORDS([incremental create remove-files remfiles08])
++AT_SETUP([remove-files on full directory in -c/non-incr. mode])
++AT_KEYWORDS([create remove-files remfiles09 remfiles09a])
+ 
+ AT_TAR_CHECK([
+ mkdir foo
+-mkdir bar
+-echo foo/foo_file > foo/foo_file
+-echo bar/bar_file > bar/bar_file
++echo foo/file > foo/file
+ decho A
+-tar -cvf foo.tar --remove-files -C `pwd`/foo . -C ../bar .
++tar -cvf foo.tar --remove-files foo
+ decho B
+-find
++find . 
+ ],
+ [0],
+ [A
+-./
+-./foo_file
+-./
+-./bar_file
++foo/
++foo/file
+ B
+ .
+ ./foo.tar
+diff --git a/tests/remfiles09b.at b/tests/remfiles09b.at
+new file mode 100644
+index 0000000..30cc3ee
+--- /dev/null
++++ b/tests/remfiles09b.at
+@@ -0,0 +1,57 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Description: check --remove-files operation when archiving/deleting
++# directory trees.
++#
++# This case checks the operation
++# in --create/incremental mode.
++#
++# Note: in tar 1.27, when run in incremental mode tar will attempt to remove
++# the directory before removing the files within that directory, and thus
++# the --remove-files operation will cause tar to abort with an error status.
++# This issue will be fixed in a later version of tar.
++
++AT_SETUP([remove-files on full directory in -c/incr. mode])
++AT_KEYWORDS([create incremental remove-files remfiles09 remfiles09b])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++mkdir foo
++echo foo/file > foo/file
++decho A
++tar -cvf foo.tar --incremental --remove-files foo
++TARSTAT=$?
++decho B
++find .
++test $TARSTAT -ne 0 && AT_SKIP_TEST   # we expect to fail in tar 1.27
++],
++[0],
++[A
++foo/
++foo/file
++B
++.
++./foo
++./foo.tar
++],
++[A
++tar: foo: Directory is new
++B
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/remfiles07.at b/tests/remfiles09c.at
+similarity index 68%
+rename from tests/remfiles07.at
+rename to tests/remfiles09c.at
+index 742e0a1..7241608 100644
+--- a/tests/remfiles07.at
++++ b/tests/remfiles09c.at
+@@ -15,45 +15,40 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
+-# Description: See remfiles06.at
+-# Reported by: Nathan Stratton Treadway <nathanst@ontko.com>
+-# References: <20130924185129.GO32256@shire.ontko.com>
++# Description: check --remove-files operation when archiving/deleting
++# directory trees.
++#
++# This case checks the operation
++# in --append mode.
++#
+ 
+-AT_SETUP([remove with -C to absolute path])
+-AT_KEYWORDS([create remove-files remfiles07])
++AT_SETUP([remove-files on full directory in -r mode])
++AT_KEYWORDS([create append remove-files remfiles09 remfiles09c])
+ 
+ AT_TAR_CHECK([
+ AT_SORT_PREREQ
+-mkdir tartest
+-cd tartest
+ mkdir foo
+ echo foo/file > foo/file
+-mkdir bar
+-echo bar/file > bar/file
++tar -cf foo.tar foo
+ decho A
+-find|sort
+-
+-DIR=`pwd`
++find . | sort
+ decho B
+-tar -cvf ../foo.tar --remove-files -C foo file -C $DIR/bar file
+-
++tar -rvf foo.tar --remove-files foo
+ decho C
+-find|sort
++find . | sort
+ ],
+ [0],
+ [A
+ .
+-./bar
+-./bar/file
+ ./foo
++./foo.tar
+ ./foo/file
+ B
+-file
+-file
++foo/
++foo/file
+ C
+ .
+-./bar
+-./foo
++./foo.tar
+ ],
+ [A
+ B
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index a9f2ab6..1cc425f 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -332,11 +332,24 @@ m4_include([grow.at])
+ m4_include([remfiles01.at])
+ m4_include([remfiles02.at])
+ m4_include([remfiles03.at])
+-m4_include([remfiles04.at])
+-m4_include([remfiles05.at])
+-m4_include([remfiles06.at])
+-m4_include([remfiles07.at])
+-m4_include([remfiles08.at])
++m4_include([remfiles04a.at])
++m4_include([remfiles04b.at])
++m4_include([remfiles04c.at])
++m4_include([remfiles05a.at])
++m4_include([remfiles05b.at])
++m4_include([remfiles05c.at])
++m4_include([remfiles06a.at])
++m4_include([remfiles06b.at])
++m4_include([remfiles06c.at])
++m4_include([remfiles07a.at])
++m4_include([remfiles07b.at])
++m4_include([remfiles07c.at])
++m4_include([remfiles08a.at])
++m4_include([remfiles08b.at])
++m4_include([remfiles08c.at])
++m4_include([remfiles09a.at])
++m4_include([remfiles09b.at])
++m4_include([remfiles09c.at])
+ 
+ m4_include([sigpipe.at])
+ 
+-- 
+2.9.3
+
+
+From c3d32c9c848f1f305cd9aefd9f485cdfbcee51b2 Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Sat, 5 Oct 2013 09:29:55 +0300
+Subject: [PATCH 08/11] Xfail the remfiles09b test.
+
+* tests/remfiles09b.at: Turn into expected failure.
+---
+ tests/remfiles09b.at | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/tests/remfiles09b.at b/tests/remfiles09b.at
+index 30cc3ee..de9b172 100644
+--- a/tests/remfiles09b.at
++++ b/tests/remfiles09b.at
+@@ -29,6 +29,8 @@
+ AT_SETUP([remove-files on full directory in -c/incr. mode])
+ AT_KEYWORDS([create incremental remove-files remfiles09 remfiles09b])
+ 
++AT_XFAIL_IF(true) # we expect to fail in tar 1.27
++
+ AT_TAR_CHECK([
+ AT_SORT_PREREQ
+ mkdir foo
+@@ -38,7 +40,6 @@ tar -cvf foo.tar --incremental --remove-files foo
+ TARSTAT=$?
+ decho B
+ find .
+-test $TARSTAT -ne 0 && AT_SKIP_TEST   # we expect to fail in tar 1.27
+ ],
+ [0],
+ [A
+-- 
+2.9.3
+
+
+From 2c5449cc473b0a9affed02feaf3ad42e5e89bfb5 Mon Sep 17 00:00:00 2001
+From: Paul Eggert <eggert@cs.ucla.edu>
+Date: Tue, 29 Apr 2014 14:22:07 -0700
+Subject: [PATCH 09/11] tar: do not dereference NULL pointer with
+ '--remove-files .'
+
+Problem reported by Thorsten Hirsch in:
+http://lists.gnu.org/archive/html/bug-tar/2014-04/msg00011.html
+* src/unlink.c (flush_deferred_unlinks):
+Do not attempt to find the parent of "." when "." is
+at the top level.
+* tests/remfiles10.at: New file.
+* tests/Makefile.am (TESTSUITE_AT):
+* tests/testsuite.at: Add it.
+---
+ src/unlink.c        |  5 +++--
+ tests/Makefile.am   |  1 +
+ tests/remfiles10.at | 46 ++++++++++++++++++++++++++++++++++++++++++++++
+ tests/testsuite.at  |  1 +
+ 4 files changed, 51 insertions(+), 2 deletions(-)
+ create mode 100644 tests/remfiles10.at
+
+diff --git a/src/unlink.c b/src/unlink.c
+index 10e0b41..6e41acc 100644
+--- a/src/unlink.c
++++ b/src/unlink.c
+@@ -84,8 +84,9 @@ flush_deferred_unlinks (bool force)
+ 	    {
+ 	      const char *fname;
+ 
+-	      if (p->file_name[0] == 0 ||
+-		  strcmp (p->file_name, ".") == 0)
++	      if (p->dir_idx
++		  && (p->file_name[0] == 0
++		      || strcmp (p->file_name, ".") == 0))
+ 		{
+ 		  fname = tar_dirname ();
+ 		  chdir_do (p->dir_idx - 1);
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index cf6f576..792c83c 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -159,6 +159,7 @@ TESTSUITE_AT = \
+  remfiles09a.at\
+  remfiles09b.at\
+  remfiles09c.at\
++ remfiles10.at\
+  same-order01.at\
+  same-order02.at\
+  shortfile.at\
+diff --git a/tests/remfiles10.at b/tests/remfiles10.at
+new file mode 100644
+index 0000000..b4fe139
+--- /dev/null
++++ b/tests/remfiles10.at
+@@ -0,0 +1,46 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2014 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++# Check --remove-files with .
++
++AT_SETUP([remove-files])
++AT_KEYWORDS([create remove-files remfiles10])
++
++AT_TAR_CHECK([
++mkdir foo
++echo foo/file > foo/file
++decho A
++(cd foo && tar -cvf ../foo.tar --remove-files .)
++tar_status=$?
++decho B
++find foo
++exit $tar_status
++],
++[2],
++[A
++./
++./file
++B
++foo
++],
++[A
++tar: .: Cannot rmdir: Invalid argument
++tar: Exiting with failure status due to previous errors
++B
++],[],[],[gnu])
++
++AT_CLEANUP
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index 1cc425f..1078724 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -350,6 +350,7 @@ m4_include([remfiles08c.at])
+ m4_include([remfiles09a.at])
+ m4_include([remfiles09b.at])
+ m4_include([remfiles09c.at])
++m4_include([remfiles10.at])
+ 
+ m4_include([sigpipe.at])
+ 
+-- 
+2.9.3
+
+
+From 612e134f4905f479b78b6d7faf9798494697a742 Mon Sep 17 00:00:00 2001
+From: Nathan Stratton Treadway <nathanst@ontko.com>
+Date: Sun, 27 Jul 2014 23:27:28 +0300
+Subject: [PATCH 10/11] Restructure the remfiles testsuite.
+
+---
+ tests/remfiles06c.at |  2 +-
+ tests/remfiles07a.at |  6 +++---
+ tests/remfiles07b.at |  6 +++---
+ tests/remfiles07c.at |  8 ++++----
+ tests/remfiles08a.at | 31 +++++++++++++++----------------
+ tests/remfiles08b.at | 38 ++++++++++++++++++++++----------------
+ tests/remfiles08c.at | 37 ++++++++++++++++++-------------------
+ tests/remfiles09a.at |  2 +-
+ tests/remfiles09b.at |  3 ---
+ 9 files changed, 67 insertions(+), 66 deletions(-)
+
+diff --git a/tests/remfiles06c.at b/tests/remfiles06c.at
+index ad9164d..abb8e68 100644
+--- a/tests/remfiles06c.at
++++ b/tests/remfiles06c.at
+@@ -37,7 +37,7 @@ tar -cf foo.tar -C foo file -C $DIR/bar file
+ decho A
+ find . | sort
+ decho B
+-tar -rvf foo.tar --remove-files -C foo file -C ../bar file
++tar -rvf foo.tar --remove-files -C foo file -C $DIR/bar file
+ decho C
+ find . | sort
+ ],
+diff --git a/tests/remfiles07a.at b/tests/remfiles07a.at
+index 95f645c..5b7df3e 100644
+--- a/tests/remfiles07a.at
++++ b/tests/remfiles07a.at
+@@ -18,11 +18,11 @@
+ # Description: ensure tar correctly respects -C option when deleting
+ # files due to the --remove-files option.
+ #
+-# This case checks the use of a relative -C option followed by an absolute -C,
++# This case checks the use of an absolute -C option followed by a relative -C,
+ # in --create/non-incremental mode.
+ #
+ 
+-AT_SETUP([remove-files with -C:rel,abs in -c/non-incr. mode])
++AT_SETUP([remove-files with -C:abs,rel in -c/non-incr. mode])
+ AT_KEYWORDS([create remove-files remfiles07 remfiles07a])
+ 
+ AT_TAR_CHECK([
+@@ -34,7 +34,7 @@ echo foo/file > foo/file
+ echo bar/file > bar/file
+ DIR=`pwd`
+ decho A
+-tar -cvf foo.tar --remove-files -C foo file -C $DIR/bar file
++tar -cvf foo.tar --remove-files -C $DIR/foo file -C ../bar file
+ decho B
+ find . | sort
+ ],
+diff --git a/tests/remfiles07b.at b/tests/remfiles07b.at
+index ca67e5d..0147c5d 100644
+--- a/tests/remfiles07b.at
++++ b/tests/remfiles07b.at
+@@ -18,11 +18,11 @@
+ # Description: ensure tar correctly respects -C option when deleting
+ # files due to the --remove-files option.
+ #
+-# This case checks the use of a relative -C option followed by an absolute -C,
++# This case checks the use of an absolute -C option followed by a relative -C,
+ # in --create/incremental mode.
+ #
+ 
+-AT_SETUP([remove-files with -C:rel,abs in -c/incr. mode])
++AT_SETUP([remove-files with -C:abs,rel in -c/incr. mode])
+ AT_KEYWORDS([create incremental remove-files remfiles07 remfiles07b])
+ 
+ AT_TAR_CHECK([
+@@ -34,7 +34,7 @@ echo foo/file > foo/file
+ echo bar/file > bar/file
+ DIR=`pwd`
+ decho A
+-tar -cvf foo.tar --incremental --remove-files -C foo file -C $DIR/bar file
++tar -cvf foo.tar --incremental --remove-files -C $DIR/foo file -C ../bar file
+ decho B
+ find . | sort
+ ],
+diff --git a/tests/remfiles07c.at b/tests/remfiles07c.at
+index 6a5c870..f190539 100644
+--- a/tests/remfiles07c.at
++++ b/tests/remfiles07c.at
+@@ -18,11 +18,11 @@
+ # Description: ensure tar correctly respects -C option when deleting
+ # files due to the --remove-files option.
+ #
+-# This case checks the use of a relative -C option followed by an absolute -C,
++# This case checks the use of an absolute -C option followed by a relative -C,
+ # in --append mode.
+ #
+ 
+-AT_SETUP([remove-files with -C:rel,abs in -r mode])
++AT_SETUP([remove-files with -C:abs,rel in -r mode])
+ AT_KEYWORDS([create append remove-files remfiles07 remfiles07c])
+ 
+ AT_TAR_CHECK([
+@@ -33,11 +33,11 @@ echo file > file
+ echo foo/file > foo/file
+ echo bar/file > bar/file
+ DIR=`pwd`
+-tar -cf foo.tar -C foo file -C $DIR/bar file
++tar -cf foo.tar -C $DIR/foo file -C ../bar file
+ decho A
+ find . | sort
+ decho B
+-tar -rvf foo.tar --remove-files -C foo file -C $DIR/bar file
++tar -rvf foo.tar --remove-files -C $DIR/foo file -C ../bar file
+ decho C
+ find . | sort
+ ],
+diff --git a/tests/remfiles08a.at b/tests/remfiles08a.at
+index eadf149..1ffffb2 100644
+--- a/tests/remfiles08a.at
++++ b/tests/remfiles08a.at
+@@ -15,38 +15,37 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
+-# Description: ensure tar correctly respects -C option when deleting
+-# files due to the --remove-files option.
++# Description: If tar 1.26 was called with the --remove-files option and told
++# to archive (and thus delete) two subdirectories where the second was
++# specified relative to the first, it would be unable to delete the
++# second directory (and its contents), since the relative path would no
++# longer be valid once the first directory was deleted.
+ #
+-# This case checks the use of an absolute -C option followed by a relative -C,
++# This case checks for successful deletion of all archived items
+ # in --create/non-incremental mode.
+ #
+ 
+-AT_SETUP([remove-files with -C:abs,rel in -c/non-incr. mode])
++AT_SETUP([remove-files deleting two subdirs in -c/non-incr. mode])
+ AT_KEYWORDS([create remove-files remfiles08 remfiles08a])
+ 
+ AT_TAR_CHECK([
+-AT_SORT_PREREQ
+ mkdir foo
+ mkdir bar
+-echo file > file
+-echo foo/file > foo/file
+-echo bar/file > bar/file
+-DIR=`pwd`
++echo foo/foo_file > foo/foo_file
++echo bar/bar_file > bar/bar_file
+ decho A
+-tar -cvf foo.tar --remove-files -C $DIR/foo file -C ../bar file
++tar -cvf foo.tar --remove-files -C foo . -C ../bar .
+ decho B
+-find . | sort
++find .
+ ],
+ [0],
+ [A
+-file
+-file
++./
++./foo_file
++./
++./bar_file
+ B
+ .
+-./bar
+-./file
+-./foo
+ ./foo.tar
+ ],
+ [A
+diff --git a/tests/remfiles08b.at b/tests/remfiles08b.at
+index 9faf2bb..d61c9ab 100644
+--- a/tests/remfiles08b.at
++++ b/tests/remfiles08b.at
+@@ -15,41 +15,47 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
+-# Description: ensure tar correctly respects -C option when deleting
+-# files due to the --remove-files option.
++# Description: If tar 1.26 was called with the --remove-files option and told
++# to archive (and thus delete) two subdirectories where the second was
++# specified relative to the first, it would be unable to delete the
++# second directory (and its contents), since the relative path would no
++# longer be valid once the first directory was deleted.
+ #
+-# This case checks the use of an absolute -C option followed by a relative -C,
++# This case checks for successful deletion of all archived items
+ # in --create/incremental mode.
+ #
++# Note: tar 1.27 fails this test case due to a more general issue
++# archving-and-removing a full directory tree when run in incremental
++# mode; see remfiles09b.at for that specific test case.
+ 
+-AT_SETUP([remove-files with -C:abs,rel in -c/incr. mode])
++AT_SETUP([remove-files deleting two subdirs in -c/incr. mode])
+ AT_KEYWORDS([create incremental remove-files remfiles08 remfiles08b])
+ 
++AT_XFAIL_IF(true) # we expect to fail in tar 1.27
++
+ AT_TAR_CHECK([
+-AT_SORT_PREREQ
+ mkdir foo
+ mkdir bar
+-echo file > file
+-echo foo/file > foo/file
+-echo bar/file > bar/file
+-DIR=`pwd`
++echo foo/foo_file > foo/foo_file
++echo bar/bar_file > bar/bar_file
+ decho A
+-tar -cvf foo.tar --incremental --remove-files -C $DIR/foo file -C ../bar file
++tar -cvf foo.tar --incremental --remove-files -C foo . -C ../bar .
+ decho B
+-find . | sort
++find .
+ ],
+ [0],
+ [A
+-file
+-file
++./
++./
++./foo_file
++./bar_file
+ B
+ .
+-./bar
+-./file
+-./foo
+ ./foo.tar
+ ],
+ [A
++tar: .: Directory is new
++tar: .: Directory is new
+ B
+ ],[],[],[gnu])
+ 
+diff --git a/tests/remfiles08c.at b/tests/remfiles08c.at
+index a220f4c..19b18e2 100644
+--- a/tests/remfiles08c.at
++++ b/tests/remfiles08c.at
+@@ -15,49 +15,48 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
+-# Description: ensure tar correctly respects -C option when deleting
+-# files due to the --remove-files option.
++# Description: If tar 1.26 was called with the --remove-files option and told
++# to archive (and thus delete) two subdirectories where the second was
++# specified relative to the first, it would be unable to delete the
++# second directory (and its contents), since the relative path would no
++# longer be valid once the first directory was deleted.
+ #
+-# This case checks the use of an absolute -C option followed by a relative -C,
++# This case checks for successful deletion of all archived items
+ # in --append mode.
+ #
+ 
+-AT_SETUP([remove-files with -C:abs,rel in -r mode])
++AT_SETUP([remove-files deleting two subdirs in -r mode])
+ AT_KEYWORDS([create append remove-files remfiles08 remfiles08c])
+ 
+ AT_TAR_CHECK([
+ AT_SORT_PREREQ
+ mkdir foo
+ mkdir bar
+-echo file > file
+-echo foo/file > foo/file
+-echo bar/file > bar/file
+-DIR=`pwd`
+-tar -cf foo.tar -C $DIR/foo file -C ../bar file
++echo foo/foo_file > foo/foo_file
++echo bar/bar_file > bar/bar_file
++tar -cf foo.tar -C foo . -C ../bar .
+ decho A
+ find . | sort
+ decho B
+-tar -rvf foo.tar --remove-files -C $DIR/foo file -C ../bar file
++tar -rvf foo.tar --remove-files -C foo . -C ../bar .
+ decho C
+-find . | sort
++find .
+ ],
+ [0],
+ [A
+ .
+ ./bar
+-./bar/file
+-./file
++./bar/bar_file
+ ./foo
+ ./foo.tar
+-./foo/file
++./foo/foo_file
+ B
+-file
+-file
++./
++./foo_file
++./
++./bar_file
+ C
+ .
+-./bar
+-./file
+-./foo
+ ./foo.tar
+ ],
+ [A
+diff --git a/tests/remfiles09a.at b/tests/remfiles09a.at
+index fd28b4f..f4a3bf5 100644
+--- a/tests/remfiles09a.at
++++ b/tests/remfiles09a.at
+@@ -31,7 +31,7 @@ echo foo/file > foo/file
+ decho A
+ tar -cvf foo.tar --remove-files foo
+ decho B
+-find . 
++find .
+ ],
+ [0],
+ [A
+diff --git a/tests/remfiles09b.at b/tests/remfiles09b.at
+index de9b172..e12fe32 100644
+--- a/tests/remfiles09b.at
++++ b/tests/remfiles09b.at
+@@ -32,12 +32,10 @@ AT_KEYWORDS([create incremental remove-files remfiles09 remfiles09b])
+ AT_XFAIL_IF(true) # we expect to fail in tar 1.27
+ 
+ AT_TAR_CHECK([
+-AT_SORT_PREREQ
+ mkdir foo
+ echo foo/file > foo/file
+ decho A
+ tar -cvf foo.tar --incremental --remove-files foo
+-TARSTAT=$?
+ decho B
+ find .
+ ],
+@@ -47,7 +45,6 @@ foo/
+ foo/file
+ B
+ .
+-./foo
+ ./foo.tar
+ ],
+ [A
+-- 
+2.9.3
+
+
+From 6030b8a2589ff69d9200578e0aecc1f10aedb073 Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org>
+Date: Wed, 11 Nov 2015 13:01:45 +0200
+Subject: [PATCH 11/11] Work around unlinkat bug on FreeBSD and GNU/Hurd
+
+* src/unlink.c (dunlink_insert): New function.
+(flush_deferred_unlinks): Skip cwds and nonempty directories
+at the first pass.  If force is requested, run a second pass
+removing them.
+(queue_deferred_unlink): Make sure current working directory
+entries are sorted in descending order by the value of dir_idx.
+This makes sure they will be removed in right order, which works
+around unlinkat bug on FreeBSD and GNU/Hurd.
+* tests/remfiles08b.at: Remove expected failure.
+* tests/remfiles09b.at: Likewise.
+---
+ src/unlink.c         | 91 +++++++++++++++++++++++++++++++++++++++++-----------
+ tests/remfiles08b.at |  2 --
+ tests/remfiles09b.at |  2 --
+ 3 files changed, 72 insertions(+), 23 deletions(-)
+
+diff --git a/src/unlink.c b/src/unlink.c
+index 6e41acc..f5fb81d 100644
+--- a/src/unlink.c
++++ b/src/unlink.c
+@@ -30,6 +30,10 @@ struct deferred_unlink
+ 				       entry got added to the queue */
+   };
+ 
++#define IS_CWD(p) \
++  ((p)->is_dir \
++   && ((p)->file_name[0] == 0 || strcmp ((p)->file_name, ".") == 0))
++
+ /* The unlink queue */
+ static struct deferred_unlink *dunlink_head, *dunlink_tail;
+ 
+@@ -59,6 +63,24 @@ dunlink_alloc (void)
+ }
+ 
+ static void
++dunlink_insert (struct deferred_unlink *anchor, struct deferred_unlink *p)
++{
++  if (anchor)
++    {
++      p->next = anchor->next;
++      anchor->next = p;
++    }
++  else
++    {
++      p->next = dunlink_head;
++      dunlink_head = p;
++    }
++  if (!p->next)
++    dunlink_tail = p;
++  dunlink_count++;
++}
++
++static void
+ dunlink_reclaim (struct deferred_unlink *p)
+ {
+   free (p->file_name);
+@@ -84,12 +106,11 @@ flush_deferred_unlinks (bool force)
+ 	    {
+ 	      const char *fname;
+ 
+-	      if (p->dir_idx
+-		  && (p->file_name[0] == 0
+-		      || strcmp (p->file_name, ".") == 0))
++	      if (p->dir_idx && IS_CWD (p))
+ 		{
+-		  fname = tar_dirname ();
+-		  chdir_do (p->dir_idx - 1);
++		  prev = p;
++		  p = next;
++		  continue;
+ 		}
+ 	      else
+ 		fname = p->file_name;
+@@ -102,15 +123,12 @@ flush_deferred_unlinks (bool force)
+ 		      /* nothing to worry about */
+ 		      break;
+ 		    case ENOTEMPTY:
+-		      if (!force)
+-			{
+-			  /* Keep the record in list, in the hope we'll
+-			     be able to remove it later */
+-			  prev = p;
+-			  p = next;
+-			  continue;
+-			}
+-		      /* fall through */
++		      /* Keep the record in list, in the hope we'll
++			 be able to remove it later */
++		      prev = p;
++		      p = next;
++		      continue;
++
+ 		    default:
+ 		      rmdir_error (fname);
+ 		    }
+@@ -137,6 +155,34 @@ flush_deferred_unlinks (bool force)
+     }
+   if (!dunlink_head)
+     dunlink_tail = NULL;
++  else if (force)
++    {
++      for (p = dunlink_head; p; )
++	{
++	  struct deferred_unlink *next = p->next;
++	  const char *fname;
++
++	  chdir_do (p->dir_idx);
++	  if (p->dir_idx && IS_CWD (p))
++	    {
++	      fname = tar_dirname ();
++	      chdir_do (p->dir_idx - 1);
++	    }
++	  else
++	    fname = p->file_name;
++
++	  if (unlinkat (chdir_fd, fname, AT_REMOVEDIR) != 0)
++	    {
++	      if (errno != ENOENT)
++		rmdir_error (fname);
++	    }
++	  dunlink_reclaim (p);
++	  dunlink_count--;
++	  p = next;
++	}
++      dunlink_head = dunlink_tail = NULL;
++    }
++
+   chdir_do (saved_chdir);
+ }
+ 
+@@ -169,10 +215,17 @@ queue_deferred_unlink (const char *name, bool is_dir)
+   p->is_dir = is_dir;
+   p->records_written = records_written;
+ 
+-  if (dunlink_tail)
+-    dunlink_tail->next = p;
++  if (IS_CWD (p))
++    {
++      struct deferred_unlink *q, *prev;
++      for (q = dunlink_head, prev = NULL; q; prev = q, q = q->next)
++	if (IS_CWD (q) && q->dir_idx < p->dir_idx)
++	  break;
++      if (q)
++	dunlink_insert (prev, p);
++      else
++	dunlink_insert (dunlink_tail, p);
++    }
+   else
+-    dunlink_head = p;
+-  dunlink_tail = p;
+-  dunlink_count++;
++    dunlink_insert (dunlink_tail, p);
+ }
+diff --git a/tests/remfiles08b.at b/tests/remfiles08b.at
+index d61c9ab..4487f83 100644
+--- a/tests/remfiles08b.at
++++ b/tests/remfiles08b.at
+@@ -31,8 +31,6 @@
+ AT_SETUP([remove-files deleting two subdirs in -c/incr. mode])
+ AT_KEYWORDS([create incremental remove-files remfiles08 remfiles08b])
+ 
+-AT_XFAIL_IF(true) # we expect to fail in tar 1.27
+-
+ AT_TAR_CHECK([
+ mkdir foo
+ mkdir bar
+diff --git a/tests/remfiles09b.at b/tests/remfiles09b.at
+index e12fe32..4d05aa5 100644
+--- a/tests/remfiles09b.at
++++ b/tests/remfiles09b.at
+@@ -29,8 +29,6 @@
+ AT_SETUP([remove-files on full directory in -c/incr. mode])
+ AT_KEYWORDS([create incremental remove-files remfiles09 remfiles09b])
+ 
+-AT_XFAIL_IF(true) # we expect to fail in tar 1.27
+-
+ AT_TAR_CHECK([
+ mkdir foo
+ echo foo/file > foo/file
+-- 
+2.9.3
+
diff --git a/SOURCES/tar-1.26-docu-xattrs.patch b/SOURCES/tar-1.26-docu-xattrs.patch
new file mode 100644
index 0000000..14d047e
--- /dev/null
+++ b/SOURCES/tar-1.26-docu-xattrs.patch
@@ -0,0 +1,372 @@
+diff --git a/doc/tar.texi b/doc/tar.texi
+index d678db9..ab8a0c8 100644
+--- a/doc/tar.texi
++++ b/doc/tar.texi
+@@ -37,7 +37,8 @@ This manual is for @acronym{GNU} @command{tar} (version
+ from archives.
+ 
+ Copyright @copyright{} 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
+-2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
++2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software
++Foundation, Inc.
+ 
+ @quotation
+ Permission is granted to copy, distribute and/or modify this document
+@@ -162,6 +163,7 @@ How to Create Archives
+ How to List Archives
+ 
+ * list dir::
++* List Extended Attributes::
+ 
+ How to Extract Members from an Archive
+ 
+@@ -1492,6 +1494,7 @@ for a detailed discussion of globbing patterns and related
+ 
+ @menu
+ * list dir::
++* List Extended Attributes::
+ @end menu
+ 
+ @node list dir
+@@ -1522,6 +1525,116 @@ drwxrwxrwx myself/user       0 1990-05-31 21:49 practice/
+ When you use a directory name as a file name argument, @command{tar} acts on
+ all the files (including sub-directories) in that directory.
+ 
++@node List Extended Attributes
++@unnumberedsubsec Listing xattrs, POSIX ACLs and SELinux context
++
++From upstream GNU tar 1.26.9, tar is able to store, extract and list extended
++file attributes.  Listing of those attributes is then active only in verbose and
++double-verbose mode.
++
++This section exercises how to list attributes on examples.  Lets start with
++simple verbose mode.  This output is inspired by GNU @command{ls -l} command
++output.
++
++@itemize @bullet
++@item
++Show only pure extended attributes.
++
++@smallexample
++$ tar --xattrs --list -v archive.tar
++-rw-rwxr--  user/group 0 2012-08-08 15:15 acls.txt
++-rw-rw-r--* user/group 0 2012-08-08 15:15 xattrs.txt
++@end smallexample
++
++Note the asterisk on the third line!  It reflects the situation that the file
++'xattrs.txt' has some extended attribute set.  The default mode (same as if you
++are extracting extended attributes) shows information only about extended
++attributes from 'user.*' domain.  Anyway, feel free to change the sensitivity
++using @option{--xattrs-include} or @option{--xattrs-exclude} options.
++
++@item Show only POSIX ACLs - the character you should look for is '+':
++
++@smallexample
++$ tar --acls --list -v archive.tar
++-rw-rwxr--+ praiskup/praiskup 0 2012-08-08 15:15 acls.txt
++-rw-rw-r--  praiskup/praiskup 0 2012-08-08 15:15 xattrs.txt
++@end smallexample
++
++@item Show only SELinux - the key character is '.':
++
++@smallexample
++$ tar --selinux --list -v archive.tar
++-rw-rw-r--.  praiskup/praiskup 0 2012-08-08 15:16 selinux_only.txt
++-rw-rw-r--   praiskup/praiskup 0 2012-08-08 15:15 xattrs.txt
++@end smallexample
++
++@item
++Show info about ACLs, SELinux and general extended attributes together:
++
++@smallexample
++$ tar --selinux --acls --xattrs --list -v archive.tar
++-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:16 selinux_only.txt
++-rw-rwxr--+ praiskup/praiskup 0 2012-08-08 15:15 acls.txt
++-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:15 xattrs.txt
++@end smallexample
++
++In this case, the priority of character is '+' > '.' > '*'.  You don't see the
++general extended attributes flag ('*' character) on this example because it is
++hidden by '.' (meaning that the file has SELinux context set).
++
++@end itemize
++
++The example of double verbose mode is here.  In this output the single verbose
++characters '.', '+' and '*' are also present after the permission string.
++
++@smallexample
++$ tar --xattrs --selinux --acls -tvvf archive.tar
++-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:16 selinux_only.txt
++  s: unconfined_u:object_r:user_tmp_t:s0
++-rw-rwxr--+ praiskup/praiskup 0 2012-08-08 15:15 acls.txt
++  s: unconfined_u:object_r:user_tmp_t:s0
++  a: user::rw-,user:tester:rwx,group::rw-,mask::rwx,other::r--
++-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:15 xattrs.txt
++  s: unconfined_u:object_r:user_tmp_t:s0
++  x: 12 user.xattr
++  x: 12 user.we_like_tar
++@end smallexample
++
++This mode extends tar's output with additional lines beginning with
++distinguishing characters - 's' for SELinux context, 'a' for POSIX Access
++Control Lists  and 'x' for generic extended attributes.
++
++In this format, POSIX ACLs are written in SHORT TEXT FORM as specified in manual
++page @command{man 5 acl}.
++
++Use the @option{--xattrs-include} again if you want to print other than default
++'user.*' extended attributes domain:
++
++@smallexample
++$ tar --xattrs --xattrs-include='*' --acls --selinux -tvvf archive.tar
++-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:16 selinux_only.txt
++  s: unconfined_u:object_r:user_tmp_t:s0
++  x: 36 security.selinux
++-rw-rwxr--+ praiskup/praiskup 0 2012-08-08 15:15 acls.txt
++  s: unconfined_u:object_r:user_tmp_t:s0
++  a: user::rw-,user:tester:rwx,group::rw-,mask::rwx,other::r--
++  x: 36 security.selinux
++  x: 44 system.posix_acl_access
++-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:15 xattrs.txt
++  s: unconfined_u:object_r:user_tmp_t:s0
++  x: 36 security.selinux
++  x: 12 user.xattr
++  x: 12 user.we_like_tar
++@end smallexample
++
++As is in @pxref{Option Summary} section described, tar by default stores all
++extended attributes that are available (not only 'user.*' domain).  It means
++that the SELinux context and POSIX ACLs (because they are implemented using the
++generic extended attributes on usual file system) may be stored twice sometimes
++-- firstly in "raw" file system binary format and secondly in more portable way
++-- using appropriate system calls (invoked by @command{tar} options
++@option{--selinux} and @option{--acls}).
++
+ @node extract
+ @section How to Extract Members from an Archive
+ @cindex Extraction
+@@ -2371,6 +2484,10 @@ Normally when creating an archive, @command{tar} strips an initial
+ @samp{/} from member names.  This option disables that behavior.
+ @xref{absolute}.
+ 
++@opsummary{acls}
++@item --acls
++Causes @command{tar} to store/restore/list POSIX ACL's.  @xref{Attributes}.
++
+ @opsummary{after-date}
+ @item --after-date
+ 
+@@ -2919,6 +3036,11 @@ contents have changed (as opposed to just @option{--newer}, which will
+ also back up files for which any status information has
+ changed).  @xref{after}.
+ 
++@opsummary{no-acls}
++@item --no-acls
++Causes @command{tar} not to store, extract or list POSIX ACL's.
++@xref{Attributes}.
++
+ @opsummary{no-anchored}
+ @item --no-anchored
+ An exclude pattern can match any subsequence of the name's components.
+@@ -3002,11 +3124,20 @@ locations.  Usually @command{tar} determines automatically whether
+ the archive can be seeked or not.  Use this option to disable this
+ mechanism.
+ 
++@opsummary{no-selinux}
++@item --no-selinux
++Causes @command{tar} not to store, extract or list SELinux security context.
++@xref{Attributes}.
++
+ @opsummary{no-unquote}
+ @item --no-unquote
+ Treat all input file or member names literally, do not interpret
+ escape sequences.  @xref{input name quoting}.
+ 
++@opsummary{no-xattrs}
++@item --no-xattrs
++Causes @command{tar} not to store, extract or list xattrs.  @xref{Attributes}.
++
+ @opsummary{no-wildcards}
+ @item --no-wildcards
+ Do not use wildcards.
+@@ -3239,6 +3370,11 @@ in cases when such recognition fails.  It takes effect only if the
+ archive is open for reading (e.g. with @option{--list} or
+ @option{--extract} options).
+ 
++@opsummary{selinux}
++@item --selinux
++Causes @command{tar} to store, extract or list SELinux security context.
++@xref{Attributes}.
++
+ @opsummary{show-defaults}
+ @item --show-defaults
+ 
+@@ -3466,6 +3602,11 @@ Enable or disable warning messages identified by @var{keyword}.  The
+ messages are suppressed if @var{keyword} is prefixed with @samp{no-}.
+ @xref{warnings}.
+ 
++@opsummary{xattrs}
++@item --xattrs
++Causes @command{tar} to store, restore or list extended file attributes.  For
++more info see @xref{Attributes}.
++
+ @opsummary{wildcards}
+ @item --wildcards
+ Use wildcards when matching member names with patterns.
+@@ -4218,6 +4359,11 @@ tar (child): trying gzip
+ This means that @command{tar} first tried to decompress
+ @file{archive.Z} using @command{compress}, and, when that
+ failed, switched to @command{gzip}.
++@kwindex xattr-write
++@item xattr-write
++@samp{%s: Cannot set '%s' extended attribute for file '%s'}
++@*@samp{%s: Cannot set POSIX ACLs for file '%s'}
++@*@samp{%s: Cannot set SELinux context for file '%s'}
+ @end table
+ 
+ @subheading Keywords controlling incremental extraction:
+@@ -8770,6 +8916,8 @@ implementation able to read @samp{ustar} archives will be able to read
+ most @samp{posix} archives as well, with the only exception that any
+ additional information (such as long file names etc.) will in such
+ case be extracted as plain text files along with the files it refers to.
++This is the only format that can store ACLs, SELinux context and extended
++attributes.
+ 
+ This archive format will be the default format for future versions
+ of @GNUTAR{}.
+@@ -9412,6 +9560,135 @@ Same as both @option{--same-permissions} and @option{--same-order}.
+ 
+ This option is deprecated, and will be removed in @GNUTAR{} version 1.23.
+ 
++@opindex xattrs
++@item --xattrs
++This option causes @command{tar} to store, restore or list the extended file
++attributes (for information about extended attributes see @command{man(5)
++attr}).
++
++Note that all extended attributes are stored "as-is" (in file system binary
++format) and the resulting archive may be not fully portable.  See the
++@option{--selinux} and @option{--acls} options when you want to deal with these
++types of extended attributes in a better way.
++
++The @option{--xattrs} option implies the option @option{--format=posix} when
++tar is in @option{--create} operation mode.  It is the only one format which
++hase usable headers for storing additional file information like extended
++attributes are.
++
++By default, all extended attributes are stored into the archive.  The reason is
++that we want to make the backup process as complete as possible by default.  On
++the other hand, during extracting only the 'user.*' domain is extracted by
++default.  Anyway, this default behaviour may be easily modified by the
++@option{--xattrs-include} and @option{--xattrs-exclude} options.
++
++When you list an archive in verbose mode
++(@command{tar --xattrs --verbose -tf archive.tar}), tar shows the '*' character
++after the permissions string of concrete file ringht to tell you that at least
++one extended attribute is stored with corresponding file.
++
++Double verbose mode (@command{tar --xattrs -tvvf archive.tar}) prints the
++extended attribute length (in bytes) and its ASCII key (for printed examples
++@pxref{List Extended Attributes}).
++
++@option{--xattrs} option has no equivalent short option.
++
++Warnings which occur during impossible writing of extended attributes to
++a file system may be suppressed using the @option{--warning=no-xattr-write}
++option.
++
++@opindex no-xattrs
++@item --no-xattrs
++This option causes @command{tar} not to store/extract or list the current
++extended attributes.  This option does not affect options @option{--no-selinux}
++or @option{--no-acls}.
++
++The @option{--no-xattrs} option has no equivalent short option name.
++
++@opindex xattrs-include
++@opindex xattrs-exclude
++@item --xattrs-include=MASK
++@itemx --xattrs-exclude=MASK
++
++These options allows the xattr store/restore/list process to be more fine
++grained.  The default configuration is that @option{--create} mode handles all
++available extended attributes and the @option{--extract}/@option{--list} mode
++handles only 'user.*' domain.  These options may be used for editing of this
++default behaviour.
++
++@itemize @bullet
++@item
++Lets say we want to store all attributes except some "public restricted" domain
++(e.g.  'user.restricted.*' domain.  The correct way how to do it is:
++
++@command{tar --xattrs --xattrs-include='*' --xattrs-exclude='user.restricted.*'
++-cf archive.tar FILES}
++@item
++And, when we want to extract only some specific domain from an archive - we can
++use:
++
++@command{tar --xattrs --xattrs-include='security.capability' -xf archive.tar
++FILES}
++@end itemize
++
++Multiple passed include/exclude patterns are combined together.  The attribute
++is covered then only if (1) at least one of all include patterns matches its
++keyword and (2) no exclude pattern matches its keyword.
++
++When only include pattern is set - exclude pattern is left in default mode (and
++vice versa).
++
++@opindex selinux
++@item --selinux
++This option causes @command{tar} to store/extract/list the SELinux context
++information into/from an archive.  Command @command{tar} is able to show info
++whether the SELinux context is present in archived file using the verbose
++listing mode (@command{tar --selinux -tvf archive.tar}).  It shows the '.'
++character after permission string in that case.  Double-verbose listing mode
++(@command{tar -tvvf archive.tar}) then prints the full SELinux context to
++standard output, @pxref{List Extended Attributes} for printed example.
++
++This option implies the @option{--format=posix} when @command{tar} works in
++@option{--create} operation mode.
++
++Warnings complaining that SELinux context may not be written to a file system
++may be suppressed by the @option{--warning=no-xattr-write} option.
++
++The @option{--selinux} option has no equivalent short option name.
++
++@opindex no-selinux
++@item --no-selinux
++This option causes @command{tar} not to store the current SELinux security
++context information in the archive and not to extract any SELinux information in
++an archive.
++
++The @option{--no-selinux} option has no equivalent short option name.
++
++@opindex acls
++@item --acls
++This option causes @command{tar} to store the current POSIX access control lists
++into the archive or restore POSIX ACLs from an archive.  It also allows
++@command{tar} to show whether archived file contains ACLs when the verbose mode
++is active (@option{tar --acls -tvf} shows the symbol '+' after the permission
++characters in that case).  Double-verbose mode allows @command{tar} to list
++contained POSIX ACLs (@command{tar --acls -tvvf archive.tar}), for printed
++examples @pxref{List Extended Attributes}.
++
++This option implies the @option{--format=posix} when @command{tar} works in
++@option{--create} operation mode.
++
++Warnings complaining that POSIX ACLs may not be written to a file system may be
++suppressed by the @option{--warning=no-xattr-write} option.
++
++The @option{--acls} option has no equivalent short form.
++
++@opindex no-acls
++@item --no-acls
++This option causes @command{tar} not to store the current POSIX ACL into the
++archive and not to extract any POSIX ACL information from an archive.
++
++The @option{--no-acls} option has no equivalent short option name.
++
+ @end table
+ 
+ @node Portability
diff --git a/SOURCES/tar-1.26-dont-segfault-with-disabled-selinux.patch b/SOURCES/tar-1.26-dont-segfault-with-disabled-selinux.patch
new file mode 100644
index 0000000..701bd27
--- /dev/null
+++ b/SOURCES/tar-1.26-dont-segfault-with-disabled-selinux.patch
@@ -0,0 +1,32 @@
+From b6b3ed1fa4c6de12908a9f01d1689f156c3cd441 Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Wed, 1 Jul 2015 12:30:57 +0200
+Subject: [PATCH] selinux-h: avoid double free after *getfilecon()
+
+Originally reported by Ben Shelton on bug-tar:
+http://lists.gnu.org/archive/html/bug-tar/2015-04/msg00009.html
+
+* lib/getfilecon.c (map_to_failure): Set the already freed '*con'
+pointer to NULL.  Man getfilecon(3) says that any non-NULL '*con'
+parameter should be freed by freecon(3) (regardless the return
+value).
+---
+ ChangeLog        | 9 +++++++++
+ lib/getfilecon.c | 1 +
+ 2 files changed, 10 insertions(+)
+
+diff --git a/lib/getfilecon.c b/lib/getfilecon.c
+index 9ac69be..ef6adc8 100644
+--- a/gnu/getfilecon.c
++++ b/gnu/getfilecon.c
+@@ -57,6 +57,7 @@ map_to_failure (int ret, security_context_t *con)
+   if (ret == 10 && strcmp (*con, "unlabeled") == 0)
+     {
+       freecon (*con);
++      *con = NULL;
+       errno = ENODATA;
+       return -1;
+     }
+-- 
+2.7.4
+
diff --git a/SOURCES/tar-1.26-fix-symlink-eating-bug.patch b/SOURCES/tar-1.26-fix-symlink-eating-bug.patch
new file mode 100644
index 0000000..c9f8887
--- /dev/null
+++ b/SOURCES/tar-1.26-fix-symlink-eating-bug.patch
@@ -0,0 +1,91 @@
+diff --git a/gnu/stat-time.h b/gnu/stat-time.h
+index 1dc4098..7b8428e 100644
+--- a/gnu/stat-time.h
++++ b/gnu/stat-time.h
+@@ -144,7 +144,7 @@ get_stat_mtime (struct stat const *st)
+ }
+ 
+ /* Return *ST's birth time, if available; otherwise return a value
+-   with negative tv_nsec.  */
++   with tv_sec and tv_nsec both equal to -1.  */
+ static inline struct timespec
+ get_stat_birthtime (struct stat const *st)
+ {
+@@ -163,7 +163,7 @@ get_stat_birthtime (struct stat const *st)
+   t.tv_sec = st->st_ctime;
+   t.tv_nsec = 0;
+ #else
+-  /* Birth time is not supported.  Set tv_sec to avoid undefined behavior.  */
++  /* Birth time is not supported.  */
+   t.tv_sec = -1;
+   t.tv_nsec = -1;
+   /* Avoid a "parameter unused" warning.  */
+@@ -177,10 +177,12 @@ get_stat_birthtime (struct stat const *st)
+      using zero.  Attempt to work around this problem.  Alas, this can
+      report failure even for valid time stamps.  Also, NetBSD
+      sometimes returns junk in the birth time fields; work around this
+-     bug if it it is detected.  There's no need to detect negative
+-     tv_nsec junk as negative tv_nsec already indicates an error.  */
+-  if (t.tv_sec == 0 || 1000000000 <= t.tv_nsec)
+-    t.tv_nsec = -1;
++     bug if it is detected.  */
++  if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000))
++    {
++      t.tv_sec = -1;
++      t.tv_nsec = -1;
++    }
+ #endif
+ 
+   return t;
+diff --git a/src/extract.c b/src/extract.c
+index 340beea..3afb95d 100644
+--- a/src/extract.c
++++ b/src/extract.c
+@@ -119,12 +119,15 @@ struct delayed_link
+     /* The next delayed link in the list.  */
+     struct delayed_link *next;
+ 
+-    /* The device, inode number and ctime of the placeholder.  Use
+-       ctime, not mtime, to make false matches less likely if some
+-       other process removes the placeholder.  */
++    /* The device, inode number and birthtime of the placeholder.
++       birthtime.tv_nsec is negative if the birthtime is not available.
++       Don't use mtime as this would allow for false matches if some
++       other process removes the placeholder.  Don't use ctime as
++       this would cause race conditions and other screwups, e.g.,
++       when restoring hard-linked symlinks.  */
+     dev_t dev;
+     ino_t ino;
+-    struct timespec ctime;
++    struct timespec birthtime;
+ 
+     /* True if the link is symbolic.  */
+     bool is_symlink;
+@@ -1200,7 +1203,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
+       delayed_link_head = p;
+       p->dev = st.st_dev;
+       p->ino = st.st_ino;
+-      p->ctime = get_stat_ctime (&st);
++      p->birthtime = get_stat_birthtime (&st);
+       p->is_symlink = is_symlink;
+       if (is_symlink)
+ 	{
+@@ -1265,7 +1268,8 @@ extract_link (char *file_name, int typeflag)
+ 	      if (ds->change_dir == chdir_current
+ 		  && ds->dev == st1.st_dev
+ 		  && ds->ino == st1.st_ino
+-		  && timespec_cmp (ds->ctime, get_stat_ctime (&st1)) == 0)
++		  && (timespec_cmp (ds->birthtime, get_stat_birthtime (&st1))
++		      == 0))
+ 		{
+ 		  struct string_list *p =  xmalloc (offsetof (struct string_list, string)
+ 						    + strlen (file_name) + 1);
+@@ -1638,7 +1642,7 @@ apply_delayed_links (void)
+ 	  if (fstatat (chdir_fd, source, &st, AT_SYMLINK_NOFOLLOW) == 0
+ 	      && st.st_dev == ds->dev
+ 	      && st.st_ino == ds->ino
+-	      && timespec_cmp (get_stat_ctime (&st), ds->ctime) == 0)
++	      && timespec_cmp (get_stat_birthtime (&st), ds->birthtime) == 0)
+ 	    {
+ 	      /* Unlink the placeholder, then create a hard link if possible,
+ 		 a symbolic link otherwise.  */
diff --git a/SOURCES/tar-1.26-keep-directory-symlink-doc-and-test.patch b/SOURCES/tar-1.26-keep-directory-symlink-doc-and-test.patch
new file mode 100644
index 0000000..9f0d61f
--- /dev/null
+++ b/SOURCES/tar-1.26-keep-directory-symlink-doc-and-test.patch
@@ -0,0 +1,209 @@
+From 49b5cd11bc3d64b0316cfc5b7245d25e4f7f4fcd Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Thu, 19 Oct 2017 16:53:00 +0200
+Subject: [PATCH] test keep-directory-symlink
+
+Upstream commit:
+From d06126f814563b01e598b85a8cc233604a2948f2 Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Tue, 28 Feb 2017 09:55:09 +0100
+Subject: [PATCH] Test and document --keep-directory-symlink
+
+* doc/tar.1: Document the option.
+* tests/extrac20.at: New testcase.
+* tests/Makefile.am: Mention extrac20.
+* tests/testsuite.at: Likewise.
+---
+ tests/Makefile.am  |   1 +
+ tests/extrac20.at  | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ tests/testsuite.at |   2 +-
+ 3 files changed, 153 insertions(+), 1 deletion(-)
+ create mode 100644 tests/extrac20.at
+
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 094b71c..bd8d3e8 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -79,6 +79,7 @@ TESTSUITE_AT = \
+  extrac09.at\
+  extrac18.at\
+  extrac19.at\
++ extrac20.at\
+  extrac10.at\
+  extrac11.at\
+  extrac12.at\
+diff --git a/tests/extrac20.at b/tests/extrac20.at
+new file mode 100644
+index 0000000..dd9b00d
+--- /dev/null
++++ b/tests/extrac20.at
+@@ -0,0 +1,151 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright 2017 Free Software Foundation, Inc.
++
++# This file is part of GNU tar.
++
++# GNU tar 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.
++
++# GNU tar 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/>.
++
++AT_SETUP([keep-directory-symlink])
++AT_KEYWORDS([extrac20 extract old-files keep-old-files])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++
++for i in a b c
++do
++  dir=in$i
++  mkdir -p $dir/root/dir $dir/root/dirsymlink
++  touch $dir/root/dirsymlink/file$i
++  test $i != a && touch $dir/root/dirsymlink/file.conflict
++  tar cf archive$i.tar -C $dir root
++done
++
++prep()
++{
++  echo "== $1 =="
++  echo "== $1 ==" >&2
++  backup_dir=$1
++  dir=out
++  mkdir -p $dir/root/dir
++  ln -s dir $dir/root/dirsymlink
++  test $round = normal && cd $dir >/dev/null
++}
++
++clean()
++{
++  test $round = normal && cd .. >/dev/null
++  find $dir | sort
++  mv $dir $backup_dir
++}
++
++# Expand to '-f ../$1' or '-f $1 -C $dir' depending on $round variable
++file_spec()
++{
++  if test $round = normal
++  then
++    echo "-f ../$1"
++  else
++    echo "-f $1 -C $dir"
++  fi
++}
++
++for round in normal dir
++do
++  # Check that 'dirsymlink' replaces 'dir'
++  prep without_option_$round
++  tar -x `file_spec archivea.tar` || exit 1
++  tar -x `file_spec archiveb.tar` || exit 1
++  clean
++
++  # Keep directory symlink must keep root/dirsymlink
++  prep with_option_$round
++  tar -x --keep-directory-symlink `file_spec archivea.tar` || exit 1
++  tar -x --keep-directory-symlink `file_spec archiveb.tar` || exit 1
++  clean
++
++  prep collision_$round
++  tar -x --keep-directory-symlink `file_spec archivea.tar` --keep-old-files || exit 1
++  tar -x --keep-directory-symlink `file_spec archiveb.tar` --keep-old-files || exit 1
++  tar -x --keep-directory-symlink `file_spec archivec.tar` --keep-old-files && exit 1
++  clean
++done
++],
++[0],
++[== without_option_normal ==
++out
++out/root
++out/root/dir
++out/root/dirsymlink
++out/root/dirsymlink/file.conflict
++out/root/dirsymlink/filea
++out/root/dirsymlink/fileb
++== with_option_normal ==
++out
++out/root
++out/root/dir
++out/root/dir/file.conflict
++out/root/dir/filea
++out/root/dir/fileb
++out/root/dirsymlink
++== collision_normal ==
++out
++out/root
++out/root/dir
++out/root/dir/file.conflict
++out/root/dir/filea
++out/root/dir/fileb
++out/root/dir/filec
++out/root/dirsymlink
++== without_option_dir ==
++out
++out/root
++out/root/dir
++out/root/dirsymlink
++out/root/dirsymlink/file.conflict
++out/root/dirsymlink/filea
++out/root/dirsymlink/fileb
++== with_option_dir ==
++out
++out/root
++out/root/dir
++out/root/dir/file.conflict
++out/root/dir/filea
++out/root/dir/fileb
++out/root/dirsymlink
++== collision_dir ==
++out
++out/root
++out/root/dir
++out/root/dir/file.conflict
++out/root/dir/filea
++out/root/dir/fileb
++out/root/dir/filec
++out/root/dirsymlink
++],
++[== without_option_normal ==
++== with_option_normal ==
++== collision_normal ==
++tar: root/dirsymlink/file.conflict: Cannot open: File exists
++tar: Exiting with failure status due to previous errors
++== without_option_dir ==
++== with_option_dir ==
++== collision_dir ==
++tar: root/dirsymlink/file.conflict: Cannot open: File exists
++tar: Exiting with failure status due to previous errors
++])
++
++AT_CLEANUP
++
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index f7f00ee..b540948 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -234,9 +234,9 @@ m4_include([extrac14.at])
+ m4_include([extrac15.at])
+ m4_include([extrac16.at])
+ m4_include([extrac17.at])
+-
+ m4_include([extrac18.at])
+ m4_include([extrac19.at])
++m4_include([extrac20.at])
+ 
+ m4_include([label01.at])
+ m4_include([label02.at])
+-- 
+2.13.6
+
diff --git a/SOURCES/tar-1.26-keep-directory-symlink.patch b/SOURCES/tar-1.26-keep-directory-symlink.patch
new file mode 100644
index 0000000..63f4c77
--- /dev/null
+++ b/SOURCES/tar-1.26-keep-directory-symlink.patch
@@ -0,0 +1,170 @@
+From c4a4cafaa330793d776b001c272bf19869aac39c Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Mon, 23 Sep 2013 19:35:29 +0300
+Subject: [PATCH] Changes for compatibility with Slackware installation
+ scripts.
+
+* src/buffer.c (short_read): the "Record size" message
+is controlled by the WARN_RECORD_SIZE warning_option bit.
+* src/common.h (keep_directory_symlink_option): New global.
+(WARN_RECORD_SIZE): New constant.
+(WARN_VERBOSE_WARNINGS): Add WARN_RECORD_SIZE.
+* src/extract.c (extract_dir): If keep_directory_symlink_option is
+set, follow symlinks to directories.
+* src/suffix.c (compression_suffixes): Add support for txz
+suffix.
+* src/tar.c (KEEP_DIRECTORY_SYMLINK_OPTION): New constant.
+(options): New option --keep-directory-symlink.
+(parse_opt): Handle this option.
+* src/warning.c: Implement "record-size" warning control.
+
+* NEWS: Update.
+* doc/tar.texi: Document new features.
+---
+ NEWS          | 12 ++++++++++++
+ doc/tar.texi  | 15 +++++++++++++++
+ src/common.h  |  2 ++
+ src/extract.c | 19 +++++++++++++++++++
+ src/tar.c     |  8 ++++++++
+ 5 files changed, 56 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index 8f3c416..36a27da 100644
+--- a/NEWS
++++ b/NEWS
+@@ -6,6 +6,18 @@ Please send GNU tar bug reports to <bug-tar@gnu.org>
+ When creating a PAX-format archive, tar no longer arbitrarily restricts
+ the size of the representation of a sparse file to be less than 8 GiB.
+ 
++* New command line option --keep-directory-symlink
++
++By default, if when trying to extract a directory from the archive,
++tar discovers that the corresponding file name already exists and is a
++symbolic link, it first unlinks the entry, and then extracts the directory.
++
++This option disables this behavior and instructs tar to follow
++symlinks to directories when extracting from the archive.
++
++It is mainly intended to provide compatibility with the Slackware
++installation scripts.
++
+ 
+ version 1.26 - Sergey Poznyakoff, 2011-03-12
+ 
+diff --git a/doc/tar.texi b/doc/tar.texi
+index 6bd59c7..fb03b85 100644
+--- a/doc/tar.texi
++++ b/doc/tar.texi
+@@ -2923,6 +2923,21 @@ Specifies that @command{tar} should ask the user for confirmation before
+ performing potentially destructive options, such as overwriting files.
+ @xref{interactive}.
+ 
++@opsummary{--keep-directory-symlink}
++@item --keep-directory-symlink
++
++This option changes the behavior of tar when it encounters a symlink
++with the same name as the directory that it is about to extract.  By
++default, in this case tar would first remove the symlink and then
++proceed extracting the directory.
++
++The @option{--keep-directory-symlink} option disables this behavior
++and instructs tar to follow symlinks to directories when extracting
++from the archive.
++
++It is mainly intended to provide compatibility with the Slackware
++installation scripts.
++
+ @opsummary{keep-newer-files}
+ @item --keep-newer-files
+ 
+diff --git a/src/common.h b/src/common.h
+index 16ba401..274da01 100644
+--- a/src/common.h
++++ b/src/common.h
+@@ -192,6 +192,8 @@ enum old_files
+ };
+ GLOBAL enum old_files old_files_option;
+ 
++GLOBAL bool keep_directory_symlink_option;
++
+ /* Specified file name for incremental list.  */
+ GLOBAL const char *listed_incremental_option;
+ /* Incremental dump level */
+diff --git a/src/extract.c b/src/extract.c
+index 3afb95d..b622a2a 100644
+--- a/src/extract.c
++++ b/src/extract.c
+@@ -854,7 +854,21 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
+ }
+ 
+ 
++static bool
++is_directory_link (const char *file_name)
++{
++  struct stat st;
++  int e = errno;
++  int res;
+ 
++  res = (fstatat (chdir_fd, file_name, &st, AT_SYMLINK_NOFOLLOW) == 0 &&
++	 S_ISLNK (st.st_mode) &&
++	 fstatat (chdir_fd, file_name, &st, 0) == 0 &&
++	 S_ISDIR (st.st_mode));
++  errno = e;
++  return res;
++}
++
+ /* Extractor functions for various member types */
+ 
+ static int
+@@ -910,10 +924,15 @@ extract_dir (char *file_name, int typeflag)
+ 
+       if (errno == EEXIST
+ 	  && (interdir_made
++	      || keep_directory_symlink_option
+ 	      || old_files_option == DEFAULT_OLD_FILES
+ 	      || old_files_option == OVERWRITE_OLD_FILES))
+ 	{
+ 	  struct stat st;
++
++	  if (keep_directory_symlink_option && is_directory_link (file_name))
++	    return 0;
++
+ 	  if (deref_stat (file_name, &st) == 0)
+ 	    {
+ 	      current_mode = st.st_mode;
+diff --git a/src/tar.c b/src/tar.c
+index 18277e4..d62ca0e 100644
+--- a/src/tar.c
++++ b/src/tar.c
+@@ -290,6 +290,7 @@ enum
+   IGNORE_COMMAND_ERROR_OPTION,
+   IGNORE_FAILED_READ_OPTION,
+   INDEX_FILE_OPTION,
++  KEEP_DIRECTORY_SYMLINK_OPTION,
+   KEEP_NEWER_FILES_OPTION,
+   LEVEL_OPTION,
+   LZIP_OPTION,
+@@ -488,6 +489,9 @@ static struct argp_option options[] = {
+   {"overwrite-dir", OVERWRITE_DIR_OPTION, 0, 0,
+    N_("overwrite metadata of existing directories when extracting (default)"),
+    GRID+1 },
++  {"keep-directory-symlink", KEEP_DIRECTORY_SYMLINK_OPTION, 0, 0,
++   N_("preserve existing symlinks to directories when extracting"),
++   GRID+1 },
+ #undef GRID
+ 
+ #define GRID 40
+@@ -1878,6 +1882,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
+       ignore_failed_read_option = true;
+       break;
+ 
++    case KEEP_DIRECTORY_SYMLINK_OPTION:
++      keep_directory_symlink_option = true;
++      break;
++
+     case KEEP_NEWER_FILES_OPTION:
+       old_files_option = KEEP_NEWER_FILES;
+       break;
+-- 
+2.9.3
+
diff --git a/SOURCES/tar-1.26-large-sparse-file-listing.patch b/SOURCES/tar-1.26-large-sparse-file-listing.patch
new file mode 100644
index 0000000..c334250
--- /dev/null
+++ b/SOURCES/tar-1.26-large-sparse-file-listing.patch
@@ -0,0 +1,390 @@
+From 77cef4ee39ee083838e5cf2137b0f344b49afb6a Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Tue, 29 Jan 2013 10:39:30 +0100
+Subject: [PATCH 1/4] Fix bug in sparse file listing
+
+List posix archives containing sparse files >8GB correctly and do not fail.
+This fixes also bug in format of listing for sparse files >8GB - now the
+real size is printed instead of the effective one (this is not strictly
+posix format related).
+
+* src/list.c: Remove redundant assignment.
+* src/tar.h: Add new 'real_size' and 'real_size_set' fields in
+  tar_stat_info struct.
+* src/xheader.c: Correctly handle (especially sparse) file sizes directly in
+  xheader_decode().
+---
+ src/list.c    |  1 -
+ src/tar.h     |  4 ++++
+ src/xheader.c | 15 ++++++++++++++-
+ 3 files changed, 18 insertions(+), 2 deletions(-)
+
+diff --git a/src/list.c b/src/list.c
+index dd501a9..6db36d1 100644
+--- a/src/list.c
++++ b/src/list.c
+@@ -670,7 +670,6 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
+ 	}
+     }
+ 
+-  stat_info->archive_file_size = stat_info->stat.st_size;
+   xheader_decode (stat_info);
+ 
+   if (sparse_member_p (stat_info))
+diff --git a/src/tar.h b/src/tar.h
+index b181e58..690c146 100644
+--- a/src/tar.h
++++ b/src/tar.h
+@@ -327,6 +327,10 @@ struct tar_stat_info
+   size_t sparse_map_size;   /* Size of the sparse map */
+   struct sp_array *sparse_map;
+ 
++  off_t real_size;          /* The real size of sparse file */
++  int   real_size_set;      /* True when GNU.sparse.realsize is set in
++			       archived file */
++
+   size_t xattr_map_size;   /* Size of the xattr map */
+   struct xattr_array *xattr_map;
+ 
+diff --git a/src/xheader.c b/src/xheader.c
+index be793d4..708aece 100644
+--- a/src/xheader.c
++++ b/src/xheader.c
+@@ -764,6 +764,16 @@ xheader_decode (struct tar_stat_info *st)
+ 	continue;
+     }
+   run_override_list (keyword_override_list, st);
++
++  /* The archived (effective) file size is always set directly in tar header
++     field, possibly overridden by "size" extended header - in both cases,
++     result is now decoded in st->stat.st_size */
++  st->archive_file_size = st->stat.st_size;
++
++  /* The real file size (given by stat()) may be redefined for sparse
++     files in "GNU.sparse.realsize" extended header */
++  if (st->real_size_set)
++    st->stat.st_size = st->real_size;
+ }
+ 
+ static void
+@@ -1438,7 +1435,10 @@ sparse_size_decoder (struct tar_stat_info *st,
+ {
+   uintmax_t u;
+   if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
+-    st->stat.st_size = u;
++    {
++      st->real_size_set = 1;
++      st->real_size = u;
++    }
+ }
+ 
+ static void
+-- 
+2.13.5
+
+
+From 198d4621b2a367986c71cd2489c1465ec3be89dc Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org>
+Date: Fri, 7 Nov 2014 11:47:44 +0200
+Subject: [PATCH 2/4] Add testcase for the previous commit.
+
+* tests/sparse05.at: New file.
+* tests/Makefile.am: Add sparse05.at
+* tests/testsuite.at: Include sparse05.at
+---
+ tests/Makefile.am  |  1 +
+ tests/sparse05.at  | 46 ++++++++++++++++++++++++++++++++++++++++++++++
+ tests/testsuite.at |  1 +
+ 3 files changed, 48 insertions(+)
+ create mode 100644 tests/sparse05.at
+
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 8e1ef8d..094b71c 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -171,6 +171,7 @@ TESTSUITE_AT = \
+  sparse02.at\
+  sparse03.at\
+  sparse04.at\
++ sparse05.at\
+  sparsemv.at\
+  sparsemvp.at\
+  spmvp00.at\
+diff --git a/tests/sparse05.at b/tests/sparse05.at
+new file mode 100644
+index 0000000..72f3274
+--- /dev/null
++++ b/tests/sparse05.at
+@@ -0,0 +1,46 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright 2014 Free Software Foundation, Inc.
++
++# This file is part of GNU tar.
++
++# GNU tar 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.
++
++# GNU tar 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/>.
++
++AT_SETUP([listing sparse files bigger than 2^33 B])
++AT_KEYWORDS([sparse sparse05])
++
++# Description: If an archive in POSIX.1-2001 archive contained a sparse file
++# member whose real size (excluding zero blocks) is bigger than 2^33 bytes,
++# tar 1.28 would incorrectly list the real member size.
++# Reported by: Pavel Raiskup <praiskup@redhat.com>
++# References: <1359119879.15037.4.camel@raiskup>,
++#             http://lists.gnu.org/archive/html/bug-tar/2013-01/msg00001.html
++
++AT_TAR_CHECK([
++(echo 0 =2560
++for i in `seq 1 999`; do
++    echo 10M =2560
++done) | genfile --sparse --file BIGFILE --block-size 4K - || AT_SKIP_TEST
++tar -f - -c --sparse --posix BIGFILE | tar tvf - | awk '{ print $3, $(NF) }'
++],
++[0],
++[20961034240 BIGFILE
++],
++[],
++[],
++[],
++[pax])
++
++AT_CLEANUP
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index 3eb0eee..f7f00ee 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -308,6 +308,7 @@ m4_include([sparse01.at])
+ m4_include([sparse02.at])
+ m4_include([sparse03.at])
+ m4_include([sparse04.at])
++m4_include([sparse05.at])
+ m4_include([sparsemv.at])
+ m4_include([spmvp00.at])
+ m4_include([spmvp01.at])
+-- 
+2.13.5
+
+
+From 8a795036f08bca508c3f3425f41c566562573e5f Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org>
+Date: Fri, 7 Nov 2014 11:37:33 +0200
+Subject: [PATCH 3/4] genfile: improve sparse mode
+
+Paxutils: 45af1632aa64a5ba1b108e248920e67c180e8485
+
+* tests/genfile.c (generate_sparse_file): Handle '-' argument
+(read from stdin);
+If content strings starts with '=', treat it as fragment size and
+use default pattern to fill it.
+* doc/genfile.texi: Document changes to genfile.
+---
+ doc/genfile.texi | 31 +++++++++++++++-------
+ tests/genfile.c  | 79 +++++++++++++++++++++++++++++++++++++++++++++++++-------
+ 2 files changed, 91 insertions(+), 19 deletions(-)
+
+diff --git a/doc/genfile.texi b/doc/genfile.texi
+index b37e26e..b993b9b 100644
+--- a/doc/genfile.texi
++++ b/doc/genfile.texi
+@@ -124,9 +124,8 @@ the rest of the command line specifies a so-called @dfn{file map}.
+ descriptors}. Each descriptor is composed of two values: a number,
+ specifying fragment offset from the end of the previous fragment or,
+ for the very first fragment, from the beginning of the file, and
+-@dfn{contents string}, i.e., a string of characters, specifying the
+-pattern to fill the fragment with. File offset can be suffixed with
+-the following quantifiers:
++@dfn{contents string}, that specifies the pattern to fill the fragment
++with. File offset can be suffixed with the following quantifiers:
+ 
+ @table @samp
+ @item k
+@@ -140,17 +139,29 @@ The number is expressed in megabytes.
+ The number is expressed in gigabytes.
+ @end table
+ 
+-    For each letter in contents string @command{genfile} will generate
+-a @dfn{block} of data, filled with this letter and will write it to
+-the fragment. The size of block is given by @option{--block-size}
+-option. It defaults to 512. Thus, if the string consists of @var{n}
+-characters, the resulting file fragment will contain
+-@code{@var{n}*@var{block-size}} of data. 
++    Contents string can be either a fragment size or a pattern.
++Fragment size is a decimal number, prefixed with an equals sign.  It
++can be suffixed with a quantifier, as discussed above.  If fragment
++size is given, the fragment of that size will be filled with the
++currently selected pattern (@pxref{Generate Mode, --pattern}) and
++written to the file.  
+ 
+-    Last fragment descriptor can have only file offset part. In this
++    A pattern is a string of arbitrary ASCII characters.  For each
++of them, @command{genfile} will generate a @dfn{block} of data,
++filled with that character and will write it to the fragment. The size
++of block is given by @option{--block-size} option. It defaults to 512.
++Thus, if pattern consists of @var{n} characters, the resulting file
++fragment will contain @code{@var{n}*@var{block-size}} bytes of data.
++
++    The last fragment descriptor can have only file offset part. In this
+ case @command{genfile} will create a hole at the end of the file up to
+ the given offset.
+ 
++    A dash appearing as a fragment descriptor instructs
++@command{genfile} to read file map from the standard input.  Each line
++of input should consist of fragment offset and contents string,
++separated by any amount of whitespace.
++
+     For example, consider the following invocation:
+ 
+ @smallexample
+diff --git a/tests/genfile.c b/tests/genfile.c
+index fa480ef..d41336b 100644
+--- a/tests/genfile.c
++++ b/tests/genfile.c
+@@ -32,6 +32,7 @@
+ #include <inttostr.h>
+ #include <fcntl.h>
+ #include <sys/stat.h>
++#include <c-ctype.h>
+ #define obstack_chunk_alloc malloc
+ #define obstack_chunk_free free
+ #include <obstack.h>
+@@ -506,6 +507,53 @@ mksparse (int fd, off_t displ, char *marks)
+     }
+ }
+ 
++static int
++make_fragment (int fd, char *offstr, char *mapstr)
++{
++  int i;
++  off_t displ = get_size (offstr, 1);
++
++  file_length += displ;
++
++  if (!mapstr || !*mapstr)
++    {
++      mkhole (fd, displ);
++      return 1;
++    }
++  else if (*mapstr == '=')
++    {
++      off_t n = get_size (mapstr + 1, 1);
++
++      switch (pattern)
++	{
++	case DEFAULT_PATTERN:
++	  for (i = 0; i < block_size; i++)
++	    buffer[i] = i & 255;
++	  break;
++	  
++	case ZEROS_PATTERN:
++	  memset (buffer, 0, block_size);
++	  break;
++	}
++
++      if (lseek (fd, displ, SEEK_CUR) == -1)
++	error (EXIT_FAILURE, errno, "lseek");
++      
++      for (; n; n--)
++	{
++	  if (write (fd, buffer, block_size) != block_size)
++	    error (EXIT_FAILURE, errno, "write");
++	  file_length += block_size;
++	}
++    }
++  else
++    {
++      file_length += block_size * strlen (mapstr);
++      mksparse (fd, displ, mapstr);
++    }
++  return 0;
++}
++
+ static void
+ generate_sparse_file (int argc, char **argv)
+ {
+@@ -526,20 +574,33 @@ generate_sparse_file (int argc, char **argv)
+ 
+   file_length = 0;
+ 
+-  for (i = 0; i < argc; i += 2)
++  while (argc)
+     {
+-      off_t displ = get_size (argv[i], 1);
+-      file_length += displ;
++      if (argv[0][0] == '-' && argv[0][1] == 0)
++	{
++	  char buf[256];
++	  while (fgets (buf, sizeof (buf), stdin))
++	    {
++	      size_t n = strlen (buf);
+ 
+-      if (i == argc-1)
+-	{
+-	  mkhole (fd, displ);
+-	  break;
++	      while (n > 0 && c_isspace (buf[n-1]))
++		buf[--n] = 0;
++	      
++	      n = strcspn (buf, " \t");
++	      buf[n++] = 0;
++	      while (buf[n] && c_isblank (buf[n]))
++		++n;
++	      make_fragment (fd, buf, buf + n);
++	    }
++	  ++argv;
++	  --argc;
+ 	}
+       else
+ 	{
+-	  file_length += block_size * strlen (argv[i+1]);
+-	  mksparse (fd, displ, argv[i+1]);
++	  if (make_fragment (fd, argv[0], argv[1]))
++	    break;
++	  argc -= 2;
++	  argv += 2;
+ 	}
+     }
+ 
+-- 
+2.13.5
+
+
+From 29e35df407d6c7b1e1ff57f7ef2030a253132a8a Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Fri, 4 Dec 2015 19:36:14 +0100
+Subject: [PATCH 4/4] genfile: remove unused variable
+
+paxutils: 58b8ac114790e2de7992db1a387ec14238783f39
+
+* tests/genfile.c (generate_sparse_file): Remove unused 'i'.
+---
+ tests/genfile.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/tests/genfile.c b/tests/genfile.c
+index d41336b..4699d21 100644
+--- a/tests/genfile.c
++++ b/tests/genfile.c
+@@ -557,7 +557,6 @@ make_fragment (int fd, char *offstr, char *mapstr)
+ static void
+ generate_sparse_file (int argc, char **argv)
+ {
+-  int i;
+   int fd;
+   int flags = O_CREAT | O_RDWR | O_BINARY;
+ 
+-- 
+2.13.5
+
diff --git a/SOURCES/tar-1.26-non-deterministic-archive-detection.patch b/SOURCES/tar-1.26-non-deterministic-archive-detection.patch
new file mode 100644
index 0000000..1f57fe9
--- /dev/null
+++ b/SOURCES/tar-1.26-non-deterministic-archive-detection.patch
@@ -0,0 +1,78 @@
+
+From 1847ec67cec36a17354115374954fea211d1f0da Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Thu, 19 Feb 2015 17:00:58 +0200
+Subject: [PATCH] Improve compression format recognition
+
+Some comressed archives can pass the checksum test, which makes tar
+treat them as uncompressed archives.
+
+* src/buffer.c (check_compressed_archive): Test the checksum only
+if the block we read looks like a valid tar header (i.e. has
+a magic string).
+---
+ src/buffer.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/src/buffer.c b/src/buffer.c
+index a7d8971..1a96595 100644
+--- a/src/buffer.c
++++ b/src/buffer.c
+@@ -391,7 +391,10 @@ check_compressed_archive (bool *pshort)
+   /* Restore global values */
+   read_full_records = sfr;
+ 
+-  if (tar_checksum (record_start, true) == HEADER_SUCCESS)
++  if ((strcmp (record_start->header.magic, TMAGIC) == 0 ||
++       strcmp (record_start->buffer + offsetof (struct posix_header, magic),
++	       OLDGNU_MAGIC) == 0) &&
++      tar_checksum (record_start, true) == HEADER_SUCCESS)
+     /* Probably a valid header */
+     return ct_tar;
+ 
+-- 
+2.13.5
+
+
+
+From 1e8b786e651d174a5fc9bf63a08d00c2d592ee3e Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Thu, 30 Mar 2017 13:30:15 +0200
+Subject: [PATCH] Fix non-deterministic archive type detection
+
+Due to analysis of partly uninitialized read-ahead buffer
+(short_read call), we sometimes mistakenly classified very small
+compressed archives as non-compressed; which in turn caused
+extraction failure.
+
+* src/buffer.c (check_compressed_archive): Don't assume that
+archives smaller than BLOCKSIZE could be non-compressed, as tar
+header always has at least one block.
+---
+ src/buffer.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/src/buffer.c b/src/buffer.c
+index 57fe813..6f96c2f 100644
+--- a/src/buffer.c
++++ b/src/buffer.c
+@@ -402,10 +402,12 @@ check_compressed_archive (bool *pshort)
+   /* Restore global values */
+   read_full_records = sfr;
+ 
+-  if ((strcmp (record_start->header.magic, TMAGIC) == 0 ||
+-       strcmp (record_start->buffer + offsetof (struct posix_header, magic),
+-	       OLDGNU_MAGIC) == 0) &&
+-      tar_checksum (record_start, true) == HEADER_SUCCESS)
++  if (record_start != record_end /* no files smaller than BLOCKSIZE */
++      && (strcmp (record_start->header.magic, TMAGIC) == 0
++          || strcmp (record_start->buffer + offsetof (struct posix_header,
++                                                      magic),
++                     OLDGNU_MAGIC) == 0)
++      && tar_checksum (record_start, true) == HEADER_SUCCESS)
+     /* Probably a valid header */
+     return ct_tar;
+ 
+-- 
+2.13.5
+
diff --git a/SOURCES/tar-1.26-pax-big-sparse-files.patch b/SOURCES/tar-1.26-pax-big-sparse-files.patch
new file mode 100644
index 0000000..be72dfa
--- /dev/null
+++ b/SOURCES/tar-1.26-pax-big-sparse-files.patch
@@ -0,0 +1,66 @@
+diff --git a/NEWS b/NEWS
+index 8aeae33..8f3c416 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,10 +1,15 @@
+ GNU tar NEWS - User visible changes. 2012-11-19
+ Please send GNU tar bug reports to <bug-tar@gnu.org>
+ 
++** Sparse files with large data
++
++When creating a PAX-format archive, tar no longer arbitrarily restricts
++the size of the representation of a sparse file to be less than 8 GiB.
++
+ 
+ version 1.26 - Sergey Poznyakoff, 2011-03-12
+ 
+-* Bugfixes
++* Bug fixes
+ 
+ ** Fix the --verify option, which broke in version 1.24.
+ 
+diff --git a/src/sparse.c b/src/sparse.c
+index 4b2f982..cfd0c66 100644
+--- a/src/sparse.c
++++ b/src/sparse.c
+@@ -919,6 +919,18 @@ pax_sparse_member_p (struct tar_sparse_file *file)
+           || file->stat_info->sparse_major > 0;
+ }
+ 
++/* Start a header that uses the effective (shrunken) file size.  */
++static union block *
++pax_start_header (struct tar_stat_info *st)
++{
++  off_t realsize = st->stat.st_size;
++  union block *blk;
++  st->stat.st_size = st->archive_file_size;
++  blk = start_header (st);
++  st->stat.st_size = realsize;
++  return blk;
++}
++
+ static bool
+ pax_dump_header_0 (struct tar_sparse_file *file)
+ {
+@@ -968,9 +980,7 @@ pax_dump_header_0 (struct tar_sparse_file *file)
+ 	  return false;
+ 	}
+     }
+-  blk = start_header (file->stat_info);
+-  /* Store the effective (shrunken) file size */
+-  OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
++  blk = pax_start_header (file->stat_info);
+   finish_header (file->stat_info, blk, block_ordinal);
+   if (save_file_name)
+     {
+@@ -1035,9 +1045,7 @@ pax_dump_header_1 (struct tar_sparse_file *file)
+   if (strlen (file->stat_info->file_name) > NAME_FIELD_SIZE)
+     file->stat_info->file_name[NAME_FIELD_SIZE] = 0;
+ 
+-  blk = start_header (file->stat_info);
+-  /* Store the effective (shrunken) file size */
+-  OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
++  blk = pax_start_header (file->stat_info);
+   finish_header (file->stat_info, blk, block_ordinal);
+   free (file->stat_info->file_name);
+   file->stat_info->file_name = save_file_name;
diff --git a/SOURCES/tar-1.26-posix-biguid.patch b/SOURCES/tar-1.26-posix-biguid.patch
new file mode 100644
index 0000000..1578b7a
--- /dev/null
+++ b/SOURCES/tar-1.26-posix-biguid.patch
@@ -0,0 +1,15 @@
+diff --git a/src/create.c b/src/create.c
+index 25387a9..9a7a05a 100644
+--- a/src/create.c
++++ b/src/create.c
+@@ -514,8 +514,8 @@ start_private_header (const char *name, size_t size, time_t t)
+ 
+   TIME_TO_CHARS (t, header->header.mtime);
+   MODE_TO_CHARS (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, header->header.mode);
+-  UID_TO_CHARS (getuid (), header->header.uid);
+-  GID_TO_CHARS (getgid (), header->header.gid);
++  UID_TO_CHARS (0, header->header.uid);
++  GID_TO_CHARS (0, header->header.gid);
+   MAJOR_TO_CHARS (0, header->header.devmajor);
+   MINOR_TO_CHARS (0, header->header.devminor);
+   strncpy (header->header.magic, TMAGIC, TMAGLEN);
diff --git a/SOURCES/tar-1.26-restore-incremental-backups.patch b/SOURCES/tar-1.26-restore-incremental-backups.patch
new file mode 100644
index 0000000..8ff9bc2
--- /dev/null
+++ b/SOURCES/tar-1.26-restore-incremental-backups.patch
@@ -0,0 +1,250 @@
+diff -urN tar-1.26/src/common.h tar-1.26new/src/common.h
+--- tar-1.26/src/common.h	2017-01-24 09:43:08.638550577 +0100
++++ tar-1.26new/src/common.h	2017-01-23 10:58:19.675411746 +0100
+@@ -598,6 +598,7 @@
+ char *normalize_filename (const char *name);
+ void replace_prefix (char **pname, const char *samp, size_t slen,
+ 		     const char *repl, size_t rlen);
++char *tar_savedir (const char *name, int must_exist);
+ 
+ typedef struct namebuf *namebuf_t;
+ namebuf_t namebuf_create (const char *dir);
+diff -urN tar-1.26/src/incremen.c tar-1.26new/src/incremen.c
+--- tar-1.26/src/incremen.c	2011-02-16 23:12:16.000000000 +0100
++++ tar-1.26new/src/incremen.c	2017-01-23 10:58:19.676411754 +0100
+@@ -1580,7 +1580,7 @@
+   if (!is_dumpdir (&current_stat_info))
+     return false;
+ 
+-  current_dir = savedir (directory_name);
++  current_dir = tar_savedir (directory_name, 0);
+ 
+   if (!current_dir)
+     /* The directory doesn't exist now.  It'll be created.  In any
+diff -urN tar-1.26/src/misc.c tar-1.26new/src/misc.c
+--- tar-1.26/src/misc.c	2011-02-16 23:12:16.000000000 +0100
++++ tar-1.26new/src/misc.c	2017-01-23 10:58:19.677411762 +0100
+@@ -483,7 +483,7 @@
+ 
+ 	case RECURSIVE_REMOVE_OPTION:
+ 	  {
+-	    char *directory = savedir (file_name);
++	    char *directory = tar_savedir (file_name, 0);
+ 	    char const *entry;
+ 	    size_t entrylen;
+ 
+@@ -945,3 +945,31 @@
+   strcpy (buf->buffer + buf->dir_length, name);
+   return buf->buffer;
+ }
++
++/* Return the filenames in directory NAME, relative to the chdir_fd.
++   If the directory does not exist, report error if MUST_EXIST is
++   true.
++
++   Return NULL on errors.
++*/
++char *
++tar_savedir (const char *name, int must_exist)
++{
++  char *ret = NULL;
++  DIR *dir = NULL;
++  int fd = openat (chdir_fd, name, open_read_flags | O_DIRECTORY);
++  if (fd < 0)
++    {
++      if (!must_exist && errno == ENOENT)
++	return NULL;
++      open_error (name);
++    }
++  else if (! ((dir = fdopendir (fd))
++	      && (ret = streamsavedir (dir))))
++    savedir_error (name);
++
++  if (dir ? closedir (dir) != 0 : 0 <= fd && close (fd) != 0)
++    savedir_error (name);
++
++  return ret;
++}
+diff -urN tar-1.26/src/update.c tar-1.26new/src/update.c
+--- tar-1.26/src/update.c	2017-01-24 09:43:08.620550423 +0100
++++ tar-1.26new/src/update.c	2017-01-23 12:29:20.410943374 +0100
+@@ -144,16 +144,8 @@
+ 		  {
+ 		    if (S_ISDIR (s.st_mode))
+ 		      {
+-			char *p, *dirp;
+-			DIR *stream;
+-			int fd = openat (chdir_fd, name->name,
+-					 open_read_flags | O_DIRECTORY);
+-			if (fd < 0)
+-			  open_error (name->name);
+-			else if (! ((stream = fdopendir (fd))
+-				    && (dirp = streamsavedir (stream))))
+-			  savedir_error (name->name);
+-			else
++			char *p, *dirp = tar_savedir (name->name, 1);
++			if (dirp)
+ 			  {
+ 			    namebuf_t nbuf = namebuf_create (name->name);
+ 
+@@ -166,11 +158,6 @@
+ 
+ 			    remname (name);
+ 			  }
+-
+-			if (stream
+-			    ? closedir (stream) != 0
+-			    : 0 <= fd && close (fd) != 0)
+-			  savedir_error (name->name);
+ 		      }
+ 		    else if (tar_timespec_cmp (get_stat_mtime (&s),
+ 					       current_stat_info.mtime)
+diff -urN tar-1.26/tests/incr07.at tar-1.26new/tests/incr07.at
+--- tar-1.26/tests/incr07.at	1970-01-01 01:00:00.000000000 +0100
++++ tar-1.26new/tests/incr07.at	2017-01-24 09:39:34.305615960 +0100
+@@ -0,0 +1,112 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++# Test suite for GNU tar.
++# Copyright 2009, 2013 Free Software Foundation, Inc.
++#
++# GNU tar 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.
++#
++# GNU tar 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/>.
++
++AT_SETUP([incremental restores with -C])
++AT_KEYWORDS([incremental extract incr07])
++
++# Tar 1.26 had problems extracting from incremental restores when given
++# the -C option.  The code in incremen.c:try_purge_directory and
++# misc.c:remove_any_file was using savedir(), which ignored eventual changes
++# in the current working directory and caused the malfunctioning.
++#
++# The problem was reported by Piotr Rotter on 2013-03-22.
++#
++# This testcase is based on scripts provided by Piotr Rotter and Nathan
++# Stratton Treadway.
++#
++# References: <514C8F56.90900@active24.pl>,
++#             http://lists.gnu.org/archive/html/bug-tar/2013-03/msg00036.html, 
++#             <20130326181922.GZ3732@shire.ontko.com>,
++#             http://lists.gnu.org/archive/html/bug-tar/2013-03/msg00042.html,
++#             <20130327051828.GA3732@shire.ontko.com>,
++#             http://lists.gnu.org/archive/html/bug-tar/2013-03/msg00043.html,
++#             <20130327054957.GB3732@shire.ontko.com>,
++#             http://lists.gnu.org/archive/html/bug-tar/2013-03/msg00044.html
++
++AT_TAR_CHECK([
++mkdir dirA
++echo 'a' > dirA/a
++echo 'a' > dirA/b
++
++decho C0
++tar -g test.snar -vcf test.0.tar dirA
++
++echo 'a' > dirA/c
++decho C1
++tar -g test.snar -vcf test.1.tar dirA
++
++rm -f dirA/a
++decho C2
++tar -g test.snar -vcf test.2.tar dirA
++
++mkdir ext
++rm -rf dirA
++
++decho E0
++tar -g test.snar -vxf test.0.tar -C ext/
++decho E1
++tar -g test.snar -vxf test.1.tar -C ext/
++
++decho E2
++tar -g test.snar -vxf test.2.tar -C ext/
++
++mkdir ext/dirA/dirB
++touch ext/dirA/dirB/file
++
++decho E3
++tar -g test.snar -vxf test.2.tar -C ext/
++
++echo FIN
++test -d dirA && echo >&2 "toplevel dirA exists"
++exit 0
++],
++[0],
++[C0
++dirA/
++dirA/a
++dirA/b
++C1
++dirA/
++dirA/c
++C2
++dirA/
++E0
++dirA/
++dirA/a
++dirA/b
++E1
++dirA/
++dirA/c
++E2
++dirA/
++tar: Deleting `dirA/a'
++E3
++dirA/
++tar: Deleting `dirA/dirB'
++FIN
++],
++[C0
++tar: dirA: Directory is new
++C1
++C2
++E0
++E1
++E2
++E3
++],[],[],[gnu, oldgnu, posix])
++
++AT_CLEANUP
+diff -urN tar-1.26/tests/Makefile.am tar-1.26new/tests/Makefile.am
+--- tar-1.26/tests/Makefile.am	2017-01-24 09:43:08.656550731 +0100
++++ tar-1.26new/tests/Makefile.am	2017-01-23 10:58:19.678411770 +0100
+@@ -98,6 +98,7 @@
+  incr04.at\
+  incr05.at\
+  incr06.at\
++ incr07.at\
+  indexfile.at\
+  ignfail.at\
+  label01.at\
+diff -urN tar-1.26/tests/testsuite.at tar-1.26new/tests/testsuite.at
+--- tar-1.26/tests/testsuite.at	2017-01-24 09:43:08.656550731 +0100
++++ tar-1.26new/tests/testsuite.at	2017-01-23 10:58:19.678411770 +0100
+@@ -259,6 +259,7 @@
+ m4_include([incr04.at])
+ m4_include([incr05.at])
+ m4_include([incr06.at])
++m4_include([incr07.at])
+ 
+ m4_include([filerem01.at])
+ m4_include([filerem02.at])
+diff -urN tar-1.26/THANKS tar-1.26new/THANKS
+--- tar-1.26/THANKS	2017-01-24 09:43:08.636550560 +0100
++++ tar-1.26new/THANKS	2017-01-23 10:58:19.674411738 +0100
+@@ -397,6 +397,7 @@
+ Philippe Defert		defert@cern.ch
+ Piercarlo Grandi	piercarl@sabi.demon.co.uk
+ Pierce Cantrell		cantrell@ee.tamu.edu
++Piotr Rotter 		piotr.rotter@active24.pl
+ R. Kent Dybvig		dyb@cadence.bloomington.in.us
+ R. Scott Butler		butler@prism.es.dupont.com
+ Rainer Orth		ro@TechFak.Uni-Bielefeld.DE
diff --git a/SOURCES/tar-1.26-selinux-gnulib.patch b/SOURCES/tar-1.26-selinux-gnulib.patch
new file mode 100644
index 0000000..78783a9
--- /dev/null
+++ b/SOURCES/tar-1.26-selinux-gnulib.patch
@@ -0,0 +1,3603 @@
+From f733da5249b0b119cb551c73b322439bcbbc013a Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Tue, 19 Feb 2013 10:41:10 +0100
+Subject: [PATCH] x
+
+---
+ build-aux/snippet/unused-parameter.h |  38 ++
+ gnu/Makefile.am                      |  93 +++-
+ gnu/acl-internal.h                   | 267 ++++++++++
+ gnu/acl.h                            |  30 ++
+ gnu/acl_entries.c                    |  77 +++
+ gnu/copy-acl.c                       | 620 +++++++++++++++++++++++
+ gnu/file-has-acl.c                   | 920 +++++++++++++++++++++++++++++++++++
+ gnu/getfilecon.c                     |  88 ++++
+ gnu/se-context.in.h                  |  30 ++
+ gnu/se-selinux.in.h                  |  99 ++++
+ gnu/selinux-at.c                     |  74 +++
+ gnu/selinux-at.h                     |  54 ++
+ gnu/set-mode-acl.c                   | 699 ++++++++++++++++++++++++++
+ m4/acl.m4                            | 165 +++++++
+ m4/gnulib-comp.m4                    |  27 +-
+ m4/selinux-context-h.m4              |  22 +
+ m4/selinux-selinux-h.m4              |  69 +++
+ 17 files changed, 3365 insertions(+), 7 deletions(-)
+ create mode 100644 build-aux/snippet/unused-parameter.h
+ create mode 100644 gnu/acl-internal.h
+ create mode 100644 gnu/acl.h
+ create mode 100644 gnu/acl_entries.c
+ create mode 100644 gnu/copy-acl.c
+ create mode 100644 gnu/file-has-acl.c
+ create mode 100644 gnu/getfilecon.c
+ create mode 100644 gnu/se-context.in.h
+ create mode 100644 gnu/se-selinux.in.h
+ create mode 100644 gnu/selinux-at.c
+ create mode 100644 gnu/selinux-at.h
+ create mode 100644 gnu/set-mode-acl.c
+ create mode 100644 m4/acl.m4
+ create mode 100644 m4/selinux-context-h.m4
+ create mode 100644 m4/selinux-selinux-h.m4
+
+diff --git a/build-aux/snippet/unused-parameter.h b/build-aux/snippet/unused-parameter.h
+new file mode 100644
+index 0000000..6b60482
+--- /dev/null
++++ b/build-aux/snippet/unused-parameter.h
+@@ -0,0 +1,38 @@
++/* -*- buffer-read-only: t -*- vi: set ro: */
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++/* A C macro for declaring that specific function parameters are not used.
++   Copyright (C) 2008-2012 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/>.  */
++
++/* _GL_UNUSED_PARAMETER is a marker that can be appended to function parameter
++   declarations for parameters that are not used.  This helps to reduce
++   warnings, such as from GCC -Wunused-parameter.  The syntax is as follows:
++       type param _GL_UNUSED_PARAMETER
++   or more generally
++       param_decl _GL_UNUSED_PARAMETER
++   For example:
++       int param _GL_UNUSED_PARAMETER
++       int *(*param)(void) _GL_UNUSED_PARAMETER
++   Other possible, but obscure and discouraged syntaxes:
++       int _GL_UNUSED_PARAMETER *(*param)(void)
++       _GL_UNUSED_PARAMETER int *(*param)(void)
++ */
++#ifndef _GL_UNUSED_PARAMETER
++# if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
++#  define _GL_UNUSED_PARAMETER __attribute__ ((__unused__))
++# else
++#  define _GL_UNUSED_PARAMETER
++# endif
++#endif
+diff --git a/gnu/Makefile.am b/gnu/Makefile.am
+index 06eb0d9..77d75d2 100644
+--- a/gnu/Makefile.am
++++ b/gnu/Makefile.am
+@@ -1,6 +1,3 @@
+-# -*- buffer-read-only: t -*- vi: set ro:
+-# DO NOT EDIT! GENERATED AUTOMATICALLY!
+-## DO NOT EDIT! GENERATED AUTOMATICALLY!
+ ## Process this file with automake to produce Makefile.in.
+ # Copyright (C) 2002-2011 Free Software Foundation, Inc.
+ #
+@@ -38,8 +35,17 @@ libgnu_a_LIBADD = $(gl_LIBOBJS)
+ libgnu_a_DEPENDENCIES = $(gl_LIBOBJS)
+ EXTRA_libgnu_a_SOURCES =
+ 
+-## begin gnulib module alloca
++## begin gnulib module acl
++
++libgnu_a_SOURCES += set-mode-acl.c copy-acl.c file-has-acl.c
++
++EXTRA_DIST += acl-internal.h acl.h acl_entries.c
+ 
++EXTRA_libgnu_a_SOURCES += acl_entries.c
++
++## end   gnulib module acl
++
++## begin gnulib module alloca
+ 
+ EXTRA_DIST += alloca.c
+ 
+@@ -179,6 +185,31 @@ EXTRA_DIST += $(top_srcdir)/build-aux/c++defs.h
+ 
+ ## end   gnulib module c++defs
+ 
++## begin gnulib module snippet/unused-parameter
++
++# The BUILT_SOURCES created by this Makefile snippet are not used via #include
++# statements but through direct file reference. Therefore this snippet must be
++# present in all Makefile.am that need it. This is ensured by the applicability
++# 'all' defined above.
++
++BUILT_SOURCES += unused-parameter.h
++# The unused-parameter.h that gets inserted into generated .h files is the same
++# as build-aux/snippet/unused-parameter.h, except that it has the copyright
++# header cut off.
++unused-parameter.h: $(top_srcdir)/build-aux/snippet/unused-parameter.h
++	$(AM_V_GEN)rm -f $@-t $@ && \
++	sed -n -e '/GL_UNUSED_PARAMETER/,$$p' \
++	  < $(top_srcdir)/build-aux/snippet/unused-parameter.h \
++	  > $@-t && \
++	mv $@-t $@
++MOSTLYCLEANFILES += unused-parameter.h unused-parameter.h-t
++
++UNUSED_PARAMETER_H=unused-parameter.h
++
++EXTRA_DIST += $(top_srcdir)/build-aux/snippet/unused-parameter.h
++
++## end   gnulib module snippet/unused-parameter
++
+ ## begin gnulib module c-ctype
+ 
+ libgnu_a_SOURCES += c-ctype.h c-ctype.c
+@@ -1386,6 +1417,60 @@ EXTRA_libgnu_a_SOURCES += savedir.c
+ 
+ ## end   gnulib module savedir
+ 
++## begin gnulib module selinux-at
++
++
++EXTRA_DIST += at-func.c selinux-at.c selinux-at.h
++
++EXTRA_libgnu_a_SOURCES += at-func.c selinux-at.c
++
++## end   gnulib module selinux-at
++
++## begin gnulib module selinux-h
++
++libgnu_a_SOURCES += se-context.in.h se-selinux.in.h
++
++BUILT_SOURCES += selinux/selinux.h
++selinux/selinux.h: se-selinux.in.h $(top_builddir)/config.status $(UNUSED_PARAMETER_H)
++	$(AM_V_at)$(MKDIR_P) selinux
++	$(AM_V_GEN)rm -f $@-t $@ && \
++	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
++	  sed -e 's|@''GUARD_PREFIX''@|GL|g' \
++	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
++	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
++	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
++	      -e 's|@''NEXT_SELINUX_SELINUX_H''@|$(NEXT_SELINUX_SELINUX_H)|g' \
++	      -e '/definition of _GL_UNUSED_PARAMETER/r $(UNUSED_PARAMETER_H)' \
++	      < $(srcdir)/se-selinux.in.h; \
++	} > $@-t && \
++	chmod a-x $@-t && \
++	mv $@-t $@
++MOSTLYCLEANFILES += selinux/selinux.h selinux/selinux.h-t
++
++BUILT_SOURCES += $(SELINUX_CONTEXT_H)
++if GL_GENERATE_SELINUX_CONTEXT_H
++selinux/context.h: se-context.in.h $(top_builddir)/config.status $(UNUSED_PARAMETER_H)
++	$(AM_V_at)$(MKDIR_P) selinux
++	$(AM_V_GEN)rm -f $@-t $@ && \
++	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
++	  sed -e '/definition of _GL_UNUSED_PARAMETER/r $(UNUSED_PARAMETER_H)' \
++	      < $(srcdir)/se-context.in.h; \
++	} > $@-t && \
++	chmod a-x $@-t && \
++	mv $@-t $@
++else
++selinux/context.h: $(top_builddir)/config.status
++	rm -f $@
++endif
++MOSTLYCLEANFILES += selinux/context.h selinux/context.h-t
++MOSTLYCLEANDIRS += selinux
++
++EXTRA_DIST += getfilecon.c
++
++EXTRA_libgnu_a_SOURCES += getfilecon.c
++
++## end   gnulib module selinux-h
++
+ ## begin gnulib module setenv
+ 
+ 
+diff --git a/gnu/acl-internal.h b/gnu/acl-internal.h
+new file mode 100644
+index 0000000..07309e0
+--- /dev/null
++++ b/gnu/acl-internal.h
+@@ -0,0 +1,267 @@
++/* -*- buffer-read-only: t -*- vi: set ro: */
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++/* Internal implementation of access control lists.
++
++   Copyright (C) 2002-2003, 2005-2012 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, Andreas Grünbacher, and Bruno Haible.  */
++
++#include "acl.h"
++
++#include <stdbool.h>
++#include <stdlib.h>
++
++/* All systems define the ACL related API in <sys/acl.h>.  */
++#if HAVE_SYS_ACL_H
++# include <sys/acl.h>
++#endif
++#if defined HAVE_FACL && ! defined GETACLCNT && defined ACL_CNT
++# define GETACLCNT ACL_CNT
++#endif
++
++/* On Linux, additional ACL related API is available in <acl/libacl.h>.  */
++#ifdef HAVE_ACL_LIBACL_H
++# include <acl/libacl.h>
++#endif
++
++/* On HP-UX >= 11.11, additional ACL API is available in <aclv.h>.  */
++#if HAVE_ACLV_H
++# include <sys/types.h>
++# include <aclv.h>
++/* HP-UX 11.11 lacks these declarations.  */
++extern int acl (char *, int, int, struct acl *);
++extern int aclsort (int, int, struct acl *);
++#endif
++
++#include "error.h"
++#include "quote.h"
++
++#include <errno.h>
++#ifndef ENOSYS
++# define ENOSYS (-1)
++#endif
++#ifndef ENOTSUP
++# define ENOTSUP (-1)
++#endif
++
++#include <limits.h>
++#ifndef MIN
++# define MIN(a,b) ((a) < (b) ? (a) : (b))
++#endif
++
++#ifndef SIZE_MAX
++# define SIZE_MAX ((size_t) -1)
++#endif
++
++#ifndef HAVE_FCHMOD
++# define HAVE_FCHMOD false
++# define fchmod(fd, mode) (-1)
++#endif
++
++/* Recognize some common errors such as from an NFS mount that does
++   not support ACLs, even when local drives do.  */
++#if defined __APPLE__ && defined __MACH__ /* Mac OS X */
++# define ACL_NOT_WELL_SUPPORTED(Err) \
++     ((Err) == ENOTSUP || (Err) == ENOSYS || (Err) == EINVAL || (Err) == EBUSY || (Err) == ENOENT)
++#elif defined EOPNOTSUPP /* Tru64 NFS */
++# define ACL_NOT_WELL_SUPPORTED(Err) \
++     ((Err) == ENOTSUP || (Err) == ENOSYS || (Err) == EINVAL || (Err) == EBUSY || (Err) == EOPNOTSUPP)
++#else
++# define ACL_NOT_WELL_SUPPORTED(Err) \
++     ((Err) == ENOTSUP || (Err) == ENOSYS || (Err) == EINVAL || (Err) == EBUSY)
++#endif
++
++#if USE_ACL
++
++# if HAVE_ACL_GET_FILE
++/* POSIX 1003.1e (draft 17 -- abandoned) specific version.  */
++/* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
++
++#  ifndef MIN_ACL_ENTRIES
++#   define MIN_ACL_ENTRIES 4
++#  endif
++
++/* POSIX 1003.1e (draft 17) */
++#  ifdef HAVE_ACL_GET_FD
++/* Most platforms have a 1-argument acl_get_fd, only OSF/1 has a 2-argument
++   macro(!).  */
++#   if HAVE_ACL_FREE_TEXT /* OSF/1 */
++static inline acl_t
++rpl_acl_get_fd (int fd)
++{
++  return acl_get_fd (fd, ACL_TYPE_ACCESS);
++}
++#    undef acl_get_fd
++#    define acl_get_fd rpl_acl_get_fd
++#   endif
++#  else
++#   define HAVE_ACL_GET_FD false
++#   undef acl_get_fd
++#   define acl_get_fd(fd) (NULL)
++#  endif
++
++/* POSIX 1003.1e (draft 17) */
++#  ifdef HAVE_ACL_SET_FD
++/* Most platforms have a 2-argument acl_set_fd, only OSF/1 has a 3-argument
++   macro(!).  */
++#   if HAVE_ACL_FREE_TEXT /* OSF/1 */
++static inline int
++rpl_acl_set_fd (int fd, acl_t acl)
++{
++  return acl_set_fd (fd, ACL_TYPE_ACCESS, acl);
++}
++#    undef acl_set_fd
++#    define acl_set_fd rpl_acl_set_fd
++#   endif
++#  else
++#   define HAVE_ACL_SET_FD false
++#   undef acl_set_fd
++#   define acl_set_fd(fd, acl) (-1)
++#  endif
++
++/* POSIX 1003.1e (draft 13) */
++#  if ! HAVE_ACL_FREE_TEXT
++#   define acl_free_text(buf) acl_free (buf)
++#  endif
++
++/* Linux-specific */
++#  ifndef HAVE_ACL_EXTENDED_FILE
++#   define HAVE_ACL_EXTENDED_FILE false
++#   define acl_extended_file(name) (-1)
++#  endif
++
++/* Linux-specific */
++#  ifndef HAVE_ACL_FROM_MODE
++#   define HAVE_ACL_FROM_MODE false
++#   define acl_from_mode(mode) (NULL)
++#  endif
++
++/* Set to 1 if a file's mode is implicit by the ACL.
++   Set to 0 if a file's mode is stored independently from the ACL.  */
++#  if (HAVE_ACL_COPY_EXT_NATIVE && HAVE_ACL_CREATE_ENTRY_NP) || defined __sgi /* Mac OS X, IRIX */
++#   define MODE_INSIDE_ACL 0
++#  else
++#   define MODE_INSIDE_ACL 1
++#  endif
++
++/* Return the number of entries in ACL.
++   Return -1 and set errno upon failure to determine it.  */
++/* Define a replacement for acl_entries if needed. (Only Linux has it.)  */
++#  if !HAVE_ACL_ENTRIES
++#   define acl_entries rpl_acl_entries
++extern int acl_entries (acl_t);
++#  endif
++
++#  if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
++/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
++   Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial.  */
++extern int acl_extended_nontrivial (acl_t);
++#  else
++/* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS.
++   Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.
++   Return -1 and set errno upon failure to determine it.  */
++extern int acl_access_nontrivial (acl_t);
++#  endif
++
++# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
++
++/* Set to 1 if a file's mode is implicit by the ACL.
++   Set to 0 if a file's mode is stored independently from the ACL.  */
++#  if defined __CYGWIN__ /* Cygwin */
++#   define MODE_INSIDE_ACL 0
++#  else /* Solaris */
++#   define MODE_INSIDE_ACL 1
++#  endif
++
++/* Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++extern int acl_nontrivial (int count, aclent_t *entries);
++
++#  ifdef ACE_GETACL /* Solaris 10 */
++
++/* Test an ACL retrieved with ACE_GETACL.
++   Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++extern int acl_ace_nontrivial (int count, ace_t *entries);
++
++/* Definitions for when the built executable is executed on Solaris 10
++   (newer version) or Solaris 11.  */
++/* For a_type.  */
++#   define OLD_ALLOW 0
++#   define OLD_DENY  1
++#   define NEW_ACE_ACCESS_ALLOWED_ACE_TYPE 0 /* replaces ALLOW */
++#   define NEW_ACE_ACCESS_DENIED_ACE_TYPE  1 /* replaces DENY */
++/* For a_flags.  */
++#   define OLD_ACE_OWNER            0x0100
++#   define OLD_ACE_GROUP            0x0200
++#   define OLD_ACE_OTHER            0x0400
++#   define NEW_ACE_OWNER            0x1000
++#   define NEW_ACE_GROUP            0x2000
++#   define NEW_ACE_IDENTIFIER_GROUP 0x0040
++#   define NEW_ACE_EVERYONE         0x4000
++/* For a_access_mask.  */
++#   define NEW_ACE_READ_DATA         0x001 /* corresponds to 'r' */
++#   define NEW_ACE_WRITE_DATA        0x002 /* corresponds to 'w' */
++#   define NEW_ACE_APPEND_DATA       0x004
++#   define NEW_ACE_READ_NAMED_ATTRS  0x008
++#   define NEW_ACE_WRITE_NAMED_ATTRS 0x010
++#   define NEW_ACE_EXECUTE           0x020
++#   define NEW_ACE_DELETE_CHILD      0x040
++#   define NEW_ACE_READ_ATTRIBUTES   0x080
++#   define NEW_ACE_WRITE_ATTRIBUTES  0x100
++#   define NEW_ACE_DELETE          0x10000
++#   define NEW_ACE_READ_ACL        0x20000
++#   define NEW_ACE_WRITE_ACL       0x40000
++#   define NEW_ACE_WRITE_OWNER     0x80000
++#   define NEW_ACE_SYNCHRONIZE    0x100000
++
++#  endif
++
++# elif HAVE_GETACL /* HP-UX */
++
++/* Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++extern int acl_nontrivial (int count, struct acl_entry *entries, struct stat *sb);
++
++#  if HAVE_ACLV_H /* HP-UX >= 11.11 */
++
++/* Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++extern int aclv_nontrivial (int count, struct acl *entries);
++
++#  endif
++
++# elif HAVE_ACLX_GET && 0 /* AIX */
++
++/* TODO */
++
++# elif HAVE_STATACL /* older AIX */
++
++/* Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++extern int acl_nontrivial (struct acl *a);
++
++# elif HAVE_ACLSORT /* NonStop Kernel */
++
++/* Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++extern int acl_nontrivial (int count, struct acl *entries);
++
++# endif
++
++#endif
+diff --git a/gnu/acl.h b/gnu/acl.h
+new file mode 100644
+index 0000000..d808a90
+--- /dev/null
++++ b/gnu/acl.h
+@@ -0,0 +1,30 @@
++/* -*- buffer-read-only: t -*- vi: set ro: */
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++/* acl.c - access control lists
++
++   Copyright (C) 2002, 2008-2012 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.  */
++
++#include <sys/types.h>
++#include <sys/stat.h>
++
++int file_has_acl (char const *, struct stat const *);
++int qset_acl (char const *, int, mode_t);
++int set_acl (char const *, int, mode_t);
++int qcopy_acl (char const *, int, char const *, int, mode_t);
++int copy_acl (char const *, int, char const *, int, mode_t);
++int chmod_or_fchmod (char const *, int, mode_t);
+diff --git a/gnu/acl_entries.c b/gnu/acl_entries.c
+new file mode 100644
+index 0000000..11adc22
+--- /dev/null
++++ b/gnu/acl_entries.c
+@@ -0,0 +1,77 @@
++/* -*- buffer-read-only: t -*- vi: set ro: */
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++/* Return the number of entries in an ACL.
++
++   Copyright (C) 2002-2003, 2005-2012 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 and Andreas Gruenbacher.  */
++
++#include <config.h>
++
++#include "acl-internal.h"
++
++/* This file assumes POSIX-draft like ACLs
++   (Linux, FreeBSD, Mac OS X, IRIX, Tru64).  */
++
++/* Return the number of entries in ACL.
++   Return -1 and set errno upon failure to determine it.  */
++
++int
++acl_entries (acl_t acl)
++{
++  int count = 0;
++
++  if (acl != NULL)
++    {
++#if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD, Mac OS X */
++# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
++      /* acl_get_entry returns 0 when it successfully fetches an entry,
++         and -1/EINVAL at the end.  */
++      acl_entry_t ace;
++      int got_one;
++
++      for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace);
++           got_one >= 0;
++           got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
++        count++;
++# else /* Linux, FreeBSD */
++      /* acl_get_entry returns 1 when it successfully fetches an entry,
++         and 0 at the end.  */
++      acl_entry_t ace;
++      int got_one;
++
++      for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace);
++           got_one > 0;
++           got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
++        count++;
++      if (got_one < 0)
++        return -1;
++# endif
++#else /* IRIX, Tru64 */
++# if HAVE_ACL_TO_SHORT_TEXT /* IRIX */
++      /* Don't use acl_get_entry: it is undocumented.  */
++      count = acl->acl_cnt;
++# endif
++# if HAVE_ACL_FREE_TEXT /* Tru64 */
++      /* Don't use acl_get_entry: it takes only one argument and does not
++         work.  */
++      count = acl->acl_num;
++# endif
++#endif
++    }
++
++  return count;
++}
+diff --git a/gnu/copy-acl.c b/gnu/copy-acl.c
+new file mode 100644
+index 0000000..a4d82f7
+--- /dev/null
++++ b/gnu/copy-acl.c
+@@ -0,0 +1,620 @@
++/* -*- buffer-read-only: t -*- vi: set ro: */
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++/* copy-acl.c - copy access control list from one file to another file
++
++   Copyright (C) 2002-2003, 2005-2012 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, Andreas Grünbacher, and Bruno Haible.  */
++
++#include <config.h>
++
++#include "acl.h"
++
++#include "acl-internal.h"
++
++#include "gettext.h"
++#define _(msgid) gettext (msgid)
++
++
++/* Copy access control lists from one file to another. If SOURCE_DESC is
++   a valid file descriptor, use file descriptor operations, else use
++   filename based operations on SRC_NAME. Likewise for DEST_DESC and
++   DST_NAME.
++   If access control lists are not available, fchmod the target file to
++   MODE.  Also sets the non-permission bits of the destination file
++   (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set.
++   Return 0 if successful.
++   Return -2 and set errno for an error relating to the source file.
++   Return -1 and set errno for an error relating to the destination file.  */
++
++int
++qcopy_acl (const char *src_name, int source_desc, const char *dst_name,
++           int dest_desc, mode_t mode)
++{
++#if USE_ACL && HAVE_ACL_GET_FILE
++  /* POSIX 1003.1e (draft 17 -- abandoned) specific version.  */
++  /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
++# if !HAVE_ACL_TYPE_EXTENDED
++  /* Linux, FreeBSD, IRIX, Tru64 */
++
++  acl_t acl;
++  int ret;
++
++  if (HAVE_ACL_GET_FD && source_desc != -1)
++    acl = acl_get_fd (source_desc);
++  else
++    acl = acl_get_file (src_name, ACL_TYPE_ACCESS);
++  if (acl == NULL)
++    {
++      if (ACL_NOT_WELL_SUPPORTED (errno))
++        return qset_acl (dst_name, dest_desc, mode);
++      else
++        return -2;
++    }
++
++  if (HAVE_ACL_SET_FD && dest_desc != -1)
++    ret = acl_set_fd (dest_desc, acl);
++  else
++    ret = acl_set_file (dst_name, ACL_TYPE_ACCESS, acl);
++  if (ret != 0)
++    {
++      int saved_errno = errno;
++
++      if (ACL_NOT_WELL_SUPPORTED (errno) && !acl_access_nontrivial (acl))
++        {
++          acl_free (acl);
++          return chmod_or_fchmod (dst_name, dest_desc, mode);
++        }
++      else
++        {
++          acl_free (acl);
++          chmod_or_fchmod (dst_name, dest_desc, mode);
++          errno = saved_errno;
++          return -1;
++        }
++    }
++  else
++    acl_free (acl);
++
++  if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX)))
++    {
++      /* We did not call chmod so far, and either the mode and the ACL are
++         separate or special bits are to be set which don't fit into ACLs.  */
++
++      if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
++        return -1;
++    }
++
++  if (S_ISDIR (mode))
++    {
++      acl = acl_get_file (src_name, ACL_TYPE_DEFAULT);
++      if (acl == NULL)
++        return -2;
++
++      if (acl_set_file (dst_name, ACL_TYPE_DEFAULT, acl))
++        {
++          int saved_errno = errno;
++
++          acl_free (acl);
++          errno = saved_errno;
++          return -1;
++        }
++      else
++        acl_free (acl);
++    }
++  return 0;
++
++# else /* HAVE_ACL_TYPE_EXTENDED */
++  /* Mac OS X */
++
++  /* On Mac OS X,  acl_get_file (name, ACL_TYPE_ACCESS)
++     and           acl_get_file (name, ACL_TYPE_DEFAULT)
++     always return NULL / EINVAL.  You have to use
++                   acl_get_file (name, ACL_TYPE_EXTENDED)
++     or            acl_get_fd (open (name, ...))
++     to retrieve an ACL.
++     On the other hand,
++                   acl_set_file (name, ACL_TYPE_ACCESS, acl)
++     and           acl_set_file (name, ACL_TYPE_DEFAULT, acl)
++     have the same effect as
++                   acl_set_file (name, ACL_TYPE_EXTENDED, acl):
++     Each of these calls sets the file's ACL.  */
++
++  acl_t acl;
++  int ret;
++
++  if (HAVE_ACL_GET_FD && source_desc != -1)
++    acl = acl_get_fd (source_desc);
++  else
++    acl = acl_get_file (src_name, ACL_TYPE_EXTENDED);
++  if (acl == NULL)
++    {
++      if (ACL_NOT_WELL_SUPPORTED (errno))
++        return qset_acl (dst_name, dest_desc, mode);
++      else
++        return -2;
++    }
++
++  if (HAVE_ACL_SET_FD && dest_desc != -1)
++    ret = acl_set_fd (dest_desc, acl);
++  else
++    ret = acl_set_file (dst_name, ACL_TYPE_EXTENDED, acl);
++  if (ret != 0)
++    {
++      int saved_errno = errno;
++
++      if (ACL_NOT_WELL_SUPPORTED (errno) && !acl_extended_nontrivial (acl))
++        {
++          acl_free (acl);
++          return chmod_or_fchmod (dst_name, dest_desc, mode);
++        }
++      else
++        {
++          acl_free (acl);
++          chmod_or_fchmod (dst_name, dest_desc, mode);
++          errno = saved_errno;
++          return -1;
++        }
++    }
++  else
++    acl_free (acl);
++
++  /* Since !MODE_INSIDE_ACL, we have to call chmod explicitly.  */
++  return chmod_or_fchmod (dst_name, dest_desc, mode);
++
++# endif
++
++#elif USE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
++
++  /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions
++     of Unixware.  The acl() call returns the access and default ACL both
++     at once.  */
++# ifdef ACE_GETACL
++  int ace_count;
++  ace_t *ace_entries;
++# endif
++  int count;
++  aclent_t *entries;
++  int did_chmod;
++  int saved_errno;
++  int ret;
++
++# ifdef ACE_GETACL
++  /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
++     file systems (whereas the other ones are used in UFS file systems).
++     There is an API
++       pathconf (name, _PC_ACL_ENABLED)
++       fpathconf (desc, _PC_ACL_ENABLED)
++     that allows to determine which of the two kinds of ACLs is supported
++     for the given file.  But some file systems may implement this call
++     incorrectly, so better not use it.
++     When fetching the source ACL, we simply fetch both ACL types.
++     When setting the destination ACL, we try either ACL types, assuming
++     that the kernel will translate the ACL from one form to the other.
++     (See in <http://docs.sun.com/app/docs/doc/819-2241/6n4huc7ia?l=en&a=view>
++     the description of ENOTSUP.)  */
++  for (;;)
++    {
++      ace_count = (source_desc != -1
++                   ? facl (source_desc, ACE_GETACLCNT, 0, NULL)
++                   : acl (src_name, ACE_GETACLCNT, 0, NULL));
++
++      if (ace_count < 0)
++        {
++          if (errno == ENOSYS || errno == EINVAL)
++            {
++              ace_count = 0;
++              ace_entries = NULL;
++              break;
++            }
++          else
++            return -2;
++        }
++
++      if (ace_count == 0)
++        {
++          ace_entries = NULL;
++          break;
++        }
++
++      ace_entries = (ace_t *) malloc (ace_count * sizeof (ace_t));
++      if (ace_entries == NULL)
++        {
++          errno = ENOMEM;
++          return -2;
++        }
++
++      ret = (source_desc != -1
++             ? facl (source_desc, ACE_GETACL, ace_count, ace_entries)
++             : acl (src_name, ACE_GETACL, ace_count, ace_entries));
++      if (ret < 0)
++        {
++          free (ace_entries);
++          if (errno == ENOSYS || errno == EINVAL)
++            {
++              ace_count = 0;
++              ace_entries = NULL;
++              break;
++            }
++          else
++            return -2;
++        }
++      if (ret == ace_count)
++        break;
++      /* Huh? The number of ACL entries changed since the last call.
++         Repeat.  */
++    }
++# endif
++
++  for (;;)
++    {
++      count = (source_desc != -1
++               ? facl (source_desc, GETACLCNT, 0, NULL)
++               : acl (src_name, GETACLCNT, 0, NULL));
++
++      if (count < 0)
++        {
++          if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP)
++            {
++              count = 0;
++              entries = NULL;
++              break;
++            }
++          else
++            return -2;
++        }
++
++      if (count == 0)
++        {
++          entries = NULL;
++          break;
++        }
++
++      entries = (aclent_t *) malloc (count * sizeof (aclent_t));
++      if (entries == NULL)
++        {
++          errno = ENOMEM;
++          return -2;
++        }
++
++      if ((source_desc != -1
++           ? facl (source_desc, GETACL, count, entries)
++           : acl (src_name, GETACL, count, entries))
++          == count)
++        break;
++      /* Huh? The number of ACL entries changed since the last call.
++         Repeat.  */
++    }
++
++  /* Is there an ACL of either kind?  */
++# ifdef ACE_GETACL
++  if (ace_count == 0)
++# endif
++    if (count == 0)
++      return qset_acl (dst_name, dest_desc, mode);
++
++  did_chmod = 0; /* set to 1 once the mode bits in 0777 have been set */
++  saved_errno = 0; /* the first non-ignorable error code */
++
++  if (!MODE_INSIDE_ACL)
++    {
++      /* On Cygwin, it is necessary to call chmod before acl, because
++         chmod can change the contents of the ACL (in ways that don't
++         change the allowed accesses, but still visible).  */
++      if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
++        saved_errno = errno;
++      did_chmod = 1;
++    }
++
++  /* If both ace_entries and entries are available, try SETACL before
++     ACE_SETACL, because SETACL cannot fail with ENOTSUP whereas ACE_SETACL
++     can.  */
++
++  if (count > 0)
++    {
++      ret = (dest_desc != -1
++             ? facl (dest_desc, SETACL, count, entries)
++             : acl (dst_name, SETACL, count, entries));
++      if (ret < 0 && saved_errno == 0)
++        {
++          saved_errno = errno;
++          if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
++              && !acl_nontrivial (count, entries))
++            saved_errno = 0;
++        }
++      else
++        did_chmod = 1;
++    }
++  free (entries);
++
++# ifdef ACE_GETACL
++  if (ace_count > 0)
++    {
++      ret = (dest_desc != -1
++             ? facl (dest_desc, ACE_SETACL, ace_count, ace_entries)
++             : acl (dst_name, ACE_SETACL, ace_count, ace_entries));
++      if (ret < 0 && saved_errno == 0)
++        {
++          saved_errno = errno;
++          if ((errno == ENOSYS || errno == EINVAL || errno == ENOTSUP)
++              && !acl_ace_nontrivial (ace_count, ace_entries))
++            saved_errno = 0;
++        }
++    }
++  free (ace_entries);
++# endif
++
++  if (MODE_INSIDE_ACL
++      && did_chmod <= ((mode & (S_ISUID | S_ISGID | S_ISVTX)) ? 1 : 0))
++    {
++      /* We did not call chmod so far, and either the mode and the ACL are
++         separate or special bits are to be set which don't fit into ACLs.  */
++
++      if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
++        {
++          if (saved_errno == 0)
++            saved_errno = errno;
++        }
++    }
++
++  if (saved_errno)
++    {
++      errno = saved_errno;
++      return -1;
++    }
++  return 0;
++
++#elif USE_ACL && HAVE_GETACL /* HP-UX */
++
++  struct acl_entry entries[NACLENTRIES];
++  int count;
++# if HAVE_ACLV_H
++  struct acl aclv_entries[NACLVENTRIES];
++  int aclv_count;
++# endif
++  int did_chmod;
++  int saved_errno;
++  int ret;
++
++  count = (source_desc != -1
++           ? fgetacl (source_desc, NACLENTRIES, entries)
++           : getacl (src_name, NACLENTRIES, entries));
++
++  if (count < 0)
++    {
++      if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
++        count = 0;
++      else
++        return -2;
++    }
++  else if (count > 0)
++    {
++      if (count > NACLENTRIES)
++        /* If NACLENTRIES cannot be trusted, use dynamic memory allocation.  */
++        abort ();
++    }
++
++# if HAVE_ACLV_H
++  aclv_count = acl ((char *) src_name, ACL_GET, NACLVENTRIES, aclv_entries);
++
++  if (aclv_count < 0)
++    {
++      if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
++        count = 0;
++      else
++        return -2;
++    }
++  else if (aclv_count > 0)
++    {
++      if (aclv_count > NACLVENTRIES)
++        /* If NACLVENTRIES cannot be trusted, use dynamic memory allocation.  */
++        abort ();
++    }
++# endif
++
++  if (count == 0)
++# if HAVE_ACLV_H
++    if (aclv_count == 0)
++# endif
++      return qset_acl (dst_name, dest_desc, mode);
++
++  did_chmod = 0; /* set to 1 once the mode bits in 0777 have been set */
++  saved_errno = 0; /* the first non-ignorable error code */
++
++  if (count > 0)
++    {
++      ret = (dest_desc != -1
++             ? fsetacl (dest_desc, count, entries)
++             : setacl (dst_name, count, entries));
++      if (ret < 0 && saved_errno == 0)
++        {
++          saved_errno = errno;
++          if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
++            {
++              struct stat source_statbuf;
++
++              if ((source_desc != -1
++                   ? fstat (source_desc, &source_statbuf)
++                   : stat (src_name, &source_statbuf)) == 0)
++                {
++                  if (!acl_nontrivial (count, entries, &source_statbuf))
++                    saved_errno = 0;
++                }
++              else
++                saved_errno = errno;
++            }
++        }
++      else
++        did_chmod = 1;
++    }
++
++# if HAVE_ACLV_H
++  if (aclv_count > 0)
++    {
++      ret = acl ((char *) dst_name, ACL_SET, aclv_count, aclv_entries);
++      if (ret < 0 && saved_errno == 0)
++        {
++          saved_errno = errno;
++          if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
++            {
++              if (!aclv_nontrivial (aclv_count, aclv_entries))
++                saved_errno = 0;
++            }
++        }
++      else
++        did_chmod = 1;
++    }
++# endif
++
++  if (did_chmod <= ((mode & (S_ISUID | S_ISGID | S_ISVTX)) ? 1 : 0))
++    {
++      /* We did not call chmod so far, and special bits are to be set which
++         don't fit into ACLs.  */
++
++      if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
++        {
++          if (saved_errno == 0)
++            saved_errno = errno;
++        }
++    }
++
++  if (saved_errno)
++    {
++      errno = saved_errno;
++      return -1;
++    }
++  return 0;
++
++#elif USE_ACL && HAVE_ACLX_GET && 0 /* AIX */
++
++  /* TODO */
++
++#elif USE_ACL && HAVE_STATACL /* older AIX */
++
++  union { struct acl a; char room[4096]; } u;
++  int ret;
++
++  if ((source_desc != -1
++       ? fstatacl (source_desc, STX_NORMAL, &u.a, sizeof (u))
++       : statacl (src_name, STX_NORMAL, &u.a, sizeof (u)))
++      < 0)
++    return -2;
++
++  ret = (dest_desc != -1
++         ? fchacl (dest_desc, &u.a, u.a.acl_len)
++         : chacl (dst_name, &u.a, u.a.acl_len));
++  if (ret < 0)
++    {
++      int saved_errno = errno;
++
++      chmod_or_fchmod (dst_name, dest_desc, mode);
++      errno = saved_errno;
++      return -1;
++    }
++
++  /* No need to call chmod_or_fchmod at this point, since the mode bits
++     S_ISUID, S_ISGID, S_ISVTX are also stored in the ACL.  */
++
++  return 0;
++
++#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */
++
++  struct acl entries[NACLENTRIES];
++  int count;
++  int ret;
++
++  count = acl ((char *) src_name, ACL_GET, NACLENTRIES, entries);
++
++  if (count < 0)
++    {
++      if (0)
++        count = 0;
++      else
++        return -2;
++    }
++  else if (count > 0)
++    {
++      if (count > NACLENTRIES)
++        /* If NACLENTRIES cannot be trusted, use dynamic memory allocation.  */
++        abort ();
++    }
++
++  if (count == 0)
++    return qset_acl (dst_name, dest_desc, mode);
++
++  ret = acl ((char *) dst_name, ACL_SET, count, entries);
++  if (ret < 0)
++    {
++      int saved_errno = errno;
++
++      if (0)
++        {
++          if (!acl_nontrivial (count, entries))
++            return chmod_or_fchmod (dst_name, dest_desc, mode);
++        }
++
++      chmod_or_fchmod (dst_name, dest_desc, mode);
++      errno = saved_errno;
++      return -1;
++    }
++
++  if (mode & (S_ISUID | S_ISGID | S_ISVTX))
++    {
++      /* We did not call chmod so far, and either the mode and the ACL are
++         separate or special bits are to be set which don't fit into ACLs.  */
++
++      return chmod_or_fchmod (dst_name, dest_desc, mode);
++    }
++  return 0;
++
++#else
++
++  return qset_acl (dst_name, dest_desc, mode);
++
++#endif
++}
++
++
++/* Copy access control lists from one file to another. If SOURCE_DESC is
++   a valid file descriptor, use file descriptor operations, else use
++   filename based operations on SRC_NAME. Likewise for DEST_DESC and
++   DST_NAME.
++   If access control lists are not available, fchmod the target file to
++   MODE.  Also sets the non-permission bits of the destination file
++   (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set.
++   Return 0 if successful, otherwise output a diagnostic and return a
++   negative error code.  */
++
++int
++copy_acl (const char *src_name, int source_desc, const char *dst_name,
++          int dest_desc, mode_t mode)
++{
++  int ret = qcopy_acl (src_name, source_desc, dst_name, dest_desc, mode);
++  switch (ret)
++    {
++    case -2:
++      error (0, errno, "%s", quote (src_name));
++      break;
++
++    case -1:
++      error (0, errno, _("preserving permissions for %s"), quote (dst_name));
++      break;
++
++    default:
++      break;
++    }
++  return ret;
++}
+diff --git a/gnu/file-has-acl.c b/gnu/file-has-acl.c
+new file mode 100644
+index 0000000..17872a5
+--- /dev/null
++++ b/gnu/file-has-acl.c
+@@ -0,0 +1,920 @@
++/* -*- buffer-read-only: t -*- vi: set ro: */
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++/* Test whether a file has a nontrivial access control list.
++
++   Copyright (C) 2002-2003, 2005-2012 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, Andreas Grünbacher, and Bruno Haible.  */
++
++/* Without this pragma, gcc 4.7.0 20120126 may suggest that the
++   file_has_acl function might be candidate for attribute 'const'  */
++#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
++# pragma GCC diagnostic ignored "-Wsuggest-attribute=const"
++#endif
++
++#include <config.h>
++
++#include "acl.h"
++
++#include "acl-internal.h"
++
++
++#if USE_ACL && HAVE_ACL_GET_FILE
++
++# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
++
++/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
++   Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial.  */
++int
++acl_extended_nontrivial (acl_t acl)
++{
++  /* acl is non-trivial if it is non-empty.  */
++  return (acl_entries (acl) > 0);
++}
++
++# else /* Linux, FreeBSD, IRIX, Tru64 */
++
++/* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS.
++   Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.
++   Return -1 and set errno upon failure to determine it.  */
++int
++acl_access_nontrivial (acl_t acl)
++{
++  /* acl is non-trivial if it has some entries other than for "user::",
++     "group::", and "other::".  Normally these three should be present
++     at least, allowing us to write
++        return (3 < acl_entries (acl));
++     but the following code is more robust.  */
++#  if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD */
++
++  acl_entry_t ace;
++  int got_one;
++
++  for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace);
++       got_one > 0;
++       got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
++    {
++      acl_tag_t tag;
++      if (acl_get_tag_type (ace, &tag) < 0)
++        return -1;
++      if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
++        return 1;
++    }
++  return got_one;
++
++#  else /* IRIX, Tru64 */
++#   if HAVE_ACL_TO_SHORT_TEXT /* IRIX */
++  /* Don't use acl_get_entry: it is undocumented.  */
++
++  int count = acl->acl_cnt;
++  int i;
++
++  for (i = 0; i < count; i++)
++    {
++      acl_entry_t ace = &acl->acl_entry[i];
++      acl_tag_t tag = ace->ae_tag;
++
++      if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ
++            || tag == ACL_OTHER_OBJ))
++        return 1;
++    }
++  return 0;
++
++#   endif
++#   if HAVE_ACL_FREE_TEXT /* Tru64 */
++  /* Don't use acl_get_entry: it takes only one argument and does not work.  */
++
++  int count = acl->acl_num;
++  acl_entry_t ace;
++
++  for (ace = acl->acl_first; count > 0; ace = ace->next, count--)
++    {
++      acl_tag_t tag;
++      acl_perm_t perm;
++
++      tag = ace->entry->acl_type;
++      if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
++        return 1;
++
++      perm = ace->entry->acl_perm;
++      /* On Tru64, perm can also contain non-standard bits such as
++         PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ... */
++      if ((perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)) != 0)
++        return 1;
++    }
++  return 0;
++
++#   endif
++#  endif
++}
++
++# endif
++
++
++#elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
++
++/* Test an ACL retrieved with GETACL.
++   Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++int
++acl_nontrivial (int count, aclent_t *entries)
++{
++  int i;
++
++  for (i = 0; i < count; i++)
++    {
++      aclent_t *ace = &entries[i];
++
++      /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
++         If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
++         We don't need to check ace->a_id in these cases.  */
++      if (!(ace->a_type == USER_OBJ
++            || ace->a_type == GROUP_OBJ
++            || ace->a_type == OTHER_OBJ
++            /* Note: Cygwin does not return a CLASS_OBJ ("mask:") entry
++               sometimes.  */
++            || ace->a_type == CLASS_OBJ))
++        return 1;
++    }
++  return 0;
++}
++
++# ifdef ACE_GETACL
++
++/* A shortcut for a bitmask.  */
++#  define NEW_ACE_WRITEA_DATA (NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA)
++
++/* Test an ACL retrieved with ACE_GETACL.
++   Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++int
++acl_ace_nontrivial (int count, ace_t *entries)
++{
++  int i;
++
++  /* The flags in the ace_t structure changed in a binary incompatible way
++     when ACL_NO_TRIVIAL etc. were introduced in <sys/acl.h> version 1.15.
++     How to distinguish the two conventions at runtime?
++     In the old convention, usually three ACEs have a_flags = ACE_OWNER /
++     ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400.  In the new
++     convention, these values are not used.  */
++  int old_convention = 0;
++
++  for (i = 0; i < count; i++)
++    if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER))
++      {
++        old_convention = 1;
++        break;
++      }
++
++  if (old_convention)
++    /* Running on Solaris 10.  */
++    for (i = 0; i < count; i++)
++      {
++        ace_t *ace = &entries[i];
++
++        /* Note:
++           If ace->a_flags = ACE_OWNER, ace->a_who is the st_uid from stat().
++           If ace->a_flags = ACE_GROUP, ace->a_who is the st_gid from stat().
++           We don't need to check ace->a_who in these cases.  */
++        if (!(ace->a_type == OLD_ALLOW
++              && (ace->a_flags == OLD_ACE_OWNER
++                  || ace->a_flags == OLD_ACE_GROUP
++                  || ace->a_flags == OLD_ACE_OTHER)))
++          return 1;
++      }
++  else
++    {
++      /* Running on Solaris 10 (newer version) or Solaris 11.  */
++      unsigned int access_masks[6] =
++        {
++          0, /* owner@ deny */
++          0, /* owner@ allow */
++          0, /* group@ deny */
++          0, /* group@ allow */
++          0, /* everyone@ deny */
++          0  /* everyone@ allow */
++        };
++
++      for (i = 0; i < count; i++)
++        {
++          ace_t *ace = &entries[i];
++          unsigned int index1;
++          unsigned int index2;
++
++          if (ace->a_type == NEW_ACE_ACCESS_ALLOWED_ACE_TYPE)
++            index1 = 1;
++          else if (ace->a_type == NEW_ACE_ACCESS_DENIED_ACE_TYPE)
++            index1 = 0;
++          else
++            return 1;
++
++          if (ace->a_flags == NEW_ACE_OWNER)
++            index2 = 0;
++          else if (ace->a_flags == (NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP))
++            index2 = 2;
++          else if (ace->a_flags == NEW_ACE_EVERYONE)
++            index2 = 4;
++          else
++            return 1;
++
++          access_masks[index1 + index2] |= ace->a_access_mask;
++        }
++
++      /* The same bit shouldn't be both allowed and denied.  */
++      if (access_masks[0] & access_masks[1])
++        return 1;
++      if (access_masks[2] & access_masks[3])
++        return 1;
++      if (access_masks[4] & access_masks[5])
++        return 1;
++
++      /* Check minimum masks.  */
++      if ((NEW_ACE_WRITE_NAMED_ATTRS
++           | NEW_ACE_WRITE_ATTRIBUTES
++           | NEW_ACE_WRITE_ACL
++           | NEW_ACE_WRITE_OWNER)
++          & ~ access_masks[1])
++        return 1;
++      access_masks[1] &= ~(NEW_ACE_WRITE_NAMED_ATTRS
++                           | NEW_ACE_WRITE_ATTRIBUTES
++                           | NEW_ACE_WRITE_ACL
++                           | NEW_ACE_WRITE_OWNER);
++      if ((NEW_ACE_READ_NAMED_ATTRS
++           | NEW_ACE_READ_ATTRIBUTES
++           | NEW_ACE_READ_ACL
++           | NEW_ACE_SYNCHRONIZE)
++          & ~ access_masks[5])
++        return 1;
++      access_masks[5] &= ~(NEW_ACE_READ_NAMED_ATTRS
++                           | NEW_ACE_READ_ATTRIBUTES
++                           | NEW_ACE_READ_ACL
++                           | NEW_ACE_SYNCHRONIZE);
++
++      /* Check the allowed or denied bits.  */
++      switch ((access_masks[0] | access_masks[1])
++              & ~(NEW_ACE_READ_NAMED_ATTRS
++                  | NEW_ACE_READ_ATTRIBUTES
++                  | NEW_ACE_READ_ACL
++                  | NEW_ACE_SYNCHRONIZE))
++        {
++        case 0:
++        case NEW_ACE_READ_DATA:
++        case                     NEW_ACE_WRITEA_DATA:
++        case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
++        case                                           NEW_ACE_EXECUTE:
++        case NEW_ACE_READ_DATA |                       NEW_ACE_EXECUTE:
++        case                     NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
++        case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
++          break;
++        default:
++          return 1;
++        }
++      switch ((access_masks[2] | access_masks[3])
++              & ~(NEW_ACE_READ_NAMED_ATTRS
++                  | NEW_ACE_READ_ATTRIBUTES
++                  | NEW_ACE_READ_ACL
++                  | NEW_ACE_SYNCHRONIZE))
++        {
++        case 0:
++        case NEW_ACE_READ_DATA:
++        case                     NEW_ACE_WRITEA_DATA:
++        case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
++        case                                           NEW_ACE_EXECUTE:
++        case NEW_ACE_READ_DATA |                       NEW_ACE_EXECUTE:
++        case                     NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
++        case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
++          break;
++        default:
++          return 1;
++        }
++      switch ((access_masks[4] | access_masks[5])
++              & ~(NEW_ACE_WRITE_NAMED_ATTRS
++                  | NEW_ACE_WRITE_ATTRIBUTES
++                  | NEW_ACE_WRITE_ACL
++                  | NEW_ACE_WRITE_OWNER))
++        {
++        case 0:
++        case NEW_ACE_READ_DATA:
++        case                     NEW_ACE_WRITEA_DATA:
++        case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
++        case                                           NEW_ACE_EXECUTE:
++        case NEW_ACE_READ_DATA |                       NEW_ACE_EXECUTE:
++        case                     NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
++        case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
++          break;
++        default:
++          return 1;
++        }
++
++      /* Check that the NEW_ACE_WRITE_DATA and NEW_ACE_APPEND_DATA bits are
++         either both allowed or both denied.  */
++      if (((access_masks[0] & NEW_ACE_WRITE_DATA) != 0)
++          != ((access_masks[0] & NEW_ACE_APPEND_DATA) != 0))
++        return 1;
++      if (((access_masks[2] & NEW_ACE_WRITE_DATA) != 0)
++          != ((access_masks[2] & NEW_ACE_APPEND_DATA) != 0))
++        return 1;
++      if (((access_masks[4] & NEW_ACE_WRITE_DATA) != 0)
++          != ((access_masks[4] & NEW_ACE_APPEND_DATA) != 0))
++        return 1;
++    }
++
++  return 0;
++}
++
++# endif
++
++#elif USE_ACL && HAVE_GETACL /* HP-UX */
++
++/* Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++int
++acl_nontrivial (int count, struct acl_entry *entries, struct stat *sb)
++{
++  int i;
++
++  for (i = 0; i < count; i++)
++    {
++      struct acl_entry *ace = &entries[i];
++
++      if (!((ace->uid == sb->st_uid && ace->gid == ACL_NSGROUP)
++            || (ace->uid == ACL_NSUSER && ace->gid == sb->st_gid)
++            || (ace->uid == ACL_NSUSER && ace->gid == ACL_NSGROUP)))
++        return 1;
++    }
++  return 0;
++}
++
++# if HAVE_ACLV_H /* HP-UX >= 11.11 */
++
++/* Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++int
++aclv_nontrivial (int count, struct acl *entries)
++{
++  int i;
++
++  for (i = 0; i < count; i++)
++    {
++      struct acl *ace = &entries[i];
++
++      /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
++         If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
++         We don't need to check ace->a_id in these cases.  */
++      if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
++            || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
++            || ace->a_type == CLASS_OBJ
++            || ace->a_type == OTHER_OBJ))
++        return 1;
++    }
++  return 0;
++}
++
++# endif
++
++#elif USE_ACL && (HAVE_ACLX_GET || HAVE_STATACL) /* AIX */
++
++/* Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++int
++acl_nontrivial (struct acl *a)
++{
++  /* The normal way to iterate through an ACL is like this:
++       struct acl_entry *ace;
++       for (ace = a->acl_ext; ace != acl_last (a); ace = acl_nxt (ace))
++         {
++           struct ace_id *aei;
++           switch (ace->ace_type)
++             {
++             case ACC_PERMIT:
++             case ACC_DENY:
++             case ACC_SPECIFY:
++               ...;
++             }
++           for (aei = ace->ace_id; aei != id_last (ace); aei = id_nxt (aei))
++             ...
++         }
++   */
++  return (acl_last (a) != a->acl_ext ? 1 : 0);
++}
++
++# if HAVE_ACLX_GET && defined ACL_AIX_WIP /* newer AIX */
++
++/* Return 1 if the given ACL is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++int
++acl_nfs4_nontrivial (nfs4_acl_int_t *a)
++{
++#  if 1 /* let's try this first */
++  return (a->aclEntryN > 0 ? 1 : 0);
++#  else
++  int count = a->aclEntryN;
++  int i;
++
++  for (i = 0; i < count; i++)
++    {
++      nfs4_ace_int_t *ace = &a->aclEntry[i];
++
++      if (!((ace->flags & ACE4_ID_SPECIAL) != 0
++            && (ace->aceWho.special_whoid == ACE4_WHO_OWNER
++                || ace->aceWho.special_whoid == ACE4_WHO_GROUP
++                || ace->aceWho.special_whoid == ACE4_WHO_EVERYONE)
++            && ace->aceType == ACE4_ACCESS_ALLOWED_ACE_TYPE
++            && ace->aceFlags == 0
++            && (ace->aceMask & ~(ACE4_READ_DATA | ACE4_LIST_DIRECTORY
++                                 | ACE4_WRITE_DATA | ACE4_ADD_FILE
++                                 | ACE4_EXECUTE)) == 0))
++        return 1;
++    }
++  return 0;
++#  endif
++}
++
++# endif
++
++#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */
++
++/* Test an ACL retrieved with ACL_GET.
++   Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
++   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
++int
++acl_nontrivial (int count, struct acl *entries)
++{
++  int i;
++
++  for (i = 0; i < count; i++)
++    {
++      struct acl *ace = &entries[i];
++
++      /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
++         If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
++         We don't need to check ace->a_id in these cases.  */
++      if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
++            || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
++            || ace->a_type == CLASS_OBJ
++            || ace->a_type == OTHER_OBJ))
++        return 1;
++    }
++  return 0;
++}
++
++#endif
++
++
++/* Return 1 if NAME has a nontrivial access control list, 0 if NAME
++   only has no or a base access control list, and -1 (setting errno)
++   on error.  SB must be set to the stat buffer of NAME, obtained
++   through stat() or lstat().  */
++
++int
++file_has_acl (char const *name, struct stat const *sb)
++{
++#if USE_ACL
++  if (! S_ISLNK (sb->st_mode))
++    {
++# if HAVE_ACL_GET_FILE
++
++      /* POSIX 1003.1e (draft 17 -- abandoned) specific version.  */
++      /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
++      int ret;
++
++      if (HAVE_ACL_EXTENDED_FILE) /* Linux */
++        {
++          /* On Linux, acl_extended_file is an optimized function: It only
++             makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for
++             ACL_TYPE_DEFAULT.  */
++          ret = acl_extended_file (name);
++        }
++      else /* FreeBSD, Mac OS X, IRIX, Tru64 */
++        {
++#  if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
++          /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS)
++             and acl_get_file (name, ACL_TYPE_DEFAULT)
++             always return NULL / EINVAL.  There is no point in making
++             these two useless calls.  The real ACL is retrieved through
++             acl_get_file (name, ACL_TYPE_EXTENDED).  */
++          acl_t acl = acl_get_file (name, ACL_TYPE_EXTENDED);
++          if (acl)
++            {
++              ret = acl_extended_nontrivial (acl);
++              acl_free (acl);
++            }
++          else
++            ret = -1;
++#  else /* FreeBSD, IRIX, Tru64 */
++          acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
++          if (acl)
++            {
++              int saved_errno;
++
++              ret = acl_access_nontrivial (acl);
++              saved_errno = errno;
++              acl_free (acl);
++              errno = saved_errno;
++#   if HAVE_ACL_FREE_TEXT /* Tru64 */
++              /* On OSF/1, acl_get_file (name, ACL_TYPE_DEFAULT) always
++                 returns NULL with errno not set.  There is no point in
++                 making this call.  */
++#   else /* FreeBSD, IRIX */
++              /* On Linux, FreeBSD, IRIX, acl_get_file (name, ACL_TYPE_ACCESS)
++                 and acl_get_file (name, ACL_TYPE_DEFAULT) on a directory
++                 either both succeed or both fail; it depends on the
++                 file system.  Therefore there is no point in making the second
++                 call if the first one already failed.  */
++              if (ret == 0 && S_ISDIR (sb->st_mode))
++                {
++                  acl = acl_get_file (name, ACL_TYPE_DEFAULT);
++                  if (acl)
++                    {
++                      ret = (0 < acl_entries (acl));
++                      acl_free (acl);
++                    }
++                  else
++                    ret = -1;
++                }
++#   endif
++            }
++          else
++            ret = -1;
++#  endif
++        }
++      if (ret < 0)
++        return ACL_NOT_WELL_SUPPORTED (errno) ? 0 : -1;
++      return ret;
++
++# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
++
++#  if defined ACL_NO_TRIVIAL
++
++      /* Solaris 10 (newer version), which has additional API declared in
++         <sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial,
++         acl_fromtext, ...).  */
++      return acl_trivial (name);
++
++#  else /* Solaris, Cygwin, general case */
++
++      /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions
++         of Unixware.  The acl() call returns the access and default ACL both
++         at once.  */
++      {
++        /* Initially, try to read the entries into a stack-allocated buffer.
++           Use malloc if it does not fit.  */
++        enum
++          {
++            alloc_init = 4000 / sizeof (aclent_t), /* >= 3 */
++            alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (aclent_t))
++          };
++        aclent_t buf[alloc_init];
++        size_t alloc = alloc_init;
++        aclent_t *entries = buf;
++        aclent_t *malloced = NULL;
++        int count;
++
++        for (;;)
++          {
++            count = acl (name, GETACL, alloc, entries);
++            if (count < 0 && errno == ENOSPC)
++              {
++                /* Increase the size of the buffer.  */
++                free (malloced);
++                if (alloc > alloc_max / 2)
++                  {
++                    errno = ENOMEM;
++                    return -1;
++                  }
++                alloc = 2 * alloc; /* <= alloc_max */
++                entries = malloced =
++                  (aclent_t *) malloc (alloc * sizeof (aclent_t));
++                if (entries == NULL)
++                  {
++                    errno = ENOMEM;
++                    return -1;
++                  }
++                continue;
++              }
++            break;
++          }
++        if (count < 0)
++          {
++            if (errno == ENOSYS || errno == ENOTSUP)
++              ;
++            else
++              {
++                int saved_errno = errno;
++                free (malloced);
++                errno = saved_errno;
++                return -1;
++              }
++          }
++        else if (count == 0)
++          ;
++        else
++          {
++            /* Don't use MIN_ACL_ENTRIES:  It's set to 4 on Cygwin, but Cygwin
++               returns only 3 entries for files with no ACL.  But this is safe:
++               If there are more than 4 entries, there cannot be only the
++               "user::", "group::", "other:", and "mask:" entries.  */
++            if (count > 4)
++              {
++                free (malloced);
++                return 1;
++              }
++
++            if (acl_nontrivial (count, entries))
++              {
++                free (malloced);
++                return 1;
++              }
++          }
++        free (malloced);
++      }
++
++#   ifdef ACE_GETACL
++      /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
++         file systems (whereas the other ones are used in UFS file systems).  */
++      {
++        /* Initially, try to read the entries into a stack-allocated buffer.
++           Use malloc if it does not fit.  */
++        enum
++          {
++            alloc_init = 4000 / sizeof (ace_t), /* >= 3 */
++            alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t))
++          };
++        ace_t buf[alloc_init];
++        size_t alloc = alloc_init;
++        ace_t *entries = buf;
++        ace_t *malloced = NULL;
++        int count;
++
++        for (;;)
++          {
++            count = acl (name, ACE_GETACL, alloc, entries);
++            if (count < 0 && errno == ENOSPC)
++              {
++                /* Increase the size of the buffer.  */
++                free (malloced);
++                if (alloc > alloc_max / 2)
++                  {
++                    errno = ENOMEM;
++                    return -1;
++                  }
++                alloc = 2 * alloc; /* <= alloc_max */
++                entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t));
++                if (entries == NULL)
++                  {
++                    errno = ENOMEM;
++                    return -1;
++                  }
++                continue;
++              }
++            break;
++          }
++        if (count < 0)
++          {
++            if (errno == ENOSYS || errno == EINVAL)
++              ;
++            else
++              {
++                int saved_errno = errno;
++                free (malloced);
++                errno = saved_errno;
++                return -1;
++              }
++          }
++        else if (count == 0)
++          ;
++        else
++          {
++            /* In the old (original Solaris 10) convention:
++               If there are more than 3 entries, there cannot be only the
++               ACE_OWNER, ACE_GROUP, ACE_OTHER entries.
++               In the newer Solaris 10 and Solaris 11 convention:
++               If there are more than 6 entries, there cannot be only the
++               ACE_OWNER, ACE_GROUP, ACE_EVERYONE entries, each once with
++               NEW_ACE_ACCESS_ALLOWED_ACE_TYPE and once with
++               NEW_ACE_ACCESS_DENIED_ACE_TYPE.  */
++            if (count > 6)
++              {
++                free (malloced);
++                return 1;
++              }
++
++            if (acl_ace_nontrivial (count, entries))
++              {
++                free (malloced);
++                return 1;
++              }
++          }
++        free (malloced);
++      }
++#   endif
++
++      return 0;
++#  endif
++
++# elif HAVE_GETACL /* HP-UX */
++
++      {
++        struct acl_entry entries[NACLENTRIES];
++        int count;
++
++        count = getacl (name, NACLENTRIES, entries);
++
++        if (count < 0)
++          {
++            /* ENOSYS is seen on newer HP-UX versions.
++               EOPNOTSUPP is typically seen on NFS mounts.
++               ENOTSUP was seen on Quantum StorNext file systems (cvfs).  */
++            if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
++              ;
++            else
++              return -1;
++          }
++        else if (count == 0)
++          return 0;
++        else /* count > 0 */
++          {
++            if (count > NACLENTRIES)
++              /* If NACLENTRIES cannot be trusted, use dynamic memory
++                 allocation.  */
++              abort ();
++
++            /* If there are more than 3 entries, there cannot be only the
++               (uid,%), (%,gid), (%,%) entries.  */
++            if (count > 3)
++              return 1;
++
++            {
++              struct stat statbuf;
++
++              if (stat (name, &statbuf) < 0)
++                return -1;
++
++              return acl_nontrivial (count, entries, &statbuf);
++            }
++          }
++      }
++
++#  if HAVE_ACLV_H /* HP-UX >= 11.11 */
++
++      {
++        struct acl entries[NACLVENTRIES];
++        int count;
++
++        count = acl ((char *) name, ACL_GET, NACLVENTRIES, entries);
++
++        if (count < 0)
++          {
++            /* EOPNOTSUPP is seen on NFS in HP-UX 11.11, 11.23.
++               EINVAL is seen on NFS in HP-UX 11.31.  */
++            if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
++              ;
++            else
++              return -1;
++          }
++        else if (count == 0)
++          return 0;
++        else /* count > 0 */
++          {
++            if (count > NACLVENTRIES)
++              /* If NACLVENTRIES cannot be trusted, use dynamic memory
++                 allocation.  */
++              abort ();
++
++            /* If there are more than 4 entries, there cannot be only the
++               four base ACL entries.  */
++            if (count > 4)
++              return 1;
++
++            return aclv_nontrivial (count, entries);
++          }
++      }
++
++#  endif
++
++# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */
++
++      acl_type_t type;
++      char aclbuf[1024];
++      void *acl = aclbuf;
++      size_t aclsize = sizeof (aclbuf);
++      mode_t mode;
++
++      for (;;)
++        {
++          /* The docs say that type being 0 is equivalent to ACL_ANY, but it
++             is not true, in AIX 5.3.  */
++          type.u64 = ACL_ANY;
++          if (aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) >= 0)
++            break;
++          if (errno == ENOSYS)
++            return 0;
++          if (errno != ENOSPC)
++            {
++              if (acl != aclbuf)
++                {
++                  int saved_errno = errno;
++                  free (acl);
++                  errno = saved_errno;
++                }
++              return -1;
++            }
++          aclsize = 2 * aclsize;
++          if (acl != aclbuf)
++            free (acl);
++          acl = malloc (aclsize);
++          if (acl == NULL)
++            {
++              errno = ENOMEM;
++              return -1;
++            }
++        }
++
++      if (type.u64 == ACL_AIXC)
++        {
++          int result = acl_nontrivial ((struct acl *) acl);
++          if (acl != aclbuf)
++            free (acl);
++          return result;
++        }
++      else if (type.u64 == ACL_NFS4)
++        {
++          int result = acl_nfs4_nontrivial ((nfs4_acl_int_t *) acl);
++          if (acl != aclbuf)
++            free (acl);
++          return result;
++        }
++      else
++        {
++          /* A newer type of ACL has been introduced in the system.
++             We should better support it.  */
++          if (acl != aclbuf)
++            free (acl);
++          errno = EINVAL;
++          return -1;
++        }
++
++# elif HAVE_STATACL /* older AIX */
++
++      union { struct acl a; char room[4096]; } u;
++
++      if (statacl (name, STX_NORMAL, &u.a, sizeof (u)) < 0)
++        return -1;
++
++      return acl_nontrivial (&u.a);
++
++# elif HAVE_ACLSORT /* NonStop Kernel */
++
++      {
++        struct acl entries[NACLENTRIES];
++        int count;
++
++        count = acl ((char *) name, ACL_GET, NACLENTRIES, entries);
++
++        if (count < 0)
++          {
++            if (errno == ENOSYS || errno == ENOTSUP)
++              ;
++            else
++              return -1;
++          }
++        else if (count == 0)
++          return 0;
++        else /* count > 0 */
++          {
++            if (count > NACLENTRIES)
++              /* If NACLENTRIES cannot be trusted, use dynamic memory
++                 allocation.  */
++              abort ();
++
++            /* If there are more than 4 entries, there cannot be only the
++               four base ACL entries.  */
++            if (count > 4)
++              return 1;
++
++            return acl_nontrivial (count, entries);
++          }
++      }
++
++# endif
++    }
++#endif
++
++  return 0;
++}
+diff --git a/gnu/getfilecon.c b/gnu/getfilecon.c
+new file mode 100644
+index 0000000..4a0f40d
+--- /dev/null
++++ b/gnu/getfilecon.c
+@@ -0,0 +1,88 @@
++/* -*- buffer-read-only: t -*- vi: set ro: */
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++/* wrap getfilecon, lgetfilecon, and fgetfilecon
++   Copyright (C) 2009-2012 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, 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 <selinux/selinux.h>
++
++#include <sys/types.h>
++#include <errno.h>
++#include <string.h>
++
++/* FIXME: remove this once there is an errno-gnu module
++   that guarantees the definition of ENODATA.  */
++#ifndef ENODATA
++# define ENODATA ENOTSUP
++#endif
++
++#undef getfilecon
++#undef lgetfilecon
++#undef fgetfilecon
++int getfilecon (char const *file, security_context_t *con);
++int lgetfilecon (char const *file, security_context_t *con);
++int fgetfilecon (int fd, security_context_t *con);
++
++/* getfilecon, lgetfilecon, and fgetfilecon can all misbehave, be it
++   via an old version of libselinux where these would return 0 and set the
++   result context to NULL, or via a modern kernel+lib operating on a file
++   from a disk whose attributes were set by a kernel from around 2006.
++   In that latter case, the functions return a length of 10 for the
++   "unlabeled" context.  Map both failures to a return value of -1, and
++   set errno to ENOTSUP in the first case, and ENODATA in the latter.  */
++
++static inline int
++map_to_failure (int ret, security_context_t *con)
++{
++  if (ret == 0)
++    {
++      errno = ENOTSUP;
++      return -1;
++    }
++
++  if (ret == 10 && strcmp (*con, "unlabeled") == 0)
++    {
++      freecon (*con);
++      errno = ENODATA;
++      return -1;
++    }
++
++  return ret;
++}
++
++int
++rpl_getfilecon (char const *file, security_context_t *con)
++{
++  int ret = getfilecon (file, con);
++  return map_to_failure (ret, con);
++}
++
++int
++rpl_lgetfilecon (char const *file, security_context_t *con)
++{
++  int ret = lgetfilecon (file, con);
++  return map_to_failure (ret, con);
++}
++
++int
++rpl_fgetfilecon (int fd, security_context_t *con)
++{
++  int ret = fgetfilecon (fd, con);
++  return map_to_failure (ret, con);
++}
+diff --git a/gnu/se-context.in.h b/gnu/se-context.in.h
+new file mode 100644
+index 0000000..adb13ba
+--- /dev/null
++++ b/gnu/se-context.in.h
+@@ -0,0 +1,30 @@
++/* -*- buffer-read-only: t -*- vi: set ro: */
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++#ifndef SELINUX_CONTEXT_H
++# define SELINUX_CONTEXT_H
++
++# include <errno.h>
++
++/* The definition of _GL_UNUSED_PARAMETER is copied here.  */
++
++typedef int context_t;
++static inline context_t context_new (char const *s _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return 0; }
++static inline char *context_str (context_t con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return (void *) 0; }
++static inline void context_free (context_t c _GL_UNUSED_PARAMETER) {}
++
++static inline int context_user_set (context_t sc _GL_UNUSED_PARAMETER,
++                                    char const *s _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int context_role_set (context_t sc _GL_UNUSED_PARAMETER,
++                                    char const *s _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int context_range_set (context_t sc _GL_UNUSED_PARAMETER,
++                                     char const *s _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int context_type_set (context_t sc _GL_UNUSED_PARAMETER,
++                                    char const *s _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++
++#endif
+diff --git a/gnu/se-selinux.in.h b/gnu/se-selinux.in.h
+new file mode 100644
+index 0000000..34205a1
+--- /dev/null
++++ b/gnu/se-selinux.in.h
+@@ -0,0 +1,99 @@
++/* -*- buffer-read-only: t -*- vi: set ro: */
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++/* Replacement <selinux/selinux.h> for platforms that lack it.
++   Copyright (C) 2008-2012 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/>.  */
++
++#ifndef _@GUARD_PREFIX@_SELINUX_SELINUX_H
++# define _@GUARD_PREFIX@_SELINUX_SELINUX_H
++
++# if __GNUC__ >= 3
++@PRAGMA_SYSTEM_HEADER@
++# endif
++@PRAGMA_COLUMNS@
++
++# if HAVE_SELINUX_SELINUX_H
++
++#@INCLUDE_NEXT@ @NEXT_SELINUX_SELINUX_H@
++
++# else
++
++#  include <sys/types.h>
++#  include <errno.h>
++
++/* The definition of _GL_UNUSED_PARAMETER is copied here.  */
++
++#  if !GNULIB_defined_security_types
++
++typedef unsigned short security_class_t;
++#   define security_context_t char*
++#   define is_selinux_enabled() 0
++
++static inline int getcon (security_context_t *con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline void freecon (security_context_t con _GL_UNUSED_PARAMETER) {}
++
++
++static inline int getfscreatecon (security_context_t *con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int setfscreatecon (security_context_t con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int matchpathcon (char const *file _GL_UNUSED_PARAMETER,
++                                mode_t m _GL_UNUSED_PARAMETER,
++                                security_context_t *con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int getfilecon (char const *file _GL_UNUSED_PARAMETER,
++                              security_context_t *con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int lgetfilecon (char const *file _GL_UNUSED_PARAMETER,
++                               security_context_t *con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int fgetfilecon (int fd,
++                               security_context_t *con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int setfilecon (char const *file _GL_UNUSED_PARAMETER,
++                              security_context_t con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int lsetfilecon (char const *file _GL_UNUSED_PARAMETER,
++                               security_context_t con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int fsetfilecon (int fd _GL_UNUSED_PARAMETER,
++                               security_context_t con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++
++static inline int security_check_context
++    (security_context_t con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int security_check_context_raw
++    (security_context_t con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int setexeccon (security_context_t con _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int security_compute_create
++    (security_context_t scon _GL_UNUSED_PARAMETER,
++     security_context_t tcon _GL_UNUSED_PARAMETER,
++     security_class_t tclass _GL_UNUSED_PARAMETER,
++     security_context_t *newcon _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++static inline int matchpathcon_init_prefix
++    (char const *path _GL_UNUSED_PARAMETER,
++     char const *prefix _GL_UNUSED_PARAMETER)
++  { errno = ENOTSUP; return -1; }
++
++#   define GNULIB_defined_security_types 1
++#  endif
++
++# endif
++#endif /* _@GUARD_PREFIX@_SELINUX_SELINUX_H */
+diff --git a/gnu/selinux-at.c b/gnu/selinux-at.c
+new file mode 100644
+index 0000000..f6619fa
+--- /dev/null
++++ b/gnu/selinux-at.c
+@@ -0,0 +1,74 @@
++/* -*- buffer-read-only: t -*- vi: set ro: */
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++/* openat-style fd-relative functions for SE Linux
++   Copyright (C) 2007, 2009-2012 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 "selinux-at.h"
++#include "openat.h"
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <errno.h>
++#include <fcntl.h>
++
++#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
++#include "save-cwd.h"
++
++#include "openat-priv.h"
++
++#define AT_FUNC_NAME getfileconat
++#define AT_FUNC_F1 getfilecon
++#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con
++#define AT_FUNC_POST_FILE_ARGS        , con
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
++
++#define AT_FUNC_NAME lgetfileconat
++#define AT_FUNC_F1 lgetfilecon
++#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con
++#define AT_FUNC_POST_FILE_ARGS        , con
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
++
++#define AT_FUNC_NAME setfileconat
++#define AT_FUNC_F1 setfilecon
++#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con
++#define AT_FUNC_POST_FILE_ARGS        , con
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
++
++#define AT_FUNC_NAME lsetfileconat
++#define AT_FUNC_F1 lsetfilecon
++#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con
++#define AT_FUNC_POST_FILE_ARGS        , con
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
+diff --git a/gnu/selinux-at.h b/gnu/selinux-at.h
+new file mode 100644
+index 0000000..4ab3109
+--- /dev/null
++++ b/gnu/selinux-at.h
+@@ -0,0 +1,54 @@
++/* -*- buffer-read-only: t -*- vi: set ro: */
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++/* Prototypes for openat-style fd-relative SELinux functions
++   Copyright (C) 2007, 2009-2012 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 <selinux/selinux.h>
++#include <selinux/context.h>
++
++/* These are the dir-fd-relative variants of the functions without the
++   "at" suffix.  For example, getfileconat (AT_FDCWD, file, &c) is usually
++   equivalent to getfilecon (file, &c).  The emulation is accomplished
++   by first attempting getfilecon ("/proc/self/fd/DIR_FD/FILE", &c).
++   Failing that, simulate it via save_cwd/fchdir/getfilecon/restore_cwd.
++   If either the save_cwd or the restore_cwd fails (relatively unlikely),
++   then give a diagnostic and exit nonzero.  */
++
++/* dir-fd-relative getfilecon.  Set *CON to the SELinux security context
++   of the file specified by DIR_FD and FILE and return the length of *CON.
++   DIR_FD and FILE are interpreted as for fstatat[*].  A non-NULL *CON
++   must be freed with freecon.  Upon error, set *CON to NULL, set errno
++   and return -1.
++   [*] with flags=0 here, with flags=AT_SYMLINK_NOFOLLOW for lgetfileconat  */
++int  getfileconat (int dir_fd, char const *file, security_context_t *con);
++
++/* dir-fd-relative lgetfilecon.  This function is just like getfileconat,
++   except when DIR_FD and FILE specify a symlink:  lgetfileconat operates on
++   the symlink, while getfileconat operates on the referent of the symlink.  */
++int lgetfileconat (int dir_fd, char const *file, security_context_t *con);
++
++/* dir-fd-relative setfilecon.  Set the SELinux security context of
++   the file specified by DIR_FD and FILE to CON.  DIR_FD and FILE are
++   interpreted as for fstatat[*].  Upon success, return 0.
++   Otherwise, return -1 and set errno.  */
++int  setfileconat (int dir_fd, char const *file, security_context_t con);
++
++/* dir-fd-relative lsetfilecon.  This function is just like setfileconat,
++   except that rather than dereferencing a symlink, this function affects it. */
++/* dir-fd-relative lsetfilecon.  This function is just like setfileconat,
++   except when DIR_FD and FILE specify a symlink:  lsetfileconat operates on
++   the symlink, while setfileconat operates on the referent of the symlink.  */
++int lsetfileconat (int dir_fd, char const *file, security_context_t con);
+diff --git a/gnu/set-mode-acl.c b/gnu/set-mode-acl.c
+new file mode 100644
+index 0000000..edc8e26
+--- /dev/null
++++ b/gnu/set-mode-acl.c
+@@ -0,0 +1,699 @@
++/* -*- buffer-read-only: t -*- vi: set ro: */
++/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
++/* set-mode-acl.c - set access control list equivalent to a mode
++
++   Copyright (C) 2002-2003, 2005-2012 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 and Andreas Gruenbacher, and Bruno Haible.  */
++
++#include <config.h>
++
++#include "acl.h"
++
++#include "acl-internal.h"
++
++#include "gettext.h"
++#define _(msgid) gettext (msgid)
++
++
++/* If DESC is a valid file descriptor use fchmod to change the
++   file's mode to MODE on systems that have fchown. On systems
++   that don't have fchown and if DESC is invalid, use chown on
++   NAME instead.
++   Return 0 if successful.  Return -1 and set errno upon failure.  */
++
++int
++chmod_or_fchmod (const char *name, int desc, mode_t mode)
++{
++  if (HAVE_FCHMOD && desc != -1)
++    return fchmod (desc, mode);
++  else
++    return chmod (name, mode);
++}
++
++/* Set the access control lists of a file. If DESC is a valid file
++   descriptor, use file descriptor operations where available, else use
++   filename based operations on NAME.  If access control lists are not
++   available, fchmod the target file to MODE.  Also sets the
++   non-permission bits of the destination file (S_ISUID, S_ISGID, S_ISVTX)
++   to those from MODE if any are set.
++   Return 0 if successful.  Return -1 and set errno upon failure.  */
++
++int
++qset_acl (char const *name, int desc, mode_t mode)
++{
++#if USE_ACL
++# if HAVE_ACL_GET_FILE
++  /* POSIX 1003.1e draft 17 (abandoned) specific version.  */
++  /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
++#  if !HAVE_ACL_TYPE_EXTENDED
++  /* Linux, FreeBSD, IRIX, Tru64 */
++
++  /* We must also have acl_from_text and acl_delete_def_file.
++     (acl_delete_def_file could be emulated with acl_init followed
++      by acl_set_file, but acl_set_file with an empty acl is
++      unspecified.)  */
++
++#   ifndef HAVE_ACL_FROM_TEXT
++#    error Must have acl_from_text (see POSIX 1003.1e draft 17).
++#   endif
++#   ifndef HAVE_ACL_DELETE_DEF_FILE
++#    error Must have acl_delete_def_file (see POSIX 1003.1e draft 17).
++#   endif
++
++  acl_t acl;
++  int ret;
++
++  if (HAVE_ACL_FROM_MODE) /* Linux */
++    {
++      acl = acl_from_mode (mode);
++      if (!acl)
++        return -1;
++    }
++  else /* FreeBSD, IRIX, Tru64 */
++    {
++      /* If we were to create the ACL using the functions acl_init(),
++         acl_create_entry(), acl_set_tag_type(), acl_set_qualifier(),
++         acl_get_permset(), acl_clear_perm[s](), acl_add_perm(), we
++         would need to create a qualifier.  I don't know how to do this.
++         So create it using acl_from_text().  */
++
++#   if HAVE_ACL_FREE_TEXT /* Tru64 */
++      char acl_text[] = "u::---,g::---,o::---,";
++#   else /* FreeBSD, IRIX */
++      char acl_text[] = "u::---,g::---,o::---";
++#   endif
++
++      if (mode & S_IRUSR) acl_text[ 3] = 'r';
++      if (mode & S_IWUSR) acl_text[ 4] = 'w';
++      if (mode & S_IXUSR) acl_text[ 5] = 'x';
++      if (mode & S_IRGRP) acl_text[10] = 'r';
++      if (mode & S_IWGRP) acl_text[11] = 'w';
++      if (mode & S_IXGRP) acl_text[12] = 'x';
++      if (mode & S_IROTH) acl_text[17] = 'r';
++      if (mode & S_IWOTH) acl_text[18] = 'w';
++      if (mode & S_IXOTH) acl_text[19] = 'x';
++
++      acl = acl_from_text (acl_text);
++      if (!acl)
++        return -1;
++    }
++  if (HAVE_ACL_SET_FD && desc != -1)
++    ret = acl_set_fd (desc, acl);
++  else
++    ret = acl_set_file (name, ACL_TYPE_ACCESS, acl);
++  if (ret != 0)
++    {
++      int saved_errno = errno;
++      acl_free (acl);
++
++      if (ACL_NOT_WELL_SUPPORTED (errno))
++        return chmod_or_fchmod (name, desc, mode);
++      else
++        {
++          errno = saved_errno;
++          return -1;
++        }
++    }
++  else
++    acl_free (acl);
++
++  if (S_ISDIR (mode) && acl_delete_def_file (name))
++    return -1;
++
++  if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX)))
++    {
++      /* We did not call chmod so far, and either the mode and the ACL are
++         separate or special bits are to be set which don't fit into ACLs.  */
++      return chmod_or_fchmod (name, desc, mode);
++    }
++  return 0;
++
++#  else /* HAVE_ACL_TYPE_EXTENDED */
++  /* Mac OS X */
++
++  /* On Mac OS X,  acl_get_file (name, ACL_TYPE_ACCESS)
++     and           acl_get_file (name, ACL_TYPE_DEFAULT)
++     always return NULL / EINVAL.  You have to use
++                   acl_get_file (name, ACL_TYPE_EXTENDED)
++     or            acl_get_fd (open (name, ...))
++     to retrieve an ACL.
++     On the other hand,
++                   acl_set_file (name, ACL_TYPE_ACCESS, acl)
++     and           acl_set_file (name, ACL_TYPE_DEFAULT, acl)
++     have the same effect as
++                   acl_set_file (name, ACL_TYPE_EXTENDED, acl):
++     Each of these calls sets the file's ACL.  */
++
++  acl_t acl;
++  int ret;
++
++  /* Remove the ACL if the file has ACLs.  */
++  if (HAVE_ACL_GET_FD && desc != -1)
++    acl = acl_get_fd (desc);
++  else
++    acl = acl_get_file (name, ACL_TYPE_EXTENDED);
++  if (acl)
++    {
++      acl_free (acl);
++
++      acl = acl_init (0);
++      if (acl)
++        {
++          if (HAVE_ACL_SET_FD && desc != -1)
++            ret = acl_set_fd (desc, acl);
++          else
++            ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl);
++          if (ret != 0)
++            {
++              int saved_errno = errno;
++
++              acl_free (acl);
++
++              if (ACL_NOT_WELL_SUPPORTED (saved_errno))
++                return chmod_or_fchmod (name, desc, mode);
++              else
++                {
++                  errno = saved_errno;
++                  return -1;
++                }
++            }
++          acl_free (acl);
++        }
++    }
++
++  /* Since !MODE_INSIDE_ACL, we have to call chmod explicitly.  */
++  return chmod_or_fchmod (name, desc, mode);
++#  endif
++
++# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
++
++  int done_setacl = 0;
++
++#  ifdef ACE_GETACL
++  /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
++     file systems (whereas the other ones are used in UFS file systems).  */
++
++  /* The flags in the ace_t structure changed in a binary incompatible way
++     when ACL_NO_TRIVIAL etc. were introduced in <sys/acl.h> version 1.15.
++     How to distinguish the two conventions at runtime?
++     We fetch the existing ACL.  In the old convention, usually three ACEs have
++     a_flags = ACE_OWNER / ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400.
++     In the new convention, these values are not used.  */
++  int convention;
++
++  {
++    /* Initially, try to read the entries into a stack-allocated buffer.
++       Use malloc if it does not fit.  */
++    enum
++      {
++        alloc_init = 4000 / sizeof (ace_t), /* >= 3 */
++        alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t))
++      };
++    ace_t buf[alloc_init];
++    size_t alloc = alloc_init;
++    ace_t *entries = buf;
++    ace_t *malloced = NULL;
++    int count;
++
++    for (;;)
++      {
++        count = (desc != -1
++                 ? facl (desc, ACE_GETACL, alloc, entries)
++                 : acl (name, ACE_GETACL, alloc, entries));
++        if (count < 0 && errno == ENOSPC)
++          {
++            /* Increase the size of the buffer.  */
++            free (malloced);
++            if (alloc > alloc_max / 2)
++              {
++                errno = ENOMEM;
++                return -1;
++              }
++            alloc = 2 * alloc; /* <= alloc_max */
++            entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t));
++            if (entries == NULL)
++              {
++                errno = ENOMEM;
++                return -1;
++              }
++            continue;
++          }
++        break;
++      }
++
++    if (count <= 0)
++      convention = -1;
++    else
++      {
++        int i;
++
++        convention = 0;
++        for (i = 0; i < count; i++)
++          if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER))
++            {
++              convention = 1;
++              break;
++            }
++      }
++    free (malloced);
++  }
++
++  if (convention >= 0)
++    {
++      ace_t entries[6];
++      int count;
++      int ret;
++
++      if (convention)
++        {
++          /* Running on Solaris 10.  */
++          entries[0].a_type = OLD_ALLOW;
++          entries[0].a_flags = OLD_ACE_OWNER;
++          entries[0].a_who = 0; /* irrelevant */
++          entries[0].a_access_mask = (mode >> 6) & 7;
++          entries[1].a_type = OLD_ALLOW;
++          entries[1].a_flags = OLD_ACE_GROUP;
++          entries[1].a_who = 0; /* irrelevant */
++          entries[1].a_access_mask = (mode >> 3) & 7;
++          entries[2].a_type = OLD_ALLOW;
++          entries[2].a_flags = OLD_ACE_OTHER;
++          entries[2].a_who = 0;
++          entries[2].a_access_mask = mode & 7;
++          count = 3;
++        }
++      else
++        {
++          /* Running on Solaris 10 (newer version) or Solaris 11.
++             The details here were found through "/bin/ls -lvd somefiles".  */
++          entries[0].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE;
++          entries[0].a_flags = NEW_ACE_OWNER;
++          entries[0].a_who = 0; /* irrelevant */
++          entries[0].a_access_mask = 0;
++          entries[1].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE;
++          entries[1].a_flags = NEW_ACE_OWNER;
++          entries[1].a_who = 0; /* irrelevant */
++          entries[1].a_access_mask = NEW_ACE_WRITE_NAMED_ATTRS
++                                     | NEW_ACE_WRITE_ATTRIBUTES
++                                     | NEW_ACE_WRITE_ACL
++                                     | NEW_ACE_WRITE_OWNER;
++          if (mode & 0400)
++            entries[1].a_access_mask |= NEW_ACE_READ_DATA;
++          else
++            entries[0].a_access_mask |= NEW_ACE_READ_DATA;
++          if (mode & 0200)
++            entries[1].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA;
++          else
++            entries[0].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA;
++          if (mode & 0100)
++            entries[1].a_access_mask |= NEW_ACE_EXECUTE;
++          else
++            entries[0].a_access_mask |= NEW_ACE_EXECUTE;
++          entries[2].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE;
++          entries[2].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP;
++          entries[2].a_who = 0; /* irrelevant */
++          entries[2].a_access_mask = 0;
++          entries[3].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE;
++          entries[3].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP;
++          entries[3].a_who = 0; /* irrelevant */
++          entries[3].a_access_mask = 0;
++          if (mode & 0040)
++            entries[3].a_access_mask |= NEW_ACE_READ_DATA;
++          else
++            entries[2].a_access_mask |= NEW_ACE_READ_DATA;
++          if (mode & 0020)
++            entries[3].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA;
++          else
++            entries[2].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA;
++          if (mode & 0010)
++            entries[3].a_access_mask |= NEW_ACE_EXECUTE;
++          else
++            entries[2].a_access_mask |= NEW_ACE_EXECUTE;
++          entries[4].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE;
++          entries[4].a_flags = NEW_ACE_EVERYONE;
++          entries[4].a_who = 0;
++          entries[4].a_access_mask = NEW_ACE_WRITE_NAMED_ATTRS
++                                     | NEW_ACE_WRITE_ATTRIBUTES
++                                     | NEW_ACE_WRITE_ACL
++                                     | NEW_ACE_WRITE_OWNER;
++          entries[5].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE;
++          entries[5].a_flags = NEW_ACE_EVERYONE;
++          entries[5].a_who = 0;
++          entries[5].a_access_mask = NEW_ACE_READ_NAMED_ATTRS
++                                     | NEW_ACE_READ_ATTRIBUTES
++                                     | NEW_ACE_READ_ACL
++                                     | NEW_ACE_SYNCHRONIZE;
++          if (mode & 0004)
++            entries[5].a_access_mask |= NEW_ACE_READ_DATA;
++          else
++            entries[4].a_access_mask |= NEW_ACE_READ_DATA;
++          if (mode & 0002)
++            entries[5].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA;
++          else
++            entries[4].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA;
++          if (mode & 0001)
++            entries[5].a_access_mask |= NEW_ACE_EXECUTE;
++          else
++            entries[4].a_access_mask |= NEW_ACE_EXECUTE;
++          count = 6;
++        }
++      if (desc != -1)
++        ret = facl (desc, ACE_SETACL, count, entries);
++      else
++        ret = acl (name, ACE_SETACL, count, entries);
++      if (ret < 0 && errno != EINVAL && errno != ENOTSUP)
++        {
++          if (errno == ENOSYS)
++            return chmod_or_fchmod (name, desc, mode);
++          return -1;
++        }
++      if (ret == 0)
++        done_setacl = 1;
++    }
++#  endif
++
++  if (!done_setacl)
++    {
++      aclent_t entries[3];
++      int ret;
++
++      entries[0].a_type = USER_OBJ;
++      entries[0].a_id = 0; /* irrelevant */
++      entries[0].a_perm = (mode >> 6) & 7;
++      entries[1].a_type = GROUP_OBJ;
++      entries[1].a_id = 0; /* irrelevant */
++      entries[1].a_perm = (mode >> 3) & 7;
++      entries[2].a_type = OTHER_OBJ;
++      entries[2].a_id = 0;
++      entries[2].a_perm = mode & 7;
++
++      if (desc != -1)
++        ret = facl (desc, SETACL,
++                    sizeof (entries) / sizeof (aclent_t), entries);
++      else
++        ret = acl (name, SETACL,
++                   sizeof (entries) / sizeof (aclent_t), entries);
++      if (ret < 0)
++        {
++          if (errno == ENOSYS || errno == EOPNOTSUPP)
++            return chmod_or_fchmod (name, desc, mode);
++          return -1;
++        }
++    }
++
++  if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX)))
++    {
++      /* We did not call chmod so far, so the special bits have not yet
++         been set.  */
++      return chmod_or_fchmod (name, desc, mode);
++    }
++  return 0;
++
++# elif HAVE_GETACL /* HP-UX */
++
++  struct stat statbuf;
++  int ret;
++
++  if (desc != -1)
++    ret = fstat (desc, &statbuf);
++  else
++    ret = stat (name, &statbuf);
++  if (ret < 0)
++    return -1;
++
++  {
++    struct acl_entry entries[3];
++
++    entries[0].uid = statbuf.st_uid;
++    entries[0].gid = ACL_NSGROUP;
++    entries[0].mode = (mode >> 6) & 7;
++    entries[1].uid = ACL_NSUSER;
++    entries[1].gid = statbuf.st_gid;
++    entries[1].mode = (mode >> 3) & 7;
++    entries[2].uid = ACL_NSUSER;
++    entries[2].gid = ACL_NSGROUP;
++    entries[2].mode = mode & 7;
++
++    if (desc != -1)
++      ret = fsetacl (desc, sizeof (entries) / sizeof (struct acl_entry), entries);
++    else
++      ret = setacl (name, sizeof (entries) / sizeof (struct acl_entry), entries);
++  }
++  if (ret < 0)
++    {
++      if (!(errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP))
++        return -1;
++
++#  if HAVE_ACLV_H /* HP-UX >= 11.11 */
++      {
++        struct acl entries[4];
++
++        entries[0].a_type = USER_OBJ;
++        entries[0].a_id = 0; /* irrelevant */
++        entries[0].a_perm = (mode >> 6) & 7;
++        entries[1].a_type = GROUP_OBJ;
++        entries[1].a_id = 0; /* irrelevant */
++        entries[1].a_perm = (mode >> 3) & 7;
++        entries[2].a_type = CLASS_OBJ;
++        entries[2].a_id = 0;
++        entries[2].a_perm = (mode >> 3) & 7;
++        entries[3].a_type = OTHER_OBJ;
++        entries[3].a_id = 0;
++        entries[3].a_perm = mode & 7;
++
++        ret = aclsort (sizeof (entries) / sizeof (struct acl), 1, entries);
++        if (ret > 0)
++          abort ();
++        if (ret < 0)
++          {
++            if (0)
++              return chmod_or_fchmod (name, desc, mode);
++            return -1;
++          }
++
++        ret = acl ((char *) name, ACL_SET,
++                   sizeof (entries) / sizeof (struct acl), entries);
++        if (ret < 0)
++          {
++            if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
++              return chmod_or_fchmod (name, desc, mode);
++            return -1;
++          }
++      }
++#  else
++      return chmod_or_fchmod (name, desc, mode);
++#  endif
++    }
++
++  if (mode & (S_ISUID | S_ISGID | S_ISVTX))
++    {
++      /* We did not call chmod so far, so the special bits have not yet
++         been set.  */
++      return chmod_or_fchmod (name, desc, mode);
++    }
++  return 0;
++
++# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */
++
++  acl_type_list_t types;
++  size_t types_size = sizeof (types);
++  acl_type_t type;
++
++  if (aclx_gettypes (name, &types, &types_size) < 0
++      || types.num_entries == 0)
++    return chmod_or_fchmod (name, desc, mode);
++
++  /* XXX Do we need to clear all types of ACLs for the given file, or is it
++     sufficient to clear the first one?  */
++  type = types.entries[0];
++  if (type.u64 == ACL_AIXC)
++    {
++      union { struct acl a; char room[128]; } u;
++      int ret;
++
++      u.a.acl_len = (char *) &u.a.acl_ext[0] - (char *) &u.a; /* no entries */
++      u.a.acl_mode = mode & ~(S_IXACL | 0777);
++      u.a.u_access = (mode >> 6) & 7;
++      u.a.g_access = (mode >> 3) & 7;
++      u.a.o_access = mode & 7;
++
++      if (desc != -1)
++        ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS,
++                         type, &u.a, u.a.acl_len, mode);
++      else
++        ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS,
++                        type, &u.a, u.a.acl_len, mode);
++      if (!(ret < 0 && errno == ENOSYS))
++        return ret;
++    }
++  else if (type.u64 == ACL_NFS4)
++    {
++      union { nfs4_acl_int_t a; char room[128]; } u;
++      nfs4_ace_int_t *ace;
++      int ret;
++
++      u.a.aclVersion = NFS4_ACL_INT_STRUCT_VERSION;
++      u.a.aclEntryN = 0;
++      ace = &u.a.aclEntry[0];
++      {
++        ace->flags = ACE4_ID_SPECIAL;
++        ace->aceWho.special_whoid = ACE4_WHO_OWNER;
++        ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE;
++        ace->aceFlags = 0;
++        ace->aceMask =
++          (mode & 0400 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0)
++          | (mode & 0200
++             ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA
++               | ACE4_ADD_SUBDIRECTORY
++             : 0)
++          | (mode & 0100 ? ACE4_EXECUTE : 0);
++        ace->aceWhoString[0] = '\0';
++        ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace;
++        ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4];
++        u.a.aclEntryN++;
++      }
++      {
++        ace->flags = ACE4_ID_SPECIAL;
++        ace->aceWho.special_whoid = ACE4_WHO_GROUP;
++        ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE;
++        ace->aceFlags = 0;
++        ace->aceMask =
++          (mode & 0040 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0)
++          | (mode & 0020
++             ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA
++               | ACE4_ADD_SUBDIRECTORY
++             : 0)
++          | (mode & 0010 ? ACE4_EXECUTE : 0);
++        ace->aceWhoString[0] = '\0';
++        ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace;
++        ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4];
++        u.a.aclEntryN++;
++      }
++      {
++        ace->flags = ACE4_ID_SPECIAL;
++        ace->aceWho.special_whoid = ACE4_WHO_EVERYONE;
++        ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE;
++        ace->aceFlags = 0;
++        ace->aceMask =
++          (mode & 0004 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0)
++          | (mode & 0002
++             ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA
++               | ACE4_ADD_SUBDIRECTORY
++             : 0)
++          | (mode & 0001 ? ACE4_EXECUTE : 0);
++        ace->aceWhoString[0] = '\0';
++        ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace;
++        ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4];
++        u.a.aclEntryN++;
++      }
++      u.a.aclLength = (char *) ace - (char *) &u.a;
++
++      if (desc != -1)
++        ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS,
++                         type, &u.a, u.a.aclLength, mode);
++      else
++        ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS,
++                        type, &u.a, u.a.aclLength, mode);
++      if (!(ret < 0 && errno == ENOSYS))
++        return ret;
++    }
++
++  return chmod_or_fchmod (name, desc, mode);
++
++# elif HAVE_STATACL /* older AIX */
++
++  union { struct acl a; char room[128]; } u;
++  int ret;
++
++  u.a.acl_len = (char *) &u.a.acl_ext[0] - (char *) &u.a; /* no entries */
++  u.a.acl_mode = mode & ~(S_IXACL | 0777);
++  u.a.u_access = (mode >> 6) & 7;
++  u.a.g_access = (mode >> 3) & 7;
++  u.a.o_access = mode & 7;
++
++  if (desc != -1)
++    ret = fchacl (desc, &u.a, u.a.acl_len);
++  else
++    ret = chacl (name, &u.a, u.a.acl_len);
++
++  if (ret < 0 && errno == ENOSYS)
++    return chmod_or_fchmod (name, desc, mode);
++
++  return ret;
++
++# elif HAVE_ACLSORT /* NonStop Kernel */
++
++  struct acl entries[4];
++  int ret;
++
++  entries[0].a_type = USER_OBJ;
++  entries[0].a_id = 0; /* irrelevant */
++  entries[0].a_perm = (mode >> 6) & 7;
++  entries[1].a_type = GROUP_OBJ;
++  entries[1].a_id = 0; /* irrelevant */
++  entries[1].a_perm = (mode >> 3) & 7;
++  entries[2].a_type = CLASS_OBJ;
++  entries[2].a_id = 0;
++  entries[2].a_perm = (mode >> 3) & 7;
++  entries[3].a_type = OTHER_OBJ;
++  entries[3].a_id = 0;
++  entries[3].a_perm = mode & 7;
++
++  ret = aclsort (sizeof (entries) / sizeof (struct acl), 1, entries);
++  if (ret > 0)
++    abort ();
++  if (ret < 0)
++    {
++      if (0)
++        return chmod_or_fchmod (name, desc, mode);
++      return -1;
++    }
++
++  ret = acl ((char *) name, ACL_SET,
++             sizeof (entries) / sizeof (struct acl), entries);
++  if (ret < 0)
++    {
++      if (0)
++        return chmod_or_fchmod (name, desc, mode);
++      return -1;
++    }
++
++  if (mode & (S_ISUID | S_ISGID | S_ISVTX))
++    {
++      /* We did not call chmod so far, so the special bits have not yet
++         been set.  */
++      return chmod_or_fchmod (name, desc, mode);
++    }
++  return 0;
++
++# else /* Unknown flavor of ACLs */
++  return chmod_or_fchmod (name, desc, mode);
++# endif
++#else /* !USE_ACL */
++  return chmod_or_fchmod (name, desc, mode);
++#endif
++}
++
++/* As with qset_acl, but also output a diagnostic on failure.  */
++
++int
++set_acl (char const *name, int desc, mode_t mode)
++{
++  int ret = qset_acl (name, desc, mode);
++  if (ret != 0)
++    error (0, errno, _("setting permissions for %s"), quote (name));
++  return ret;
++}
+diff --git a/m4/acl.m4 b/m4/acl.m4
+new file mode 100644
+index 0000000..19aa548
+--- /dev/null
++++ b/m4/acl.m4
+@@ -0,0 +1,165 @@
++# acl.m4 - check for access control list (ACL) primitives
++# serial 14
++
++# Copyright (C) 2002, 2004-2012 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.
++
++# Written by Paul Eggert and Jim Meyering.
++
++AC_DEFUN([gl_FUNC_ACL],
++[
++  AC_ARG_ENABLE([acl],
++    AS_HELP_STRING([--disable-acl], [do not support ACLs]),
++    , [enable_acl=auto])
++
++  LIB_ACL=
++  use_acl=0
++  AC_REQUIRE([AC_C_INLINE])
++  if test "x$enable_acl" != "xno"; then
++    dnl On all platforms, the ACL related API is declared in <sys/acl.h>.
++    AC_CHECK_HEADERS([sys/acl.h])
++    if test $ac_cv_header_sys_acl_h = yes; then
++      ac_save_LIBS=$LIBS
++
++      dnl Test for POSIX-draft-like API (Linux, FreeBSD, Mac OS X, IRIX, Tru64).
++      dnl -lacl is needed on Linux, -lpacl is needed on OSF/1.
++      if test $use_acl = 0; then
++        AC_SEARCH_LIBS([acl_get_file], [acl pacl],
++          [if test "$ac_cv_search_acl_get_file" != "none required"; then
++             LIB_ACL=$ac_cv_search_acl_get_file
++           fi
++           AC_CHECK_FUNCS(
++             [acl_get_file acl_get_fd acl_set_file acl_set_fd \
++              acl_free acl_from_mode acl_from_text \
++              acl_delete_def_file acl_extended_file \
++              acl_delete_fd_np acl_delete_file_np \
++              acl_copy_ext_native acl_create_entry_np \
++              acl_to_short_text acl_free_text])
++           # If the acl_get_file bug is detected, don't enable the ACL support.
++           gl_ACL_GET_FILE([use_acl=1], [])
++           if test $use_acl = 1; then
++             dnl On Linux, additional API is declared in <acl/libacl.h>.
++             AC_CHECK_HEADERS([acl/libacl.h])
++             AC_REPLACE_FUNCS([acl_entries])
++             AC_CACHE_CHECK([for ACL_FIRST_ENTRY],
++               [gl_cv_acl_ACL_FIRST_ENTRY],
++               [AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
++[[#include <sys/types.h>
++#include <sys/acl.h>
++int type = ACL_FIRST_ENTRY;]])],
++                  [gl_cv_acl_ACL_FIRST_ENTRY=yes],
++                  [gl_cv_acl_ACL_FIRST_ENTRY=no])])
++             if test $gl_cv_acl_ACL_FIRST_ENTRY = yes; then
++               AC_DEFINE([HAVE_ACL_FIRST_ENTRY], [1],
++                 [Define to 1 if the constant ACL_FIRST_ENTRY exists.])
++             fi
++             dnl On Mac OS X, other types of ACLs are supported.
++             AC_CACHE_CHECK([for ACL_TYPE_EXTENDED],
++               [gl_cv_acl_ACL_TYPE_EXTENDED],
++               [AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
++[[#include <sys/types.h>
++#include <sys/acl.h>
++int type = ACL_TYPE_EXTENDED;]])],
++                  [gl_cv_acl_ACL_TYPE_EXTENDED=yes],
++                  [gl_cv_acl_ACL_TYPE_EXTENDED=no])])
++             if test $gl_cv_acl_ACL_TYPE_EXTENDED = yes; then
++               AC_DEFINE([HAVE_ACL_TYPE_EXTENDED], [1],
++                 [Define to 1 if the ACL type ACL_TYPE_EXTENDED exists.])
++             fi
++           else
++             LIB_ACL=
++           fi
++          ])
++      fi
++
++      dnl Test for Solaris API (Solaris, Cygwin).
++      if test $use_acl = 0; then
++        AC_CHECK_FUNCS([facl])
++        if test $ac_cv_func_facl = yes; then
++          AC_SEARCH_LIBS([acl_trivial], [sec],
++            [if test "$ac_cv_search_acl_trivial" != "none required"; then
++               LIB_ACL=$ac_cv_search_acl_trivial
++             fi
++            ])
++          AC_CHECK_FUNCS([acl_trivial])
++          use_acl=1
++        fi
++      fi
++
++      dnl Test for HP-UX API.
++      if test $use_acl = 0; then
++        AC_CHECK_FUNCS([getacl])
++        if test $ac_cv_func_getacl = yes; then
++          use_acl=1
++        fi
++        dnl Test for HP-UX 11.11 API.
++        AC_CHECK_HEADERS([aclv.h], [], [], [#include <sys/types.h>])
++      fi
++
++      dnl Test for AIX API (AIX 5.3 or newer).
++      if test $use_acl = 0; then
++        AC_CHECK_FUNCS([aclx_get])
++        if test $ac_cv_func_aclx_get = yes; then
++          use_acl=1
++        fi
++      fi
++
++      dnl Test for older AIX API.
++      if test $use_acl = 0 || test "$ac_cv_func_aclx_get" = yes; then
++        AC_CHECK_FUNCS([statacl])
++        if test $ac_cv_func_statacl = yes; then
++          use_acl=1
++        fi
++      fi
++
++      dnl Test for NonStop Kernel API.
++      if test $use_acl = 0; then
++        AC_CHECK_FUNCS([aclsort])
++        if test $ac_cv_func_aclsort = yes; then
++          use_acl=1
++        fi
++      fi
++
++      LIBS=$ac_save_LIBS
++    fi
++    if test "x$enable_acl$use_acl" = "xyes0"; then
++      AC_MSG_ERROR([ACLs enabled but support not detected])
++    elif test "x$enable_acl$use_acl" = "xauto0"; then
++      AC_MSG_WARN([libacl development library was not found or not usable.])
++      AC_MSG_WARN([AC_PACKAGE_NAME will be built without ACL support.])
++    fi
++  fi
++  AC_SUBST([LIB_ACL])
++  AC_DEFINE_UNQUOTED([USE_ACL], [$use_acl],
++    [Define to nonzero if you want access control list support.])
++  USE_ACL=$use_acl
++  AC_SUBST([USE_ACL])
++])
++
++# gl_ACL_GET_FILE(IF-WORKS, IF-NOT)
++# -------------------------------------
++# If 'acl_get_file' works (does not have a particular bug),
++# run IF-WORKS, otherwise, IF-NOT.
++# This tests for a Darwin 8.7.0 bug, whereby acl_get_file returns NULL,
++# but sets errno = ENOENT for an existing file or directory.
++AC_DEFUN([gl_ACL_GET_FILE],
++[
++  AC_CACHE_CHECK([for working acl_get_file], [gl_cv_func_working_acl_get_file],
++    [AC_RUN_IFELSE(
++       [AC_LANG_PROGRAM(
++          [[#include <sys/types.h>
++           #include <sys/acl.h>
++           #include <errno.h>
++          ]],
++          [[if (!acl_get_file (".", ACL_TYPE_ACCESS) && errno == ENOENT)
++              return 1;
++            return 0;
++          ]])],
++       [gl_cv_func_working_acl_get_file=yes],
++       [gl_cv_func_working_acl_get_file=no],
++       [gl_cv_func_working_acl_get_file=cross-compiling])])
++
++  AS_IF([test $gl_cv_func_working_acl_get_file = yes], [$1], [$2])
++])
+diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
+index 837538e..147ecc0 100644
+--- a/m4/gnulib-comp.m4
++++ b/m4/gnulib-comp.m4
+@@ -1,6 +1,3 @@
+-# -*- buffer-read-only: t -*- vi: set ro:
+-# DO NOT EDIT! GENERATED AUTOMATICALLY!
+-# DO NOT EDIT! GENERATED AUTOMATICALLY!
+ # Copyright (C) 2002-2011 Free Software Foundation, Inc.
+ #
+ # This file is free software, distributed under the terms of the GNU
+@@ -256,6 +253,7 @@ AC_DEFUN([gl_INIT],
+   gl_source_base='gnu'
+   # Code from module alloca:
+   # Code from module alloca-opt:
++  gl_FUNC_ACL
+   gl_FUNC_ALLOCA
+   # Code from module areadlink:
+   # Code from module areadlinkat:
+@@ -565,6 +563,15 @@ AC_DEFUN([gl_INIT],
+   gl_SAVE_CWD
+   # Code from module savedir:
+   gl_SAVEDIR
++  # Code from module acl:
++  AC_CHECK_HEADERS([selinux/flask.h])
++  AC_LIBOBJ([selinux-at])
++  gl_HEADERS_SELINUX_SELINUX_H
++  gl_HEADERS_SELINUX_CONTEXT_H
++  AC_REQUIRE([AC_C_INLINE])
++  if test "$with_selinux" != no && test "$ac_cv_header_selinux_selinux_h" = yes; then
++    AC_LIBOBJ([getfilecon])
++  fi
+   # Code from module setenv:
+   gl_FUNC_SETENV
+   gl_STDLIB_MODULE_INDICATOR([setenv])
+@@ -875,10 +882,14 @@ AC_DEFUN([gltests_LIBSOURCES], [
+ AC_DEFUN([gl_FILE_LIST], [
+   build-aux/arg-nonnull.h
+   build-aux/c++defs.h
++  build-aux/snippet/unused-parameter.h
+   build-aux/config.rpath
+   build-aux/gitlog-to-changelog
+   build-aux/warn-on-use.h
+   doc/parse-datetime.texi
++  lib/acl-internal.h
++  lib/acl.h
++  lib/acl_entries.c
+   lib/alloca.c
+   lib/alloca.in.h
+   lib/anytostr.c
+@@ -928,6 +939,7 @@ AC_DEFUN([gl_FILE_LIST], [
+   lib/closeout.c
+   lib/closeout.h
+   lib/config.charset
++  lib/copy-acl.c
+   lib/dirent--.h
+   lib/dirent-safer.h
+   lib/dirent.in.h
+@@ -955,6 +967,7 @@ AC_DEFUN([gl_FILE_LIST], [
+   lib/fd-safer.c
+   lib/fdopendir.c
+   lib/fdutimensat.c
++  lib/file-has-acl.c
+   lib/fileblocks.c
+   lib/filenamecat-lgpl.c
+   lib/filenamecat.h
+@@ -1083,6 +1096,11 @@ AC_DEFUN([gl_FILE_LIST], [
+   lib/save-cwd.h
+   lib/savedir.c
+   lib/savedir.h
++  lib/se-context.in.h
++  lib/se-selinux.in.h
++  lib/selinux-at.c
++  lib/selinux-at.h
++  lib/set-mode-acl.c
+   lib/setenv.c
+   lib/size_max.h
+   lib/sleep.c
+@@ -1176,6 +1194,7 @@ AC_DEFUN([gl_FILE_LIST], [
+   lib/xvasprintf.c
+   lib/xvasprintf.h
+   m4/00gnulib.m4
++  m4/acl.m4
+   m4/alloca.m4
+   m4/argmatch.m4
+   m4/argp.m4
+@@ -1314,6 +1333,8 @@ AC_DEFUN([gl_FILE_LIST], [
+   m4/safe-write.m4
+   m4/save-cwd.m4
+   m4/savedir.m4
++  m4/selinux-context-h.m4
++  m4/selinux-selinux-h.m4
+   m4/setenv.m4
+   m4/size_max.m4
+   m4/sleep.m4
+diff --git a/m4/selinux-context-h.m4 b/m4/selinux-context-h.m4
+new file mode 100644
+index 0000000..7ad67bb
+--- /dev/null
++++ b/m4/selinux-context-h.m4
+@@ -0,0 +1,22 @@
++# serial 3   -*- Autoconf -*-
++# Copyright (C) 2006-2007, 2009-2012 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.
++
++# From Jim Meyering
++# Provide <selinux/context.h>, if necessary.
++
++AC_DEFUN([gl_HEADERS_SELINUX_CONTEXT_H],
++[
++  AC_REQUIRE([gl_LIBSELINUX])
++  if test "$with_selinux" != no; then
++    AC_CHECK_HEADERS([selinux/context.h],
++                     [SELINUX_CONTEXT_H=],
++                     [SELINUX_CONTEXT_H=selinux/context.h])
++  else
++    SELINUX_CONTEXT_H=selinux/context.h
++  fi
++  AC_SUBST([SELINUX_CONTEXT_H])
++  AM_CONDITIONAL([GL_GENERATE_SELINUX_CONTEXT_H], [test -n "$SELINUX_CONTEXT_H"])
++])
+diff --git a/m4/selinux-selinux-h.m4 b/m4/selinux-selinux-h.m4
+new file mode 100644
+index 0000000..ed5215b
+--- /dev/null
++++ b/m4/selinux-selinux-h.m4
+@@ -0,0 +1,69 @@
++# serial 5   -*- Autoconf -*-
++# Copyright (C) 2006-2007, 2009-2012 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.
++
++# From Jim Meyering
++# Provide <selinux/selinux.h>, if necessary.
++# If it is already present, provide wrapper functions to guard against
++# misbehavior from getfilecon, lgetfilecon, and fgetfilecon.
++
++AC_DEFUN([gl_HEADERS_SELINUX_SELINUX_H],
++[
++  AC_REQUIRE([gl_LIBSELINUX])
++  if test "$with_selinux" != no; then
++    AC_CHECK_HEADERS([selinux/selinux.h])
++
++    if test "$ac_cv_header_selinux_selinux_h" = yes; then
++      # We do have <selinux/selinux.h>, so do compile getfilecon.c
++      # and arrange to use its wrappers.
++      gl_CHECK_NEXT_HEADERS([selinux/selinux.h])
++      AC_DEFINE([getfilecon], [rpl_getfilecon],
++                [Always use our getfilecon wrapper.])
++      AC_DEFINE([lgetfilecon], [rpl_lgetfilecon],
++                [Always use our lgetfilecon wrapper.])
++      AC_DEFINE([fgetfilecon], [rpl_fgetfilecon],
++                [Always use our fgetfilecon wrapper.])
++    fi
++
++    case "$ac_cv_search_setfilecon:$ac_cv_header_selinux_selinux_h" in
++      no:*) # already warned
++        ;;
++      *:no)
++        AC_MSG_WARN([libselinux was found but selinux/selinux.h is missing.])
++        AC_MSG_WARN([AC_PACKAGE_NAME will be compiled without SELinux support.])
++    esac
++  else
++    # Do as if <selinux/selinux.h> does not exist, even if
++    # AC_CHECK_HEADERS_ONCE has already determined that it exists.
++    AC_DEFINE([HAVE_SELINUX_SELINUX_H], [0])
++  fi
++])
++
++AC_DEFUN([gl_LIBSELINUX],
++[
++  AC_REQUIRE([AC_CANONICAL_HOST])
++  AC_REQUIRE([AC_CANONICAL_BUILD])
++
++  AC_ARG_WITH([selinux],
++    AS_HELP_STRING([--without-selinux], [do not use SELinux, even on systems with SELinux]),
++    [], [with_selinux=maybe])
++
++  LIB_SELINUX=
++  if test "$with_selinux" != no; then
++    gl_save_LIBS=$LIBS
++    AC_SEARCH_LIBS([setfilecon], [selinux],
++                   [test "$ac_cv_search_setfilecon" = "none required" ||
++                    LIB_SELINUX=$ac_cv_search_setfilecon])
++    LIBS=$gl_save_LIBS
++  fi
++  AC_SUBST([LIB_SELINUX])
++
++  # Warn if SELinux is found but libselinux is absent;
++  if test "$ac_cv_search_setfilecon" = no &&
++     test "$host" = "$build" && test -d /selinux; then
++    AC_MSG_WARN([This system supports SELinux but libselinux is missing.])
++    AC_MSG_WARN([AC_PACKAGE_NAME will be compiled without SELinux support.])
++  fi
++])
+-- 
+1.8.1.2
+
diff --git a/SOURCES/tar-1.26-silence-gcc.patch b/SOURCES/tar-1.26-silence-gcc.patch
new file mode 100644
index 0000000..3286a1b
--- /dev/null
+++ b/SOURCES/tar-1.26-silence-gcc.patch
@@ -0,0 +1,152 @@
+diff --git a/lib/rmt.h b/lib/rmt.h
+index 2ce9dc5..4580e49 100644
+--- a/lib/rmt.h
++++ b/lib/rmt.h
+@@ -17,8 +17,9 @@
+    along with this program; if not, write to the Free Software Foundation,
+    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+ 
+-extern char *rmt_command;
+-extern char *rmt_dev_name__;
++/* upstream fix 0b3d84a0ee */
++extern char const *rmt_command;
++extern char const *rmt_dev_name__;
+ 
+ int rmt_open__ (const char *, int, int, const char *);
+ int rmt_close__ (int);
+diff --git a/lib/rtapelib.c b/lib/rtapelib.c
+index 3aee428..1cef0fc 100644
+--- a/lib/rtapelib.c
++++ b/lib/rtapelib.c
+@@ -90,10 +90,10 @@ static int from_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
+ /* The pipes for sending data to remote tape drives.  */
+ static int to_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
+ 
+-char *rmt_command = DEFAULT_RMT_COMMAND;
++char const *rmt_command = DEFAULT_RMT_COMMAND; /* upstream fix 0b3d84a0ee */
+ 
+ /* Temporary variable used by macros in rmt.h.  */
+-char *rmt_dev_name__;
++char const *rmt_dev_name__; /* upstream fix 0b3d84a0ee */
+ 
+ /* If true, always consider file names to be local, even if they contain
+    colons */
+@@ -490,15 +490,17 @@ rmt_open__ (const char *file_name, int open_mode, int bias,
+       {
+ 	/* Child.  */
+ 
+-	close (STDIN_FILENO);
+-	dup (to_remote[remote_pipe_number][PREAD]);
+-	close (to_remote[remote_pipe_number][PREAD]);
+-	close (to_remote[remote_pipe_number][PWRITE]);
+-
+-	close (STDOUT_FILENO);
+-	dup (from_remote[remote_pipe_number][PWRITE]);
+-	close (from_remote[remote_pipe_number][PREAD]);
+-	close (from_remote[remote_pipe_number][PWRITE]);
++	/* upstream fix 0b3d84a0ee */
++	if (dup2 (to_remote[remote_pipe_number][PREAD], STDIN_FILENO) < 0
++	    || (to_remote[remote_pipe_number][PREAD] != STDIN_FILENO
++		&& close (to_remote[remote_pipe_number][PREAD]) != 0)
++	    || (to_remote[remote_pipe_number][PWRITE] != STDIN_FILENO
++		&& close (to_remote[remote_pipe_number][PWRITE]) != 0)
++	    || dup2 (from_remote[remote_pipe_number][PWRITE], STDOUT_FILENO) < 0
++	    || close (from_remote[remote_pipe_number][PREAD]) != 0
++	    || close (from_remote[remote_pipe_number][PWRITE]) != 0)
++	  error (EXIT_ON_EXEC_ERROR, errno,
++		 _("Cannot redirect files for remote shell"));
+ 
+ 	sys_reset_uid_gid ();
+ 
+diff --git a/lib/system.h b/lib/system.h
+index 2deb585..599d4ba 100644
+--- a/lib/system.h
++++ b/lib/system.h
+@@ -471,8 +471,13 @@ char *getenv ();
+ # define SET_BINARY_MODE(arc)
+ # define ERRNO_IS_EACCES 0
+ # define TTY_NAME "/dev/tty"
+-# define sys_reset_uid_gid() \
+- do { setuid (getuid ()); setgid (getgid ()); } while (0)
++
++/* upstream fix 0b3d84a0ee */
++# define sys_reset_uid_gid()					\
++  do {								\
++    if (! (setuid (getuid ()) == 0 && setgid (getgid ()) == 0)) \
++      abort ();							\
++  } while (0)
+ #endif
+ 
+ #if XENIX
+diff --git a/src/compare.c b/src/compare.c
+index 273269a..796d7aa 100644
+--- a/src/compare.c
++++ b/src/compare.c
+@@ -362,7 +362,7 @@ static void
+ diff_dumpdir (void)
+ {
+   const char *dumpdir_buffer;
+-  dev_t dev = 0;
++  /* upstream fix 5bb04335079 */
+   struct stat stat_data;
+ 
+   if (deref_stat (current_stat_info.file_name, &stat_data) != 0)
+@@ -372,8 +372,7 @@ diff_dumpdir (void)
+       else
+ 	stat_error (current_stat_info.file_name);
+     }
+-  else
+-    dev = stat_data.st_dev;
++  /* upstream fix 5bb04335079 */
+ 
+   dumpdir_buffer = directory_contents (scan_directory (&current_stat_info));
+ 
+diff --git a/tests/genfile.c b/tests/genfile.c
+index 8541be6..fa480ef 100644
+--- a/tests/genfile.c
++++ b/tests/genfile.c
+@@ -485,9 +485,11 @@ generate_files_from_list ()
+ static void
+ mkhole (int fd, off_t displ)
+ {
+-  if (lseek (fd, displ, SEEK_CUR) == -1)
++  off_t offset = lseek (fd, displ, SEEK_CUR);
++  if (offset < 0)
+     error (EXIT_FAILURE, errno, "lseek");
+-  ftruncate (fd, lseek (fd, 0, SEEK_CUR));
++  if (ftruncate (fd, offset) != 0)
++    error (EXIT_FAILURE, errno, "ftruncate");
+ }
+ 
+ static void
+@@ -685,13 +687,18 @@ exec_checkpoint (struct action *p)
+ 	    error (0, errno, _("cannot open `%s'"), p->name);
+ 	    break;
+ 	  }
+-	ftruncate (fd, p->size);
++	if (ftruncate (fd, p->size) != 0)
++	  {
++	    error (0, errno, _("cannot truncate `%s'"), p->name);
++	    break;
++	  }
+ 	close (fd);
+       }
+       break;
+ 
+     case OPT_EXEC:
+-      system (p->name);
++      if (system (p->name) != 0)
++	error (0, 0, _("command failed: %s"), p->name);
+       break;
+ 
+     case OPT_UNLINK:
+@@ -761,7 +768,8 @@ exec_command (void)
+   signal (SIGCHLD, SIG_DFL);
+ #endif
+ 
+-  pipe (fd);
++  if (pipe (fd) != 0)
++    error (EXIT_FAILURE, errno, "pipe");
+ 
+   pid = fork ();
+   if (pid == -1)
diff --git a/SOURCES/tar-1.26-stdio.in.patch b/SOURCES/tar-1.26-stdio.in.patch
new file mode 100644
index 0000000..dd7856b
--- /dev/null
+++ b/SOURCES/tar-1.26-stdio.in.patch
@@ -0,0 +1,14 @@
+diff --git a/gnu/stdio.in.h b/gnu/stdio.in.h
+index 465a9c9..b703457 100644
+--- a/gnu/stdio.in.h
++++ b/gnu/stdio.in.h
+@@ -164,7 +164,9 @@ _GL_WARN_ON_USE (fflush, "fflush is not always POSIX compliant - "
+    so any use of gets warrants an unconditional warning.  Assume it is
+    always declared, since it is required by C89.  */
+ #undef gets
++#if HAVE_RAW_DECL_GETS
+ _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
++#endif
+ 
+ #if @GNULIB_FOPEN@
+ # if @REPLACE_FOPEN@
diff --git a/SOURCES/tar-1.26-update-with-change-directory.patch b/SOURCES/tar-1.26-update-with-change-directory.patch
new file mode 100644
index 0000000..6a9a0cf
--- /dev/null
+++ b/SOURCES/tar-1.26-update-with-change-directory.patch
@@ -0,0 +1,148 @@
+From 207b445ca7018a95f2f96d9514b8d87c80e8e11e Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Wed, 4 Apr 2012 18:04:53 +0200
+Subject: [PATCH] Bad cooperation of -C and -u options
+
+Previously, tar did not update archive with newly created files in archived
+directory --  it failed instead  with "file not found" error (because it looked
+in bad directory in filesystem).
+---
+ src/update.c       |    4 +-
+ tests/Makefile.am  |    3 +-
+ tests/testsuite.at |    3 +-
+ tests/update03.at  |   59 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 65 insertions(+), 4 deletions(-)
+ create mode 100644 tests/update03.at
+
+diff --git a/src/update.c b/src/update.c
+index e3228d4..4739e0d 100644
+--- a/src/update.c
++++ b/src/update.c
+@@ -1,7 +1,7 @@
+ /* Update a tar archive.
+ 
+    Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
+-   2004, 2005, 2007, 2010 Free Software Foundation, Inc.
++   2004, 2005, 2007, 2010, 2011, 2012 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
+@@ -159,7 +159,7 @@ update_archive (void)
+ 
+ 			    for (p = dirp; *p; p += strlen (p) + 1)
+ 			      addname (namebuf_name (nbuf, p),
+-				       0, false, NULL);
++				       name->change_dir, false, NULL);
+ 
+ 			    namebuf_free (nbuf);
+ 			    free (dirp);
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index ab7d104..119f1f3 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -1,7 +1,7 @@
+ # Makefile for GNU tar regression tests.
+ 
+ # Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003, 2004, 2005,
+-# 2006, 2007, 2009 Free Software Foundation, Inc.
++# 2006, 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+ 
+ # François Pinard <pinard@iro.umontreal.ca>, 1988.
+ # Sergey Poznyakoff <gray@mirddin.farlep.net>, 2004.
+@@ -156,6 +156,7 @@ TESTSUITE_AT = \
+  update.at\
+  update01.at\
+  update02.at\
++ update03.at\
+  volsize.at\
+  volume.at\
+  verbose.at\
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index 8366ef0..13f7506 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -1,7 +1,7 @@
+ # Process this file with autom4te to create testsuite. -*- Autotest -*-
+ 
+ # Test suite for GNU tar.
+-# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Free Software
++# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012 Free Software
+ # Foundation, Inc.
+ 
+ # This program is free software; you can redistribute it and/or modify
+@@ -241,6 +241,7 @@ m4_include([spmvp10.at])
+ m4_include([update.at])
+ m4_include([update01.at])
+ m4_include([update02.at])
++m4_include([update03.at])
+ 
+ m4_include([verify.at])
+ 
+diff --git a/tests/update03.at b/tests/update03.at
+new file mode 100644
+index 0000000..185f9eb
+--- /dev/null
++++ b/tests/update03.at
+@@ -0,0 +1,59 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++
++# Test suite for GNU tar.
++# Copyright (C) 2012 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, 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, write to the Free Software Foundation, Inc., 51 Franklin
++# Street, Fifth Floor, Boston, MA 02110-1301, USA.
++
++# Description:
++#   Test if the '--update' option works with the '--directory DIR' option
++#   properly.  In version <= 1.26 tar this combination caused problems.
++#
++# References:
++#   https://bugzilla.redhat.com/show_bug.cgi?id=688567
++#
++# Last-Affected-Version:  1.26.90
++
++AT_SETUP([update & change directory (-C)])
++AT_KEYWORDS([update update03])
++
++AT_TAR_CHECK([
++AT_SORT_PREREQ
++
++# prepare filesystem
++mkdir dir
++mkdir dir/subdir
++genfile --file dir/subdir/a
++
++# crate archive of subdir
++tar -C dir -cf file.tar subdir
++
++# update filesystem
++mkdir dir/subdir/b
++genfile --file dir/subdir/b/c
++
++# sync the 'file.tar' archive
++tar -C dir -uf file.tar subdir
++
++# print contents
++tar -tf file.tar | sort || exit 1
++],
++[0],
++[subdir/
++subdir/a
++subdir/b/
++subdir/b/c
++])
++
++AT_CLEANUP
+-- 
+1.7.7.6
+
diff --git a/SOURCES/tar-1.26-xattrs-exclude-include-repair.patch b/SOURCES/tar-1.26-xattrs-exclude-include-repair.patch
new file mode 100644
index 0000000..7c214aa
--- /dev/null
+++ b/SOURCES/tar-1.26-xattrs-exclude-include-repair.patch
@@ -0,0 +1,121 @@
+diff -urN tar-1.26/src/xattrs.c tar-1.26new/src/xattrs.c
+--- tar-1.26/src/xattrs.c	2017-01-10 10:58:11.894958586 +0100
++++ tar-1.26new/src/xattrs.c	2017-01-10 11:54:23.418221159 +0100
+@@ -436,8 +436,12 @@
+   clear_mask_map (&xattrs_setup.excl);
+ }
+ 
+-/* get all xattrs from file given by FILE_NAME or FD (when non-zero).  This
+-   includes all the user.*, security.*, system.*, etc. available domains */
++static bool xattrs_masked_out (const char *kw, bool archiving);
++
++/* get xattrs from file given by FILE_NAME or FD (when non-zero)
++   xattrs are checked against the user supplied include/exclude mask
++   if no mask is given this includes all the user.*, security.*, system.*,
++   etc. available domains */
+ void
+ xattrs_xattrs_get (int parentfd, char const *file_name,
+                    struct tar_stat_info *st, int fd)
+@@ -482,8 +486,6 @@
+               size_t len = strlen (attr);
+               ssize_t aret = 0;
+ 
+-              /* Archive all xattrs during creation, decide at extraction time
+-               * which ones are of interest/use for the target filesystem. */
+               while (((fd == 0)
+                       ? ((aret = lgetxattrat (parentfd, file_name, attr,
+                                               val, asz)) == -1)
+@@ -494,7 +496,10 @@
+                 }
+ 
+               if (aret != -1)
+-                xheader_xattr_add (st, attr, val, aret);
++                {
++                  if (!xattrs_masked_out (attr, true))
++                    xheader_xattr_add (st, attr, val, aret);
++                }
+               else if (errno != ENOATTR)
+                 call_arg_warn ((fd == 0) ? "lgetxattrat"
+                                : "fgetxattr", file_name);
+diff -urN tar-1.26/tests/Makefile.am tar-1.26new/tests/Makefile.am
+--- tar-1.26/tests/Makefile.am	2017-01-10 10:58:11.894958586 +0100
++++ tar-1.26new/tests/Makefile.am	2017-01-10 11:53:55.046987231 +0100
+@@ -177,6 +177,7 @@
+  xattr03.at\
+  xattr04.at\
+  xattr05.at\
++ xattr06.at\
+  acls01.at\
+  acls02.at\
+  acls03.at\
+diff -urN tar-1.26/tests/testsuite.at tar-1.26new/tests/testsuite.at
+--- tar-1.26/tests/testsuite.at	2017-01-10 10:58:11.896958604 +0100
++++ tar-1.26new/tests/testsuite.at	2017-01-10 11:53:55.047987240 +0100
+@@ -338,6 +338,7 @@
+ m4_include([xattr03.at])
+ m4_include([xattr04.at])
+ m4_include([xattr05.at])
++m4_include([xattr06.at])
+ 
+ m4_include([acls01.at])
+ m4_include([acls02.at])
+diff -urN tar-1.26/tests/xattr06.at tar-1.26new/tests/xattr06.at
+--- tar-1.26/tests/xattr06.at	1970-01-01 01:00:00.000000000 +0100
++++ tar-1.26new/tests/xattr06.at	2017-01-10 11:54:23.418221159 +0100
+@@ -0,0 +1,56 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright 2012-2014, 2016 Free Software Foundation, Inc.
++
++# This file is part of GNU tar.
++
++# GNU tar 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.
++
++# GNU tar 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/>.
++#
++# Test description:  Test for exclude of xattr during archive creation
++#
++# Relevant mailing list thread:
++#
++# http://lists.gnu.org/archive/html/bug-tar/2016-05/msg00031.html
++
++AT_SETUP([xattrs: exclude xattrs on create ])
++AT_KEYWORDS([xattrs xattr06])
++
++AT_TAR_CHECK([
++AT_XATTRS_PREREQ
++
++mkdir dir
++mkdir output
++genfile --file dir/file
++
++for attr in excluded incla inclb inclc incl_excluded
++do
++  setfattr -n user.${attr} -v value dir/file || AT_SKIP_TEST
++done
++
++tar --xattrs-include=user.incl'*' --xattrs-exclude=user.incl_excluded -cf archive.tar -C dir .
++tar -xf archive.tar --xattrs-include=user.incl[[ab]] --xattrs-exclude=user.inclb -C output
++
++getfattr -d output/file | grep -v \
++    -e excluded \
++    -e inclb \
++    -e inclc > filtered
++getfattr -d output/file > full
++# if they differ then the attribute is still present
++diff filtered full
++],
++[0],
++[])
++
++AT_CLEANUP
diff --git a/SOURCES/tar-1.26-xattrs-include-implies-xattrs.patch b/SOURCES/tar-1.26-xattrs-include-implies-xattrs.patch
new file mode 100644
index 0000000..77db409
--- /dev/null
+++ b/SOURCES/tar-1.26-xattrs-include-implies-xattrs.patch
@@ -0,0 +1,39 @@
+diff --git a/src/tar.c b/src/tar.c
+index e244808..18277e4 100644
+--- a/src/tar.c
++++ b/src/tar.c
+@@ -162,6 +162,14 @@ set_archive_format (char const *name)
+   archive_format = p->fmt;
+ }
+ 
++static void
++set_xattr_option (int value)
++{
++  if (value == 1)
++    set_archive_format ("posix");
++  xattrs_option = value;
++}
++
+ const char *
+ archive_format_string (enum archive_format fmt)
+ {
+@@ -2141,16 +2149,16 @@ parse_opt (int key, char *arg, struct argp_state *state)
+       break;
+ 
+     case XATTR_OPTION:
+-      set_archive_format ("posix");
+-      xattrs_option = 1;
++      set_xattr_option (1);
+       break;
+ 
+     case NO_XATTR_OPTION:
+-      xattrs_option = -1;
++      set_xattr_option (-1);
+       break;
+ 
+     case XATTR_INCLUDE:
+     case XATTR_EXCLUDE:
++      set_xattr_option (1);
+       xattrs_mask_add (arg, (key == XATTR_INCLUDE));
+       break;
+ 
diff --git a/SOURCES/tar-1.26-xattrs-printing.patch b/SOURCES/tar-1.26-xattrs-printing.patch
new file mode 100644
index 0000000..e6a4f0c
--- /dev/null
+++ b/SOURCES/tar-1.26-xattrs-printing.patch
@@ -0,0 +1,36 @@
+diff --git a/src/xattrs.c b/src/xattrs.c
+index 5a4bf72..bdf6ba0 100644
+--- a/src/xattrs.c
++++ b/src/xattrs.c
+@@ -693,7 +693,7 @@ xattrs_print_char (struct tar_stat_info const *st, char *output)
+   if (selinux_context_option > 0 && st->cntx_name)
+     *output = '.';
+ 
+-  if (acls_option && (st->acls_a_len || st->acls_d_len))
++  if (acls_option > 0 && (st->acls_a_len || st->acls_d_len))
+     *output = '+';
+ }
+ 
+@@ -704,11 +704,11 @@ xattrs_print (struct tar_stat_info const *st)
+     return;
+ 
+   /* selinux */
+-  if (selinux_context_option && st->cntx_name)
++  if (selinux_context_option > 0 && st->cntx_name)
+     fprintf (stdlis, "  s: %s\n", st->cntx_name);
+ 
+   /* acls */
+-  if (acls_option && (st->acls_a_len || st->acls_d_len))
++  if (acls_option > 0 && (st->acls_a_len || st->acls_d_len))
+     {
+       fprintf (stdlis, "  a: ");
+       acls_one_line ("", ',', st->acls_a_ptr, st->acls_a_len);
+@@ -717,7 +717,7 @@ xattrs_print (struct tar_stat_info const *st)
+     }
+ 
+   /* xattrs */
+-  if (xattrs_option && st->xattr_map_size)
++  if (xattrs_option > 0 && st->xattr_map_size)
+     {
+       int i;
+       
diff --git a/SOURCES/tar-1.26-xattrs-skip-old-files-hangs.patch b/SOURCES/tar-1.26-xattrs-skip-old-files-hangs.patch
new file mode 100644
index 0000000..8db797d
--- /dev/null
+++ b/SOURCES/tar-1.26-xattrs-skip-old-files-hangs.patch
@@ -0,0 +1,215 @@
+diff --git a/THANKS b/THANKS
+index e87381f..6fa0a9e 100644
+--- a/THANKS
++++ b/THANKS
+@@ -131,6 +131,7 @@ David Nugent		davidn@blaze.net.au
+ David Shaw		david.shaw@alcatel.com.au
+ David Steiner		dsteiner@ispa.uni-osnabrueck.de
+ David Taylor		taylor@think.com
++Dawid			dpc@dpc.pw
+ Dean Gaudet		dgaudet@watdragon.uwaterloo.ca
+ Demizu Noritoshi	nori-d@is.aist-nara.ac.jp
+ Denis Excoffier         denis.excoffier@free.fr
+diff --git a/src/extract.c b/src/extract.c
+index b622a2a..63e4d14 100644
+--- a/src/extract.c
++++ b/src/extract.c
+@@ -745,13 +745,13 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
+    in advance dramatically improves the following  performance of reading and
+    writing a file).  If not restoring permissions, invert the INVERT_PERMISSIONS
+    bits from the file's current permissions.  TYPEFLAG specifies the type of the
+-   file.  FILE_CREATED indicates set_xattr has created the file */
++   file.  Returns non-zero when error occurs (while un-available xattrs is not
++   an error, rather no-op).  Non-zero FILE_CREATED indicates set_xattr has
++   created the file. */
+ static int
+ set_xattr (char const *file_name, struct tar_stat_info const *st,
+            mode_t invert_permissions, char typeflag, int *file_created)
+ {
+-  int status = 0;
+-
+ #ifdef HAVE_XATTRS
+   bool interdir_made = false;
+ 
+@@ -759,17 +759,32 @@ set_xattr (char const *file_name, struct tar_stat_info const *st,
+     {
+       mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;
+ 
+-      do
+-        status = mknodat (chdir_fd, file_name, mode ^ invert_permissions, 0);
+-      while (status && maybe_recoverable ((char *)file_name, false,
+-                                          &interdir_made));
++      for (;;)
++        {
++          if (!mknodat (chdir_fd, file_name, mode ^ invert_permissions, 0))
++            {
++              /* Successfully created file */
++              xattrs_xattrs_set (st, file_name, typeflag, 0);
++              *file_created = 1;
++              return 0;
++            }
+ 
+-      xattrs_xattrs_set (st, file_name, typeflag, 0);
+-      *file_created = 1;
++          switch (maybe_recoverable ((char *)file_name, false, &interdir_made))
++            {
++              case RECOVER_OK:
++                continue;
++              case RECOVER_NO:
++                skip_member ();
++                open_error (file_name);
++                return 1;
++              case RECOVER_SKIP:
++                return 0;
++            }
++        }
+     }
+ #endif
+ 
+-  return(status);
++  return 0;
+ }
+ 
+ /* Fix the statuses of all directories whose statuses need fixing, and
+@@ -1089,11 +1104,7 @@ extract_file (char *file_name, int typeflag)
+       int file_created = 0;
+       if (set_xattr (file_name, &current_stat_info, invert_permissions,
+                      typeflag, &file_created))
+-        {
+-          skip_member ();
+-          open_error (file_name);
+-          return 1;
+-        }
++        return 1;
+ 
+       while ((fd = open_output_file (file_name, typeflag, mode,
+                                      file_created, &current_mode,
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 2a70314..8e1ef8d 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -200,6 +200,7 @@ TESTSUITE_AT = \
+  xattr04.at\
+  xattr05.at\
+  xattr06.at\
++ xattr07.at\
+  acls01.at\
+  acls02.at\
+  acls03.at\
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index ebce9cc..3eb0eee 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -361,6 +361,7 @@ m4_include([xattr03.at])
+ m4_include([xattr04.at])
+ m4_include([xattr05.at])
+ m4_include([xattr06.at])
++m4_include([xattr07.at])
+ 
+ m4_include([acls01.at])
+ m4_include([acls02.at])
+diff --git a/tests/xattr07.at b/tests/xattr07.at
+new file mode 100644
+index 0000000..a834981
+--- /dev/null
++++ b/tests/xattr07.at
+@@ -0,0 +1,73 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright 2011, 2013-2014, 2016 Free Software Foundation, Inc.
++
++# This file is part of GNU tar.
++
++# GNU tar 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.
++
++# GNU tar 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/>.
++#
++# Test description:
++# Test that --keep-old-files doesn't change xattrs of already existing file.
++# Per report:
++# https://lists.gnu.org/archive/html/bug-tar/2016-10/msg00001.html
++
++AT_SETUP([xattrs: xattrs and --skip-old-files])
++AT_KEYWORDS([xattrs xattr07])
++
++AT_TAR_CHECK([
++AT_XATTRS_PREREQ
++mkdir dir
++genfile --file dir/file
++genfile --file dir/file2
++
++setfattr -n user.test -v OurDirValue dir
++setfattr -n user.test -v OurFileValue dir/file
++setfattr -n user.test -v OurFileValue dir/file2
++
++tar --xattrs -cf archive.tar dir
++
++setfattr -n user.test -v OurDirValue2 dir
++setfattr -n user.test -v OurFileValue2 dir/file
++setfattr -n user.test -v OurFileValue2 dir/file2
++
++# Check that tar continues to file2 too!
++tar --xattrs -xvf archive.tar --skip-old-files
++tar --xattrs -xvf archive.tar --keep-old-files
++
++getfattr -h -d dir         | grep -v -e '^#' -e ^$
++getfattr -h -d dir/file    | grep -v -e '^#' -e ^$
++getfattr -h -d dir/file2   | grep -v -e '^#' -e ^$
++],
++[0],
++[dir/
++dir/file
++dir/file2
++dir/
++dir/file
++dir/file2
++user.test="OurDirValue2"
++user.test="OurFileValue2"
++user.test="OurFileValue2"
++], [tar: dir: skipping existing file
++tar: dir/file: skipping existing file
++tar: dir/file: skipping existing file
++tar: dir/file2: skipping existing file
++tar: dir/file2: skipping existing file
++tar: dir/file: Cannot open: File exists
++tar: dir/file2: Cannot open: File exists
++tar: Exiting with failure status due to previous errors
++])
++
++AT_CLEANUP
+From f2a7560718946e0920b55419f0953953bf824077 Mon Sep 17 00:00:00 2001
+From: Pavel Raiskup <praiskup@redhat.com>
+Date: Mon, 28 Nov 2016 08:44:42 +0100
+Subject: [PATCH] tests: more deterministic xattr07
+
+* tests/xattr07.at: Define order of files within tested archive.
+---
+ tests/xattr07.at | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tests/xattr07.at b/tests/xattr07.at
+index a834981..47d54b8 100644
+--- a/tests/xattr07.at
++++ b/tests/xattr07.at
+@@ -36,7 +36,7 @@ setfattr -n user.test -v OurDirValue dir
+ setfattr -n user.test -v OurFileValue dir/file
+ setfattr -n user.test -v OurFileValue dir/file2
+ 
+-tar --xattrs -cf archive.tar dir
++tar --xattrs --no-recursion -cf archive.tar dir dir/file dir/file2
+ 
+ setfattr -n user.test -v OurDirValue2 dir
+ setfattr -n user.test -v OurFileValue2 dir/file
+-- 
+2.13.5
+
diff --git a/SOURCES/tar-1.26-xattrs.patch b/SOURCES/tar-1.26-xattrs.patch
new file mode 100644
index 0000000..80ef5a2
--- /dev/null
+++ b/SOURCES/tar-1.26-xattrs.patch
@@ -0,0 +1,3233 @@
+diff --git a/NEWS b/NEWS
+index 12c1dd6..8aeae33 100644
+--- a/NEWS
++++ b/NEWS
+@@ -1,4 +1,4 @@
+-GNU tar NEWS - User visible changes. 2011-03-12
++GNU tar NEWS - User visible changes. 2012-11-19
+ Please send GNU tar bug reports to <bug-tar@gnu.org>
+ 
+ 
+@@ -22,6 +22,17 @@ zero-sized files.
+ When invoked with these two options, tar 1.25 would add only the
+ top-level directory to the archive, but not its contents.
+ 
++* Support for POSIX ACLs, extended attributes and SELinux context.
++
++Starting with this version tar is able to store, extract and list
++extended file attributes, POSIX.1e ACLs and SELinux context.  This is
++controlled by the command line options --xattrs, --acls and --selinux,
++correspondingly.  Each of these options has a `--no-' counterpart
++(e.g. --no-xattrs), which disables the corresponding feature.
++Additionally, the options --xattrs-include and --xattrs-exclude allow
++you to selectively control for which files to store (or extract) the
++extended attributes.
++
+ 
+ version 1.25 - Sergey Poznyakoff, 2010-11-07
+ 
+diff --git a/THANKS b/THANKS
+index 0364c50..54c96a0 100644
+--- a/THANKS
++++ b/THANKS
+@@ -296,6 +296,7 @@ Kimmy Posey		kimmyd@bnr.ca
+ Koji Kishi		kis@rqa.sony.co.jp
+ Konno Hiroharu		konno@pac.co.jp
+ Kurt Jaeger		pi@lf.net
++James Antill            jantill@redhat.com
+ Larry Creech		lcreech@lonestar.rcclub.org
+ Larry Schwimmer		rosebud@cyclone.stanford.edu
+ Lasse Collin 		lasse.collin@tukaani.org
+@@ -374,6 +375,7 @@ Oswald P. Backus IV	backus@lks.csi.com
+ Pascal Meheut		pascal@cnam.cnam.fr
+ Patrick Fulconis	fulco@sig.uvsq.fr
+ Patrick Timmons		timmons@electech.polymtl.ca
++Pavel Raiskup           praiskup@redhat.com
+ Paul Eggert		eggert@twinsun.com
+ Paul Kanz		paul@icx.com
+ Paul Mitchell		P.Mitchell@surrey.ac.uk
+diff --git a/acinclude.m4 b/acinclude.m4
+index 10a27e5..30381d3 100644
+--- a/acinclude.m4
++++ b/acinclude.m4
+@@ -24,3 +24,29 @@ AC_DEFUN([TAR_COMPR_PROGRAM],[
+ 	     [tar_compr_var=m4_if($2,,$1,$2)])
+  AC_DEFINE_UNQUOTED(tar_compr_define, "$tar_compr_var",
+                     [Define to the program name of ]$1[ compressor program])])
++
++# Provide <attr/xattr.h>, if necessary
++
++AC_DEFUN([TAR_HEADERS_ATTR_XATTR_H],
++[
++  AC_ARG_WITH([xattrs],
++    AS_HELP_STRING([--without-xattrs], [don't use linux extended attributes]),
++    [], [with_xattrs=maybe]
++  )
++
++  AC_CHECK_HEADERS([attr/xattr.h])
++  AM_CONDITIONAL([TAR_COND_XATTR_H],[test "$ac_cv_header_attr_xattr_h" = yes])
++  if test "$ac_cv_header_attr_xattr_h" = yes; then
++    AC_CHECK_FUNCS(getxattr  fgetxattr  lgetxattr \
++                   setxattr  fsetxattr  lsetxattr \
++                   listxattr flistxattr llistxattr,
++        # only when functions are present
++        AC_DEFINE([HAVE_ATTR_XATTR_H], [1],
++                    [define to 1 if we have <attr/xattr.h> header])
++        if test "$with_xattrs" != no; then
++          AC_DEFINE([HAVE_XATTRS],,[Define when we have working linux xattrs.])
++        fi
++    )
++  fi
++])
++		    
+\ No newline at end of file
+diff --git a/configure.ac b/configure.ac
+index db69cb8..9b3e0c8 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -70,6 +70,29 @@ if test $diff_cv_st_fstype_string = yes; then
+     [Define if struct stat has a char st_fstype[] member.])
+ fi
+ 
++# even if we use gnulib's acl.h with integrated m4 file later on (used because
++# of very useful file_has_acl() function) we need following checks that restrict
++# tar to use POSIX.1e ACLs only.
++AC_ARG_WITH([posix-acls],
++    AS_HELP_STRING([--without-posix-acls],
++                   [do not use POSIX.1e access control lists]),
++    [with_posix_acls=no])
++if test "x$with_posix_acls" != "xno"; then
++  AC_CHECK_HEADERS(sys/acl.h,, [with_posix_acl=no])
++  AC_SEARCH_LIBS([acl_get_file],  [acl pacl],, [with_posix_acl=no])
++  AC_SEARCH_LIBS([acl_get_fd],    [acl pacl],, [with_posix_acl=no])
++  AC_SEARCH_LIBS([acl_set_file],  [acl pacl],, [with_posix_acl=no])
++  AC_SEARCH_LIBS([acl_set_fd],    [acl pacl],, [with_posix_acl=no])
++  AC_SEARCH_LIBS([acl_to_text],   [acl pacl],, [with_posix_acl=no])
++  AC_SEARCH_LIBS([acl_from_text], [acl pacl],, [with_posix_acl=no])
++  if test "x$with_posix_acls" != xno; then
++    AC_DEFINE(HAVE_POSIX_ACLS,,[Define when we have working POSIX acls])
++  fi
++else
++  # disable acls in gnulib's checks
++  export enable_acl=no
++fi
++
+ AC_TYPE_SIGNAL
+ AC_TYPE_MODE_T
+ AC_TYPE_PID_T
+@@ -90,7 +113,10 @@ gl_INIT
+ # paxutils modules
+ tar_PAXUTILS
+ 
++TAR_HEADERS_ATTR_XATTR_H
++
+ AC_CHECK_FUNCS_ONCE([fchmod fchown fsync lstat mkfifo readlink symlink])
++
+ AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
+ AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
+ AC_CHECK_DECLS([time],,, [#include <time.h>])
+diff --git a/lib/Makefile.am b/lib/Makefile.am
+index efd6826..d73fac8 100644
+--- a/lib/Makefile.am
++++ b/lib/Makefile.am
+@@ -28,11 +28,24 @@ BUILT_SOURCES = rmt-command.h
+ CLEANFILES = rmt-command.h rmt-command.h-t
+ INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu
+ 
+-noinst_HEADERS = system.h system-ioctl.h rmt.h paxlib.h stdopen.h
++noinst_HEADERS = system.h system-ioctl.h rmt.h paxlib.h stdopen.h xattr-at.h
+ libtar_a_SOURCES = \
+   paxerror.c paxexit-status.c paxlib.h paxnames.c \
+   prepargs.c prepargs.h \
+   rtapelib.c \
+   rmt.h \
+   stdopen.c stdopen.h \
+-  system.h system-ioctl.h
++  system.h system-ioctl.h \
++  xattr-at.c
++
++if !TAR_COND_XATTR_H
++BUILT_SOURCES += attr/xattr.h
++attr/xattr.h: attr-xattr.in.h $(top_builddir)/config.status
++	$(AM_V_at)$(MKDIR_P) attr
++	$(AM_V_GEN)rm -f $@-t $@ && \
++	 cp $(srcdir)/attr-xattr.in.h attr/xattr.h
++
++MOSTLYCLEANFILES = attr/xattr.h attr/xattr.h
++endif
++
++EXTRA_DIST = attr-xattr.in.h
+diff --git a/lib/attr-xattr.in.h b/lib/attr-xattr.in.h
+new file mode 100644
+index 0000000..b5796fe
+--- /dev/null
++++ b/lib/attr-xattr.in.h
+@@ -0,0 +1,58 @@
++/* Replacement <attr/xattr.h> for platforms that lack it.
++   Copyright (C) 2012 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/>.  */
++
++#ifndef TAR_ATTR_XATTR_H
++#define TAR_ATTR_XATTR_H
++#include <errno.h>
++
++/* setting */
++static inline int setxattr (const char *path, const char *name, const void
++                            *value, size_t size, int flags)
++{ errno = ENOTSUP; return -1; }
++
++static inline int lsetxattr (const char *path, const char *name, const void
++                             *value, size_t size, int flags)
++{ errno = ENOTSUP; return -1; }
++
++static inline int fsetxattr (int filedes, const char *name, const void *value,
++                             size_t size, int flags)
++{ errno = ENOTSUP; return -1; }
++
++
++/* getting */
++static inline ssize_t getxattr (const char *path, const char *name, void *value,
++                                size_t size)
++{ errno = ENOTSUP; return -1; }
++static inline ssize_t lgetxattr (const char *path, const char *name, void
++                                 *value, size_t size)
++{ errno = ENOTSUP; return -1; }
++static inline ssize_t fgetxattr (int filedes, const char *name, void *value,
++                                 size_t size)
++{ errno = ENOTSUP; return -1; }
++
++
++/* listing */
++static inline ssize_t listxattr (const char *path, char *list, size_t size)
++{ errno = ENOTSUP; return -1; }
++
++static inline ssize_t llistxattr (const char *path, char *list, size_t size)
++{ errno = ENOTSUP; return -1; }
++
++static inline ssize_t flistxattr (int filedes, char *list, size_t size)
++{ errno = ENOTSUP; return -1; }
++
++#endif
++
+diff --git a/lib/xattr-at.c b/lib/xattr-at.c
+new file mode 100644
+index 0000000..746578c
+--- /dev/null
++++ b/lib/xattr-at.c
+@@ -0,0 +1,110 @@
++/* openat-style fd-relative functions for operating with extended file
++   attributes.
++
++   Copyright (C) 2012 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>
++
++#include "xattr-at.h"
++#include "openat.h"
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <errno.h>
++#include <fcntl.h>
++
++#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
++#include "save-cwd.h"
++
++#include "openat-priv.h"
++
++/* setxattrat */
++#define AT_FUNC_NAME setxattrat
++#define AT_FUNC_F1 setxattr
++#define AT_FUNC_POST_FILE_PARAM_DECLS   , const char *name, const void *value \
++                                        , size_t size, int flags
++#define AT_FUNC_POST_FILE_ARGS          , name, value, size, flags
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
++
++/* lsetxattrat */
++#define AT_FUNC_NAME lsetxattrat
++#define AT_FUNC_F1 lsetxattr
++#define AT_FUNC_POST_FILE_PARAM_DECLS   , const char *name, const void *value \
++                                        , size_t size, int flags
++#define AT_FUNC_POST_FILE_ARGS          , name, value, size, flags
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
++
++/* getxattrat */
++#define AT_FUNC_NAME getxattrat
++#define AT_FUNC_RESULT ssize_t
++#define AT_FUNC_F1 getxattr
++#define AT_FUNC_POST_FILE_PARAM_DECLS   , const char *name, void *value \
++                                        , size_t size
++#define AT_FUNC_POST_FILE_ARGS          , name, value, size
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_RESULT
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
++
++/* lgetxattrat */
++#define AT_FUNC_NAME lgetxattrat
++#define AT_FUNC_RESULT ssize_t
++#define AT_FUNC_F1 lgetxattr
++#define AT_FUNC_POST_FILE_PARAM_DECLS   , const char *name, void *value \
++                                        , size_t size
++#define AT_FUNC_POST_FILE_ARGS          , name, value, size
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_RESULT
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
++
++/* listxattrat */
++#define AT_FUNC_NAME listxattrat
++#define AT_FUNC_RESULT ssize_t
++#define AT_FUNC_F1 listxattr
++#define AT_FUNC_POST_FILE_PARAM_DECLS   , char *list , size_t size
++#define AT_FUNC_POST_FILE_ARGS          , list , size
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_RESULT
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
++
++/* llistxattrat */
++#define AT_FUNC_NAME llistxattrat
++#define AT_FUNC_RESULT ssize_t
++#define AT_FUNC_F1 llistxattr
++#define AT_FUNC_POST_FILE_PARAM_DECLS   , char *list , size_t size
++#define AT_FUNC_POST_FILE_ARGS          , list , size
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_RESULT
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
+diff --git a/lib/xattr-at.h b/lib/xattr-at.h
+new file mode 100644
+index 0000000..360245c
+--- /dev/null
++++ b/lib/xattr-at.h
+@@ -0,0 +1,66 @@
++/* Prototypes for openat-style fd-relative functions for operating with
++   extended file attributes.
++
++   Copyright (C) 2012 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/>.  */
++
++#ifndef XATTRS_AT_H
++#define XATTRS_AT_H
++
++#include <sys/types.h>
++#include <attr/xattr.h>
++
++/* These are the dir-fd-relative variants of the functions without the
++   "at" suffix.  For example, setxattrat (AT_FDCWD, path, name, value, size,
++   flags &c) is usually equivalent to setxattr (file, name, value, size,
++   flags).  For more info use the setxattr(2), getxattr(2) or listxattr(2)
++   manpages. */
++
++/* dir-fd-relative setxattr.  Operation sets the VALUE of the extended
++   attribute identified by NAME and associated with the given PATH in the
++   filesystem relatively to directory identified by DIR_FD.  See the
++   setxattr(2) manpage for the description of all parameters. */
++int setxattrat (int dir_fd, const char *path, const char *name,
++                const void *value, size_t size, int flags);
++
++/* dir-fd-relative lsetxattr.  This function is just like setxattrat,
++   except when DIR_FD and FILE specify a symlink:  lsetxattrat operates on the
++   symlink, while the setxattrat operates on the referent of the symlink.  */
++int lsetxattrat (int dir_fd, const char *path, const char *name,
++                 const void *value, size_t size, int flags);
++
++/* dir-fd-relative getxattr.  Operation gets the VALUE of the extended
++   attribute idenfified by NAME and associated with the given PATH in the
++   filesystem relatively to directory identified by DIR_FD.  For more info
++   about all parameters see the getxattr(2) manpage. */
++ssize_t getxattrat (int dir_fd, const char *path, const char *name,
++                    void *value, size_t size);
++
++/* dir-fd-relative lgetxattr.  This function is just like getxattrat,
++   except when DIR_FD and FILE specify a symlink:  lgetxattrat operates on the
++   symlink, while the getxattrat operates on the referent of the symlink.  */
++ssize_t lgetxattrat (int dir_fd, const char *path, const char *name,
++                     void *value, size_t size);
++
++/* dir-fd-relative listxattr.  Obtain the list of extended attrubtes names.  For
++   more info see the listxattr(2) manpage. */
++ssize_t listxattrat (int dir_fd, const char *path, char *list, size_t size);
++
++/* dir-fd-relative llistxattr.  This function is just like listxattrat,
++   except when DIR_FD and FILE specify a symlink:  llistxattr operates on the
++   symlink, while the listxattrat operates on the referent of the symlink.  */
++ssize_t llistxattrat (int dir_fd, const char *path, char *list, size_t size);
++
++#endif /* XATTRS_AT_H */
+diff --git a/src/Makefile.am b/src/Makefile.am
+index de310f4..782df19 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -20,7 +20,7 @@
+ 
+ bin_PROGRAMS = tar
+ 
+-noinst_HEADERS = arith.h common.h tar.h
++noinst_HEADERS = arith.h common.h tar.h xattrs.h
+ tar_SOURCES = \
+  buffer.c\
+  checkpoint.c\
+@@ -42,10 +42,11 @@ tar_SOURCES = \
+  unlink.c\
+  update.c\
+  utf8.c\
+- warning.c
++ warning.c\
++ xattrs.c
+ 
+ INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
+ 
+ LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
+ 
+-tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS)
++tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS) $(LIB_SELINUX)
+diff --git a/src/common.h b/src/common.h
+index 2409413..16ba401 100644
+--- a/src/common.h
++++ b/src/common.h
+@@ -1,8 +1,8 @@
+ /* Common declarations for the tar program.
+ 
+    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
+-   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
+-   Inc.
++   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012
++   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
+@@ -91,6 +91,11 @@ enum subcommand
+ 
+ GLOBAL enum subcommand subcommand_option;
+ 
++#define READ_LIKE_SUBCOMMAND                    \
++  (subcommand_option == EXTRACT_SUBCOMMAND      \
++   || subcommand_option == DIFF_SUBCOMMAND      \
++   || subcommand_option == LIST_SUBCOMMAND)
++
+ /* Selected format for output archive.  */
+ GLOBAL enum archive_format archive_format;
+ 
+@@ -254,6 +259,15 @@ GLOBAL int same_owner_option;
+ /* If positive, preserve permissions when extracting.  */
+ GLOBAL int same_permissions_option;
+ 
++/* If positive, save the SELinux context.  */
++GLOBAL int selinux_context_option;
++
++/* If positive, save the ACLs.  */
++GLOBAL int acls_option;
++
++/* If positive, save the user and root xattrs.  */
++GLOBAL int xattrs_option;
++
+ /* When set, strip the given number of file name components from the file name
+    before extracting */
+ GLOBAL size_t strip_name_components;
+@@ -708,6 +722,9 @@ extern char *output_start;
+ 
+ void update_archive (void);
+ 
++/* Module attrs.c.  */
++#include "xattrs.h"
++
+ /* Module xheader.c.  */
+ 
+ void xheader_decode (struct tar_stat_info *stat);
+@@ -728,6 +745,12 @@ bool xheader_string_end (struct xheader *xhdr, char const *keyword);
+ bool xheader_keyword_deleted_p (const char *kw);
+ char *xheader_format_name (struct tar_stat_info *st, const char *fmt,
+ 			   size_t n);
++void xheader_xattr_init (struct tar_stat_info *st);
++void xheader_xattr_free (struct xattr_array *vals, size_t sz);
++void xheader_xattr_copy (const struct tar_stat_info *st,
++                         struct xattr_array **vals, size_t *sz);
++void xheader_xattr_add (struct tar_stat_info *st,
++                        const char *key, const char *val, size_t len);
+ 
+ /* Module system.c */
+ 
+@@ -809,6 +832,7 @@ void checkpoint_run (bool do_write);
+ #define WARN_XDEV                0x00040000
+ #define WARN_DECOMPRESS_PROGRAM  0x00080000
+ #define WARN_EXISTING_FILE       0x00100000
++#define WARN_XATTR_WRITE         0x00200000
+ 
+ /* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default
+    in verbose mode */
+diff --git a/src/create.c b/src/create.c
+index f98cbb5..25387a9 100644
+--- a/src/create.c
++++ b/src/create.c
+@@ -1,7 +1,8 @@
+ /* Create a tar archive.
+ 
+    Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
+-   2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
++   2003, 2004, 2005, 2006, 2007, 2009, 2010, 2012
++   Free Software Foundation, Inc.
+ 
+    Written by John Gilmore, on 1985-08-25.
+ 
+@@ -936,6 +937,30 @@ start_header (struct tar_stat_info *st)
+       GNAME_TO_CHARS (st->gname, header->header.gname);
+     }
+ 
++  if (archive_format == POSIX_FORMAT)
++    {
++      if (acls_option > 0)
++        {
++          if (st->acls_a_ptr)
++            xheader_store ("SCHILY.acl.access", st, NULL);
++          if (st->acls_d_ptr)
++            xheader_store ("SCHILY.acl.default", st, NULL);
++        }
++      if ((selinux_context_option > 0) && st->cntx_name)
++        xheader_store ("RHT.security.selinux", st, NULL);
++      if (xattrs_option > 0)
++        {
++          size_t scan_xattr = 0;
++          struct xattr_array *xattr_map = st->xattr_map;
++
++          while (scan_xattr < st->xattr_map_size)
++            {
++              xheader_store (xattr_map[scan_xattr].xkey, st, &scan_xattr);
++              ++scan_xattr;
++            }
++        }
++    }
++
+   return header;
+ }
+ 
+@@ -1711,6 +1736,10 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
+       bool ok;
+       struct stat final_stat;
+ 
++      xattrs_acls_get (parentfd, name, st, 0, !is_dir);
++      xattrs_selinux_get (parentfd, name, st, fd);
++      xattrs_xattrs_get (parentfd, name, st, fd);
++
+       if (is_dir)
+ 	{
+ 	  const char *tag_file_name;
+@@ -1830,6 +1859,9 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
+       if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT) < size)
+ 	write_long_link (st);
+ 
++      xattrs_selinux_get (parentfd, name, st, 0);
++      xattrs_xattrs_get (parentfd, name, st, 0);
++
+       block_ordinal = current_block_ordinal ();
+       st->stat.st_size = 0;	/* force 0 size on symlink */
+       header = start_header (st);
+@@ -1848,11 +1880,26 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
+     }
+ #endif
+   else if (S_ISCHR (st->stat.st_mode))
+-    type = CHRTYPE;
++    {
++      type = CHRTYPE;
++      xattrs_acls_get (parentfd, name, st, 0, true);
++      xattrs_selinux_get (parentfd, name, st, 0);
++      xattrs_xattrs_get (parentfd, name, st, 0);
++    }
+   else if (S_ISBLK (st->stat.st_mode))
+-    type = BLKTYPE;
++    {
++      type = BLKTYPE;
++      xattrs_acls_get (parentfd, name, st, 0, true);
++      xattrs_selinux_get (parentfd, name, st, 0);
++      xattrs_xattrs_get (parentfd, name, st, 0);
++    }
+   else if (S_ISFIFO (st->stat.st_mode))
+-    type = FIFOTYPE;
++    {
++      type = FIFOTYPE;
++      xattrs_acls_get (parentfd, name, st, 0, true);
++      xattrs_selinux_get (parentfd, name, st, 0);
++      xattrs_xattrs_get (parentfd, name, st, 0);
++    }
+   else if (S_ISSOCK (st->stat.st_mode))
+     {
+       WARNOPT (WARN_FILE_IGNORED,
+diff --git a/src/extract.c b/src/extract.c
+index 662ea0b..87b383a 100644
+--- a/src/extract.c
++++ b/src/extract.c
+@@ -1,7 +1,8 @@
+ /* Extract files from a tar archive.
+ 
+    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
+-   2001, 2003, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc.
++   2001, 2003, 2004, 2005, 2006, 2007, 2010, 2012
++   Free Software Foundation, Inc.
+ 
+    Written by John Gilmore, on 1985-11-19.
+ 
+@@ -97,6 +98,14 @@ struct delayed_set_stat
+     /* Directory that the name is relative to.  */
+     int change_dir;
+ 
++    /* extended attributes*/
++    char *cntx_name;
++    char *acls_a_ptr;
++    size_t acls_a_len;
++    char *acls_d_ptr;
++    size_t acls_d_len;
++    size_t xattr_map_size;
++    struct xattr_array *xattr_map;
+     /* Length and contents of name.  */
+     size_t file_name_len;
+     char file_name[1];
+@@ -134,6 +143,18 @@ struct delayed_link
+        hard-linked together.  */
+     struct string_list *sources;
+ 
++    /* SELinux context */
++    char *cntx_name;
++
++    /* ACLs */
++    char *acls_a_ptr;
++    size_t acls_a_len;
++    char *acls_d_ptr;
++    size_t acls_d_len;
++
++    size_t xattr_map_size;
++    struct xattr_array *xattr_map;
++
+     /* The desired target of the desired link.  */
+     char target[1];
+   };
+@@ -360,6 +381,12 @@ set_stat (char const *file_name,
+ 	    st->stat.st_mode & ~ current_umask,
+ 	    0 < same_permissions_option && ! interdir ? MODE_ALL : MODE_RWX,
+ 	    fd, current_mode, current_mode_mask, typeflag, atflag);
++
++  /* these three calls must be done *after* fd_chown() call because fd_chown
++     causes that linux capabilities becomes cleared. */
++  xattrs_xattrs_set (st, file_name, typeflag, 1);
++  xattrs_acls_set (st, file_name, typeflag);
++  xattrs_selinux_set (st, file_name, typeflag);
+ }
+ 
+ /* For each entry H in the leading prefix of entries in HEAD that do
+@@ -431,6 +458,36 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
+   data->atflag = atflag;
+   data->after_links = 0;
+   data->change_dir = chdir_current;
++  data->cntx_name = NULL;
++  if (st)
++    assign_string (&data->cntx_name, st->cntx_name);
++  if (st && st->acls_a_ptr)
++    {
++      data->acls_a_ptr = xmemdup (st->acls_a_ptr, st->acls_a_len + 1);
++      data->acls_a_len = st->acls_a_len;
++    }
++  else
++    {
++      data->acls_a_ptr = NULL;
++      data->acls_a_len = 0;
++    }
++  if (st && st->acls_d_ptr)
++    {
++      data->acls_d_ptr = xmemdup (st->acls_d_ptr, st->acls_d_len + 1);
++      data->acls_d_len = st->acls_d_len;
++    }
++  else
++    {
++      data->acls_d_ptr = NULL;
++      data->acls_d_len = 0;
++    }
++  if (st)
++    xheader_xattr_copy (st, &data->xattr_map, &data->xattr_map_size);
++  else
++    {
++      data->xattr_map = NULL;
++      data->xattr_map_size = 0;
++    }
+   strcpy (data->file_name, file_name);
+   delayed_set_stat_head = data;
+   if (must_be_dot_or_slash (file_name))
+@@ -678,6 +735,40 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
+   return RECOVER_NO;
+ }
+ 
++/* Restore stat extended attributes (xattr) for FILE_NAME, using information
++   given in *ST.  Restore before extraction because they may affect file layout
++   (e.g. on Lustre distributed parallel filesystem - setting info about how many
++   servers is this file striped over, stripe size, mirror copies, etc.
++   in advance dramatically improves the following  performance of reading and
++   writing a file).  If not restoring permissions, invert the INVERT_PERMISSIONS
++   bits from the file's current permissions.  TYPEFLAG specifies the type of the
++   file.  FILE_CREATED indicates set_xattr has created the file */
++static int
++set_xattr (char const *file_name, struct tar_stat_info const *st,
++           mode_t invert_permissions, char typeflag, int *file_created)
++{
++  int status = 0;
++
++#ifdef HAVE_XATTRS
++  bool interdir_made = false;
++
++  if ((xattrs_option > 0) && st->xattr_map_size)
++    {
++      mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;
++
++      do
++        status = mknodat (chdir_fd, file_name, mode ^ invert_permissions, 0);
++      while (status && maybe_recoverable ((char *)file_name, false,
++                                          &interdir_made));
++
++      xattrs_xattrs_set (st, file_name, typeflag, 0);
++      *file_created = 1;
++    }
++#endif
++
++  return(status);
++}
++
+ /* Fix the statuses of all directories whose statuses need fixing, and
+    which are not ancestors of FILE_NAME.  If AFTER_LINKS is
+    nonzero, do this for all such directories; otherwise, stop at the
+@@ -738,12 +829,23 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
+ 	  sb.stat.st_gid = data->gid;
+ 	  sb.atime = data->atime;
+ 	  sb.mtime = data->mtime;
++	  sb.cntx_name = data->cntx_name;
++	  sb.acls_a_ptr = data->acls_a_ptr;
++	  sb.acls_a_len = data->acls_a_len;
++	  sb.acls_d_ptr = data->acls_d_ptr;
++	  sb.acls_d_len = data->acls_d_len;
++	  sb.xattr_map = data->xattr_map;
++	  sb.xattr_map_size = data->xattr_map_size;
+ 	  set_stat (data->file_name, &sb,
+ 		    -1, current_mode, current_mode_mask,
+ 		    DIRTYPE, data->interdir, data->atflag);
+ 	}
+ 
+       delayed_set_stat_head = data->next;
++      xheader_xattr_free (data->xattr_map, data->xattr_map_size);
++      free (data->cntx_name);
++      free (data->acls_a_ptr);
++      free (data->acls_d_ptr);
+       free (data);
+     }
+ }
+@@ -859,7 +961,8 @@ extract_dir (char *file_name, int typeflag)
+ 
+ static int
+ open_output_file (char const *file_name, int typeflag, mode_t mode,
+-		  mode_t *current_mode, mode_t *current_mode_mask)
++                  int file_created, mode_t *current_mode,
++                  mode_t *current_mode_mask)
+ {
+   int fd;
+   bool overwriting_old_files = old_files_option == OVERWRITE_OLD_FILES;
+@@ -869,6 +972,10 @@ open_output_file (char const *file_name, int typeflag, mode_t mode,
+ 		     ? O_TRUNC | (dereference_option ? 0 : O_NOFOLLOW)
+ 		     : O_EXCL));
+ 
++  /* File might be created in set_xattr. So clear O_EXCL to avoid open() fail */
++  if (file_created)
++    openflag = openflag & ~O_EXCL;
++
+   if (typeflag == CONTTYPE)
+     {
+       static int conttype_diagnosed;
+@@ -939,6 +1046,8 @@ extract_file (char *file_name, int typeflag)
+   bool interdir_made = false;
+   mode_t mode = (current_stat_info.stat.st_mode & MODE_RWX
+ 		 & ~ (0 < same_owner_option ? S_IRWXG | S_IRWXO : 0));
++  mode_t invert_permissions = 0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO)
++                                                    : 0;
+   mode_t current_mode = 0;
+   mode_t current_mode_mask = 0;
+ 
+@@ -955,8 +1064,18 @@ extract_file (char *file_name, int typeflag)
+     }
+   else
+     {
++      int file_created = 0;
++      if (set_xattr (file_name, &current_stat_info, invert_permissions,
++                     typeflag, &file_created))
++        {
++          skip_member ();
++          open_error (file_name);
++          return 1;
++        }
++
+       while ((fd = open_output_file (file_name, typeflag, mode,
+-				     &current_mode, &current_mode_mask))
++                                     file_created, &current_mode,
++                                     &current_mode_mask))
+ 	     < 0)
+ 	{
+ 	  int recover = maybe_recoverable (file_name, true, &interdir_made);
+@@ -1096,6 +1215,13 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
+ 			    + strlen (file_name) + 1);
+       p->sources->next = 0;
+       strcpy (p->sources->string, file_name);
++      p->cntx_name = NULL;
++      assign_string (&p->cntx_name, current_stat_info.cntx_name);
++      p->acls_a_ptr = NULL;
++      p->acls_a_len = 0;
++      p->acls_d_ptr = NULL;
++      p->acls_d_len = 0;
++      xheader_xattr_copy (&current_stat_info, &p->xattr_map, &p->xattr_map_size);
+       strcpy (p->target, current_stat_info.link_name);
+ 
+       h = delayed_set_stat_head;
+@@ -1530,6 +1656,13 @@ apply_delayed_links (void)
+ 		  st1.stat.st_gid = ds->gid;
+ 		  st1.atime = ds->atime;
+ 		  st1.mtime = ds->mtime;
++                  st1.cntx_name = ds->cntx_name;
++                  st1.acls_a_ptr = ds->acls_a_ptr;
++                  st1.acls_a_len = ds->acls_a_len;
++                  st1.acls_d_ptr = ds->acls_d_ptr;
++                  st1.acls_d_len = ds->acls_d_len;
++                  st1.xattr_map = ds->xattr_map;
++                  st1.xattr_map_size = ds->xattr_map_size;
+ 		  set_stat (source, &st1, -1, 0, 0, SYMTYPE,
+ 			    false, AT_SYMLINK_NOFOLLOW);
+ 		  valid_source = source;
+@@ -1544,6 +1677,9 @@ apply_delayed_links (void)
+ 	  sources = next;
+ 	}
+ 
++   xheader_xattr_free (ds->xattr_map, ds->xattr_map_size);
++   free (ds->cntx_name);
++
+       {
+ 	struct delayed_link *next = ds->next;
+ 	free (ds);
+diff --git a/src/list.c b/src/list.c
+index f4e6e0a..dd501a9 100644
+--- a/src/list.c
++++ b/src/list.c
+@@ -1,7 +1,8 @@
+ /* List a tar archive, with support routines for reading a tar archive.
+ 
+    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
+-   2001, 2003, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc.
++   2001, 2003, 2004, 2005, 2006, 2007, 2010, 2012
++   Free Software Foundation, Inc.
+ 
+    Written by John Gilmore, on 1985-08-26.
+ 
+@@ -615,6 +616,8 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
+   assign_string (&stat_info->gname,
+ 		 header->header.gname[0] ? header->header.gname : NULL);
+ 
++  xheader_xattr_init (stat_info);
++
+   if (format == OLDGNU_FORMAT && incremental_option)
+     {
+       stat_info->atime.tv_sec = TIME_FROM_HEADER (header->oldgnu_header.atime);
+@@ -1075,7 +1078,7 @@ static void
+ simple_print_header (struct tar_stat_info *st, union block *blk,
+ 		     off_t block_ordinal)
+ {
+-  char modes[11];
++  char modes[12];
+   char const *time_stamp;
+   int time_stamp_len;
+   char *temp_name;
+@@ -1167,6 +1170,9 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
+ 
+       pax_decode_mode (st->stat.st_mode, modes + 1);
+ 
++      /* extended attributes:  GNU `ls -l'-like preview */
++      xattrs_print_char (st, modes + 10);
++
+       /* Time stamp.  */
+ 
+       time_stamp = tartime (st->mtime, full_time_option);
+@@ -1312,6 +1318,7 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
+ 	}
+     }
+   fflush (stdlis);
++  xattrs_print (st);
+ }
+ 
+ 
+diff --git a/src/tar.c b/src/tar.c
+index 7a673e0..e244808 100644
+--- a/src/tar.c
++++ b/src/tar.c
+@@ -1,7 +1,8 @@
+ /* A tar (tape archiver) program.
+ 
+    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000,
+-   2001, 2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
++   2001, 2003, 2004, 2005, 2006, 2007, 2012
++   Free Software Foundation, Inc.
+ 
+    Written by John Gilmore, starting 1985-08-25.
+ 
+@@ -255,7 +256,8 @@ tar_set_quoting_style (char *arg)
+ 
+ enum
+ {
+-  ANCHORED_OPTION = CHAR_MAX + 1,
++  ACLS_OPTION = CHAR_MAX + 1,
++  ANCHORED_OPTION,
+   ATIME_PRESERVE_OPTION,
+   BACKUP_OPTION,
+   CHECK_DEVICE_OPTION,
+@@ -288,6 +290,7 @@ enum
+   MODE_OPTION,
+   MTIME_OPTION,
+   NEWER_MTIME_OPTION,
++  NO_ACLS_OPTION,
+   NO_ANCHORED_OPTION,
+   NO_AUTO_COMPRESS_OPTION,
+   NO_CHECK_DEVICE_OPTION,
+@@ -301,9 +304,11 @@ enum
+   NO_SAME_OWNER_OPTION,
+   NO_SAME_PERMISSIONS_OPTION,
+   NO_SEEK_OPTION,
++  NO_SELINUX_CONTEXT_OPTION,
+   NO_UNQUOTE_OPTION,
+   NO_WILDCARDS_MATCH_SLASH_OPTION,
+   NO_WILDCARDS_OPTION,
++  NO_XATTR_OPTION,
+   NULL_OPTION,
+   NUMERIC_OWNER_OPTION,
+   OCCURRENCE_OPTION,
+@@ -325,6 +330,7 @@ enum
+   RMT_COMMAND_OPTION,
+   RSH_COMMAND_OPTION,
+   SAME_OWNER_OPTION,
++  SELINUX_CONTEXT_OPTION,
+   SHOW_DEFAULTS_OPTION,
+   SHOW_OMITTED_DIRS_OPTION,
+   SHOW_TRANSFORMED_NAMES_OPTION,
+@@ -341,7 +347,10 @@ enum
+   VOLNO_FILE_OPTION,
+   WARNING_OPTION,
+   WILDCARDS_MATCH_SLASH_OPTION,
+-  WILDCARDS_OPTION
++  WILDCARDS_OPTION,
++  XATTR_OPTION,
++  XATTR_EXCLUDE,
++  XATTR_INCLUDE
+ };
+ 
+ const char *argp_program_version = "tar (" PACKAGE_NAME ") " VERSION;
+@@ -530,6 +539,28 @@ static struct argp_option options[] = {
+    N_("cancel the effect of --delay-directory-restore option"), GRID+1 },
+ #undef GRID
+ 
++#define GRID 55
++  {NULL, 0, NULL, 0,
++   N_("Handling of extended file attributes:"), GRID },
++
++  {"xattrs", XATTR_OPTION, 0, 0,
++   N_("Enable extended attributes support"), GRID+1 },
++  {"no-xattrs", NO_XATTR_OPTION, 0, 0,
++   N_("Disable extended attributes support"), GRID+1 },
++  {"xattrs-include", XATTR_INCLUDE, N_("MASK"), 0,
++   N_("specify the include pattern for xattr keys"), GRID+1 },
++  {"xattrs-exclude", XATTR_EXCLUDE, N_("MASK"), 0,
++   N_("specify the exclude pattern for xattr keys"), GRID+1 },
++  {"selinux", SELINUX_CONTEXT_OPTION, 0, 0,
++   N_("Enable the SELinux context support"), GRID+1 },
++  {"no-selinux", NO_SELINUX_CONTEXT_OPTION, 0, 0,
++   N_("Disable the SELinux context support"), GRID+1 },
++  {"acls", ACLS_OPTION, 0, 0,
++   N_("Enable the POSIX ACLs support"), GRID+1 },
++  {"no-acls", NO_ACLS_OPTION, 0, 0,
++   N_("Disable the POSIX ACLs support"), GRID+1 },
++#undef GRID
++
+ #define GRID 60
+   {NULL, 0, NULL, 0,
+    N_("Device selection and switching:"), GRID },
+@@ -2091,6 +2122,38 @@ parse_opt (int key, char *arg, struct argp_state *state)
+       same_permissions_option = -1;
+       break;
+ 
++    case ACLS_OPTION:
++      set_archive_format ("posix");
++      acls_option = 1;
++      break;
++
++    case NO_ACLS_OPTION:
++      acls_option = -1;
++      break;
++
++    case SELINUX_CONTEXT_OPTION:
++      set_archive_format ("posix");
++      selinux_context_option = 1;
++      break;
++
++    case NO_SELINUX_CONTEXT_OPTION:
++      selinux_context_option = -1;
++      break;
++
++    case XATTR_OPTION:
++      set_archive_format ("posix");
++      xattrs_option = 1;
++      break;
++
++    case NO_XATTR_OPTION:
++      xattrs_option = -1;
++      break;
++
++    case XATTR_INCLUDE:
++    case XATTR_EXCLUDE:
++      xattrs_mask_add (arg, (key == XATTR_INCLUDE));
++      break;
++
+     case RECURSION_OPTION:
+       recursion_option = FNM_LEADING_DIR;
+       break;
+@@ -2468,11 +2531,26 @@ decode_options (int argc, char **argv)
+      --gray */
+   if (args.pax_option
+       && archive_format != POSIX_FORMAT
+-      && (subcommand_option != EXTRACT_SUBCOMMAND
+-	  || subcommand_option != DIFF_SUBCOMMAND
+-	  || subcommand_option != LIST_SUBCOMMAND))
++      && !READ_LIKE_SUBCOMMAND)
+     USAGE_ERROR ((0, 0, _("--pax-option can be used only on POSIX archives")));
+ 
++  /* star creates non-POSIX typed archives with xattr support, so allow the
++     extra headers whenn reading */
++  if ((acls_option > 0)
++      && archive_format != POSIX_FORMAT
++      && !READ_LIKE_SUBCOMMAND)
++    USAGE_ERROR ((0, 0, _("--acls can be used only on POSIX archives")));
++
++  if ((selinux_context_option > 0)
++      && archive_format != POSIX_FORMAT
++      && !READ_LIKE_SUBCOMMAND)
++    USAGE_ERROR ((0, 0, _("--selinux can be used only on POSIX archives")));
++
++  if ((xattrs_option > 0)
++      && archive_format != POSIX_FORMAT
++      && !READ_LIKE_SUBCOMMAND)
++    USAGE_ERROR ((0, 0, _("--xattrs can be used only on POSIX archives")));
++
+   /* If ready to unlink hierarchies, so we are for simpler files.  */
+   if (recursive_unlink_option)
+     old_files_option = UNLINK_FIRST_OLD_FILES;
+@@ -2681,6 +2759,7 @@ main (int argc, char **argv)
+   /* Dispose of allocated memory, and return.  */
+ 
+   free (archive_name_array);
++  xattrs_clear_setup ();
+   name_term ();
+ 
+   if (exit_status == TAREXIT_FAILURE)
+@@ -2725,11 +2804,15 @@ void
+ tar_stat_destroy (struct tar_stat_info *st)
+ {
+   tar_stat_close (st);
++  xheader_xattr_free (st->xattr_map, st->xattr_map_size);
+   free (st->orig_file_name);
+   free (st->file_name);
+   free (st->link_name);
+   free (st->uname);
+   free (st->gname);
++  free (st->cntx_name);
++  free (st->acls_a_ptr);
++  free (st->acls_d_ptr);
+   free (st->sparse_map);
+   free (st->dumpdir);
+   xheader_destroy (&st->xhdr);
+diff --git a/src/tar.h b/src/tar.h
+index ce9850c..b181e58 100644
+--- a/src/tar.h
++++ b/src/tar.h
+@@ -1,7 +1,8 @@
+ /* GNU tar Archive Format description.
+ 
+    Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+-   2000, 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
++   2000, 2001, 2003, 2004, 2005, 2006, 2007, 2012
++   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
+@@ -276,6 +277,14 @@ struct xheader
+   uintmax_t string_length;
+ };
+ 
++/* Information about xattrs for a file.  */
++struct xattr_array
++  {
++    char *xkey;
++    char *xval_ptr;
++    size_t xval_len;
++  };
++
+ struct tar_stat_info
+ {
+   char *orig_file_name;     /* name of file read from the archive header */
+@@ -287,6 +296,15 @@ struct tar_stat_info
+ 
+   char          *uname;     /* user name of owner */
+   char          *gname;     /* group name of owner */
++
++  char *cntx_name;          /* SELinux context for the current archive entry. */
++
++  char *acls_a_ptr;         /* Access ACLs for the current archive entry. */
++  size_t acls_a_len;        /* Access ACLs for the current archive entry. */
++
++  char *acls_d_ptr;         /* Default ACLs for the current archive entry. */
++  size_t acls_d_len;        /* Default ACLs for the current archive entry. */
++
+   struct stat   stat;       /* regular filesystem stat */
+ 
+   /* STAT doesn't always have access, data modification, and status
+@@ -309,6 +327,9 @@ struct tar_stat_info
+   size_t sparse_map_size;   /* Size of the sparse map */
+   struct sp_array *sparse_map;
+ 
++  size_t xattr_map_size;   /* Size of the xattr map */
++  struct xattr_array *xattr_map;
++
+   /* Extended headers */
+   struct xheader xhdr;
+ 
+diff --git a/src/warning.c b/src/warning.c
+index ee9d684..570b3c1 100644
+--- a/src/warning.c
++++ b/src/warning.c
+@@ -1,6 +1,6 @@
+ /* This file is part of GNU tar.
+ 
+-   Copyright (C) 2009 Free Software Foundation, Inc.
++   Copyright (C) 2009, 2012 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
+@@ -43,6 +43,7 @@ static char const *const warning_args[] = {
+   "xdev",
+   "decompress-program",
+   "existing-file",
++  "xattr-write",
+   NULL
+ };
+ 
+@@ -69,6 +70,7 @@ static int warning_types[] = {
+   WARN_XDEV,
+   WARN_DECOMPRESS_PROGRAM,
+   WARN_EXISTING_FILE,
++  WARN_XATTR_WRITE
+ };
+ 
+ ARGMATCH_VERIFY (warning_args, warning_types);
+diff --git a/src/xattrs.c b/src/xattrs.c
+new file mode 100644
+index 0000000..5a4bf72
+--- /dev/null
++++ b/src/xattrs.c
+@@ -0,0 +1,732 @@
++/* Support for extended attributes.
++
++   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software
++   Foundation, Inc.
++
++   Written by James Antill, on 2006-07-27.
++
++   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 2, 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, write to the Free Software Foundation, Inc.,
++   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
++
++#include <config.h>
++#include <system.h>
++
++#include <fnmatch.h>
++#include <quotearg.h>
++
++#include "common.h"
++
++#include "xattr-at.h"
++#include "selinux-at.h"
++
++struct xattrs_mask_map
++{
++  const char **masks;
++  size_t size;
++  size_t used;
++};
++
++/* list of fnmatch patterns */
++static struct
++{
++  /* lists of fnmatch patterns */
++  struct xattrs_mask_map incl;
++  struct xattrs_mask_map excl;
++} xattrs_setup;
++
++/* disable posix acls when problem found in gnulib script m4/acl.m4 */
++#if ! USE_ACL
++# undef HAVE_POSIX_ACLS
++#endif
++
++#ifdef HAVE_POSIX_ACLS
++# include "acl.h"
++# include <sys/acl.h>
++#endif
++
++#ifdef HAVE_POSIX_ACLS
++
++/* acl-at wrappers, TODO: move to gnulib in future? */
++acl_t acl_get_file_at (int dirfd, const char *file, acl_type_t type);
++int acl_set_file_at (int dirfd, const char *file, acl_type_t type, acl_t acl);
++int file_has_acl_at (int dirfd, char const *, struct stat const *);
++
++/* acl_get_file_at */
++#define AT_FUNC_NAME acl_get_file_at
++#define AT_FUNC_RESULT acl_t
++#define AT_FUNC_FAIL (acl_t)NULL
++#define AT_FUNC_F1 acl_get_file
++#define AT_FUNC_POST_FILE_PARAM_DECLS   , acl_type_t type
++#define AT_FUNC_POST_FILE_ARGS          , type
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_RESULT
++#undef AT_FUNC_FAIL
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
++
++/* acl_set_file_at */
++#define AT_FUNC_NAME acl_set_file_at
++#define AT_FUNC_F1 acl_set_file
++#define AT_FUNC_POST_FILE_PARAM_DECLS   , acl_type_t type, acl_t acl
++#define AT_FUNC_POST_FILE_ARGS          , type, acl
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
++
++/* gnulib file_has_acl_at */
++#define AT_FUNC_NAME file_has_acl_at
++#define AT_FUNC_F1 file_has_acl
++#define AT_FUNC_POST_FILE_PARAM_DECLS   , struct stat const *st
++#define AT_FUNC_POST_FILE_ARGS          , st
++#include "at-func.c"
++#undef AT_FUNC_NAME
++#undef AT_FUNC_F1
++#undef AT_FUNC_POST_FILE_PARAM_DECLS
++#undef AT_FUNC_POST_FILE_ARGS
++
++/* convert unix permissions into an ACL ... needed due to "default" ACLs */
++static acl_t
++perms2acl (int perms)
++{
++  char val[] = "user::---,group::---,other::---";
++  /*            0123456789 123456789 123456789 123456789 */
++
++  /* user */
++  if (perms & 0400)
++    val[6] = 'r';
++  if (perms & 0200)
++    val[7] = 'w';
++  if (perms & 0100)
++    val[8] = 'x';
++
++  /* group */
++  if (perms & 0040)
++    val[17] = 'r';
++  if (perms & 0020)
++    val[18] = 'w';
++  if (perms & 0010)
++    val[19] = 'x';
++
++  /* other */
++  if (perms & 0004)
++    val[28] = 'r';
++  if (perms & 0002)
++    val[29] = 'w';
++  if (perms & 0001)
++    val[30] = 'x';
++
++  return acl_from_text (val);
++}
++
++static char *
++skip_to_ext_fields (char *ptr)
++{
++  /* skip tag name (user/group/default/mask) */
++  ptr += strcspn (ptr, ":,\n"); 
++
++  if (*ptr != ':')
++    return ptr;
++  ++ptr;
++
++  ptr += strcspn (ptr, ":,\n"); /* skip user/group name */
++
++  if (*ptr != ':')
++    return ptr;
++  ++ptr;
++
++  ptr += strcspn (ptr, ":,\n"); /* skip perms */
++
++  return ptr;
++}
++
++/* The POSIX draft allows extra fields after the three main ones. Star
++   uses this to add a fourth field for user/group which is the numeric ID.
++   This function removes such extra fields by overwriting them with the
++   characters that follow. */
++static char *
++fixup_extra_acl_fields (char *ptr)
++{
++  char *src = ptr;
++  char *dst = ptr;
++
++  while (*src)
++    {
++      const char *old = src;
++      size_t len = 0;
++
++      src = skip_to_ext_fields (src);
++      len = src - old;
++      if (old != dst)
++        memmove (dst, old, len);
++      dst += len;
++
++      if (*src == ':')          /* We have extra fields, skip them all */
++        src += strcspn (src, "\n,");
++
++      if ((*src == '\n') || (*src == ','))
++        *dst++ = *src++;        /* also done when dst == src, but that's ok */
++    }
++  if (src != dst)
++    *dst = 0;
++
++  return ptr;
++}
++
++/* "system.posix_acl_access" */
++static void
++xattrs__acls_set (struct tar_stat_info const *st,
++                  char const *file_name, int type,
++                  char *ptr, size_t len, bool def)
++{  
++  acl_t acl;
++
++  if (ptr)
++    {
++      /* assert (strlen (ptr) == len); */
++      ptr = fixup_extra_acl_fields (ptr);
++
++      acl = acl_from_text (ptr);
++      acls_option = 1;
++    }
++  else if (acls_option > 0)
++    acl = perms2acl (st->stat.st_mode);
++  else
++    return;  /* don't call acl functions unless we first hit an ACL, or
++		--acls was passed explicitly */
++
++  if (!acl)
++    {
++      call_arg_warn ("acl_from_text", file_name);
++      return;
++    }
++
++  if (acl_set_file_at (chdir_fd, file_name, type, acl) == -1)
++    /* warn even if filesystem does not support acls */
++    WARNOPT (WARN_XATTR_WRITE,
++	     (0, errno,
++	      _ ("acl_set_file_at: Cannot set POSIX ACLs for file '%s'"),
++	      file_name));
++
++  acl_free (acl);
++}
++
++static void
++xattrs__acls_get_a (int parentfd, const char *file_name,
++                    struct tar_stat_info *st,
++                    char **ret_ptr, size_t * ret_len)
++{             
++  char *val = NULL;
++  ssize_t len;
++  acl_t acl;
++
++  if (!(acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_ACCESS)))
++    {
++      if (errno != ENOTSUP)
++        call_arg_warn ("acl_get_file_at", file_name);
++      return;
++    }
++
++  val = acl_to_text (acl, &len);
++  acl_free (acl);
++
++  if (!val)
++    {
++      call_arg_warn ("acl_to_text", file_name);
++      return;
++    }
++
++  *ret_ptr = xstrdup (val);
++  *ret_len = len;
++
++  acl_free (val);
++}
++
++/* "system.posix_acl_default" */
++static void
++xattrs__acls_get_d (int parentfd, char const *file_name,
++                    struct tar_stat_info *st,
++                    char **ret_ptr, size_t * ret_len)
++{         
++  char *val = NULL;
++  ssize_t len;
++  acl_t acl;
++
++  if (!(acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_DEFAULT)))
++    {
++      if (errno != ENOTSUP)
++        call_arg_warn ("acl_get_file_at", file_name);
++      return;
++    }
++
++  val = acl_to_text (acl, &len);
++  acl_free (acl);
++
++  if (!val)
++    {
++      call_arg_warn ("acl_to_text", file_name);
++      return;
++    }
++
++  *ret_ptr = xstrdup (val);
++  *ret_len = len;
++
++  acl_free (val);
++}
++#endif /* HAVE_POSIX_ACLS */
++
++static void
++acls_one_line (const char *prefix, char delim,
++               const char *aclstring, size_t len)
++{
++  /* support both long and short text representation of posix acls */
++  struct obstack stk;
++  int pref_len = strlen (prefix);
++  const char *oldstring = aclstring;
++  int pos = 0;
++
++  if (!aclstring || !len)
++    return;
++
++  obstack_init (&stk);
++  while (pos <= len)
++    {
++      int move = strcspn (aclstring, ",\n");
++      if (!move)
++        break;
++
++      if (oldstring != aclstring)
++        obstack_1grow (&stk, delim);
++
++      obstack_grow (&stk, prefix, pref_len);
++      obstack_grow (&stk, aclstring, move);
++
++      aclstring += move + 1;
++    }
++
++  obstack_1grow (&stk, '\0');
++
++  fprintf (stdlis, "%s", (char *) obstack_finish (&stk));
++
++  obstack_free (&stk, NULL);
++}
++
++void
++xattrs_acls_get (int parentfd, char const *file_name,
++                 struct tar_stat_info *st, int fd, int xisfile)
++{
++  if (acls_option > 0)
++    {
++#ifndef HAVE_POSIX_ACLS
++      static int done = 0;
++      if (!done)
++        WARN ((0, 0, _("POSIX ACL support is not available")));
++      done = 1;
++#else
++      int err = file_has_acl_at (parentfd, file_name, &st->stat);
++      if (err == 0)
++        return;
++      if (err == -1)
++        {
++          call_arg_warn ("file_has_acl_at", file_name);
++          return;
++        }
++
++      xattrs__acls_get_a (parentfd, file_name, st,
++                          &st->acls_a_ptr, &st->acls_a_len);
++      if (!xisfile)
++        xattrs__acls_get_d (parentfd, file_name, st,
++                            &st->acls_d_ptr, &st->acls_d_len);
++#endif
++    }
++}
++
++void
++xattrs_acls_set (struct tar_stat_info const *st,
++                 char const *file_name, char typeflag)
++{
++  if (acls_option > 0 && typeflag != SYMTYPE)
++    {
++#ifndef HAVE_POSIX_ACLS
++      static int done = 0;
++      if (!done)
++        WARN ((0, 0, _("POSIX ACL support is not available")));
++      done = 1;
++#else
++      xattrs__acls_set (st, file_name, ACL_TYPE_ACCESS,
++                        st->acls_a_ptr, st->acls_a_len, false);
++      if (typeflag == DIRTYPE || typeflag == GNUTYPE_DUMPDIR)
++        xattrs__acls_set (st, file_name, ACL_TYPE_DEFAULT,
++                          st->acls_d_ptr, st->acls_d_len, true);
++#endif
++    }
++}
++
++static void
++mask_map_realloc (struct xattrs_mask_map *map)
++{
++  if (map->used == map->size)
++    {
++      if (map->size == 0)
++	map->size = 4;
++      map->masks = x2nrealloc (map->masks, &map->size, sizeof (map->masks[0]));
++    }
++}
++
++void
++xattrs_mask_add (const char *mask, bool incl)
++{
++  struct xattrs_mask_map *mask_map =
++    incl ? &xattrs_setup.incl : &xattrs_setup.excl;
++  /* ensure there is enough space */
++  mask_map_realloc (mask_map);
++  /* just assign pointers -- we silently expect that pointer "mask" is valid
++     through the whole program (pointer to argv array) */
++  mask_map->masks[mask_map->used++] = mask;
++}
++
++static void
++clear_mask_map (struct xattrs_mask_map *mask_map)
++{
++  if (mask_map->size)
++    free (mask_map->masks);
++}
++
++void
++xattrs_clear_setup ()
++{
++  clear_mask_map (&xattrs_setup.incl);
++  clear_mask_map (&xattrs_setup.excl);
++}
++
++/* get all xattrs from file given by FILE_NAME or FD (when non-zero).  This
++   includes all the user.*, security.*, system.*, etc. available domains */
++void
++xattrs_xattrs_get (int parentfd, char const *file_name,
++                   struct tar_stat_info *st, int fd)
++{
++  if (xattrs_option > 0)
++    {
++#ifndef HAVE_XATTRS
++      static int done = 0;
++      if (!done)
++        WARN ((0, 0, _("XATTR support is not available")));
++      done = 1;
++#else
++      static size_t xsz = 1024;
++      static char *xatrs = NULL;
++      ssize_t xret = -1;
++
++      if (!xatrs)
++	xatrs = x2nrealloc (xatrs, &xsz, 1);
++
++      while (((fd == 0) ?
++              ((xret =
++                llistxattrat (parentfd, file_name, xatrs, xsz)) == -1) :
++	      ((xret = flistxattr (fd, xatrs, xsz)) == -1))
++             && (errno == ERANGE))
++        {
++	  xatrs = x2nrealloc (xatrs, &xsz, 1);
++        }
++
++      if (xret == -1)
++        call_arg_warn ((fd == 0) ? "llistxattrat" : "flistxattr", file_name);
++      else
++        {
++          const char *attr = xatrs;
++          static size_t asz = 1024;
++          static char *val = NULL;
++
++          if (!val)
++            val = x2nrealloc (val, &asz, 1);
++
++          while (xret > 0)
++            {
++              size_t len = strlen (attr);
++              ssize_t aret = 0;
++
++              /* Archive all xattrs during creation, decide at extraction time
++               * which ones are of interest/use for the target filesystem. */
++              while (((fd == 0)
++                      ? ((aret = lgetxattrat (parentfd, file_name, attr,
++                                              val, asz)) == -1)
++                      : ((aret = fgetxattr (fd, attr, val, asz)) == -1))
++                     && (errno == ERANGE))
++                {
++		  val = x2nrealloc (val, &asz, 1);
++                }
++
++              if (aret != -1)
++                xheader_xattr_add (st, attr, val, aret);
++              else if (errno != ENOATTR)
++                call_arg_warn ((fd == 0) ? "lgetxattrat"
++                               : "fgetxattr", file_name);
++
++              attr += len + 1;
++              xret -= len + 1;
++            }
++        }
++#endif
++    }
++}
++
++static void
++xattrs__fd_set (struct tar_stat_info const *st,
++                char const *file_name, char typeflag,
++                const char *attr, const char *ptr, size_t len)
++{
++  if (ptr)
++    {
++      const char *sysname = "setxattrat";
++      int ret = -1;
++
++      if (typeflag != SYMTYPE)
++        ret = setxattrat (chdir_fd, file_name, attr, ptr, len, 0);
++      else
++        {
++          sysname = "lsetxattr";
++          ret = lsetxattrat (chdir_fd, file_name, attr, ptr, len, 0);
++        }
++
++      if (ret == -1)
++        WARNOPT (WARN_XATTR_WRITE,
++		 (0, errno,
++		  _("%s: Cannot set '%s' extended attribute for file '%s'"),
++		  sysname, attr, file_name));
++    }
++}
++
++/* lgetfileconat is called against FILE_NAME iff the FD parameter is set to
++   zero, otherwise the fgetfileconat is used against correct file descriptor */
++void
++xattrs_selinux_get (int parentfd, char const *file_name,
++                    struct tar_stat_info *st, int fd)
++{
++  if (selinux_context_option > 0)
++    {
++#if HAVE_SELINUX_SELINUX_H != 1
++      static int done = 0;
++      if (!done)
++        WARN ((0, 0, _("SELinux support is not available")));
++      done = 1;
++#else
++      int result = fd ?
++	            fgetfilecon (fd, &st->cntx_name)
++                    : lgetfileconat (parentfd, file_name, &st->cntx_name);
++
++      if (result == -1 && errno != ENODATA && errno != ENOTSUP)
++        call_arg_warn (fd ? "fgetfilecon" : "lgetfileconat", file_name);
++#endif
++    }
++}
++
++void
++xattrs_selinux_set (struct tar_stat_info const *st,
++                    char const *file_name, char typeflag)
++{
++  if (selinux_context_option > 0)
++    {
++#if HAVE_SELINUX_SELINUX_H != 1
++      static int done = 0;
++      if (!done)
++        WARN ((0, 0, _("SELinux support is not available")));
++      done = 1;
++#else
++      const char *sysname = "setfilecon";
++      int ret;
++
++      if (!st->cntx_name)
++        return;
++
++      if (typeflag != SYMTYPE)
++        {
++          ret = setfileconat (chdir_fd, file_name, st->cntx_name);
++          sysname = "setfileconat";
++        }
++      else
++        {
++          ret = lsetfileconat (chdir_fd, file_name, st->cntx_name);
++          sysname = "lsetfileconat";
++        }
++
++      if (ret == -1)
++        WARNOPT (WARN_XATTR_WRITE,
++		 (0, errno,
++		  _("%s: Cannot set SELinux context for file '%s'"),
++		  sysname, file_name));
++#endif
++    }
++}
++
++static bool
++xattrs_matches_mask (const char *kw, struct xattrs_mask_map *mm)
++{
++  int i;
++
++  if (!mm->size)
++    return false;
++
++  for (i = 0; i < mm->used; i++)
++    if (fnmatch (mm->masks[i], kw, 0) == 0)
++      return true;
++
++  return false;
++}
++
++#define USER_DOT_PFX "user."
++
++static bool
++xattrs_kw_included (const char *kw, bool archiving)
++{
++  if (xattrs_setup.incl.size)
++    return xattrs_matches_mask (kw, &xattrs_setup.incl);
++  else if (archiving)
++    return true;
++  else
++    return strncmp (kw, USER_DOT_PFX, sizeof (USER_DOT_PFX) - 1) == 0;
++}
++
++static bool
++xattrs_kw_excluded (const char *kw, bool archiving)
++{
++  return xattrs_setup.excl.size ?
++    xattrs_matches_mask (kw, &xattrs_setup.excl) : false;
++}
++
++/* Check whether the xattr with keyword KW should be discarded from list of
++   attributes that are going to be archived/excluded (set ARCHIVING=true for
++   archiving, false for excluding) */
++static bool
++xattrs_masked_out (const char *kw, bool archiving)
++{
++  return xattrs_kw_included (kw, archiving) ?
++    xattrs_kw_excluded (kw, archiving) : true; 
++}
++
++void
++xattrs_xattrs_set (struct tar_stat_info const *st,
++                   char const *file_name, char typeflag, int later_run)
++{
++  if (xattrs_option > 0)
++    {
++#ifndef HAVE_XATTRS
++      static int done = 0;
++      if (!done)
++        WARN ((0, 0, _("XATTR support is not available")));
++      done = 1;
++#else
++      size_t scan = 0;
++
++      if (!st->xattr_map_size)
++        return;
++
++      for (; scan < st->xattr_map_size; ++scan)
++        {
++          char *keyword = st->xattr_map[scan].xkey;
++          keyword += strlen ("SCHILY.xattr.");
++
++          /* TODO: this 'later_run' workaround is temporary solution -> once
++             capabilities should become fully supported by it's API and there
++             should exist something like xattrs_capabilities_set() call.
++             For a regular files: all extended attributes are restored during
++             the first run except 'security.capability' which is restored in
++             'later_run == 1'.  */
++          if (typeflag == REGTYPE
++              && later_run == !!strcmp (keyword, "security.capability"))
++            continue;
++
++          if (xattrs_masked_out (keyword, false /* extracting */ ))
++            /* we don't want to restore this keyword */
++            continue;
++
++          xattrs__fd_set (st, file_name, typeflag, keyword,
++                          st->xattr_map[scan].xval_ptr,
++                          st->xattr_map[scan].xval_len);
++        }
++#endif
++    }
++}
++
++void
++xattrs_print_char (struct tar_stat_info const *st, char *output)
++{
++  int i;
++
++  if (verbose_option < 2)
++    {
++      *output = 0;
++      return;
++    }
++
++  if (xattrs_option > 0 || selinux_context_option > 0 || acls_option > 0)
++    {
++      /* placeholders */
++      *output = ' ';
++      output[1] = 0;
++    }
++
++  if (xattrs_option > 0 && st->xattr_map_size)
++    for (i = 0; i < st->xattr_map_size; ++i)
++      {
++        char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr.");
++        if (!xattrs_masked_out (keyword, false /* like extracting */ ))
++	  {
++	    *output = '*';
++	    break;
++	  }
++      }
++
++  if (selinux_context_option > 0 && st->cntx_name)
++    *output = '.';
++
++  if (acls_option && (st->acls_a_len || st->acls_d_len))
++    *output = '+';
++}
++
++void
++xattrs_print (struct tar_stat_info const *st)
++{
++  if (verbose_option < 3)
++    return;
++
++  /* selinux */
++  if (selinux_context_option && st->cntx_name)
++    fprintf (stdlis, "  s: %s\n", st->cntx_name);
++
++  /* acls */
++  if (acls_option && (st->acls_a_len || st->acls_d_len))
++    {
++      fprintf (stdlis, "  a: ");
++      acls_one_line ("", ',', st->acls_a_ptr, st->acls_a_len);
++      acls_one_line ("default:", ',', st->acls_d_ptr, st->acls_d_len);
++      fprintf (stdlis, "\n");
++    }
++
++  /* xattrs */
++  if (xattrs_option && st->xattr_map_size)
++    {
++      int i;
++      
++      for (i = 0; i < st->xattr_map_size; ++i)
++        {
++          char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr.");
++          if (!xattrs_masked_out (keyword, false /* like extracting */ ))
++	    fprintf (stdlis, "  x: %lu %s\n",
++		     (unsigned long) st->xattr_map[i].xval_len, keyword);
++        }
++    }
++}
+diff --git a/src/xattrs.h b/src/xattrs.h
+new file mode 100644
+index 0000000..bfef466
+--- /dev/null
++++ b/src/xattrs.h
+@@ -0,0 +1,51 @@
++/* Support for extended attributes.
++
++   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software
++   Foundation, Inc.
++
++   Written by James Antill, on 2006-07-27.
++
++   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, 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, write to the Free Software Foundation, Inc.,
++   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++*/
++
++#ifndef GUARD_XATTTRS_H
++#define GUARD_XATTTRS_H
++
++/* Add include/exclude fnmatch pattern for xattr key domain.  Set INCL parameter
++   to true/false if you want to add include/exclude pattern */
++extern void xattrs_mask_add (const char *mask, bool incl);
++
++/* clear helping structures when tar finishes */
++extern void xattrs_clear_setup ();
++
++extern void xattrs_acls_get (int parentfd, char const *file_name,
++                             struct tar_stat_info *st, int fd, int xisfile);
++extern void xattrs_selinux_get (int parentfd, char const *file_name,
++                                struct tar_stat_info *st, int fd);
++extern void xattrs_xattrs_get (int parentfd, char const *file_name,
++                               struct tar_stat_info *st, int fd);
++
++extern void xattrs_acls_set (struct tar_stat_info const *st,
++                             char const *file_name, char typeflag);
++extern void xattrs_selinux_set (struct tar_stat_info const *st,
++                                char const *file_name, char typeflag);
++extern void xattrs_xattrs_set (struct tar_stat_info const *st,
++                               char const *file_name, char typeflag,
++                               int later_run);
++
++extern void xattrs_print_char (struct tar_stat_info const *st, char *output);
++extern void xattrs_print (struct tar_stat_info const *st);
++
++#endif /* GUARD_XATTTRS_H */
+diff --git a/src/xheader.c b/src/xheader.c
+index 2284e97..be793d4 100644
+--- a/src/xheader.c
++++ b/src/xheader.c
+@@ -1,7 +1,7 @@
+ /* POSIX extended headers for tar.
+ 
+-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software
+-   Foundation, Inc.
++   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2012
++   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
+@@ -460,6 +460,123 @@ xheader_write_global (struct xheader *xhdr)
+     }
+ }
+ 
++void
++xheader_xattr_init (struct tar_stat_info *st)
++{
++  st->xattr_map = NULL;
++  st->xattr_map_size = 0;
++
++  st->acls_a_ptr = NULL;
++  st->acls_a_len = 0;
++  st->acls_d_ptr = NULL;
++  st->acls_d_len = 0;
++  st->cntx_name = NULL;
++}
++
++void
++xheader_xattr_free (struct xattr_array *xattr_map, size_t xattr_map_size)
++{
++  size_t scan = 0;
++
++  while (scan < xattr_map_size)
++    {
++      free (xattr_map[scan].xkey);
++      free (xattr_map[scan].xval_ptr);
++
++      ++scan;
++    }
++  free (xattr_map);
++}
++
++static void
++xheader_xattr__add (struct xattr_array **xattr_map,
++		    size_t *xattr_map_size,
++		    const char *key, const char *val, size_t len)
++{
++  size_t pos = (*xattr_map_size)++;
++
++  *xattr_map = xrealloc (*xattr_map,
++                         *xattr_map_size * sizeof(struct xattr_array));
++  (*xattr_map)[pos].xkey = xstrdup (key);
++  (*xattr_map)[pos].xval_ptr = xmemdup (val, len + 1);
++  (*xattr_map)[pos].xval_len = len;
++}
++
++/* This is reversal function for xattr_encode_keyword.  See comment for
++   xattr_encode_keyword() for more info. */
++static void
++xattr_decode_keyword (char *keyword)
++{
++  char *kpr, *kpl; /* keyword pointer left/right */
++  kpr = kpl = keyword;
++
++  for (;;)
++    {
++      if (*kpr == '%')
++        {
++          if (kpr[1] == '3' && kpr[2] == 'D')
++            {
++              *kpl = '=';
++              kpr += 3;
++              kpl ++;
++              continue;
++            }
++          else if (kpr[1] == '2' && kpr[2] == '5')
++            {
++              *kpl = '%';
++              kpr += 3;
++              kpl ++;
++              continue;
++            }
++        }
++
++      *kpl = *kpr;
++
++      if (*kpr == 0)
++        break;
++
++      kpr++;
++      kpl++;
++    }
++}
++
++void
++xheader_xattr_add (struct tar_stat_info *st,
++		   const char *key, const char *val, size_t len)
++{
++  size_t klen = strlen (key);
++  char *xkey = xmalloc (strlen("SCHILY.xattr.") + klen + 1);
++  char *tmp = xkey;
++
++  tmp = stpcpy (tmp, "SCHILY.xattr.");
++  stpcpy (tmp, key);
++
++  xheader_xattr__add (&st->xattr_map, &st->xattr_map_size, xkey, val, len);
++
++  free (xkey);
++}
++
++void
++xheader_xattr_copy (const struct tar_stat_info *st,
++		    struct xattr_array **xattr_map, size_t *xattr_map_size)
++{
++  size_t scan = 0;
++
++  *xattr_map = NULL;
++  *xattr_map_size = 0;
++
++  while (scan < st->xattr_map_size)
++    {
++      char  *key = st->xattr_map[scan].xkey;
++      char  *val = st->xattr_map[scan].xval_ptr;
++      size_t len = st->xattr_map[scan].xval_len;
++
++      xheader_xattr__add(xattr_map, xattr_map_size, key, val, len);
++
++      ++scan;
++    }
++}
++
+ 
+ /* General Interface */
+ 
+@@ -473,6 +590,7 @@ struct xhdr_tab
+ 		 struct xheader *, void const *data);
+   void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);
+   int flags;
++  bool prefix; /* select handler comparing prefix only */
+ };
+ 
+ /* This declaration must be extern, because ISO C99 section 6.9.2
+@@ -489,8 +607,17 @@ locate_handler (char const *keyword)
+   struct xhdr_tab const *p;
+ 
+   for (p = xhdr_tab; p->keyword; p++)
+-    if (strcmp (p->keyword, keyword) == 0)
+-      return p;
++    if (p->prefix)
++      {
++        if (strncmp (p->keyword, keyword, strlen(p->keyword)) == 0)
++          return p;
++      }
++    else
++      {
++        if (strcmp (p->keyword, keyword) == 0)
++          return p;
++      }
++
+   return NULL;
+ }
+ 
+@@ -500,7 +627,8 @@ xheader_protected_pattern_p (const char *pattern)
+   struct xhdr_tab const *p;
+ 
+   for (p = xhdr_tab; p->keyword; p++)
+-    if ((p->flags & XHDR_PROTECTED) && fnmatch (pattern, p->keyword, 0) == 0)
++    if (!p->prefix && (p->flags & XHDR_PROTECTED)
++        && fnmatch (pattern, p->keyword, 0) == 0)
+       return true;
+   return false;
+ }
+@@ -511,7 +639,8 @@ xheader_protected_keyword_p (const char *keyword)
+   struct xhdr_tab const *p;
+ 
+   for (p = xhdr_tab; p->keyword; p++)
+-    if ((p->flags & XHDR_PROTECTED) && strcmp (p->keyword, keyword) == 0)
++    if (!p->prefix && (p->flags & XHDR_PROTECTED)
++        && strcmp (p->keyword, keyword) == 0)
+       return true;
+   return false;
+ }
+@@ -721,15 +850,71 @@ xheader_read (struct xheader *xhdr, union block *p, size_t size)
+   while (size > 0);
+ }
+ 
++/* xattr_encode_keyword() substitutes '=' ~~> '%3D' and '%' ~~> '%25'
++   in extended attribute keywords.  This is needed because the '=' character
++   has special purpose in extended attribute header - it splits keyword and
++   value part of header.  If there was the '=' occurrence allowed inside
++   keyword, there would be no unambiguous way how to decode this extended
++   attribute.
++
++   (http://lists.gnu.org/archive/html/bug-tar/2012-10/msg00017.html)
++ */
++static char *
++xattr_encode_keyword(const char *keyword)
++{
++  static char *encode_buffer = NULL;
++  static size_t encode_buffer_size = 0;
++  size_t bp; /* keyword/buffer pointers */
++
++  if (!encode_buffer)
++    {
++      encode_buffer_size = 256;
++      encode_buffer = xmalloc (encode_buffer_size);
++    }
++  else
++    *encode_buffer = 0;
++
++  for (bp = 0; *keyword != 0; ++bp, ++keyword)
++    {
++      char c = *keyword;
++
++      if (bp + 2 /* enough for URL encoding also.. */ >= encode_buffer_size)
++        {
++          encode_buffer = x2realloc (encode_buffer, &encode_buffer_size);
++        }
++
++      if (c == '%')
++        {
++          strcpy (encode_buffer + bp, "%25");
++          bp += 2;
++        }
++      else if (c == '=')
++        {
++          strcpy (encode_buffer + bp, "%3D");
++          bp += 2;
++        }
++      else
++        encode_buffer[bp] = c;
++    }
++
++  encode_buffer[bp] = 0;
++
++  return encode_buffer;
++}
++
+ static void
+ xheader_print_n (struct xheader *xhdr, char const *keyword,
+ 		 char const *value, size_t vsize)
+ {
+-  size_t len = strlen (keyword) + vsize + 3; /* ' ' + '=' + '\n' */
+   size_t p;
+   size_t n = 0;
+   char nbuf[UINTMAX_STRSIZE_BOUND];
+   char const *np;
++  size_t len, klen;
++
++  keyword = xattr_encode_keyword (keyword);
++  klen = strlen (keyword);
++  len = klen + vsize + 3; /* ' ' + '=' + '\n' */
+ 
+   do
+     {
+@@ -741,7 +926,7 @@ xheader_print_n (struct xheader *xhdr, char const *keyword,
+ 
+   x_obstack_grow (xhdr, np, n);
+   x_obstack_1grow (xhdr, ' ');
+-  x_obstack_grow (xhdr, keyword, strlen (keyword));
++  x_obstack_grow (xhdr, keyword, klen);
+   x_obstack_1grow (xhdr, '=');
+   x_obstack_grow (xhdr, value, vsize);
+   x_obstack_1grow (xhdr, '\n');
+@@ -1002,8 +1187,6 @@ decode_time (struct timespec *ts, char const *arg, char const *keyword)
+   return true;
+ }
+ 
+-
+-
+ static void
+ code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
+ {
+@@ -1470,6 +1653,80 @@ volume_filename_decoder (struct tar_stat_info *st,
+ }
+ 
+ static void
++xattr_selinux_coder (struct tar_stat_info const *st, char const *keyword,
++                     struct xheader *xhdr, void const *data)
++{
++  code_string (st->cntx_name, keyword, xhdr);
++}
++
++static void
++xattr_selinux_decoder (struct tar_stat_info *st,
++                       char const *keyword, char const *arg, size_t size)
++{
++  decode_string (&st->cntx_name, arg);
++}
++
++static void
++xattr_acls_a_coder (struct tar_stat_info const *st , char const *keyword,
++                    struct xheader *xhdr, void const *data)
++{
++  xheader_print_n (xhdr, keyword, st->acls_a_ptr, st->acls_a_len);
++}
++
++static void
++xattr_acls_a_decoder (struct tar_stat_info *st,
++                      char const *keyword, char const *arg, size_t size)
++{
++  st->acls_a_ptr = xmemdup (arg, size + 1);
++  st->acls_a_len = size;
++}
++
++static void
++xattr_acls_d_coder (struct tar_stat_info const *st , char const *keyword,
++                    struct xheader *xhdr, void const *data)
++{
++  xheader_print_n (xhdr, keyword, st->acls_d_ptr, st->acls_d_len);
++}
++
++static void
++xattr_acls_d_decoder (struct tar_stat_info *st,
++                      char const *keyword, char const *arg, size_t size)
++{
++  st->acls_d_ptr = xmemdup (arg, size + 1);
++  st->acls_d_len = size;
++}
++
++static void
++xattr_coder (struct tar_stat_info const *st, char const *keyword,
++             struct xheader *xhdr, void const *data)
++{
++  struct xattr_array *xattr_map = st->xattr_map;
++  const size_t *off = data;
++  xheader_print_n (xhdr, keyword,
++                   xattr_map[*off].xval_ptr, xattr_map[*off].xval_len);
++}
++
++static void
++xattr_decoder (struct tar_stat_info *st,
++               char const *keyword, char const *arg, size_t size)
++{
++  char *xstr, *xkey;
++
++  /* copy keyword */
++  size_t klen_raw = strlen (keyword);
++  xkey = alloca (klen_raw + 1);
++  memcpy (xkey, keyword, klen_raw + 1) /* including null-terminating */;
++
++  /* copy value */
++  xstr = alloca (size + 1);
++  memcpy (xstr, arg, size + 1); /* separator included, for GNU tar '\n' */;
++
++  xattr_decode_keyword (xkey);
++
++  xheader_xattr_add (st, xkey + strlen("SCHILY.xattr."), xstr, size);
++}
++
++static void
+ sparse_major_coder (struct tar_stat_info const *st, char const *keyword,
+ 		    struct xheader *xhdr, void const *data)
+ {
+@@ -1506,53 +1763,53 @@ sparse_minor_decoder (struct tar_stat_info *st,
+ }
+ 
+ struct xhdr_tab const xhdr_tab[] = {
+-  { "atime",	atime_coder,	atime_decoder,	  0 },
+-  { "comment",	dummy_coder,	dummy_decoder,	  0 },
+-  { "charset",	dummy_coder,	dummy_decoder,	  0 },
+-  { "ctime",	ctime_coder,	ctime_decoder,	  0 },
+-  { "gid",	gid_coder,	gid_decoder,	  0 },
+-  { "gname",	gname_coder,	gname_decoder,	  0 },
+-  { "linkpath", linkpath_coder, linkpath_decoder, 0 },
+-  { "mtime",	mtime_coder,	mtime_decoder,	  0 },
+-  { "path",	path_coder,	path_decoder,	  0 },
+-  { "size",	size_coder,	size_decoder,	  0 },
+-  { "uid",	uid_coder,	uid_decoder,	  0 },
+-  { "uname",	uname_coder,	uname_decoder,	  0 },
++  { "atime",    atime_coder,    atime_decoder,    0, false },
++  { "comment",  dummy_coder,    dummy_decoder,    0, false },
++  { "charset",  dummy_coder,    dummy_decoder,    0, false },
++  { "ctime",    ctime_coder,    ctime_decoder,    0, false },
++  { "gid",      gid_coder,      gid_decoder,      0, false },
++  { "gname",    gname_coder,    gname_decoder,    0, false },
++  { "linkpath", linkpath_coder, linkpath_decoder, 0, false },
++  { "mtime",    mtime_coder,    mtime_decoder,    0, false },
++  { "path",     path_coder,     path_decoder,     0, false },
++  { "size",     size_coder,     size_decoder,     0, false },
++  { "uid",      uid_coder,      uid_decoder,      0, false },
++  { "uname",    uname_coder,    uname_decoder,    0, false },
+ 
+   /* Sparse file handling */
+   { "GNU.sparse.name",       path_coder, path_decoder,
+-    XHDR_PROTECTED },
++    XHDR_PROTECTED, false },
+   { "GNU.sparse.major",      sparse_major_coder, sparse_major_decoder,
+-    XHDR_PROTECTED },
++    XHDR_PROTECTED, false },
+   { "GNU.sparse.minor",      sparse_minor_coder, sparse_minor_decoder,
+-    XHDR_PROTECTED },
++    XHDR_PROTECTED, false },
+   { "GNU.sparse.realsize",   sparse_size_coder, sparse_size_decoder,
+-    XHDR_PROTECTED },
++    XHDR_PROTECTED, false },
+   { "GNU.sparse.numblocks",  sparse_numblocks_coder, sparse_numblocks_decoder,
+-    XHDR_PROTECTED },
++    XHDR_PROTECTED, false },
+ 
+   /* tar 1.14 - 1.15.90 keywords. */
+   { "GNU.sparse.size",       sparse_size_coder, sparse_size_decoder,
+-    XHDR_PROTECTED },
++    XHDR_PROTECTED, false },
+   /* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
+      headers, and each of them was meaningful. It confilcted with POSIX specs,
+      which requires that "when extended header records conflict, the last one
+      given in the header shall take precedence." */
+   { "GNU.sparse.offset",     sparse_offset_coder, sparse_offset_decoder,
+-    XHDR_PROTECTED },
++    XHDR_PROTECTED, false },
+   { "GNU.sparse.numbytes",   sparse_numbytes_coder, sparse_numbytes_decoder,
+-    XHDR_PROTECTED },
++    XHDR_PROTECTED, false },
+   /* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
+   { "GNU.sparse.map",        NULL /* Unused, see pax_dump_header() */,
+-    sparse_map_decoder, 0 },
++    sparse_map_decoder, 0, false },
+ 
+   { "GNU.dumpdir",           dumpdir_coder, dumpdir_decoder,
+-    XHDR_PROTECTED },
++    XHDR_PROTECTED, false },
+ 
+   /* Keeps the tape/volume label. May be present only in the global headers.
+      Equivalent to GNUTYPE_VOLHDR.  */
+   { "GNU.volume.label", volume_label_coder, volume_label_decoder,
+-    XHDR_PROTECTED | XHDR_GLOBAL },
++    XHDR_PROTECTED | XHDR_GLOBAL, false },
+ 
+   /* These may be present in a first global header of the archive.
+      They provide the same functionality as GNUTYPE_MULTIVOL header.
+@@ -1561,11 +1818,28 @@ struct xhdr_tab const xhdr_tab[] = {
+      GNU.volume.offset keeps the offset of the start of this volume,
+      otherwise kept in oldgnu_header.offset.  */
+   { "GNU.volume.filename", volume_label_coder, volume_filename_decoder,
+-    XHDR_PROTECTED | XHDR_GLOBAL },
++    XHDR_PROTECTED | XHDR_GLOBAL, false },
+   { "GNU.volume.size", volume_size_coder, volume_size_decoder,
+-    XHDR_PROTECTED | XHDR_GLOBAL },
++    XHDR_PROTECTED | XHDR_GLOBAL, false },
+   { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder,
+-    XHDR_PROTECTED | XHDR_GLOBAL },
++    XHDR_PROTECTED | XHDR_GLOBAL, false },
++
++  /* We get the SELinux value from filecon, so add a namespace for SELinux
++     instead of storing it in SCHILY.xattr.* (which would be RAW). */
++  { "RHT.security.selinux",
++    xattr_selinux_coder, xattr_selinux_decoder, 0, false },
++
++  /* ACLs, use the star format... */
++  { "SCHILY.acl.access",
++    xattr_acls_a_coder, xattr_acls_a_decoder, 0, false },
++
++  { "SCHILY.acl.default",
++    xattr_acls_d_coder, xattr_acls_d_decoder, 0, false },
++
++  /* We are storing all extended attributes using this rule even if some of them
++     were stored by some previous rule (duplicates) -- we just have to make sure
++     they are restored *only once* during extraction later on. */
++  { "SCHILY.xattr", xattr_coder, xattr_decoder, 0, true },
+ 
+-  { NULL, NULL, NULL, 0 }
++  { NULL, NULL, NULL, 0, false }
+ };
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 3d78ea2..b0da439 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -171,7 +171,17 @@ TESTSUITE_AT = \
+  star/multi-fail.at\
+  star/ustar-big-2g.at\
+  star/ustar-big-8g.at\
+- star/pax-big-10g.at
++ star/pax-big-10g.at\
++ xattr01.at\
++ xattr02.at\
++ xattr03.at\
++ xattr04.at\
++ xattr05.at\
++ acls01.at\
++ acls02.at\
++ selnx01.at\
++ selacl01.at\
++ capabs_raw01.at
+ 
+ TESTSUITE = $(srcdir)/testsuite
+ 
+diff --git a/tests/acls01.at b/tests/acls01.at
+new file mode 100644
+index 0000000..0149f2d
+--- /dev/null
++++ b/tests/acls01.at
+@@ -0,0 +1,53 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2011 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, 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/>.
++#
++# Test description:
++#
++# This is basic test for acl support.
++
++AT_SETUP([acls: basic functionality])
++AT_KEYWORDS([xattrs acls acls01])
++
++AT_TAR_CHECK([
++AT_XATTRS_UTILS_PREREQ
++AT_ACLS_PREREQ
++
++mkdir dir
++genfile --file dir/file
++
++MYNAME=$( id -un )
++
++setfacl -m u:$MYNAME:--x dir/file
++setfacl -m u:$MYNAME:--x dir
++
++getfattr -h -m. -d dir dir/file > before
++
++tar --acls -cf archive.tar dir
++rm -rf dir
++
++tar --acls -xf archive.tar
++
++getfattr -h -m. -d dir dir/file > after
++
++diff before after
++test "$?" = 0
++],
++[0],
++[])
++
++AT_CLEANUP
+diff --git a/tests/acls02.at b/tests/acls02.at
+new file mode 100644
+index 0000000..2ee1c5f
+--- /dev/null
++++ b/tests/acls02.at
+@@ -0,0 +1,59 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2011 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, 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/>.
++#
++# Test description:
++#
++# This is basic test for acl support.
++
++AT_SETUP([acls: work with -C])
++AT_KEYWORDS([xattrs acls acls02])
++
++AT_TAR_CHECK([
++AT_XATTRS_UTILS_PREREQ
++AT_ACLS_PREREQ
++
++mkdir dir
++mkdir dir/subdir
++genfile --file dir/subdir/file
++
++MYNAME=$( id -un )
++
++setfacl -m u:$MYNAME:--x dir/subdir
++setfacl -m u:$MYNAME:--x dir/subdir/file
++
++cd dir
++getfattr -h -m. -d subdir subdir/file > ../before
++cd ..
++
++tar --acls -cf archive.tar -C dir subdir
++rm -rf dir
++
++mkdir dir
++tar --acls -xf archive.tar -C dir
++
++cd dir
++getfattr -h -m. -d subdir subdir/file > ../after
++cd ..
++
++diff before after
++test "$?" = 0
++],
++[0],
++[])
++
++AT_CLEANUP
+diff --git a/tests/capabs_raw01.at b/tests/capabs_raw01.at
+new file mode 100644
+index 0000000..8eea0cf
+--- /dev/null
++++ b/tests/capabs_raw01.at
+@@ -0,0 +1,51 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2012 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, 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/>.
++#
++# Test description:  Test if file capabilities are archived/restored correctly
++# using just the default xattr support (capabilities are stored/restored in
++# binary format -> system dependant).
++
++AT_SETUP([capabilities: binary store/restore])
++AT_KEYWORDS([xattrs capabilities capabs_raw01])
++
++AT_TAR_CHECK([
++AT_PRIVILEGED_PREREQ
++AT_XATTRS_PREREQ
++AT_CAPABILITIES_UTILS_PREREQ
++
++mkdir dir
++genfile --file dir/file
++
++setcap "= cap_chown=ei" dir/file
++
++# archive whole directory including binary xattrs
++tar --xattrs -cf archive.tar dir
++
++# clear the directory
++rm -rf dir
++
++# restore _all_ xattrs (not just the user.* domain)
++tar --xattrs --xattrs-include='*' -xf archive.tar
++
++getcap dir/file
++],
++[0],
++[dir/file = cap_chown+ei
++])
++
++AT_CLEANUP
+diff --git a/tests/selacl01.at b/tests/selacl01.at
+new file mode 100644
+index 0000000..90d0c5b
+--- /dev/null
++++ b/tests/selacl01.at
+@@ -0,0 +1,64 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2011 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, 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/>.
++#
++# Test description:
++#
++# This is basic test for support of extended attributes.
++
++AT_SETUP([acls/selinux: special files & fifos])
++AT_KEYWORDS([xattrs selinux acls selacls01])
++
++AT_TAR_CHECK([
++AT_PRIVILEGED_PREREQ
++AT_XATTRS_UTILS_PREREQ
++AT_SELINUX_PREREQ
++AT_ACLS_PREREQ
++
++mkdir dir
++mkfifo dir/fifo
++MAJOR=$( stat /dev/urandom --printf="%t" )
++MINOR=$( stat /dev/urandom --printf="%T" )
++mknod dir/chartype c $MAJOR $MINOR
++
++# setup attributes
++restorecon -R dir
++chcon -h --user=system_u dir/fifo
++chcon -h --user=system_u dir/chartype
++setfacl -m u:$UID:--- dir/fifo
++setfacl -m u:$UID:rwx dir/chartype
++
++getfacl dir/fifo >> before
++getfattr -msecurity.selinux dir/chartype >> before
++
++tar --xattrs --selinux --acls -cf archive.tar dir
++
++mv dir olddir
++
++tar --xattrs --selinux --acls -xf archive.tar
++
++getfacl dir/fifo >> after
++getfattr -msecurity.selinux dir/chartype >> after
++
++diff before after
++echo separator
++],
++[0],
++[separator
++])
++
++AT_CLEANUP
+diff --git a/tests/selnx01.at b/tests/selnx01.at
+new file mode 100644
+index 0000000..79f7267
+--- /dev/null
++++ b/tests/selnx01.at
+@@ -0,0 +1,96 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2012 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, 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/>.
++#
++# Test description:
++#
++# This is basic test for selinux support (store & restore).
++
++AT_SETUP([selinux: basic store/restore])
++AT_KEYWORDS([xattrs selinux selnx01])
++
++AT_TAR_CHECK([
++AT_XATTRS_UTILS_PREREQ
++AT_SELINUX_PREREQ
++
++mkdir dir
++genfile --file dir/file
++ln -s file dir/link
++
++getfattr -h -d -msecurity.selinux dir dir/file dir/link > start
++
++restorecon -R dir
++chcon -h --user=system_u     dir
++chcon -h --user=unconfined_u dir/file
++chcon -h --user=system_u     dir/link
++
++# archive whole directory including selinux contexts
++tar --selinux -cf archive.tar dir
++
++# clear the directory
++rm -rf dir
++
++# ================================================
++# check if selinux contexts are correctly restored
++
++tar --selinux -xf archive.tar
++
++# archive for later debugging
++cp archive.tar archive_origin.tar
++
++# check if selinux contexts were restored
++getfattr -h -d dir dir/file dir/link -msecurity.selinux | \
++    grep -v -e '^#' -e ^$ | cut -d: -f1
++
++# ===========================================================================
++# check if selinux contexts are not restored when --selinux option is missing
++
++getfattr -h -d -msecurity.selinux dir dir/file dir/link > with_selinux
++rm -rf dir
++tar -xf archive.tar
++getfattr -h -d -msecurity.selinux dir dir/file dir/link > without_selinux
++
++diff with_selinux without_selinux > diff_with_without
++if test "$?" -eq "0"; then
++    echo "selinux contexts probably restored while --selinux is off"
++fi
++
++# =================================================================
++# check if selinux is not archived when --selinux option is missing
++
++tar -cf archive.tar dir
++
++# clear the directory
++rm -rf dir
++
++# restore (with --selinux)
++tar --selinux -xf archive.tar dir
++
++getfattr -h -d -msecurity.selinux dir dir/file dir/link > final
++diff start final > final_diff
++if test "$?" -ne "0"; then
++    echo "bad result"
++fi
++
++],
++[0],
++[security.selinux="system_u
++security.selinux="unconfined_u
++security.selinux="system_u
++])
++
++AT_CLEANUP
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index e43653e..8d5811d 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -81,13 +81,6 @@ m4_define([AT_GZIP_PREREQ],[
+ cat /dev/null | m4_if([$1],[],gzip,[$1]) - > /dev/null 2>&1 || AT_SKIP_TEST
+ ])
+ 
+-dnl AT_SIGPIPE_PREREQ - Skip test unless SIGPIPE handling is the default
+-m4_define([AT_SIGPIPE_PREREQ],[
+-case `(cat "$at_myself" 2>&3 | :) 3>&1 >/dev/null` in #(
+-?*) AT_SKIP_TEST;;
+-esac
+-])
+-
+ dnl AT_SORT_PREREQ - Skip test if sort utility outputs unwanted data on stderr
+ m4_define([AT_SORT_PREREQ],[
+ test -z "`sort < /dev/null 2>&1`" || AT_SKIP_TEST
+@@ -103,10 +96,86 @@ rm -f $[]$
+ test $result -eq 0 && AT_SKIP_TEST
+ ])
+ 
++dnl AT_SIGPIPE_PREREQ - Skip test unless SIGPIPE handling is the default
++m4_define([AT_SIGPIPE_PREREQ],[
++case `(cat "$at_myself" 2>&3 | :) 3>&1 >/dev/null` in #(
++?*) AT_SKIP_TEST;;
++esac
++])
++
++dnl AT_PRIVILEGED_PREREQ - Skip test if not running at root privileges
++m4_define([AT_PRIVILEGED_PREREQ],[
++echo "test" > $[]$
++chmod 0 $[]$
++cat $[]$ > /dev/null 2>&1
++result=$?
++rm -f $[]$
++test $result -eq 0 || AT_SKIP_TEST
++])
++
+ m4_define([AT_TAR_MKHIER],[
+ install-sh -d $1 >/dev/null dnl
+ m4_if([$2],,,&& genfile --file [$1]/[$2]) || AT_SKIP_TEST])
+ 
++dnl Skip test when utlity does not return expected return value
++m4_define([AT_CHECK_UTIL],[
++  $1 &> /dev/null
++  if test "$?" != $2; then
++    AT_SKIP_TEST
++  fi
++])
++
++m4_define([AT_XATTRS_UTILS_PREREQ],[
++  file=$( mktemp -p . )
++  AT_CHECK_UTIL(setfattr -n user.test -v test $file,0)
++  AT_CHECK_UTIL(getfattr $file,0)
++])
++m4_define([AT_SELINUX_UTILS_PREREQ],[
++  file=$( mktemp -p . )
++  AT_CHECK_UTIL(restorecon $file, 0)
++  AT_CHECK_UTIL(chcon -h --user=unconfined_u $file,0)
++  rm -rf $file
++])
++m4_define([AT_ACLS_UTILS_PREREQ],[
++  file=$( mktemp -p . )
++  AT_CHECK_UTIL(setfacl -m u:$UID:rwx $file,0)
++  AT_CHECK_UTIL(getfacl $file,0)
++  rm -rf $file
++])
++m4_define([AT_CAPABILITIES_UTILS_PREREQ],[
++  file=$( mktemp -p . )
++  AT_CHECK_UTIL(setcap "= cap_chown=ei" $file,0)
++  AT_CHECK_UTIL(getcap $file,0)
++  rm -rf $file
++])
++m4_define([AT_XATTRS_PREREQ],[
++  AT_XATTRS_UTILS_PREREQ
++  file=$( mktemp -p . )
++  setfattr -n user.test -v ahoj $file
++  # check whether tar fails to store xattrs
++  err=$( tar --xattrs -cf /dev/null $file 2>&1 >/dev/null | wc -l )
++  if test "$err" != "0"; then
++    AT_SKIP_TEST
++  fi
++])
++m4_define([AT_SELINUX_PREREQ],[
++  AT_SELINUX_UTILS_PREREQ
++  file=$( mktemp -p . )
++  err=$( tar --selinux -cf /dev/null $file 2>&1 >/dev/null | wc -l )
++  if test "$err" != "0"; then
++    AT_SKIP_TEST
++  fi
++])
++m4_define([AT_ACLS_PREREQ],[
++  AT_ACLS_UTILS_PREREQ
++  file=$( mktemp -p . )
++  setfacl -m u:$UID:rwx $file
++  err=$( tar --acls -cf /dev/null $file 2>&1 >/dev/null | wc -l )
++  if test "$err" != "0"; then
++    AT_SKIP_TEST
++  fi
++])
++
+ m4_include([sparsemvp.at])
+ 
+ AT_INIT
+@@ -264,6 +334,20 @@ m4_include([remfiles03.at])
+ 
+ m4_include([sigpipe.at])
+ 
++m4_include([xattr01.at])
++m4_include([xattr02.at])
++m4_include([xattr03.at])
++m4_include([xattr04.at])
++m4_include([xattr05.at])
++
++m4_include([acls01.at])
++m4_include([acls02.at])
++
++m4_include([selnx01.at])
++m4_include([selacl01.at])
++
++m4_include([capabs_raw01.at])
++
+ m4_include([star/gtarfail.at])
+ m4_include([star/gtarfail2.at])
+ 
+@@ -273,3 +357,4 @@ m4_include([star/ustar-big-2g.at])
+ m4_include([star/ustar-big-8g.at])
+ 
+ m4_include([star/pax-big-10g.at])
++
+diff --git a/tests/xattr01.at b/tests/xattr01.at
+new file mode 100644
+index 0000000..fd960d5
+--- /dev/null
++++ b/tests/xattr01.at
+@@ -0,0 +1,47 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2011 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, 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/>.
++#
++# Test description:
++#
++# This is basic test for support of extended attributes.
++
++AT_SETUP([xattrs: basic functionality])
++AT_KEYWORDS([xattrs xattr01])
++
++AT_TAR_CHECK([
++AT_XATTRS_PREREQ
++mkdir dir
++genfile --file dir/file
++
++setfattr -n user.test -v OurDirValue dir
++setfattr -n user.test -v OurFileValue dir/file
++
++tar --xattrs -cf archive.tar dir
++
++rm -rf dir
++tar --xattrs -xf archive.tar
++
++getfattr -h -d dir         | grep -v -e '^#' -e ^$
++getfattr -h -d dir/file    | grep -v -e '^#' -e ^$
++],
++[0],
++[user.test="OurDirValue"
++user.test="OurFileValue"
++])
++
++AT_CLEANUP
+diff --git a/tests/xattr02.at b/tests/xattr02.at
+new file mode 100644
+index 0000000..3aae3f9
+--- /dev/null
++++ b/tests/xattr02.at
+@@ -0,0 +1,55 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2011 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, 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/>.
++#
++# Test description:
++#
++# Cooperation of the '-C' option and storing/restoring extended attributes.
++
++AT_SETUP([xattrs: change directory with -C option])
++AT_KEYWORDS([xattrs xattr02])
++
++AT_TAR_CHECK([
++AT_XATTRS_PREREQ
++
++mkdir dir
++mkdir dir/subdir
++mkdir dir/subdir/subsubdir
++genfile --file dir/file1
++genfile --file dir/subdir/file2
++
++setfattr -n user.test -v OurFile1Value dir/file1
++setfattr -n user.test -v OurFile2Value dir/subdir/file2
++setfattr -n user.test -v OurDirValue   dir/subdir/subsubdir
++
++tar --xattrs -cf archive.tar -C dir file1 -C subdir file2 subsubdir
++
++rm -rf dir
++
++tar --xattrs -xf archive.tar
++
++getfattr -h -d file1        | grep -v -e '^#' -e ^$
++getfattr -h -d file2        | grep -v -e '^#' -e ^$
++getfattr -h -d subsubdir    | grep -v -e '^#' -e ^$
++],
++[0],
++[user.test="OurFile1Value"
++user.test="OurFile2Value"
++user.test="OurDirValue"
++])
++
++AT_CLEANUP
+diff --git a/tests/xattr03.at b/tests/xattr03.at
+new file mode 100644
+index 0000000..d834f9f
+--- /dev/null
++++ b/tests/xattr03.at
+@@ -0,0 +1,56 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2012 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, 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/>.
++#
++# Test description:
++#
++# Setup of the trusted.* domain under privileged user.
++
++AT_SETUP([xattrs: trusted.* attributes])
++AT_KEYWORDS([xattrs xattr03])
++
++AT_TAR_CHECK([
++AT_PRIVILEGED_PREREQ
++AT_XATTRS_PREREQ
++
++mkdir dir
++mkdir dir/subdir
++mkdir dir/subdir/subsubdir
++genfile --file dir/file1
++genfile --file dir/subdir/file2
++
++setfattr -n trusted.test -v OurFile1Value dir/file1
++setfattr -n trusted.test -v OurFile2Value dir/subdir/file2
++setfattr -n trusted.test -v OurDirValue   dir/subdir/subsubdir
++
++tar --xattrs -cf archive.tar -C dir file1 -C subdir file2 subsubdir
++
++rm -rf dir
++
++tar --xattrs --xattrs-include=trusted* -xf archive.tar
++
++getfattr -mtrusted. -d file1        | grep -v -e '^#' -e ^$
++getfattr -mtrusted. -d file2        | grep -v -e '^#' -e ^$
++getfattr -mtrusted. -d subsubdir    | grep -v -e '^#' -e ^$
++],
++[0],
++[trusted.test="OurFile1Value"
++trusted.test="OurFile2Value"
++trusted.test="OurDirValue"
++])
++
++AT_CLEANUP
+diff --git a/tests/xattr04.at b/tests/xattr04.at
+new file mode 100644
+index 0000000..31832af
+--- /dev/null
++++ b/tests/xattr04.at
+@@ -0,0 +1,48 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2012 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, 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/>.
++#
++# Test description:  Test for the regression caused by tar update from 1.23 to
++# 1.26, Red Hat xattr patch was not ready for open->openat conversion.
++#
++# Related commit 4bde4f3.  See the bug: https://bugzilla.redhat.com/717684
++
++AT_SETUP([xattrs: s/open/openat/ regression])
++AT_KEYWORDS([xattrs xattr04])
++
++AT_TAR_CHECK([
++AT_XATTRS_PREREQ
++
++mkdir dir
++mkdir output
++genfile --file dir/file
++
++setfattr -n user.test -v value dir/file
++
++# archive whole directory including binary xattrs
++tar --xattrs -cf archive.tar -C dir .
++
++tar --xattrs -xf archive.tar -C output
++ret=$?
++getfattr -h -d output/file | grep -v -e '^#' -e ^$
++exit $ret
++],
++[0],
++[user.test="value"
++])
++
++AT_CLEANUP
+diff --git a/tests/xattr05.at b/tests/xattr05.at
+new file mode 100644
+index 0000000..27dc469
+--- /dev/null
++++ b/tests/xattr05.at
+@@ -0,0 +1,49 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2012 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, 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/>.
++#
++# Test description:  Test for archiving/extracting of extended attributes
++# having the '=' character in its keyword.
++#
++# Relevant mailing list thread:
++#
++# http://lists.gnu.org/archive/html/bug-tar/2012-10/msg00017.html
++
++AT_SETUP([xattrs: keywords with '=' and '%'])
++AT_KEYWORDS([xattrs xattr05])
++
++AT_TAR_CHECK([
++AT_XATTRS_PREREQ
++
++mkdir dir
++mkdir output
++genfile --file dir/file
++
++setfattr -n user.=NAME%3D= -v value dir/file
++getfattr -d dir/file | grep -v '# ' > before
++
++# archive whole directory including binary xattrs
++tar --xattrs -cf archive.tar -C dir .
++
++tar --xattrs -xf archive.tar -C output
++getfattr -d output/file | grep -v '# ' > after
++diff before after
++],
++[0],
++[])
++
++AT_CLEANUP
diff --git a/SOURCES/tar-1.26.tar.xz.sig b/SOURCES/tar-1.26.tar.xz.sig
new file mode 100644
index 0000000..59d9265
--- /dev/null
+++ b/SOURCES/tar-1.26.tar.xz.sig
@@ -0,0 +1,7 @@
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.9 (GNU/Linux)
+
+iD8DBQBNe1BENgKwf1XQxzIRAkWKAKCI0sMm1lxSHHhRN9n1clg41NMcmgCeKuGh
+mOMXqD7BB5D2s6kosgvTYEc=
+=Tzy2
+-----END PGP SIGNATURE-----
diff --git a/SOURCES/tar-1.27-sparse-stat-detection.patch b/SOURCES/tar-1.27-sparse-stat-detection.patch
new file mode 100644
index 0000000..3eb3fb8
--- /dev/null
+++ b/SOURCES/tar-1.27-sparse-stat-detection.patch
@@ -0,0 +1,22 @@
+diff --git a/lib/system.h b/lib/system.h
+index ef46267..e7f531c 100644
+--- a/lib/system.h
++++ b/lib/system.h
+@@ -389,9 +389,16 @@ extern int errno;
+ # define ST_NBLOCKSIZE 512
+ #endif
+ 
++/* Network Appliance file systems store small files directly in the
++   inode if st_size <= 64; in this case the number of blocks can be
++   zero.  Perhaps other file systems have similar problems; so,
++   somewhat arbitrarily, do not consider a file to be sparse if
++   it has no blocks but st_size < ST_NBLOCKSIZE.  */
+ #define ST_IS_SPARSE(st)                                  \
+   (ST_NBLOCKS (st)                                        \
+-    < ((st).st_size / ST_NBLOCKSIZE + ((st).st_size % ST_NBLOCKSIZE != 0)))
++   < ((st).st_size / ST_NBLOCKSIZE			  \
++      + ((st).st_size % ST_NBLOCKSIZE != 0		  \
++	 && (st).st_size / ST_NBLOCKSIZE != 0)))
+ 
+ /* Declare standard functions.  */
+ 
diff --git a/SOURCES/tar.1 b/SOURCES/tar.1
new file mode 100644
index 0000000..3beb97f
--- /dev/null
+++ b/SOURCES/tar.1
@@ -0,0 +1,638 @@
+.\" This file was originally generated by help2man
+.TH TAR "1" "February 2013" "tar 1.26" "User Commands"
+.SH NAME
+tar \- manual page for tar 1.26
+.SH SYNOPSIS
+.B tar
+[\fIOPTION\fR...] [\fIFILE\fR]...
+.SH DESCRIPTION
+GNU `tar' saves many files together into a single tape or disk archive, and can
+restore individual files from the archive.
+
+Note that this manual page contains just very brief description (or more like
+a list of possible functionality) originally generated by the
+.B
+help2man
+utility.  The full documentation for
+.B tar
+is maintained as a Texinfo manual.  If the
+.B info
+and
+.B tar
+programs are properly installed at your site, the command
+.B `info tar'
+should give you access to the complete manual.
+.SH EXAMPLES
+.TP
+tar \fB\-cf\fR archive.tar foo bar
+# Create archive.tar from files foo and bar.
+.TP
+tar \fB\-tvf\fR archive.tar
+# List all files in archive.tar verbosely.
+.TP
+tar \fB\-xf\fR archive.tar
+# Extract all files from archive.tar.
+.IP
+.SH DEFAULTS
+*This* tar installation defaults to:
+
+\fB\-\-format\fR=\fIgnu\fR \fB\-f\-\fR \fB\-b20\fR \fB\-\-quoting\-style\fR=\fIescape\fR \fB\-\-rmt\-command=\fR/sbin/rmt
+\fB\-\-rsh\-command=\fR/usr/bin/rsh
+.SH \fBMain operation mode:\fR
+.TP
+\fB\-A\fR, \fB\-\-catenate\fR, \fB\-\-concatenate\fR
+append tar files to an archive
+.TP
+\fB\-c\fR, \fB\-\-create\fR
+create a new archive
+.TP
+\fB\-d\fR, \fB\-\-diff\fR, \fB\-\-compare\fR
+find differences between archive and file system
+.TP
+\fB\-\-delete\fR
+delete from the archive (not on mag tapes!)
+.TP
+\fB\-r\fR, \fB\-\-append\fR
+append files to the end of an archive
+.TP
+\fB\-t\fR, \fB\-\-list\fR
+list the contents of an archive
+.TP
+\fB\-\-test\-label\fR
+test the archive volume label and exit
+.TP
+\fB\-u\fR, \fB\-\-update\fR
+only append files newer than copy in archive
+.TP
+\fB\-x\fR, \fB\-\-extract\fR, \fB\-\-get\fR
+extract files from an archive
+.IP
+.SH \fBCommon options:\fR
+.TP
+\fB-C\fR, \fB--directory=DIR\fR
+change to directory DIR
+.TP
+\fB-f\fR, \fB--file=ARCHIVE\fR
+use archive file or device ARCHIVE
+.TP
+\fB-j\fR, \fB--bzip2\fR
+filter the archive through bzip2
+.TP
+\fB -J\fR, \fB--xz\fR
+filter the archive through xz
+.TP
+\fB-p\fR, \fB--preserve-permissions\fR
+extract  information  about  file permissions (default for superuser)
+.TP
+\fB-v\fR, \fB--verbose\fR
+verbosely list files processed
+.TP
+\fB-z\fR, \fB--gzip\fR
+filter the archive through gzip
+
+.SH \fBOperation modifiers:\fR
+.TP
+\fB\-\-check\-device\fR
+check device numbers when creating incremental
+archives (default)
+.TP
+\fB\-g\fR, \fB\-\-listed\-incremental\fR=\fIFILE\fR
+handle new GNU\-format incremental backup
+.TP
+\fB\-G\fR, \fB\-\-incremental\fR
+handle old GNU\-format incremental backup
+.TP
+\fB\-\-ignore\-failed\-read\fR
+do not exit with nonzero on unreadable files
+.TP
+\fB\-\-level\fR=\fINUMBER\fR
+dump level for created listed\-incremental archive
+.TP
+\fB\-n\fR, \fB\-\-seek\fR
+archive is seekable
+.TP
+\fB\-\-no\-check\-device\fR
+do not check device numbers when creating
+incremental archives
+.TP
+\fB\-\-no\-seek\fR
+archive is not seekable
+.TP
+\fB\-\-occurrence\fR[=\fINUMBER\fR]
+process only the NUMBERth occurrence of each file
+in the archive; this option is valid only in
+conjunction with one of the subcommands \fB\-\-delete\fR,
+\fB\-\-diff\fR, \fB\-\-extract\fR or \fB\-\-list\fR and when a list of
+files is given either on the command line or via
+the \fB\-T\fR option; NUMBER defaults to 1
+.TP
+\fB\-\-sparse\-version\fR=\fIMAJOR[\fR.MINOR]
+set version of the sparse format to use (implies
+\fB\-\-sparse\fR)
+.TP
+\fB\-S\fR, \fB\-\-sparse\fR
+handle sparse files efficiently
+.IP
+.SH \fBOverwrite control:\fR
+.TP
+\fB\-k\fR, \fB\-\-keep\-old\-files\fR
+don't replace existing files when extracting,
+treat them as errors
+.TP
+\fB\-\-keep\-newer\-files\fR
+don't replace existing files that are newer than
+their archive copies
+.TP
+\fB\-\-keep\-directory\-symlink\fR
+Don't replace existing symlinks to directories when extracting.
+.TP
+\fB\-\-no\-overwrite\-dir\fR
+preserve metadata of existing directories
+.TP
+\fB\-\-overwrite\fR
+overwrite existing files when extracting
+.TP
+\fB\-\-overwrite\-dir\fR
+overwrite metadata of existing directories when
+extracting (default)
+.TP
+\fB\-\-recursive\-unlink\fR
+empty hierarchies prior to extracting directory
+.TP
+\fB\-\-remove\-files\fR
+remove files after adding them to the archive
+.TP
+\fB\-\-skip\-old\-files\fR
+don't replace existing files when extracting,
+silently skip over them
+.TP
+\fB\-U\fR, \fB\-\-unlink\-first\fR
+remove each file prior to extracting over it
+.TP
+\fB\-W\fR, \fB\-\-verify\fR
+attempt to verify the archive after writing it
+.IP
+.SH \fBSelect output stream:\fR
+.HP
+\fB\-\-ignore\-command\-error\fR ignore exit codes of children
+.TP
+\fB\-\-no\-ignore\-command\-error\fR
+treat non\-zero exit codes of children as
+error
+.TP
+\fB\-O\fR, \fB\-\-to\-stdout\fR
+extract files to standard output
+.TP
+\fB\-\-to\-command\fR=\fICOMMAND\fR
+pipe extracted files to another program
+.IP
+.SH \fBHandling of file attributes:\fR
+.TP
+\fB\-\-atime\-preserve\fR[=\fIMETHOD\fR]
+preserve access times on dumped files, either
+by restoring the times after reading
+(METHOD='replace'; default) or by not setting the
+times in the first place (METHOD='system')
+.TP
+\fB\-\-delay\-directory\-restore\fR
+delay setting modification times and
+permissions of extracted directories until the end
+of extraction
+.TP
+\fB\-\-group\fR=\fINAME\fR
+force NAME as group for added files
+.TP
+\fB\-\-mode\fR=\fICHANGES\fR
+force (symbolic) mode CHANGES for added files
+.TP
+\fB\-\-mtime\fR=\fIDATE\-OR\-FILE\fR
+set mtime for added files from DATE\-OR\-FILE
+.TP
+\fB\-m\fR, \fB\-\-touch\fR
+don't extract file modified time
+.TP
+\fB\-\-no\-delay\-directory\-restore\fR
+cancel the effect of \fB\-\-delay\-directory\-restore\fR
+option
+.TP
+\fB\-\-no\-same\-owner\fR
+extract files as yourself (default for ordinary
+users)
+.TP
+\fB\-\-no\-same\-permissions\fR
+apply the user's umask when extracting permissions
+from the archive (default for ordinary users)
+.TP
+\fB\-\-numeric\-owner\fR
+always use numbers for user/group names
+.TP
+\fB\-\-owner\fR=\fINAME\fR
+force NAME as owner for added files
+.TP
+\fB\-p\fR, \fB\-\-preserve\-permissions\fR, \fB\-\-same\-permissions\fR
+extract information about file permissions
+(default for superuser)
+.TP
+\fB\-\-preserve\fR
+same as both \fB\-p\fR and \fB\-s\fR
+.TP
+\fB\-\-same\-owner\fR
+try extracting files with the same ownership as
+exists in the archive (default for superuser)
+.TP
+\fB\-s\fR, \fB\-\-preserve\-order\fR, \fB\-\-same\-order\fR
+sort names to extract to match archive
+.IP
+.SH \fBHandling of extended file attributes:\fR
+.TP
+\fB\-\-acls\fR
+Enable the POSIX ACLs support
+.TP
+\fB\-\-no\-acls\fR
+Disable the POSIX ACLs support
+.TP
+\fB\-\-no\-selinux\fR
+Disable the SELinux context support
+.TP
+\fB\-\-no\-xattrs\fR
+Disable extended attributes support
+.TP
+\fB\-\-selinux\fR
+Enable the SELinux context support
+.TP
+\fB\-\-xattrs\fR
+Enable extended attributes support
+.TP
+\fB\-\-xattrs\-exclude\fR=\fIMASK\fR
+specify the exclude pattern for xattr keys
+.TP
+\fB\-\-xattrs\-include\fR=\fIMASK\fR
+specify the include pattern for xattr keys
+.IP
+.SH \fBDevice selection and switching:\fR
+.TP
+\fB\-f\fR, \fB\-\-file\fR=\fIARCHIVE\fR
+use archive file or device ARCHIVE
+.TP
+\fB\-\-force\-local\fR
+archive file is local even if it has a colon
+.TP
+\fB\-F\fR, \fB\-\-info\-script\fR=\fINAME\fR, \fB\-\-new\-volume\-script\fR=\fINAME\fR
+run script at end of each tape (implies \fB\-M\fR)
+.TP
+\fB\-L\fR, \fB\-\-tape\-length\fR=\fINUMBER\fR
+change tape after writing NUMBER x 1024 bytes
+.TP
+\fB\-M\fR, \fB\-\-multi\-volume\fR
+create/list/extract multi\-volume archive
+.TP
+\fB\-\-rmt\-command\fR=\fICOMMAND\fR
+use given rmt COMMAND instead of rmt
+.TP
+\fB\-\-rsh\-command\fR=\fICOMMAND\fR
+use remote COMMAND instead of rsh
+.TP
+\fB\-\-volno\-file\fR=\fIFILE\fR
+use/update the volume number in FILE
+.IP
+.SH \fBDevice blocking:\fR
+.TP
+\fB\-b\fR, \fB\-\-blocking\-factor\fR=\fIBLOCKS\fR
+BLOCKS x 512 bytes per record
+.TP
+\fB\-B\fR, \fB\-\-read\-full\-records\fR
+reblock as we read (for 4.2BSD pipes)
+.TP
+\fB\-i\fR, \fB\-\-ignore\-zeros\fR
+ignore zeroed blocks in archive (means EOF)
+.TP
+\fB\-\-record\-size\fR=\fINUMBER\fR
+NUMBER of bytes per record, multiple of 512
+.IP
+.SH \fBArchive format selection:\fR
+\fB\-H\fR, \fB\-\-format\fR=\fIFORMAT\fR
+.RS
+create archive of the given format
+.sp
+FORMAT is one of the following:
+.RS
+.TP
+gnu
+GNU tar 1.13.x format
+.TP
+oldgnu
+GNU format as per tar <= 1.12
+.TP
+pax
+POSIX 1003.1\-2001 (pax) format
+.TP
+posix
+same as pax
+.TP
+ustar
+POSIX 1003.1\-1988 (ustar) format
+.TP
+v7
+old V7 tar format
+.RE
+.RE
+.TP
+\fB\-\-old\-archive\fR, \fB\-\-portability\fR
+same as \fB\-\-format\fR=\fIv7\fR
+.TP
+\fB\-\-pax\-option\fR=\fIkeyword[[\fR:]=value][,keyword[[:]=value]]...
+control pax keywords
+.TP
+\fB\-\-posix\fR
+same as \fB\-\-format\fR=\fIposix\fR
+.TP
+\fB\-V\fR, \fB\-\-label\fR=\fITEXT\fR
+create archive with volume name TEXT; at
+list/extract time, use TEXT as a globbing pattern
+for volume name
+.IP
+.SH \fBCompression options:\fR
+.TP
+\fB\-a\fR, \fB\-\-auto\-compress\fR
+use archive suffix to determine the compression
+program
+.TP
+\fB\-I\fR, \fB\-\-use\-compress\-program\fR=\fIPROG\fR
+filter through PROG (must accept \fB\-d\fR)
+.TP
+\fB\-j\fR, \fB\-\-bzip2\fR
+filter the archive through bzip2
+.TP
+\fB\-J\fR, \fB\-\-xz\fR
+filter the archive through xz
+.TP
+\fB\-\-lzip\fR
+filter the archive through lzip
+.TP
+\fB\-\-lzma\fR
+filter the archive through lzma
+.HP
+\fB\-\-lzop\fR
+.TP
+\fB\-\-no\-auto\-compress\fR
+do not use archive suffix to determine the
+compression program
+.TP
+\fB\-z\fR, \fB\-\-gzip\fR, \fB\-\-gunzip\fR, \fB\-\-ungzip\fR
+filter the archive through gzip
+.TP
+\fB\-Z\fR, \fB\-\-compress\fR, \fB\-\-uncompress\fR
+filter the archive through compress
+.TP
+\fBNote: You might need to install external program (lzip/ncompress/lzma...) to use some of these compression options\fB
+.IP
+.SH \fBLocal file selection:\fR
+.TP
+\fB\-\-add\-file\fR=\fIFILE\fR
+add given FILE to the archive (useful if its name
+starts with a dash)
+.TP
+\fB\-\-backup\fR[=\fICONTROL\fR]
+backup before removal, choose version CONTROL
+.TP
+\fB\-C\fR, \fB\-\-directory\fR=\fIDIR\fR
+change to directory DIR
+.TP
+\fB\-\-exclude\fR=\fIPATTERN\fR
+exclude files, given as a PATTERN
+.TP
+\fB\-\-exclude\-backups\fR
+exclude backup and lock files
+.TP
+\fB\-\-exclude\-caches\fR
+exclude contents of directories containing
+CACHEDIR.TAG, except for the tag file itself
+.TP
+\fB\-\-exclude\-caches\-all\fR
+exclude directories containing CACHEDIR.TAG
+.TP
+\fB\-\-exclude\-caches\-under\fR exclude everything under directories containing
+CACHEDIR.TAG
+.TP
+\fB\-\-exclude\-tag\fR=\fIFILE\fR
+exclude contents of directories containing FILE,
+except for FILE itself
+.HP
+\fB\-\-exclude\-tag\-all\fR=\fIFILE\fR exclude directories containing FILE
+.TP
+\fB\-\-exclude\-tag\-under\fR=\fIFILE\fR
+exclude everything under directories
+containing FILE
+.TP
+\fB\-\-exclude\-vcs\fR
+exclude version control system directories
+.TP
+\fB\-h\fR, \fB\-\-dereference\fR
+follow symlinks; archive and dump the files they
+point to
+.TP
+\fB\-\-hard\-dereference\fR
+follow hard links; archive and dump the files they
+refer to
+.TP
+\fB\-K\fR, \fB\-\-starting\-file\fR=\fIMEMBER\-NAME\fR
+begin at member MEMBER\-NAME in the archive
+.TP
+\fB\-\-newer\-mtime\fR=\fIDATE\fR
+compare date and time when data changed only
+.TP
+\fB\-\-no\-null\fR
+disable the effect of the previous \fB\-\-null\fR option
+.TP
+\fB\-\-no\-recursion\fR
+avoid descending automatically in directories
+.TP
+\fB\-\-no\-unquote\fR
+do not unquote filenames read with \fB\-T\fR
+.HP
+\fB\-\-null\fR                 \fB\-T\fR reads null\-terminated names, disable \fB\-C\fR
+.TP
+\fB\-N\fR, \fB\-\-newer\fR=\fIDATE\-OR\-FILE\fR, \fB\-\-after\-date\fR=\fIDATE\-OR\-FILE\fR
+only store files newer than DATE\-OR\-FILE
+.TP
+\fB\-\-one\-file\-system\fR
+stay in local file system when creating archive
+.TP
+\fB\-P\fR, \fB\-\-absolute\-names\fR
+don't strip leading `/'s from file names
+.TP
+\fB\-\-recursion\fR
+recurse into directories (default)
+.TP
+\fB\-\-suffix\fR=\fISTRING\fR
+backup before removal, override usual suffix ('~'
+unless overridden by environment variable
+SIMPLE_BACKUP_SUFFIX)
+.TP
+\fB\-T\fR, \fB\-\-files\-from\fR=\fIFILE\fR
+get names to extract or create from FILE
+.TP
+\fB\-\-unquote\fR
+unquote filenames read with \fB\-T\fR (default)
+.TP
+\fB\-X\fR, \fB\-\-exclude\-from\fR=\fIFILE\fR
+exclude patterns listed in FILE
+.IP
+.SH \fBFile name transformations:\fR
+.TP
+\fB\-\-strip\-components\fR=\fINUMBER\fR
+strip NUMBER leading components from file
+names on extraction
+.TP
+\fB\-\-transform\fR=\fIEXPRESSION\fR, \fB\-\-xform\fR=\fIEXPRESSION\fR
+use sed replace EXPRESSION to transform file
+names
+.IP
+File name matching options (affect both exclude and include patterns):
+.TP
+\fB\-\-anchored\fR
+patterns match file name start
+.TP
+\fB\-\-ignore\-case\fR
+ignore case
+.TP
+\fB\-\-no\-anchored\fR
+patterns match after any `/' (default for
+exclusion)
+.TP
+\fB\-\-no\-ignore\-case\fR
+case sensitive matching (default)
+.TP
+\fB\-\-no\-wildcards\fR
+verbatim string matching
+.TP
+\fB\-\-no\-wildcards\-match\-slash\fR
+wildcards do not match `/'
+.TP
+\fB\-\-wildcards\fR
+use wildcards (default)
+.TP
+\fB\-\-wildcards\-match\-slash\fR
+wildcards match `/' (default for exclusion)
+.IP
+.SH \fBInformative output:\fR
+.TP
+\fB\-\-checkpoint\fR[=\fINUMBER\fR]
+display progress messages every NUMBERth record
+(default 10)
+.TP
+\fB\-\-checkpoint\-action\fR=\fIACTION\fR
+execute ACTION on each checkpoint
+.TP
+\fB\-\-full\-time\fR
+print file time to its full resolution
+.TP
+\fB\-\-index\-file\fR=\fIFILE\fR
+send verbose output to FILE
+.TP
+\fB\-l\fR, \fB\-\-check\-links\fR
+print a message if not all links are dumped
+.TP
+\fB\-\-no\-quote\-chars\fR=\fISTRING\fR
+disable quoting for characters from STRING
+.TP
+\fB\-\-quote\-chars\fR=\fISTRING\fR
+additionally quote characters from STRING
+.TP
+\fB\-\-quoting\-style\fR=\fISTYLE\fR
+set name quoting style; see below for valid STYLE
+values
+.TP
+\fB\-R\fR, \fB\-\-block\-number\fR
+show block number within archive with each
+message
+.TP
+\fB\-\-show\-defaults\fR
+show tar defaults
+.TP
+\fB\-\-show\-omitted\-dirs\fR
+when listing or extracting, list each directory
+that does not match search criteria
+.TP
+\fB\-\-show\-transformed\-names\fR, \fB\-\-show\-stored\-names\fR
+show file or archive names after transformation
+.TP
+\fB\-\-totals\fR[=\fISIGNAL\fR]
+print total bytes after processing the archive;
+with an argument \- print total bytes when this
+SIGNAL is delivered; Allowed signals are: SIGHUP,
+SIGQUIT, SIGINT, SIGUSR1 and SIGUSR2; the names
+without SIG prefix are also accepted
+.TP
+\fB\-\-utc\fR
+print file modification dates in UTC
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+verbosely list files processed
+.TP
+\fB\-\-warning\fR=\fIKEYWORD\fR
+warning control
+.TP
+\fB\-w\fR, \fB\-\-interactive\fR, \fB\-\-confirmation\fR
+ask for confirmation for every action
+.IP
+.SH \fBCompatibility options:\fR
+.TP
+\fB\-o\fR
+when creating, same as \fB\-\-old\-archive\fR; when
+extracting, same as \fB\-\-no\-same\-owner\fR
+.IP
+.SH \fBOther options:\fR
+.TP
+\-?, \fB\-\-help\fR
+give this help list
+.TP
+\fB\-\-restrict\fR
+disable use of some potentially harmful options
+.TP
+\fB\-\-usage\fR
+give a short usage message
+.TP
+\fB\-\-version\fR
+print program version
+.PP
+.PP
+Mandatory or optional arguments to long options are also mandatory or optional
+for any corresponding short options.
+.PP
+The backup suffix is `~', unless set with \fB\-\-suffix\fR or SIMPLE_BACKUP_SUFFIX.
+The version control may be set with \fB\-\-backup\fR or VERSION_CONTROL, values are:
+.TP
+none, off
+never make backups
+.TP
+t, numbered
+make numbered backups
+.TP
+nil, existing
+numbered if numbered backups exist, simple otherwise
+.TP
+never, simple
+always make simple backups
+.PP
+Valid arguments for the \fB\-\-quoting\-style\fR option are:
+.IP
+literal
+shell
+shell\-always
+c
+c\-maybe
+escape
+locale
+clocale
+.PP
+.SH AUTHOR
+Written by John Gilmore and Jay Fenlason.
+.SH "REPORTING BUGS"
+Report bugs to <bug\-tar@gnu.org>.
+.SH COPYRIGHT
+Copyright \(co 2013 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
+.br
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
diff --git a/SPECS/tar.spec b/SPECS/tar.spec
new file mode 100644
index 0000000..426fc82
--- /dev/null
+++ b/SPECS/tar.spec
@@ -0,0 +1,956 @@
+%if %{?WITH_SELINUX:0}%{!?WITH_SELINUX:1}
+%global WITH_SELINUX 1
+%endif
+Summary: A GNU file archiving program
+Name: tar
+Epoch: 2
+Version: 1.26
+Release: 34%{?dist}
+License: GPLv3+
+Group: Applications/Archiving
+URL: http://www.gnu.org/software/tar/
+
+Source0: ftp://ftp.gnu.org/pub/gnu/tar/tar-%{version}.tar.xz
+Source1: ftp://ftp.gnu.org/pub/gnu/tar/tar-%{version}.tar.xz.sig
+# Manpage for tar and gtar, a bit modified help2man generated manpage
+Source2: tar.1
+
+# Stop issuing lone zero block warnings.
+# ~> https://bugzilla.redhat.com/show_bug.cgi?id=135601
+# ~> downstream
+Patch1: tar-1.14-loneZeroWarning.patch
+
+# Fix extracting sparse files to a file system like vfat, when ftruncate may fail
+# to grow the size of a file.
+# ~> #179507,
+# ~> http://lists.gnu.org/archive/html/bug-tar/2006-02/msg00000.html
+# ~> still downtream (do we need this now? ftruncate & vfat works is now OK)
+Patch2: tar-1.15.1-vfatTruncate.patch
+
+# Change inclusion defaults of tar to
+# "--wildcards --anchored --wildcards-match-slash" for compatibility reasons.
+# ~> #206841
+# ~> downstream (compatibility)
+Patch3: tar-1.17-wildcards.patch
+
+# Ignore errors from setting utime() for source file on read-only file-system.
+# ~> #500742
+# ~> http://lists.gnu.org/archive/html/bug-tar/2009-06/msg00016.html
+# ~> still downstream
+Patch4: tar-1.22-atime-rofs.patch
+
+# The --old-archive option was not working.
+# ~> #594044
+# ~> http://lists.gnu.org/archive/html/bug-tar/2010-05/msg00015.html
+# ~> upstream (2a61a37)
+Patch5: tar-1.23-oldarchive.patch
+
+# Fix for bad cooperation of -C and -u options.
+# ~> #688567
+# ~> http://lists.gnu.org/archive/html/bug-tar/2012-02/msg00007.html
+# ~> still downstream
+Patch6: tar-1.26-update-with-change-directory.patch
+
+# Fix rawhide build failure with undefined gets.
+# ~> upstream (gnulib)
+Patch7: tar-1.26-stdio.in.patch
+
+# Fix regression with --keep-old-files option.
+# ~> #799252
+# ~> http://lists.gnu.org/archive/html/bug-tar/2011-11/msg00043.html
+# ~> upstream (7a5a3708c)
+Patch8: tar-1.26-add-skip-old-files-option.patch
+
+# Prepare included gnulib library for SELinux support.
+# -> Related to the next patch.
+Patch9:  tar-1.26-selinux-gnulib.patch
+
+# Add support for extended attributes, SELinux and POSIX ACLs.
+# ~> Original implementation #200925
+# ~> http://lists.gnu.org/archive/html/bug-tar/2012-08/msg00012.html
+# ~> upstream (b997c90f9, 696338043, d36f5a3cc, 085cace18, up-to ~> 83701a590)
+Patch10: tar-1.26-xattrs.patch
+
+# Fix problem with bit UIDs/GIDs (> 2^21) and --posix format.
+# ~> #913406
+# ~> upstream (it is part of df7b55a8f6354e)
+Patch11: tar-1.26-posix-biguid.patch
+
+# Allow store sparse files of effective size >8GB into pax archives
+# ~> #516309
+# ~> http://lists.gnu.org/archive/html/bug-tar/2013-01/msg00001.html
+# ~> already upstream (2f6c03cba)
+Patch12: tar-1.26-pax-big-sparse-files.patch
+
+# Fix: Allow extracting single volume in a multi-volume archive
+# ~> #919897
+# ~> http://lists.gnu.org/archive/html/bug-tar/2013-03/msg00002.html
+# ~> upstream (beca89bc)
+Patch13: tar-1.26-allow-extract-single-volume.patch
+
+# Do not print xattrs/selinux/acls when --no-xattrs/--no-acls/--no-selinux
+# options are used during -tvv output.  (TODO: merge this with xattrs patch
+# once becomes upstream)
+# ~> downstream (yet)
+# ~> proposal: http://lists.gnu.org/archive/html/bug-tar/2013-05/msg00020.html
+Patch14: tar-1.26-xattrs-printing.patch
+
+# Use a birthtime instead of ctime.
+# ~> upstream (189e43 & 49bd10)
+# ~> http://lists.gnu.org/archive/html/bug-tar/2011-06/msg00000.html
+# ~> http://lists.gnu.org/archive/html/bug-tar/2013-05/msg00022.html
+Patch15: tar-1.26-fix-symlink-eating-bug.patch
+
+# Add documentation which was not yet pushed upstream
+# ~> downstream
+# ~> #996753
+Patch16: tar-1.26-docu-xattrs.patch
+
+# The --xattrs-include or --xattrs-exclude options should imply --xattrs.
+# ~> still downstream
+#    http://lists.gnu.org/archive/html/bug-tar/2013-05/msg00020.html
+# ~> #965969
+Patch17: tar-1.26-xattrs-include-implies-xattrs.patch
+
+# If the 'st_size' != 0 && count(blocks) == 0 && st_size < size(block), this
+# does not necessarily must be a sparse file.
+# ~> upstream (paxutils):  986382a0bb3261
+# ~> #1024095, #1024268
+Patch18: tar-1.27-sparse-stat-detection.patch
+
+# Don't add "false" default acls when during extraction (#1220890)
+# ~> #1220890
+Patch19: tar-1.26-default-acls.patch
+
+# Make sure getfilecon's wrapper set's freed pointer to NULL to avoid double
+# free later in client code.
+# ~> upstream commit (gnulib): b6b3ed1fa4c
+# ~> rhbz#1347396
+Patch20: tar-1.26-dont-segfault-with-disabled-selinux.patch
+
+# Restore incremental backups correctly, files were not being removed
+# ~> upstream commits: 738fb9c2f44 b6979c7278e f86e0605d0e
+# ~> rhbz#1184697
+Patch21: tar-1.26-restore-incremental-backups.patch
+
+# Fix the behavior of tar when --directory option is used together with
+# --remove-files.
+# ~> upstream commits: e3d28d84bda b41b004638f f7077dd38b0 d3fd92c6fb2
+# 	d28eee6b4f1 74ce228f6df 3125d311e17 3de5db2a151 fc58a8bd984
+#	fcde08534bd e6fcc73efa7
+# ~> rhbz#1319820
+Patch22: tar-1.26-directory_with_remove-files.patch
+
+# Repair the ignorance of --xattrs-exclude/include options
+# ~> upstream: bb6ddd8e04c and c81a0853bb8
+# ~> rhbz#1341786
+Patch23: tar-1.26-xattrs-exclude-include-repair.patch
+
+# Intorduce new option "--keep-directory-symlink", backported from version 1.27
+# ~> upstream: 2c06a809180
+# ~> rhbz#1350640
+Patch24: tar-1.26-keep-directory-symlink.patch
+
+# Fix non-determinism in archive-type-heuristic
+# ~> upstream: 1847ec67cec + 1e8b786e651
+# ~> rhbz#1437297
+Patch25: tar-1.26-non-deterministic-archive-detection.patch
+
+# Avoid tar to hang with --extract --xatrrs and --skip-old-files options
+# ~> upstream: 597b0ae509 and ca9399d4e
+# -> proposed: https://www.mail-archive.com/bug-tar@gnu.org/msg05229.html
+# ~> rhbz#1408168
+Patch26: tar-1.26-xattrs-skip-old-files-hangs.patch
+
+# List sparse files of 8GB+ properly, without failure.
+# ~> upstream: 586a6263e9d97 ec94fbdf458ad
+# ~> paxutils-upstream: 45af1632aa64a 58b8ac114790e
+Patch27: tar-1.26-large-sparse-file-listing.patch
+
+# Document (and test) --keep-directory-option
+# ~> upstream: d06126f814563b01e598b85a8cc233604a2948f2
+# ~> rhbz#1504146
+Patch28: tar-1.26-keep-directory-symlink-doc-and-test.patch
+
+# Silence gcc warnings
+# ~> upstream tar: 17f99bc6f, 5bb0433
+# ~> upstream paxutils: 0b3d84a0
+Patch999: tar-1.26-silence-gcc.patch
+
+# run "make check" by default
+%bcond_without check
+
+BuildRequires: autoconf automake texinfo gettext libacl-devel rsh
+
+%if %{with check}
+# cover needs of tar's testsuite
+BuildRequires: attr acl policycoreutils
+%endif
+
+%if %{WITH_SELINUX}
+BuildRequires: libselinux-devel
+%endif
+Provides: bundled(gnulib)
+Provides: /bin/tar
+Provides: /bin/gtar
+Requires(post): /sbin/install-info
+Requires(preun): /sbin/install-info
+
+%description
+The GNU tar program saves many files together in one archive and can
+restore individual files (or all of the files) from that archive. Tar
+can also be used to add supplemental files to an archive and to update
+or list files in the archive. Tar includes multivolume support,
+automatic archive compression/decompression, the ability to perform
+remote archives, and the ability to perform incremental and full
+backups.
+
+If you want to use tar for remote backups, you also need to install
+the rmt package on the remote box.
+
+%prep
+%setup -q
+%patch1 -p1 -b .loneZeroWarning
+%patch2 -p1 -b .vfatTruncate
+%patch3 -p1 -b .wildcards
+%patch4 -p1 -b .rofs
+%patch5 -p1 -b .oldarchive
+%patch6 -p1 -b .update_and_changedir
+%patch7 -p1 -b .gets  %{?_rawbuild}
+%patch8 -p1 -b .skip-old-files
+%patch9 -p1 -b .selinux-gnulib-prep
+%patch10 -p1 -b .xattrs-selinux-acls
+%patch11 -p1 -b .big_uid_gid
+%patch12 -p1 -b .pax-sparse-big-files
+%patch13 -p1 -b .extract-single-volume
+%patch14 -p1 -b .print-xattrs-fix
+%patch15 -p1 -b .birthtime
+%patch16 -p1 -b .xattrs-documentation
+%patch17 -p1 -b .xattrs-if-xattrs-include
+%patch18 -p1 -b .sparse-stat-detection
+%patch19 -p1 -b .default-acls
+%patch20 -p1 -b .disabled-selinux
+%patch21 -p1 -b .incremental-backups
+%patch22 -p1 -b .directory
+%patch23 -p1 -b .xattrs-exclude-include
+%patch24 -p1 -b .keep-directory-symlink
+%patch25 -p1 -b .fix-archive-detection-heuristic
+%patch26 -p1 -b .extract-xattrs-hangs
+%patch27 -p1 -b .large-sparse-file-listing
+%patch28 -p1 -b .test-and-doc-for-keep-dir-symlink
+%patch999 -p1 -b .silence-gcc
+
+autoreconf -v
+
+%build
+%if ! %{WITH_SELINUX}
+%global CONFIGURE_SELINUX --without-selinux
+%endif
+
+%configure %{?CONFIGURE_SELINUX} \
+    DEFAULT_RMT_DIR=%{_sysconfdir} \
+    RSH=/usr/bin/ssh
+make
+
+%install
+make DESTDIR=$RPM_BUILD_ROOT install
+
+ln -s tar $RPM_BUILD_ROOT%{_bindir}/gtar
+rm -f $RPM_BUILD_ROOT/%{_infodir}/dir
+mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1
+install -c -p -m 0644 %{SOURCE2} $RPM_BUILD_ROOT%{_mandir}/man1
+ln -s tar.1.gz $RPM_BUILD_ROOT%{_mandir}/man1/gtar.1
+
+# XXX Nuke unpackaged files.
+rm -f $RPM_BUILD_ROOT%{_sysconfdir}/rmt
+
+%find_lang %name
+
+%check
+%if %{with check}
+rm -f $RPM_BUILD_ROOT/test/testsuite
+make check || TESTSUITEFLAGS=-v make check
+%endif
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+if [ -f %{_infodir}/tar.info.gz ]; then
+   /sbin/install-info %{_infodir}/tar.info.gz %{_infodir}/dir || :
+fi
+
+%preun
+if [ $1 = 0 ]; then
+   if [ -f %{_infodir}/tar.info.gz ]; then
+      /sbin/install-info --delete %{_infodir}/tar.info.gz %{_infodir}/dir || :
+   fi
+fi
+
+%files -f %{name}.lang
+%doc AUTHORS ChangeLog ChangeLog.1 COPYING NEWS README THANKS TODO
+%{_bindir}/tar
+%{_bindir}/gtar
+%{_mandir}/man1/tar.1*
+%{_mandir}/man1/gtar.1*
+%{_infodir}/tar.info*
+
+%changelog
+* Thu Oct 19 2017 Pavel Raiskup <praiskup@redhat.com> - 1.26-34
+- document --keep-directory-symlink in manual page (rhbz#1504146)
+
+* Thu Sep 07 2017 Pavel Raiskup <praiskup@redhat.com> - 1.26-33
+- extract: deterministic archive type detection (rhbz#1437297)
+- avoid hang when extracting with --xattrs --skip-old-files (rhbz#1408168)
+- fix listing of large sparse members (rhbz#1347229)
+
+* Tue Feb 28 2017 Tomas Repik <trepik@redhat.com> - 2:1.26-32
+- restore incremental backups correctly, files were not being removed (rhbz#1184697)
+- fix the behavior of tar when --directory option is used together with
+  --remove-files
+- repair the ignorance of --xattrs-exclude/include options (rhbz#1341786)
+- Intorduce new option '--keep-directory-symlink'
+
+* Mon Jun 20 2016 Pavel Raiskup <praiskup@redhat.com> - 1.26-31
+- avoid double free in selinux code (rhbz#1347396)
+
+* Thu Jun 04 2015 Pavel Raiskup <praiskup@redhat.com> - 1.26-30
+- don't mistakenly set default ACLs (#1220890)
+
+* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 2:1.26-29
+- Mass rebuild 2014-01-24
+
+* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 2:1.26-28
+- Mass rebuild 2013-12-27
+
+* Mon Nov 18 2013 Pavel Raiskup <praiskup@redhat.com> - 1.26-27
+- sparse file detection based on fstat() fix (#1024268)
+
+* Mon Sep 09 2013 Pavel Raiskup <praiskup@redhat.com> - 1.26-26
+- the --xattrs-include implies --xattrs now (#965969)
+
+* Wed Aug 14 2013 Pavel Raiskup <praiskup@redhat.com> - 1.26-26
+- add documenation for xattrs-like options (#996753)
+
+* Thu Jun 20 2013 Pavel Raiskup <praiskup@redhat.com> - 1.26-25
+- the /etc/rmt seems to be the best place where to look for rmt binary (see the
+  commit message in Fedora's cpio.git for more info)
+
+* Tue Jun 04 2013 Pavel Raiskup <praiskup@redhat.com> - 2:1.26-24
+- fix "symlink eating" bug (already fixed in upstream git)
+
+* Thu May 30 2013 Pavel Raiskup <praiskup@redhat.com> - 2:1.26-23
+- use /usr/bin/ssh as the default remote shell binary (#969015)
+- do not verbose-print xattrs when --no-xattrs option is used
+- do not override the config.{guess,sub} twice, this is already done by the
+  redhat-rpm-config package (#951442)
+
+* Tue May 28 2013 Pavel Raiskup <praiskup@redhat.com> - 2:1.26-22
+- again search for 'rmt' binary in %%{_sbindir} on target host
+
+* Tue Mar 26 2013 Pavel Raiskup <praiskup@redhat.com> - 2:1.26-21
+- enable build for arm64 (#926610)
+- silence gcc warnings (lint fixes without risk from upstream) for RPMDiff
+
+* Tue Mar 19 2013 Pavel Raiskup <praiskup@redhat.com> - 2:1.26-20
+- allow extracting single volume from multi-volume archive (#919897)
+- usrmove: /bin/tar ~> /usr/bin/tar, selinux handling edit
+
+* Fri Mar 01 2013 Pavel Raiskup <praiskup@redhat.com> - 2:1.26-19
+- fix creating sparse pax archives containing files of effective
+  size >8GB (#516309)
+- silence rpmlint (fix bad dates in changelog based on git log dates)
+
+* Wed Feb 20 2013 Pavel Raiskup <praiskup@redhat.com> - 2:1.26-18
+- fix problems with big uids/gids and pax format (> 2^21) (#913406)
+
+* Mon Feb 18 2013 Pavel Raiskup <praiskup@redhat.com> - 2:1.26-17
+- add possibility to 'rpmbuild' without %%check phase
+- make the autoreconf phase verbose
+- re-create older patches (avoid offset warnings during patching)
+- remove patches which we don't need now (xattrs - will be updated, sigpipe -
+  test should work now, partial revert of *at() conversion was done because of
+  incompatible xattr patch)
+- add upstream up2date xattr patch
+
+* Fri Feb 01 2013 Pavel Raiskup <praiskup@redhat.com> - 2:1.26-16
+- make the info documentation more visible in manpage (#903666)
+- sync tar.1 manpage with actual --help output (e.g. added --skip-old-files)
+- add the last_help2man_run file to git repo to allow more easily find changes
+  in --help in future
+- make the DEFAULTS section to be more visible in man page
+- verbose 'make check' only when some fail happened (append to koji build.log)
+
+* Thu Nov 29 2012 Ondrej Vasik <ovasik@redhat.com> - 2:1.26-15
+- add missing --full-time option to manpage
+
+* Thu Oct 18 2012 Pavel Raiskup <praiskup@redhat.com> - 2:1.26-14
+- fix bad behaviour of --keep-old-files and add --skip-old-files option
+  (#799252)
+
+* Wed Oct 10 2012 Pavel Raiskup <praiskup@redhat.com> 2:1.26-13
+- fix badly written macro for building --without-selinux
+- allow to build tar in difference CoverityScan by forcing the '.gets' patch to
+  be applied even in the run without patches
+
+* Fri Oct 05 2012 Pavel Raiskup <praiskup@redhat.com> 2:1.26-12
+- repair the xattr-gnulib-prepare patch to allow build tar without SELinux
+  support
+- fedora-review compliance -> remove trailing white-spaces, remove macro from
+  comment, remove BR of gawk;coreutils;gzip that should be covered automatically
+  by minimum build environment, do not `rm -rf' buildroot at the beginning of
+  install phase (needed only in EPEL), remove BuildRoot definition, remove
+  defattr macro, s/define/global/
+- do not use ${VAR} syntax for bash variables, use just $VAR
+
+* Wed Aug 22 2012 Pavel Raiskup <praiskup@redhat.com> 2:1.26-11
+- fix manpage to reflect #850291 related commit
+
+* Tue Aug 21 2012 Pavel Raiskup <praiskup@redhat.com> 2:1.26-10
+- prepare Gnulib for new xattrs (#850291)
+- new version of RH xattrs patch (#850291)
+- enable verbose mode in testsuite to allow better debugging on error
+
+* Sat Jul 21 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2:1.26-9
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Thu Jul 12 2012 Pavel Raiskup <praiskup@redhat.com> 2:1.26-8
+- force the fchown() be called before xattrs_set() (#771927)
+
+* Sat Jun 16 2012 Ondrej Vasik <ovasik@redhat.com> 2:1.26-7
+- store&restore security.capability extended attributes category
+  (#771927)
+- fix build failure with undefined gets
+
+* Tue May 15 2012 Ondrej Vasik <ovasik@redhat.com> 2:1.26-6
+- add virtual provides for bundled(gnulib) copylib (#821790)
+
+* Thu Apr 05 2012 Pavel Raiskup <praiskup@redhat.com> 2:1.26-5
+- fix for bad cooperation of the '-C' (change directory) and '-u' (update
+  package) options (#688567)
+
+* Sat Jan 14 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2:1.26-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Sun Oct  2 2011 Ville Skyttä <ville.skytta@iki.fi> - 2:1.26-3
+- Man page heading formatting fixes.
+
+* Mon Sep 26 2011 Kamil Dudka <kdudka@redhat.com> 2:1.26-2
+- restore basic functionality of --acl, --selinux, and --xattr (#717684)
+
+* Sat Mar 12 2011 Ondrej Vasik <ovasik@redhat.com> 2:1.26-1
+- new upstream release 1.26
+* Wed Feb 09 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2:1.25-6
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Thu Jan 20 2011 Ondrej Vasik <ovasik@redhat.com> 2:1.25-5
+- drop unnecessary hard dependency on info package(#671157)
+
+* Mon Jan 03 2011 Ondrej Vasik <ovasik@redhat.com> 2:1.25-4
+- mention that some compression options might not work if
+  the external program is not available(#666755)
+
+* Wed Dec 08 2010 Kamil Dudka <kdudka@redhat.com> 2:1.25-3
+- correctly store long sparse file names in PAX archives (#656834)
+
+* Tue Nov 23 2010 Ondrej Vasik <ovasik@redhat.com> 2:1.25-2
+- fix issue with --one-file-system and --listed-incremental
+  (#654718)
+
+* Mon Nov 08 2010 Ondrej Vasik <ovasik@redhat.com> 2:1.25-1
+- new upstream release 1.25
+
+* Mon Oct 25 2010 Ondrej Vasik <ovasik@redhat.com> 2:1.24-1
+- new upstream release 1.24, use .xz archive
+
+* Wed Sep 29 2010 jkeating - 2:1.23-8
+- Rebuilt for gcc bug 634757
+
+* Fri Sep 24 2010 Kamil Dudka <kdudka@redhat.com> 2:1.23-7
+- match non-stripped file names (#637085)
+
+* Mon Sep 20 2010 Kamil Dudka <kdudka@redhat.com> 2:1.23-6
+- fix exclusion of long file names with --xattrs (#634866)
+- do not crash with --listed-incremental (#635318)
+
+* Mon Aug 16 2010 Ondrej Vasik <ovasik@redhat.com> 2:1.23-5
+- add support for security.NTACL xattrs (#621215)
+
+* Tue Jun 01 2010 Ondrej Vasik <ovasik@redhat.com> 2:1.23-4
+- recognize old-archive/portability options(#594044)
+
+* Wed Apr 07 2010 Ondrej Vasik <ovasik@redhat.com> 2:1.23-3
+- allow storing of extended attributes for fifo and block
+  or character devices files(#573147)
+
+* Mon Mar 15 2010 Ondrej Vasik <ovasik@redhat.com> 2:1.23-2
+- update help2maned manpage
+
+* Fri Mar 12 2010 Ondrej Vasik <ovasik@redhat.com> 2:1.23-1
+- new upstream release 1.23, remove applied patches
+
+* Wed Mar 10 2010 Ondrej Vasik <ovasik@redhat.com> 2:1.22-17
+- CVE-2010-0624 tar, cpio: Heap-based buffer overflow
+  by expanding a specially-crafted archive (#572149)
+- realloc within check_exclusion_tags() caused invalid write
+  (#570591)
+- not closing file descriptors for excluded files/dirs with
+  exlude-tag... options could cause descriptor exhaustion
+  (#570591)
+
+* Sat Feb 20 2010 Kamil Dudka <kdudka@redhat.com> 2:1.22-16
+- support for "lustre.*" extended attributes (#561855)
+
+* Thu Feb 04 2010 Ondrej Vasik <ovasik@redhat.com> 2:1.22-15
+- fix segfault with corrupted metadata in code_ns_fraction
+  (#531441)
+
+* Wed Feb 03 2010 Kamil Dudka <kdudka@redhat.com> 2:1.22-14
+- allow also build with SELinux support
+
+* Mon Feb 01 2010 Ondrej Vasik <ovasik@redhat.com> 2:1.22-13
+- allow build without SELinux support(#556679)
+
+* Tue Jan 05 2010 Ondrej Vasik <ovasik@redhat.com> 2:1.22-12
+- do not fail with POSIX 2008 glibc futimens() (#552320)
+- temporarily disable fix for #531441, causing stack smashing
+  with newer glibc(#551206)
+
+* Tue Dec 08 2009 Ondrej Vasik <ovasik@redhat.com> 2:1.22-11
+- fix segfault with corrupted metadata in code_ns_fraction
+  (#531441)
+- commented patches and sources
+
+* Fri Nov 27 2009 Ondrej Vasik <ovasik@redhat.com> 2:1.22-10
+- store xattrs for symlinks (#525992) - by Kamil Dudka
+- update tar(1) manpage (#539787)
+- fix memory leak in xheader (#518079)
+
+* Wed Nov 18 2009 Kamil Dudka <kdudka@redhat.com> 2:1.22-9
+- store SELinux context for symlinks (#525992)
+
+* Thu Aug 27 2009 Ondrej Vasik <ovasik@redhat.com> 2:1.22-8
+- provide symlink manpage for gtar
+
+* Thu Aug 06 2009 Ondrej Vasik <ovasik@redhat.com> 2:1.22-7
+- do process install-info only without --excludedocs(#515923)
+
+* Sun Jul 26 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2:1.22-6
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Thu Jul 16 2009 Ondrej Vasik <ovasik@redhat.com> 2:1.22-5
+- Fix restoring of directory default acls(#511145)
+- Do not patch generated autotools files
+
+* Thu Jun 25 2009 Ondrej Vasik <ovasik@redhat.com> 2:1.22-4
+- Report record size only if the archive refers to a device
+  (#487760)
+- Do not sigabrt with new gcc/glibc because of writing to
+  struct members of gnutar header at once via strcpy
+
+* Fri May 15 2009 Ondrej Vasik <ovasik@redhat.com> 2:1.22-3
+- ignore errors from setting utime() for source file
+  on read-only filesystem (#500742)
+
+* Fri Mar 06 2009 Kamil Dudka <kdudka@redhat.com> 2:1.22-2
+- improve tar-1.14-loneZeroWarning.patch (#487315)
+
+* Mon Mar 02 2009 Ondrej Vasik <ovasik@redhat.com> 2:1.22-1
+- New upstream release 1.22, removed applied patch
+
+* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2:1.21-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Mon Jan 05 2009 Ondrej Vasik <ovasik@redhat.com> 2:1.21-1
+- New upstream release 1.21, removed applied patches
+- add support for -I option, fix testsuite failure
+
+* Thu Dec 11 2008 Ondrej Vasik <ovasik@redhat.com> 2:1.20-6
+- add BuildRequires for rsh (#475950)
+
+* Fri Nov 21 2008 Ondrej Vasik <ovasik@redhat.com> 2:1.20-5
+- fix off-by-one errors in xattrs patch (#472355)
+
+* Mon Nov 10 2008 Kamil Dudka <kdudka@redhat.com> 2:1.20-4
+- fixed bug #465803: labels with --multi-volume (upstream patch)
+
+* Fri Oct 10 2008 Ondrej Vasik <ovasik@redhat.com> 2:1.20-3
+- Fixed wrong documentation for xattrs options (#466517)
+- fixed bug with null file terminator and change dirs
+  (upstream)
+
+* Fri Aug 29 2008 Ondrej Vasik <ovasik@redhat.com> 2:1.20-2
+- patch fuzz clean up
+
+* Mon May 26 2008 Ondrej Vasik <ovasik@redhat.com> 2:1.20-1
+- new upstream release 1.20 (lzma support, few new options
+  and bugfixes)
+- heavily modified xattrs patches(as tar-1.20 now uses automake
+  1.10.1)
+
+* Tue Feb 12 2008 Radek Brich <rbrich@redhat.com> 2:1.19-3
+- do not print getfilecon/setfilecon warnings when SELinux is disabled
+  or SELinux data are not available (bz#431879)
+- fix for GCC 4.3
+
+* Mon Jan 21 2008 Radek Brich <rbrich@redhat.com> 2:1.19-2
+- fix errors in man page
+  * fix definition of --occurrence (bz#416661, patch by Jonathan Wakely)
+  * update meaning of -l: it has changed from --one-filesystem
+    to --check-links (bz#426717)
+- update license tag, tar 1.19 is GPLv3+
+
+* Mon Dec 17 2007 Radek Brich <rbrich@redhat.com> 2:1.19-1
+- upgrade to 1.19
+- updated xattrs patch, removed 3 upstream patches
+
+* Wed Dec 12 2007 Radek Brich <rbrich@redhat.com> 2:1.17-5
+- fix (non)detection of xattrs
+- move configure stuff from -xattrs patch to -xattrs-conf,
+  so the original patch could be easily read
+- fix -xattrs patch to work with zero length files and show
+  warnings when xattrs not available (fixes by James Antill)
+- possible corruption (#408621) - add warning to man page
+  for now, may be actually fixed later, depending on upstream
+
+* Tue Oct 23 2007 Radek Brich <rbrich@redhat.com> 2:1.17-4
+- upstream patch for CVE-2007-4476
+  (tar stack crashing in safer_name_suffix)
+
+* Tue Aug 28 2007 Radek Brich <rbrich@redhat.com> 2:1.17-3
+- gawk build dependency
+
+* Tue Aug 28 2007 Radek Brich <rbrich@redhat.com> 2:1.17-2
+- updated license tag
+- fixed CVE-2007-4131 tar directory traversal vulnerability (#251921)
+
+* Thu Jun 28 2007 Radek Brich <rbrich@redhat.com> 2:1.17-1
+- new upstream version
+- patch for wildcards (#206841), restoring old behavior
+- patch for testsuite
+- update -xattrs patch
+- drop 13 obsolete patches
+
+* Tue Feb 06 2007 Peter Vrabec <pvrabec@redhat.com> 2:1.15.1-26
+- fix spec file to meet Fedora standards (#226478)
+
+* Mon Jan 22 2007 Peter Vrabec <pvrabec@redhat.com> 2:1.15.1-25
+- fix non-failsafe install-info use in scriptlets (#223718)
+
+* Wed Jan 03 2007 Peter Vrabec <pvrabec@redhat.com> 2:1.15.1-24
+- supply tar man page (#219375)
+
+* Tue Dec 12 2006 Florian La Roche <laroche@redhat.com> 2:1.15.1-23
+- fix CVE-2006-6097 GNU tar directory traversal (#216937)
+
+* Sun Dec 10 2006 Peter Vrabec <pvrabec@redhat.com> 2:1.15.1-22
+- fix some rpmlint spec file issues
+
+* Wed Oct 25 2006 Peter Vrabec <pvrabec@redhat.com> 2:1.15.1-21
+- build with dist-tag
+
+* Mon Oct 09 2006 Peter Vrabec <pvrabec@redhat.com> 2:1.15.1-20
+- another fix of tar-1.15.1-xattrs.patch from James Antill
+
+* Wed Oct 04 2006 Peter Vrabec <pvrabec@redhat.com> 2:1.15.1-19
+- another fix of tar-1.15.1-xattrs.patch from James Antill
+
+* Sun Oct 01 2006 Peter Vrabec <pvrabec@redhat.com> 2:1.15.1-18
+- fix tar-1.15.1-xattrs.patch (#208701)
+
+* Tue Sep 19 2006 Peter Vrabec <pvrabec@redhat.com> 2:1.15.1-17
+- start new epoch, downgrade to solid stable 1.15.1-16 (#206979),
+- all patches are backported
+
+* Tue Sep 19 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.91-2
+- apply patches, which were forgotten during upgrade
+
+* Wed Sep 13 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.91-1
+- upgrade, which also fix incremental backup (#206121)
+
+* Fri Sep 08 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.90-7
+- fix tar-debuginfo package (#205615)
+
+* Thu Aug 10 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.90-6
+- add xattr support (#200925), patch from james.antill@redhat.com
+
+* Mon Jul 24 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.90-5
+- fix incompatibilities in appending files to the end
+  of an archive (#199515)
+
+* Tue Jul 18 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.90-4
+- fix problem with unpacking archives in a directory for which
+  one has write permission but does not own (such as /tmp) (#149686)
+
+* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 1.15.90-3.1
+- rebuild
+
+* Thu Jun 29 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.90-3
+- fix typo in tar.1 man page
+
+* Tue Apr 25 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.90-2
+- exclude listed02.at from testsuite again, because it
+  still fails on s390
+
+* Tue Apr 25 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.90-1
+- upgrade
+
+* Mon Apr 24 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.1-16
+- fix problem when options at the end of command line were
+  not recognized (#188707)
+
+* Thu Apr 13 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.1-15
+- fix segmentation faul introduced with hugeSparse.patch
+
+* Wed Mar 22 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.1-14
+- fix problems with extracting large sparse archive members (#185460)
+
+* Fri Feb 17 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.1-13
+- fix heap overlfow bug CVE-2006-0300 (#181773)
+
+* Fri Feb 10 2006 Jesse Keating <jkeating@redhat.com> - 1.15.1-12.2
+- bump again for double-long bug on ppc(64)
+
+* Tue Feb 07 2006 Jesse Keating <jkeating@redhat.com> - 1.15.1-12.1
+- rebuilt for new gcc4.1 snapshot and glibc changes
+
+* Mon Feb 06 2006 Peter Vrabec <pvrabec@redhat.com> 1.15.1-12
+- fix extracting sparse files to a filesystem like vfat,
+  when ftruncate may fail to grow the size of a file.(#179507)
+
+* Fri Dec 09 2005 Jesse Keating <jkeating@redhat.com>
+- rebuilt
+
+* Fri Nov 04 2005 Peter Vrabec <pvrabec@redhat.com> 1.15.1-11
+- correctly pad archive members that shrunk during archiving (#172373)
+
+* Tue Sep 06 2005 Peter Vrabec <pvrabec@redhat.com> 1.15.1-10
+- provide man page (#163709, #54243, #56041)
+
+* Mon Aug 15 2005 Peter Vrabec <pvrabec@redhat.com> 1.15.1-9
+- silence newer option (#164902)
+
+* Wed Jul 27 2005 Peter Vrabec <pvrabec@redhat.com> 1.15.1-8
+- A file is dumpable if it is sparse and both --sparse
+  and --totals are specified (#154882)
+
+* Tue Jul 26 2005 Peter Vrabec <pvrabec@redhat.com> 1.15.1-7
+- exclude listed02.at from testsuite
+
+* Fri Jul 22 2005 Peter Vrabec <pvrabec@redhat.com> 1.15.1-6
+- remove tar-1.14-err.patch, not needed (158743)
+
+* Fri Apr 15 2005 Peter Vrabec <pvrabec@redhat.com> 1.15.1-5
+- extract sparse files even if the output fd is not seekable.(#154882)
+- (sparse_scan_file): Bugfix. offset had incorrect type.
+
+* Mon Mar 14 2005 Peter Vrabec <pvrabec@redhat.com>
+- gcc4 fix (#150993) 1.15.1-4
+
+* Mon Jan 31 2005 Peter Vrabec <pvrabec@redhat.com>
+- rebuild 1.15.1-3
+
+* Mon Jan 17 2005 Peter Vrabec <pvrabec@redhat.com>
+- fix tests/testsuite
+
+* Fri Jan 07 2005 Peter Vrabec <pvrabec@redhat.com>
+- upgrade to 1.15.1
+
+* Mon Oct 11 2004 Peter Vrabec <pvrabec@redhat.com>
+- patch to stop issuing lone zero block warnings
+- rebuilt
+
+* Mon Oct 11 2004 Peter Vrabec <pvrabec@redhat.com>
+- URL added to spec file
+- spec file clean up
+
+* Tue Jun 15 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Mon Jun  7 2004 Jeff Johnson <jbj@jbj.org> 1.14-1
+- upgrade to 1.14.
+
+* Fri Feb 13 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Tue Jun 17 2003 Jeff Johnson <jbj@redhat.com> 1.13.25-13
+- rebuilt because of crt breakage on ppc64.
+- dump automake15 requirement.
+
+* Wed Jun 04 2003 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Wed Jan 22 2003 Tim Powers <timp@redhat.com>
+- rebuilt
+
+* Fri Nov 29 2002 Tim Powers <timp@redhat.com> 1.13.25-10
+- fix broken buildrquires on autoconf253
+
+* Thu Nov  7 2002 Jeff Johnson <jbj@redhat.com> 1.13.25-9
+- rebuild from CVS.
+
+* Fri Aug 23 2002 Phil Knirsch <pknirsch@redhat.com> 1.13.25-8
+- Included security patch from errata release.
+
+* Mon Jul  1 2002 Bernhard Rosenkraenzer <bero@redhat.com> 1.13.25-7
+- Fix argv NULL termination (#64869)
+
+* Thu May 23 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Tue Apr  9 2002 Bernhard Rosenkraenzer <bero@redhat.com> 1.13.25-4
+- Fix build with autoconf253 (LIBOBJ change; autoconf252 worked)
+
+* Wed Jan 09 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Tue Oct 23 2001 Bernhard Rosenkraenzer <bero@redhat.com> 1.13.25-2
+- Don't include hardlinks to sockets in a tar file (#54827)
+
+* Thu Sep 27 2001 Bernhard Rosenkraenzer <bero@redhat.com> 1.13.25-1
+- 1.13.25
+
+* Tue Sep 18 2001 Bernhard Rosenkraenzer <bero@redhat.com> 1.13.22-1
+- Update to 1.13.22, adapt patches
+
+* Mon Aug 27 2001 Bernhard Rosenkraenzer <bero@redhat.com> 1.13.19-6
+- Fix #52084
+
+* Thu May 17 2001 Bernhard Rosenkraenzer <bero@redhat.com> 1.13.19-5
+- Fix build with current autoconf (stricter checking on AC_DEFINE)
+- Fix segfault when tarring directories without having read permissions
+  (#40802)
+
+* Tue Mar  6 2001 Bernhard Rosenkraenzer <bero@redhat.com>
+- Don't depend on librt.
+
+* Fri Feb 23 2001 Trond Eivind Glomsröd <teg@redhat.com>
+- langify
+
+* Thu Feb 22 2001 Bernhard Rosenkraenzer <bero@redhat.com>
+- Fix up the man page (#28915)
+
+* Wed Feb 21 2001 Bernhard Rosenkraenzer <bero@redhat.com>
+- 1.3.19, nukes -I and fixes up -N
+- Add -I back in as an alias to -j with a nice loud warning
+
+* Mon Oct 30 2000 Bernhard Rosenkraenzer <bero@redhat.com>
+- 1.3.18
+- Update man page to reflect changes
+
+* Thu Oct  5 2000 Bernhard Rosenkraenzer <bero@redhat.com>
+- Fix the "ignore failed read" option (Bug #8330)
+
+* Mon Sep 25 2000 Bernhard Rosenkraenzer <bero@redhat.com>
+- fix hang on tar tvzf - <something.tar.gz, introduced by
+  exit code fix (Bug #15448), Patch from Tim Waugh <twaugh@redhat.com>
+
+* Fri Aug 18 2000 Bernhard Rosenkraenzer <bero@redhat.com>
+- really fix exit code (Bug #15448)
+
+* Mon Aug  7 2000 Bernhard Rosenkraenzer <bero@redhat.com>
+- fix exit code (Bug #15448), patch from Tim Waugh <twaugh@redhat.com>
+
+* Wed Jul 12 2000 Prospector <bugzilla@redhat.com>
+- automatic rebuild
+
+* Mon Jun 19 2000 Bernhard Rosenkraenzer <bero@redhat.com>
+- FHSify
+
+* Fri Apr 28 2000 Bill Nottingham <notting@redhat.com>
+- fix for ia64
+
+* Wed Feb  9 2000 Bernhard Rosenkränzer <bero@redhat.com>
+- Fix the exclude bug (#9201)
+
+* Wed Feb 02 2000 Cristian Gafton <gafton@redhat.com>
+- man pages are compressed
+- fix description
+- fix fnmatch build problems
+
+* Sun Jan  9 2000 Bernhard Rosenkränzer <bero@redhat.com>
+- 1.13.17
+- remove dotbug patch (fixed in base)
+- update download URL
+
+* Fri Jan  7 2000 Bernhard Rosenkränzer <bero@redhat.com>
+- Fix a severe bug (tar xf any_package_containing_. would delete the
+  current directory)
+
+* Wed Jan  5 2000 Bernhard Rosenkränzer <bero@redhat.com>
+- 1.3.16
+- unset LINGUAS before running configure
+
+* Tue Nov  9 1999 Bernhard Rosenkränzer <bero@redhat.com>
+- 1.13.14
+- Update man page to know about -I / --bzip
+- Remove dependancy on rmt - tar can be used for anything local
+  without it.
+
+* Fri Aug 27 1999 Preston Brown <pbrown@redhat.com>
+- upgrade to 1.13.11.
+
+* Wed Aug 18 1999 Jeff Johnson <jbj@redhat.com>
+- update to 1.13.9.
+
+* Thu Aug 12 1999 Jeff Johnson <jbj@redhat.com>
+- update to 1.13.6.
+- support -y --bzip2 options for bzip2 compression (#2415).
+
+* Fri Jul 23 1999 Jeff Johnson <jbj@redhat.com>
+- update to 1.13.5.
+
+* Tue Jul 13 1999 Bill Nottingham <notting@redhat.com>
+- update to 1.13
+
+* Sat Jun 26 1999 Jeff Johnson <jbj@redhat.com>
+- update to 1.12.64014.
+- pipe patch corrected for remote tars now merged in.
+
+* Sun Jun 20 1999 Jeff Johnson <jbj@redhat.com>
+- update to tar-1.12.64013.
+- subtract (and reopen #2415) bzip2 support using -y.
+- move gtar to /bin.
+
+* Tue Jun 15 1999 Jeff Johnson <jbj@redhat.com>
+- upgrade to tar-1.12.64011 to
+-   add bzip2 support (#2415)
+-   fix filename bug (#3479)
+
+* Mon Mar 29 1999 Jeff Johnson <jbj@redhat.com>
+- fix suspended tar with compression over pipe produces error (#390).
+
+* Sun Mar 21 1999 Cristian Gafton <gafton@redhat.com>
+- auto rebuild in the new build environment (release 8)
+
+* Mon Mar 08 1999 Michael Maher <mike@redhat.com>
+- added patch for bad name cache.
+- FIXES BUG 320
+
+* Wed Feb 24 1999 Preston Brown <pbrown@redhat.com>
+- Injected new description and group.
+
+* Fri Dec 18 1998 Preston Brown <pbrown@redhat.com>
+- bumped spec number for initial rh 6.0 build
+
+* Tue Aug  4 1998 Jeff Johnson <jbj@redhat.com>
+- add /usr/bin/gtar symlink (change #421)
+
+* Tue Jul 14 1998 Jeff Johnson <jbj@redhat.com>
+- Fiddle bindir/libexecdir to get RH install correct.
+- Don't include /sbin/rmt -- use the rmt from dump.
+- Turn on nls.
+
+* Mon Apr 27 1998 Prospector System <bugs@redhat.com>
+- translations modified for de, fr, tr
+
+* Thu Oct 16 1997 Donnie Barnes <djb@redhat.com>
+- updated from 1.11.8 to 1.12
+- various spec file cleanups
+- /sbin/install-info support
+
+* Thu Jun 19 1997 Erik Troan <ewt@redhat.com>
+- built against glibc
+
+* Thu May 29 1997 Michael Fulbright <msf@redhat.com>
+- Fixed to include rmt