From 67775841f5ba4bd4266a050b0e1b14cde46dc25b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Va=C5=A1=C3=ADk?= Date: Wed, 9 Oct 2013 11:39:11 +0200 Subject: [PATCH] new upstream release 1.27 (#1016288) --- .gitignore | 2 + sources | 4 +- tar-1.23-oldarchive.patch | 14 - tar-1.26-add-skip-old-files-option.patch | 370 -- tar-1.26-allow-extract-single-volume.patch | 27 - tar-1.26-docu-xattrs.patch | 20 +- tar-1.26-fix-symlink-eating-bug.patch | 91 - tar-1.26-pax-big-sparse-files.patch | 66 - tar-1.26-posix-biguid.patch | 15 - tar-1.26-selinux-gnulib.patch | 3603 ------------------- tar-1.26-silence-gcc.patch | 230 -- tar-1.26-stdio.in.patch | 14 - tar-1.26-update-with-change-directory.patch | 35 +- tar-1.26-xattrs-printing.patch | 2 +- tar-1.26-xattrs.patch | 3233 ----------------- tar.spec | 94 +- 16 files changed, 27 insertions(+), 7793 deletions(-) delete mode 100644 tar-1.23-oldarchive.patch delete mode 100644 tar-1.26-add-skip-old-files-option.patch delete mode 100644 tar-1.26-allow-extract-single-volume.patch delete mode 100644 tar-1.26-fix-symlink-eating-bug.patch delete mode 100644 tar-1.26-pax-big-sparse-files.patch delete mode 100644 tar-1.26-posix-biguid.patch delete mode 100644 tar-1.26-selinux-gnulib.patch delete mode 100644 tar-1.26-silence-gcc.patch delete mode 100644 tar-1.26-stdio.in.patch delete mode 100644 tar-1.26-xattrs.patch diff --git a/.gitignore b/.gitignore index adb5fae..f83e5f4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ tar-1.23.tar.bz2.sig /tar-1.25.tar.xz.sig /tar-1.26.tar.xz /tar-1.26.tar.xz.sig +/tar-1.27.tar.xz +/tar-1.27.tar.xz.sig diff --git a/sources b/sources index b6efdc0..1d3d356 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -0ced6f20b9fa1bea588005b5ad4b52c1 tar-1.26.tar.xz -6618d5fe7785e138c27d7d6a24e998b2 tar-1.26.tar.xz.sig +3484fc42b7a82b82f2305b2971aa0e56 tar-1.27.tar.xz +402afd4829f508991c7e85b3d9a87077 tar-1.27.tar.xz.sig diff --git a/tar-1.23-oldarchive.patch b/tar-1.23-oldarchive.patch deleted file mode 100644 index 6163916..0000000 --- a/tar-1.23-oldarchive.patch +++ /dev/null @@ -1,14 +0,0 @@ -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/tar-1.26-add-skip-old-files-option.patch b/tar-1.26-add-skip-old-files-option.patch deleted file mode 100644 index 00d632d..0000000 --- a/tar-1.26-add-skip-old-files-option.patch +++ /dev/null @@ -1,370 +0,0 @@ -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, ¤t_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 . -+ -+# 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 , -+# Gary Partis , -+# Jim Meyering -+# -+# 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 . -+ -+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/tar-1.26-allow-extract-single-volume.patch b/tar-1.26-allow-extract-single-volume.patch deleted file mode 100644 index 6ec830d..0000000 --- a/tar-1.26-allow-extract-single-volume.patch +++ /dev/null @@ -1,27 +0,0 @@ -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/tar-1.26-docu-xattrs.patch b/tar-1.26-docu-xattrs.patch index 14d047e..65b316e 100644 --- a/tar-1.26-docu-xattrs.patch +++ b/tar-1.26-docu-xattrs.patch @@ -2,16 +2,6 @@ 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 @@ -146,8 +136,8 @@ index d678db9..ab8a0c8 100644 @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}. + treats names specially if they have initial @samp{/} or internal + @samp{..}. This option disables that behavior. @xref{absolute}. +@opsummary{acls} +@item --acls @@ -214,9 +204,9 @@ index d678db9..ab8a0c8 100644 @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}. + @cindex @samp{Record size = %lu blocks}, warning message + @item record-size + @samp{Record size = %lu blocks} +@kwindex xattr-write +@item xattr-write +@samp{%s: Cannot set '%s' extended attribute for file '%s'} diff --git a/tar-1.26-fix-symlink-eating-bug.patch b/tar-1.26-fix-symlink-eating-bug.patch deleted file mode 100644 index c9f8887..0000000 --- a/tar-1.26-fix-symlink-eating-bug.patch +++ /dev/null @@ -1,91 +0,0 @@ -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/tar-1.26-pax-big-sparse-files.patch b/tar-1.26-pax-big-sparse-files.patch deleted file mode 100644 index be72dfa..0000000 --- a/tar-1.26-pax-big-sparse-files.patch +++ /dev/null @@ -1,66 +0,0 @@ -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 - -+** 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/tar-1.26-posix-biguid.patch b/tar-1.26-posix-biguid.patch deleted file mode 100644 index 1578b7a..0000000 --- a/tar-1.26-posix-biguid.patch +++ /dev/null @@ -1,15 +0,0 @@ -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/tar-1.26-selinux-gnulib.patch b/tar-1.26-selinux-gnulib.patch deleted file mode 100644 index 78783a9..0000000 --- a/tar-1.26-selinux-gnulib.patch +++ /dev/null @@ -1,3603 +0,0 @@ -From f733da5249b0b119cb551c73b322439bcbbc013a Mon Sep 17 00:00:00 2001 -From: Pavel Raiskup -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 . */ -+ -+/* _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 . -+ -+ Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ -+ -+#include "acl.h" -+ -+#include -+#include -+ -+/* All systems define the ACL related API in . */ -+#if HAVE_SYS_ACL_H -+# include -+#endif -+#if defined HAVE_FACL && ! defined GETACLCNT && defined ACL_CNT -+# define GETACLCNT ACL_CNT -+#endif -+ -+/* On Linux, additional ACL related API is available in . */ -+#ifdef HAVE_ACL_LIBACL_H -+# include -+#endif -+ -+/* On HP-UX >= 11.11, additional ACL API is available in . */ -+#if HAVE_ACLV_H -+# include -+# include -+/* 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 -+#ifndef ENOSYS -+# define ENOSYS (-1) -+#endif -+#ifndef ENOTSUP -+# define ENOTSUP (-1) -+#endif -+ -+#include -+#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 . -+ -+ Written by Paul Eggert. */ -+ -+#include -+#include -+ -+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 . -+ -+ Written by Paul Eggert and Andreas Gruenbacher. */ -+ -+#include -+ -+#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 . -+ -+ Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ -+ -+#include -+ -+#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 -+ 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 . -+ -+ 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 -+ -+#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 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 -+ (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 . */ -+ -+/* written by Jim Meyering */ -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+/* 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 -+ -+/* 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 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 . */ -+ -+#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 -+# include -+ -+/* 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 . */ -+ -+/* written by Jim Meyering */ -+ -+#include -+ -+#include "selinux-at.h" -+#include "openat.h" -+ -+#include -+#include -+#include -+#include -+ -+#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 . */ -+ -+#include -+#include -+ -+/* 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 . -+ -+ Written by Paul Eggert and Andreas Gruenbacher, and Bruno Haible. */ -+ -+#include -+ -+#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 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 . -+ 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 . -+ 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 -+#include -+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 -+#include -+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 ]) -+ 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 -+ #include -+ #include -+ ]], -+ [[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 , 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 , 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 , 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 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/tar-1.26-silence-gcc.patch b/tar-1.26-silence-gcc.patch deleted file mode 100644 index 108f376..0000000 --- a/tar-1.26-silence-gcc.patch +++ /dev/null @@ -1,230 +0,0 @@ -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/lib/wordsplit.c b/lib/wordsplit.c -index bd5d59d..5f555ea 100644 ---- a/lib/wordsplit.c -+++ b/lib/wordsplit.c -@@ -796,6 +796,8 @@ expvar (struct wordsplit *wsp, const char *str, size_t len, - value = ""; - } - /* FIXME: handle defstr */ -+ (void) defstr; /* upstream commit 17f99bc6f1 */ -+ - if (value) - { - if (flg & _WSNF_QUOTE) -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 (¤t_stat_info)); - -diff --git a/src/system.c b/src/system.c -index a27a7de..2049240 100644 ---- a/src/system.c -+++ b/src/system.c -@@ -25,7 +25,7 @@ - #include - #include - --static void -+static void __attribute__ ((__noreturn__)) /* upstream (similar) fix in 17f99bc6f1405 */ - xexec (const char *cmd) - { - struct wordsplit ws; -@@ -745,8 +745,7 @@ int - sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st) - { - int p[2]; -- char *argv[4]; -- -+ - xpipe (p); - pipe_handler = signal (SIGPIPE, SIG_IGN); - global_pid = xfork (); -@@ -806,7 +805,6 @@ int - sys_exec_info_script (const char **archive_name, int volume_number) - { - pid_t pid; -- char *argv[4]; - char uintbuf[UINTMAX_STRSIZE_BOUND]; - int p[2]; - static RETSIGTYPE (*saved_handler) (int sig); -@@ -881,7 +879,7 @@ sys_exec_checkpoint_script (const char *script_name, - int checkpoint_number) - { - pid_t pid; -- char *argv[4]; -+ /* upstream commit 17f99bc6f */ - char uintbuf[UINTMAX_STRSIZE_BOUND]; - - pid = xfork (); -@@ -912,10 +910,7 @@ sys_exec_checkpoint_script (const char *script_name, - setenv ("TAR_FORMAT", - archive_format_string (current_format == DEFAULT_FORMAT ? - archive_format : current_format), 1); -- argv[0] = "/bin/sh"; -- argv[1] = "-c"; -- argv[2] = (char *) script_name; -- argv[3] = NULL; -+ /* upstream commit 17f99bc6f */ - - priv_set_restore_linkdir (); - xexec (script_name); -diff --git a/src/update.c b/src/update.c -index 4739e0d..3b28734 100644 ---- a/src/update.c -+++ b/src/update.c -@@ -145,7 +145,7 @@ update_archive (void) - if (S_ISDIR (s.st_mode)) - { - char *p, *dirp; -- DIR *stream; -+ DIR *stream = NULL; /* upstream commit 5bb043350790 */ - int fd = openat (chdir_fd, name->name, - open_read_flags | O_DIRECTORY); - if (fd < 0) -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/tar-1.26-stdio.in.patch b/tar-1.26-stdio.in.patch deleted file mode 100644 index dd7856b..0000000 --- a/tar-1.26-stdio.in.patch +++ /dev/null @@ -1,14 +0,0 @@ -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/tar-1.26-update-with-change-directory.patch b/tar-1.26-update-with-change-directory.patch index 6a9a0cf..ec5ca85 100644 --- a/tar-1.26-update-with-change-directory.patch +++ b/tar-1.26-update-with-change-directory.patch @@ -7,9 +7,9 @@ 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 +- + src/update.c | 2 +- + tests/Makefile.am | 1 +- + tests/testsuite.at | 1 +- tests/update03.at | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 tests/update03.at @@ -18,15 +18,6 @@ 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) @@ -40,15 +31,6 @@ 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 , 1988. - # Sergey Poznyakoff , 2004. @@ -156,6 +156,7 @@ TESTSUITE_AT = \ update.at\ update01.at\ @@ -61,23 +43,14 @@ 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]) + AT_BANNER([Verifying the archive]) m4_include([verify.at]) - diff --git a/tests/update03.at b/tests/update03.at new file mode 100644 index 0000000..185f9eb diff --git a/tar-1.26-xattrs-printing.patch b/tar-1.26-xattrs-printing.patch index e6a4f0c..ce872ce 100644 --- a/tar-1.26-xattrs-printing.patch +++ b/tar-1.26-xattrs-printing.patch @@ -33,4 +33,4 @@ index 5a4bf72..bdf6ba0 100644 + if (xattrs_option > 0 && st->xattr_map_size) { int i; - + diff --git a/tar-1.26-xattrs.patch b/tar-1.26-xattrs.patch deleted file mode 100644 index 80ef5a2..0000000 --- a/tar-1.26-xattrs.patch +++ /dev/null @@ -1,3233 +0,0 @@ -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 - - -@@ -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 , 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 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 ]) - AC_CHECK_DECLS([getpwuid],,, [#include ]) - AC_CHECK_DECLS([time],,, [#include ]) -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 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 . */ -+ -+#ifndef TAR_ATTR_XATTR_H -+#define TAR_ATTR_XATTR_H -+#include -+ -+/* 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 . */ -+ -+#include -+ -+#include "xattr-at.h" -+#include "openat.h" -+ -+#include -+#include -+#include -+#include -+ -+#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 . */ -+ -+#ifndef XATTRS_AT_H -+#define XATTRS_AT_H -+ -+#include -+#include -+ -+/* 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, ¤t_stat_info, invert_permissions, -+ typeflag, &file_created)) -+ { -+ skip_member (); -+ open_error (file_name); -+ return 1; -+ } -+ - while ((fd = open_output_file (file_name, typeflag, mode, -- ¤t_mode, ¤t_mode_mask)) -+ file_created, ¤t_mode, -+ ¤t_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 (¤t_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 -+#include -+ -+#include -+#include -+ -+#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 -+#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 . -+# -+# 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 . -+# -+# 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 . -+# -+# 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 . -+# -+# 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 . -+# -+# 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 . -+# -+# 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 . -+# -+# 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 . -+# -+# 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 . -+# -+# 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 . -+# -+# 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/tar.spec b/tar.spec index 5a944be..96cc5b2 100644 --- a/tar.spec +++ b/tar.spec @@ -4,8 +4,8 @@ Summary: A GNU file archiving program Name: tar Epoch: 2 -Version: 1.26 -Release: 28%{?dist} +Version: 1.27 +Release: 1%{?dist} License: GPLv3+ Group: Applications/Archiving URL: http://www.gnu.org/software/tar/ @@ -39,90 +39,30 @@ Patch3: tar-1.17-wildcards.patch # ~> 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 - -# Allow to pass arguments to commands called from tar -# ~> resolves #819187 (now we can use ./configure --with-lzma) -# ~> http://lists.gnu.org/archive/html/bug-tar/2013-02/msg00003.html -# ~> upstream: 7b5e803963 -Patch14: tar-1.26-command-args.patch +Patch5: tar-1.26-update-with-change-directory.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 -Patch15: 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 -Patch16: tar-1.26-fix-symlink-eating-bug.patch +Patch6: tar-1.26-xattrs-printing.patch # Add documentation which was not yet pushed upstream # ~> downstream # ~> #996753 -Patch17: tar-1.26-docu-xattrs.patch +Patch7: 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 -Patch18: tar-1.26-xattrs-include-implies-xattrs.patch - -# Silence gcc warnings -# ~> upstream tar: 17f99bc6f, 5bb0433 -# ~> upstream paxutils: 0b3d84a0 -Patch999: tar-1.26-silence-gcc.patch +Patch8: tar-1.26-xattrs-include-implies-xattrs.patch # run "make check" by default %bcond_without check @@ -161,21 +101,10 @@ the rmt package on the remote box. %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 .command-args -%patch15 -p1 -b .print-xattrs-fix -%patch16 -p1 -b .birthtime -%patch17 -p1 -b .xattrs-documentation -%patch18 -p1 -b .xattrs-if-xattrs-include -%patch999 -p1 -b .silence-gcc +%patch5 -p1 -b .update_and_changedir +%patch6 -p1 -b .print-xattrs-fix +%patch7 -p1 -b .xattrs-documentation +%patch8 -p1 -b .xattrs-if-xattrs-include autoreconf -v @@ -234,6 +163,9 @@ fi %{_infodir}/tar.info* %changelog +* Wed Oct 09 2013 Ondrej Vasik - 1.27-1 +- new upstream release 1.27 (#1016288) + * Mon Sep 09 2013 Pavel Raiskup - 1.26-28 - add documenation for xattrs-like options (#996753) - the --xattrs-include implies --xattrs now (#965969)