From 98b687cc8be3e6594c50fb0a35636e089659d40f Mon Sep 17 00:00:00 2001 From: Pavel Raiskup Date: Tue, 19 Feb 2013 09:30:08 +0100 Subject: [PATCH] spec/patches: little bit of reorganization * re-create patches against latest release (to avoid fuzzy offset warnings during patching) * remove old xattr patch (up2date upstream patch will be added in next commit) * remove some old patches which are not needed against 1.26 tarball now * add more verbose comments for patches Version: 2:1.26-17 --- tar-1.14-loneZeroWarning.patch | 11 +- tar-1.15.1-vfatTruncate.patch | 8 +- tar-1.17-wildcards.patch | 105 +- tar-1.22-atime-rofs.patch | 11 +- tar-1.26-add-skip-old-files-option.patch | 53 +- tar-1.26-stdio.in.patch | 9 +- tar-1.26-xattrs-gnulib-prepare.patch | 3970 ---------------------- tar-1.26-xattrs.patch | 3061 ----------------- tar-sigpipe.patch | 12 - tar.spec | 94 +- 10 files changed, 161 insertions(+), 7173 deletions(-) delete mode 100644 tar-1.26-xattrs-gnulib-prepare.patch delete mode 100644 tar-1.26-xattrs.patch delete mode 100644 tar-sigpipe.patch diff --git a/tar-1.14-loneZeroWarning.patch b/tar-1.14-loneZeroWarning.patch index cefa83d..70b20d3 100644 --- a/tar-1.14-loneZeroWarning.patch +++ b/tar-1.14-loneZeroWarning.patch @@ -1,7 +1,8 @@ -diff -ruNp tar-1.22.orig/src/list.c tar-1.22/src/list.c ---- tar-1.22.orig/src/list.c 2008-10-30 12:10:04.000000000 +0100 -+++ tar-1.22/src/list.c 2009-03-06 00:03:05.925105425 +0100 -@@ -138,6 +138,14 @@ read_and (void (*do_something) (void)) +diff --git a/src/list.c b/src/list.c +index cf2de09..f4e6e0a 100644 +--- a/src/list.c ++++ b/src/list.c +@@ -212,6 +212,14 @@ read_and (void (*do_something) (void)) if (!ignore_zeros_option) { @@ -16,7 +17,7 @@ diff -ruNp tar-1.22.orig/src/list.c tar-1.22/src/list.c char buf[UINTMAX_STRSIZE_BOUND]; status = read_header (¤t_header, ¤t_stat_info, -@@ -147,6 +155,9 @@ read_and (void (*do_something) (void)) +@@ -221,6 +229,9 @@ read_and (void (*do_something) (void)) WARNOPT (WARN_ALONE_ZERO_BLOCK, (0, 0, _("A lone zero block at %s"), STRINGIFY_BIGINT (current_block_ordinal (), buf))); diff --git a/tar-1.15.1-vfatTruncate.patch b/tar-1.15.1-vfatTruncate.patch index bcbb88e..a61684e 100644 --- a/tar-1.15.1-vfatTruncate.patch +++ b/tar-1.15.1-vfatTruncate.patch @@ -1,6 +1,8 @@ ---- tar-1.15.1/src/system.c.vfatTruncate 2004-09-06 07:31:00.000000000 -0400 -+++ tar-1.15.1/src/system.c 2006-02-03 14:40:51.000000000 -0500 -@@ -272,8 +272,25 @@ +diff --git a/src/system.c b/src/system.c +index ba4ac2d..ea88cd6 100644 +--- a/src/system.c ++++ b/src/system.c +@@ -231,8 +231,25 @@ sys_compare_links (struct stat *link_data, struct stat *stat_data) int sys_truncate (int fd) { diff --git a/tar-1.17-wildcards.patch b/tar-1.17-wildcards.patch index 0ea5269..62919d1 100644 --- a/tar-1.17-wildcards.patch +++ b/tar-1.17-wildcards.patch @@ -1,6 +1,8 @@ ---- tar-1.17/doc/tar.texi.wildcards 2007-06-28 13:23:46.000000000 +0200 -+++ tar-1.17/doc/tar.texi 2007-06-28 13:23:46.000000000 +0200 -@@ -6871,7 +6871,7 @@ The following table summarizes pattern-m +diff --git a/doc/tar.texi b/doc/tar.texi +index db8f986..d70d113 100644 +--- a/doc/tar.texi ++++ b/doc/tar.texi +@@ -7597,7 +7597,7 @@ The following table summarizes pattern-matching default values: @multitable @columnfractions .3 .7 @headitem Members @tab Default settings @@ -9,7 +11,7 @@ @item Exclusion @tab @option{--wildcards --no-anchored --wildcards-match-slash} @end multitable -@@ -10666,6 +10666,9 @@ version of this document is available at +@@ -12038,6 +12038,9 @@ version of this document is available at @table @asis @item Use of globbing patterns when listing and extracting. @@ -19,48 +21,11 @@ Previous versions of GNU tar assumed shell-style globbing when extracting from or listing an archive. For example: ---- tar-1.17/src/tar.c.wildcards 2007-06-28 13:23:46.000000000 +0200 -+++ tar-1.17/src/tar.c 2007-06-28 13:23:46.000000000 +0200 -@@ -686,7 +686,7 @@ static struct argp_option options[] = { - {"no-ignore-case", NO_IGNORE_CASE_OPTION, 0, 0, - N_("case sensitive matching (default)"), GRID+1 }, - {"wildcards", WILDCARDS_OPTION, 0, 0, -- N_("use wildcards (default for exclusion)"), GRID+1 }, -+ N_("use wildcards (default)"), GRID+1 }, - {"no-wildcards", NO_WILDCARDS_OPTION, 0, 0, - N_("verbatim string matching"), GRID+1 }, - {"no-wildcards-match-slash", NO_WILDCARDS_MATCH_SLASH_OPTION, 0, 0, -@@ -780,8 +780,7 @@ ARGMATCH_VERIFY (atime_preserve_args, at - /* Wildcard matching settings */ - enum wildcards - { -- default_wildcards, /* For exclusion == enable_wildcards, -- for inclusion == disable_wildcards */ -+ default_wildcards, /* enable_wildcards */ - disable_wildcards, - enable_wildcards - }; -@@ -809,7 +808,7 @@ struct tar_args /* Variables used - | recursion_option) - - #define MAKE_INCL_OPTIONS(args) \ -- ((((args)->wildcards == enable_wildcards) ? EXCLUDE_WILDCARDS : 0) \ -+ ((((args)->wildcards != disable_wildcards) ? EXCLUDE_WILDCARDS : 0) \ - | (args)->include_anchored \ - | (args)->matching_flags \ - | recursion_option) -@@ -2126,7 +2125,7 @@ decode_options (int argc, char **argv) - - /* Warn about implicit use of the wildcards in command line arguments. - See TODO */ -- warn_regex_usage = args.wildcards == default_wildcards; -+ warn_regex_usage = 0; /* args.wildcards == default_wildcards; */ - - /* Derive option values and check option consistency. */ - ---- tar-1.17/src/names.c.wildcards 2007-04-03 14:17:13.000000000 +0200 -+++ tar-1.17/src/names.c 2007-06-28 13:30:48.000000000 +0200 -@@ -812,10 +812,7 @@ collect_and_sort_names (void) +diff --git a/src/names.c b/src/names.c +index ba4d509..3911f8c 100644 +--- a/src/names.c ++++ b/src/names.c +@@ -966,10 +966,7 @@ collect_and_sort_names (void) if (name->found_count || name->directory) continue; @@ -72,9 +37,51 @@ chdir_do (name->change_dir); if (name->name[0] == 0) -diff -urNp tar-1.23-orig/tests/exclude01.at tar-1.23/tests/exclude01.at ---- tar-1.23-orig/tests/exclude01.at 2010-01-26 12:30:20.000000000 +0100 -+++ tar-1.23/tests/exclude01.at 2010-03-12 14:42:31.000000000 +0100 +diff --git a/src/tar.c b/src/tar.c +index 928cfdd..22d3db1 100644 +--- a/src/tar.c ++++ b/src/tar.c +@@ -722,7 +722,7 @@ static struct argp_option options[] = { + {"no-ignore-case", NO_IGNORE_CASE_OPTION, 0, 0, + N_("case sensitive matching (default)"), GRID+1 }, + {"wildcards", WILDCARDS_OPTION, 0, 0, +- N_("use wildcards (default for exclusion)"), GRID+1 }, ++ N_("use wildcards (default)"), GRID+1 }, + {"no-wildcards", NO_WILDCARDS_OPTION, 0, 0, + N_("verbatim string matching"), GRID+1 }, + {"no-wildcards-match-slash", NO_WILDCARDS_MATCH_SLASH_OPTION, 0, 0, +@@ -815,8 +815,7 @@ ARGMATCH_VERIFY (atime_preserve_args, atime_preserve_types); + /* Wildcard matching settings */ + enum wildcards + { +- default_wildcards, /* For exclusion == enable_wildcards, +- for inclusion == disable_wildcards */ ++ default_wildcards, /* enable_wildcards */ + disable_wildcards, + enable_wildcards + }; +@@ -847,7 +846,7 @@ struct tar_args /* Variables used during option parsing */ + | recursion_option) + + #define MAKE_INCL_OPTIONS(args) \ +- ((((args)->wildcards == enable_wildcards) ? EXCLUDE_WILDCARDS : 0) \ ++ ((((args)->wildcards != disable_wildcards) ? EXCLUDE_WILDCARDS : 0) \ + | (args)->include_anchored \ + | (args)->matching_flags \ + | recursion_option) +@@ -2347,7 +2346,7 @@ decode_options (int argc, char **argv) + + /* Warn about implicit use of the wildcards in command line arguments. + See TODO */ +- warn_regex_usage = args.wildcards == default_wildcards; ++ warn_regex_usage = 0; /* args.wildcards == default_wildcards; */ + + /* Derive option values and check option consistency. */ + +diff --git a/tests/exclude01.at b/tests/exclude01.at +index 778a7fc..bd65ae0 100644 +--- a/tests/exclude01.at ++++ b/tests/exclude01.at @@ -59,6 +59,7 @@ testdir/dir2/file2 testdir/dir3/ NEXT diff --git a/tar-1.22-atime-rofs.patch b/tar-1.22-atime-rofs.patch index 12f022b..c61cbc4 100644 --- a/tar-1.22-atime-rofs.patch +++ b/tar-1.22-atime-rofs.patch @@ -1,10 +1,11 @@ -diff -urNp tar-1.22-orig/src/create.c tar-1.22/src/create.c ---- tar-1.22-orig/src/create.c 2009-05-15 10:50:38.000000000 +0200 -+++ tar-1.22/src/create.c 2009-05-15 10:51:52.000000000 +0200 -@@ -1827,7 +1827,8 @@ dump_file0 (struct tar_stat_info *st, co +diff --git a/src/create.c b/src/create.c +index 43b5a4c..f98cbb5 100644 +--- a/src/create.c ++++ b/src/create.c +@@ -1798,7 +1798,8 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p) } else if (atime_preserve_option == replace_atime_preserve - && fd && (is_dir || original_size != 0) + && fd && (is_dir || original_size != 0) - && set_file_atime (fd, parentfd, name, st->atime) != 0) + && set_file_atime (fd, parentfd, name, st->atime) != 0 + && errno != EROFS ) diff --git a/tar-1.26-add-skip-old-files-option.patch b/tar-1.26-add-skip-old-files-option.patch index fa70669..00d632d 100644 --- a/tar-1.26-add-skip-old-files-option.patch +++ b/tar-1.26-add-skip-old-files-option.patch @@ -1,8 +1,8 @@ diff --git a/doc/tar.texi b/doc/tar.texi -index 567745b..38c8bae 100644 +index d70d113..a0e3d5f 100644 --- a/doc/tar.texi +++ b/doc/tar.texi -@@ -1994,6 +1994,7 @@ The other operations of @command{tar} (@option{--list}, +@@ -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. @@ -10,7 +10,7 @@ index 567745b..38c8bae 100644 @cindex exit status @cindex return status Besides successful exits, @GNUTAR{} may fail for -@@ -2932,7 +2933,10 @@ when extracting files from an archive. +@@ -2815,7 +2816,10 @@ when extracting files from an archive. @item --keep-old-files @itemx -k @@ -22,7 +22,7 @@ index 567745b..38c8bae 100644 @xref{Keep Old Files}. @opsummary{label} -@@ -3404,6 +3408,20 @@ the archive creation operations it instructs @command{tar} to list the +@@ -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}. @@ -43,7 +43,7 @@ index 567745b..38c8bae 100644 @opsummary{sparse} @item --sparse @itemx -S -@@ -4589,11 +4607,11 @@ in the archive; the most recently archived members will be extracted +@@ -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 @@ -60,7 +60,7 @@ index 567745b..38c8bae 100644 @cindex extracting @var{n}th copy of the file @xopindex{occurrence, described} -@@ -5269,10 +5287,25 @@ such a directory, use the @option{--no-overwrite-dir} option. +@@ -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 @@ -90,7 +90,7 @@ index 567745b..38c8bae 100644 @xopindex{overwrite, introduced} To be more aggressive about altering existing files, use the -@@ -5338,16 +5371,24 @@ archive, but remove other files before extracting. +@@ -5192,16 +5225,24 @@ archive, but remove other files before extracting. @node Keep Old Files @unnumberedsubsubsec Keep Old Files @@ -122,10 +122,10 @@ index 567745b..38c8bae 100644 @node Keep Newer Files diff --git a/src/common.h b/src/common.h -index 4cf1459..b34aef0 100644 +index 0b9bd7a..2409413 100644 --- a/src/common.h +++ b/src/common.h -@@ -187,6 +187,7 @@ enum old_files +@@ -182,6 +182,7 @@ enum old_files OVERWRITE_OLD_FILES, /* --overwrite */ UNLINK_FIRST_OLD_FILES, /* --unlink-first */ KEEP_OLD_FILES, /* --keep-old-files */ @@ -133,14 +133,11 @@ index 4cf1459..b34aef0 100644 KEEP_NEWER_FILES /* --keep-newer-files */ }; GLOBAL enum old_files old_files_option; -@@ -830,13 +831,15 @@ void checkpoint_run (bool do_write); +@@ -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 -+ - - #define WARN_XATTR_WRITE 0x00200000 /* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default in verbose mode */ @@ -151,10 +148,10 @@ index 4cf1459..b34aef0 100644 void set_warning_option (const char *arg); diff --git a/src/extract.c b/src/extract.c -index 8a7a6ad..87b383a 100644 +index aaea56e..662ea0b 100644 --- a/src/extract.c +++ b/src/extract.c -@@ -696,9 +696,14 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made) +@@ -639,9 +639,14 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made) switch (old_files_option) { @@ -171,10 +168,10 @@ index 8a7a6ad..87b383a 100644 if (file_newer_p (file_name, stp, ¤t_stat_info)) break; diff --git a/src/tar.c b/src/tar.c -index 0ed1717..e244808 100644 +index 7b62996..7a673e0 100644 --- a/src/tar.c +++ b/src/tar.c -@@ -334,6 +334,7 @@ enum +@@ -328,6 +328,7 @@ enum SHOW_DEFAULTS_OPTION, SHOW_OMITTED_DIRS_OPTION, SHOW_TRANSFORMED_NAMES_OPTION, @@ -182,7 +179,7 @@ index 0ed1717..e244808 100644 SPARSE_VERSION_OPTION, STRIP_COMPONENTS_OPTION, SUFFIX_OPTION, -@@ -461,7 +462,11 @@ static struct argp_option options[] = { +@@ -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, @@ -195,7 +192,7 @@ index 0ed1717..e244808 100644 {"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, -@@ -1649,6 +1654,10 @@ parse_opt (int key, char *arg, struct argp_state *state) +@@ -1618,6 +1623,10 @@ parse_opt (int key, char *arg, struct argp_state *state) sparse_option = true; break; @@ -207,7 +204,7 @@ index 0ed1717..e244808 100644 sparse_option = true; { diff --git a/src/warning.c b/src/warning.c -index b0b9884..f00a842 100644 +index 5d1bcab..ee9d684 100644 --- a/src/warning.c +++ b/src/warning.c @@ -42,6 +42,7 @@ static char const *const warning_args[] = { @@ -215,19 +212,21 @@ index b0b9884..f00a842 100644 "xdev", "decompress-program", + "existing-file", - "xattr-write", NULL }; -@@ -68,6 +69,7 @@ static int warning_types[] = { + +@@ -66,7 +67,8 @@ static int warning_types[] = { + WARN_UNKNOWN_CAST, WARN_UNKNOWN_KEYWORD, WARN_XDEV, - WARN_DECOMPRESS_PROGRAM, +- WARN_DECOMPRESS_PROGRAM ++ WARN_DECOMPRESS_PROGRAM, + WARN_EXISTING_FILE, - WARN_XATTR_WRITE }; + ARGMATCH_VERIFY (warning_args, warning_types); diff --git a/tests/Makefile.am b/tests/Makefile.am -index b3c24dc..cbdda29 100644 +index 119f1f3..3d78ea2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -77,6 +77,8 @@ TESTSUITE_AT = \ @@ -356,10 +355,10 @@ index 0000000..43c4c50 +AT_CLEANUP + diff --git a/tests/testsuite.at b/tests/testsuite.at -index 3f02a52..4d59532 100644 +index d1dab36..e43653e 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at -@@ -231,6 +231,9 @@ m4_include([extrac15.at]) +@@ -166,6 +166,9 @@ m4_include([extrac15.at]) m4_include([extrac16.at]) m4_include([extrac17.at]) diff --git a/tar-1.26-stdio.in.patch b/tar-1.26-stdio.in.patch index a687592..dd7856b 100644 --- a/tar-1.26-stdio.in.patch +++ b/tar-1.26-stdio.in.patch @@ -1,7 +1,8 @@ -diff -urNp tar-1.26-orig/gnu/stdio.in.h tar-1.26/gnu/stdio.in.h ---- tar-1.26-orig/gnu/stdio.in.h -+++ tar-1.26/gnu/stdio.in.h -@@ -139,7 +139,9 @@ _GL_WARN_ON_USE (fflush, "fflush is not +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 diff --git a/tar-1.26-xattrs-gnulib-prepare.patch b/tar-1.26-xattrs-gnulib-prepare.patch deleted file mode 100644 index f51f3c0..0000000 --- a/tar-1.26-xattrs-gnulib-prepare.patch +++ /dev/null @@ -1,3970 +0,0 @@ -From 3a172f4a23be198bf79da30c38453c231b059500 Mon Sep 17 00:00:00 2001 -From: Pavel Raiskup -Date: Fri, 5 Oct 2012 09:29:31 +0200 -Subject: [PATCH 1/2] Prepare gnulib for xattrs patch - ---- - build-aux/snippet/unused-parameter.h | 38 ++ - gnu/Makefile.am | 123 ++++++- - gnu/acl-internal.h | 267 ++++++++++++++ - gnu/acl.h | 30 ++ - gnu/acl_entries.c | 77 ++++ - gnu/attr-xattr.in.h | 67 ++++ - 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 ++++++++++++++++++++++++++++++++++++ - gnu/xattr-at.c | 112 ++++++ - gnu/xattr-at.h | 68 ++++ - m4/acl.m4 | 165 +++++++++ - m4/attr-xattr-h.m4 | 28 ++ - m4/gnulib-comp.m4 | 33 +- - m4/selinux-context-h.m4 | 22 ++ - m4/selinux-selinux-h.m4 | 69 ++++ - 21 files changed, 3676 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/attr-xattr.in.h - 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 gnu/xattr-at.c - create mode 100644 gnu/xattr-at.h - create mode 100644 m4/acl.m4 - create mode 100644 m4/attr-xattr-h.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..406999c 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 - - -@@ -2695,6 +2780,36 @@ libgnu_a_SOURCES += xalloc-die.c - - ## end gnulib module xalloc-die - -+## begin gnulib module xattr-at -+ -+ -+EXTRA_DIST += at-func.c xattr-at.c xattr-at.h -+ -+EXTRA_libgnu_a_SOURCES += at-func.c xattr-at.c -+ -+## end gnulib module xattr-at -+ -+## begin gnulib module xattr-h -+ -+libgnu_a_SOURCES += attr-xattr.in.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 $@ && \ -+ { 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 '/definition of _GL_UNUSED_PARAMETER/r $(UNUSED_PARAMETER_H)' \ -+ < $(srcdir)/attr-xattr.in.h; \ -+ } > $@-t && \ -+ chmod a-x $@-t && \ -+ mv $@-t $@ -+MOSTLYCLEANFILES += attr/xattr.h attr/xattr.h-t -+ -+## end gnulib module xattr-h -+ - ## begin gnulib module xgetcwd - - -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/attr-xattr.in.h b/gnu/attr-xattr.in.h -new file mode 100644 -index 0000000..4349c69 ---- /dev/null -+++ b/gnu/attr-xattr.in.h -@@ -0,0 +1,67 @@ -+/* -*- buffer-read-only: t -*- vi: set ro: */ -+/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ -+#ifndef _@GUARD_PREFIX@_ATTR_XATTR_H -+#define _@GUARD_PREFIX@_ATTR_XATTR_H -+ -+/* 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 . */ -+ -+#if HAVE_ATTR_XATTR_H -+ -+#include -+#include_next -+ -+#else -+# 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 /* if HAVE_ATTR_XATTR_H */ -+#endif /* _@GUARD_PREFIX@_ATTR_XATTR_H */ -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/gnu/xattr-at.c b/gnu/xattr-at.c -new file mode 100644 -index 0000000..73e8a6e ---- /dev/null -+++ b/gnu/xattr-at.c -@@ -0,0 +1,112 @@ -+/* -*- buffer-read-only: t -*- vi: set ro: */ -+/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ -+/* 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/gnu/xattr-at.h b/gnu/xattr-at.h -new file mode 100644 -index 0000000..d7c3901 ---- /dev/null -+++ b/gnu/xattr-at.h -@@ -0,0 +1,68 @@ -+/* -*- buffer-read-only: t -*- vi: set ro: */ -+/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ -+#ifndef XATTRS_AT_H -+#define XATTRS_AT_H -+ -+/* 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 . */ -+ -+#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/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/attr-xattr-h.m4 b/m4/attr-xattr-h.m4 -new file mode 100644 -index 0000000..271834b ---- /dev/null -+++ b/m4/attr-xattr-h.m4 -@@ -0,0 +1,28 @@ -+# Copyright (C) 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. -+ -+# Provide , if necessary -+ -+AC_DEFUN([gl_HEADERS_ATTR_XATTR_H], -+[ -+ AC_ARG_WITH([xattrs], -+ AS_HELP_STRING([--without-xattrs], [don't use linux exteneded atttributes]), -+ [], [with_xattrs=maybe] -+ ) -+ -+ AC_CHECK_HEADERS([attr/xattr.h]) -+ 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 -+]) -diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 -index 837538e..428ad04 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]) -@@ -719,6 +726,9 @@ AC_DEFUN([gl_INIT], - gl_UNISTD_MODULE_INDICATOR([write]) - # Code from module xalloc: - gl_XALLOC -+ AC_CHECK_HEADERS([attr/xattr.h]) -+ AC_LIBOBJ([xattr-at]) -+ gl_HEADERS_ATTR_XATTR_H - # Code from module xalloc-die: - # Code from module xgetcwd: - gl_XGETCWD -@@ -875,10 +885,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 +942,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 +970,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 +1099,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 -@@ -1162,6 +1183,8 @@ AC_DEFUN([gl_FILE_LIST], [ - lib/xalloc-die.c - lib/xalloc.h - lib/xasprintf.c -+ lib/xattr-at.c -+ lib/xattr-at.h - lib/xgetcwd.c - lib/xgetcwd.h - lib/xmalloc.c -@@ -1176,9 +1199,11 @@ 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 -+ m4/attr-xattr-h.m4 - m4/backupfile.m4 - m4/bison.m4 - m4/btowc.m4 -@@ -1314,6 +1339,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.7.11.4 - diff --git a/tar-1.26-xattrs.patch b/tar-1.26-xattrs.patch deleted file mode 100644 index 17ef8e2..0000000 --- a/tar-1.26-xattrs.patch +++ /dev/null @@ -1,3061 +0,0 @@ -From f661d5c38ec585f364e47a981ebada092936d38a Mon Sep 17 00:00:00 2001 -From: Pavel Raiskup -Date: Tue, 14 Aug 2012 17:00:30 +0200 -Subject: [PATCH] Adding support for extended attributes (including listing - feature) - ---- - Makefile.am | 2 +- - configure.ac | 24 ++ - doc/tar.texi | 281 +++++++++++++++++- - src/Makefile.am | 7 +- - src/common.h | 29 +- - src/create.c | 55 +++- - src/extract.c | 142 ++++++++- - src/list.c | 11 +- - src/tar.c | 95 +++++- - src/tar.h | 23 +- - src/warning.c | 4 +- - src/xattrs.c | 705 ++++++++++++++++++++++++++++++++++++++++++++ - src/xattrs.h | 52 ++++ - src/xheader.c | 236 ++++++++++++--- - tests/Makefile.am | 11 +- - tests/testsuite.at | 85 +++++- - tests/xattr/acls01.at | 53 ++++ - tests/xattr/acls02.at | 59 ++++ - tests/xattr/capabs_raw01.at | 51 ++++ - tests/xattr/selacl01.at | 64 ++++ - tests/xattr/selnx01.at | 96 ++++++ - tests/xattr/xattr01.at | 47 +++ - tests/xattr/xattr02.at | 55 ++++ - tests/xattr/xattr03.at | 56 ++++ - tests/xattr/xattr04.at | 48 +++ - 25 files changed, 2228 insertions(+), 63 deletions(-) - create mode 100644 src/xattrs.c - create mode 100644 src/xattrs.h - create mode 100644 tests/xattr/acls01.at - create mode 100644 tests/xattr/acls02.at - create mode 100644 tests/xattr/capabs_raw01.at - create mode 100644 tests/xattr/selacl01.at - create mode 100644 tests/xattr/selnx01.at - create mode 100644 tests/xattr/xattr01.at - create mode 100644 tests/xattr/xattr02.at - create mode 100644 tests/xattr/xattr03.at - create mode 100644 tests/xattr/xattr04.at - -diff --git a/Makefile.am b/Makefile.am -index af332d7..67ba39b 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1,7 +1,7 @@ - # Main Makefile for GNU tar. - - # Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2007, --# 2009 Free Software Foundation, Inc. -+# 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 -diff --git a/configure.ac b/configure.ac -index db69cb8..4aecee3 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 -@@ -91,6 +114,7 @@ gl_INIT - tar_PAXUTILS - - 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/doc/tar.texi b/doc/tar.texi -index d70d113..567745b 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, 2012 -+Free Software Foundation, Inc. - - @quotation - Permission is granted to copy, distribute and/or modify this document -@@ -162,6 +163,7 @@ How to Create Archives - How to List Archives - - * list dir:: -+* List Extended Attributes:: - - How to Extract Members from an Archive - -@@ -1492,6 +1494,7 @@ for a detailed discussion of globbing patterns and related - - @menu - * list dir:: -+* List Extended Attributes:: - @end menu - - @node list dir -@@ -1522,6 +1525,116 @@ drwxrwxrwx myself/user 0 1990-05-31 21:49 practice/ - When you use a directory name as a file name argument, @command{tar} acts on - all the files (including sub-directories) in that directory. - -+@node List Extended Attributes -+@unnumberedsubsec Listing xattrs, POSIX ACLs and SELinux context -+ -+From upstream GNU tar 1.26.9, tar is able to store, extract and list extended -+file attributes. Listing of those attributes is then active only in verbose and -+double-verbose mode. -+ -+This section exercises how to list attributes on examples. Lets start with -+simple verbose mode. This output is inspired by GNU @command{ls -l} command -+output. -+ -+@itemize @bullet -+@item -+Show only pure extended attributes. -+ -+@smallexample -+$ tar --xattrs --list -v archive.tar -+-rw-rwxr-- user/group 0 2012-08-08 15:15 acls.txt -+-rw-rw-r--* user/group 0 2012-08-08 15:15 xattrs.txt -+@end smallexample -+ -+Note the asterisk on the third line! It reflects the situation that the file -+'xattrs.txt' has some extended attribute set. The default mode (same as if you -+are extracting extended attributes) shows information only about extended -+attributes from 'user.*' domain. Anyway, feel free to change the sensitivity -+using @option{--xattrs-include} or @option{--xattrs-exclude} options. -+ -+@item Show only POSIX ACLs - the character you should look for is '+': -+ -+@smallexample -+$ tar --acls --list -v archive.tar -+-rw-rwxr--+ praiskup/praiskup 0 2012-08-08 15:15 acls.txt -+-rw-rw-r-- praiskup/praiskup 0 2012-08-08 15:15 xattrs.txt -+@end smallexample -+ -+@item Show only SELinux - the key character is '.': -+ -+@smallexample -+$ tar --selinux --list -v archive.tar -+-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:16 selinux_only.txt -+-rw-rw-r-- praiskup/praiskup 0 2012-08-08 15:15 xattrs.txt -+@end smallexample -+ -+@item -+Show info about ACLs, SELinux and general extended attributes together: -+ -+@smallexample -+$ tar --selinux --acls --xattrs --list -v archive.tar -+-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:16 selinux_only.txt -+-rw-rwxr--+ praiskup/praiskup 0 2012-08-08 15:15 acls.txt -+-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:15 xattrs.txt -+@end smallexample -+ -+In this case, the priority of character is '+' > '.' > '*'. You don't see the -+general extended attributes flag ('*' character) on this example because it is -+hidden by '.' (meaning that the file has SELinux context set). -+ -+@end itemize -+ -+The example of double verbose mode is here. In this output the single verbose -+characters '.', '+' and '*' are also present after the permission string. -+ -+@smallexample -+$ tar --xattrs --selinux --acls -tvvf archive.tar -+-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:16 selinux_only.txt -+ s: unconfined_u:object_r:user_tmp_t:s0 -+-rw-rwxr--+ praiskup/praiskup 0 2012-08-08 15:15 acls.txt -+ s: unconfined_u:object_r:user_tmp_t:s0 -+ a: user::rw-,user:tester:rwx,group::rw-,mask::rwx,other::r-- -+-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:15 xattrs.txt -+ s: unconfined_u:object_r:user_tmp_t:s0 -+ x: 12 user.xattr -+ x: 12 user.we_like_tar -+@end smallexample -+ -+This mode extends tar's output with additional lines beginning with -+distinguishing characters - 's' for SELinux context, 'a' for POSIX Access -+Control Lists and 'x' for generic extended attributes. -+ -+In this format, POSIX ACLs are written in SHORT TEXT FORM as specified in manual -+page @command{man 5 acl}. -+ -+Use the @option{--xattrs-include} again if you want to print other than default -+'user.*' extended attributes domain: -+ -+@smallexample -+$ tar --xattrs --xattrs-include='*' --acls --selinux -tvvf archive.tar -+-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:16 selinux_only.txt -+ s: unconfined_u:object_r:user_tmp_t:s0 -+ x: 36 security.selinux -+-rw-rwxr--+ praiskup/praiskup 0 2012-08-08 15:15 acls.txt -+ s: unconfined_u:object_r:user_tmp_t:s0 -+ a: user::rw-,user:tester:rwx,group::rw-,mask::rwx,other::r-- -+ x: 36 security.selinux -+ x: 44 system.posix_acl_access -+-rw-rw-r--. praiskup/praiskup 0 2012-08-08 15:15 xattrs.txt -+ s: unconfined_u:object_r:user_tmp_t:s0 -+ x: 36 security.selinux -+ x: 12 user.xattr -+ x: 12 user.we_like_tar -+@end smallexample -+ -+As is in @pxref{Option Summary} section described, tar by default stores all -+extended attributes that are available (not only 'user.*' domain). It means -+that the SELinux context and POSIX ACLs (because they are implemented using the -+generic extended attributes on usual file system) may be stored twice sometimes -+-- firstly in "raw" file system binary format and secondly in more portable way -+-- using appropriate system calls (invoked by @command{tar} options -+@option{--selinux} and @option{--acls}). -+ - @node extract - @section How to Extract Members from an Archive - @cindex Extraction -@@ -2369,6 +2482,10 @@ Normally when creating an archive, @command{tar} strips an initial - @samp{/} from member names. This option disables that behavior. - @xref{absolute}. - -+@opsummary{acls} -+@item --acls -+Causes @command{tar} to store/restore/list POSIX ACL's. @xref{Attributes}. -+ - @opsummary{after-date} - @item --after-date - -@@ -2914,6 +3031,11 @@ contents have changed (as opposed to just @option{--newer}, which will - also back up files for which any status information has - changed). @xref{after}. - -+@opsummary{no-acls} -+@item --no-acls -+Causes @command{tar} not to store, extract or list POSIX ACL's. -+@xref{Attributes}. -+ - @opsummary{no-anchored} - @item --no-anchored - An exclude pattern can match any subsequence of the name's components. -@@ -2997,11 +3119,20 @@ locations. Usually @command{tar} determines automatically whether - the archive can be seeked or not. Use this option to disable this - mechanism. - -+@opsummary{no-selinux} -+@item --no-selinux -+Causes @command{tar} not to store, extract or list SELinux security context. -+@xref{Attributes}. -+ - @opsummary{no-unquote} - @item --no-unquote - Treat all input file or member names literally, do not interpret - escape sequences. @xref{input name quoting}. - -+@opsummary{no-xattrs} -+@item --no-xattrs -+Causes @command{tar} not to store, extract or list xattrs. @xref{Attributes}. -+ - @opsummary{no-wildcards} - @item --no-wildcards - Do not use wildcards. -@@ -3234,6 +3365,11 @@ in cases when such recognition fails. It takes effect only if the - archive is open for reading (e.g. with @option{--list} or - @option{--extract} options). - -+@opsummary{selinux} -+@item --selinux -+Causes @command{tar} to store, extract or list SELinux security context. -+@xref{Attributes}. -+ - @opsummary{show-defaults} - @item --show-defaults - -@@ -3447,6 +3583,11 @@ Enable or disable warning messages identified by @var{keyword}. The - messages are suppressed if @var{keyword} is prefixed with @samp{no-}. - @xref{warnings}. - -+@opsummary{xattrs} -+@item --xattrs -+Causes @command{tar} to store, restore or list extended file attributes. For -+more info see @xref{Attributes}. -+ - @opsummary{wildcards} - @item --wildcards - Use wildcards when matching member names with patterns. -@@ -4182,6 +4323,11 @@ tar (child): trying gzip - This means that @command{tar} first tried to decompress - @file{archive.Z} using @command{compress}, and, when that - failed, switched to @command{gzip}. -+@kwindex xattr-write -+@item xattr-write -+@samp{%s: Cannot set '%s' extended attribute for file '%s'} -+@*@samp{%s: Cannot set POSIX ACLs for file '%s'} -+@*@samp{%s: Cannot set SELinux context for file '%s'} - @end table - - @subheading Keywords controlling incremental extraction: -@@ -8659,6 +8805,8 @@ implementation able to read @samp{ustar} archives will be able to read - most @samp{posix} archives as well, with the only exception that any - additional information (such as long file names etc.) will in such - case be extracted as plain text files along with the files it refers to. -+This is the only format that can store ACLs, SELinux context and extended -+attributes. - - This archive format will be the default format for future versions - of @GNUTAR{}. -@@ -9293,6 +9441,135 @@ Same as both @option{--same-permissions} and @option{--same-order}. - - This option is deprecated, and will be removed in @GNUTAR{} version 1.23. - -+@opindex xattrs -+@item --xattrs -+This option causes @command{tar} to store, restore or list the extended file -+attributes (for information about extended attributes see @command{man(5) -+attr}). -+ -+Note that all extended attributes are stored "as-is" (in file system binary -+format) and the resulting archive may be not fully portable. See the -+@option{--selinux} and @option{--acls} options when you want to deal with these -+types of extended attributes in a better way. -+ -+The @option{--xattrs} option implies the option @option{--format=posix} when -+tar is in @option{--create} operation mode. It is the only one format which -+has usable headers for storing additional file information like extended -+attributes are. -+ -+By default, all extended attributes are stored into the archive. The reason is -+that we want to make the backup process as complete as possible by default. On -+the other hand, during extracting only the 'user.*' domain is extracted by -+default. Anyway, this default behaviour may be easily modified by the -+@option{--xattrs-include} and @option{--xattrs-exclude} options. -+ -+When you list an archive in verbose mode -+(@command{tar --xattrs --verbose -tf archive.tar}), tar shows the '*' character -+after the permissions string of concrete file right to tell you that at least -+one extended attribute is stored with corresponding file. -+ -+Double verbose mode (@command{tar --xattrs -tvvf archive.tar}) prints the -+extended attribute length (in bytes) and its ASCII key (for printed examples -+@pxref{List Extended Attributes}). -+ -+@option{--xattrs} option has no equivalent short option. -+ -+Warnings which occur during impossible writing of extended attributes to -+a file system may be suppressed using the @option{--warning=no-xattr-write} -+option. -+ -+@opindex no-xattrs -+@item --no-xattrs -+This option causes @command{tar} not to store/extract or list the current -+extended attributes. This option does not affect options @option{--no-selinux} -+or @option{--no-acls}. -+ -+The @option{--no-xattrs} option has no equivalent short option name. -+ -+@opindex xattrs-include -+@opindex xattrs-exclude -+@item --xattrs-include=MASK -+@itemx --xattrs-exclude=MASK -+ -+These options allows the xattr store/restore/list process to be more fine -+grained. The default configuration is that @option{--create} mode handles all -+available extended attributes and the @option{--extract}/@option{--list} mode -+handles only 'user.*' domain. These options may be used for editing of this -+default behaviour. -+ -+@itemize @bullet -+@item -+Lets say we want to store all attributes except some "public restricted" domain -+(e.g. 'user.restricted.*' domain. The correct way how to do it is: -+ -+@command{tar --xattrs --xattrs-include='*' --xattrs-exclude='user.restricted.*' -+-cf archive.tar FILES} -+@item -+And, when we want to extract only some specific domain from an archive - we can -+use: -+ -+@command{tar --xattrs --xattrs-include='security.capability' -xf archive.tar -+FILES} -+@end itemize -+ -+Multiple passed include/exclude patterns are combined together. The attribute -+is covered then only if (1) at least one of all include patterns matches its -+keyword and (2) no exclude pattern matches its keyword. -+ -+When only include pattern is set - exclude pattern is left in default mode (and -+vice versa). -+ -+@opindex selinux -+@item --selinux -+This option causes @command{tar} to store/extract/list the SELinux context -+information into/from an archive. Command @command{tar} is able to show info -+whether the SELinux context is present in archived file using the verbose -+listing mode (@command{tar --selinux -tvf archive.tar}). It shows the '.' -+character after permission string in that case. Double-verbose listing mode -+(@command{tar -tvvf archive.tar}) then prints the full SELinux context to -+standard output, @pxref{List Extended Attributes} for printed example. -+ -+This option implies the @option{--format=posix} when @command{tar} works in -+@option{--create} operation mode. -+ -+Warnings complaining that SELinux context may not be written to a file system -+may be suppressed by the @option{--warning=no-xattr-write} option. -+ -+The @option{--selinux} option has no equivalent short option name. -+ -+@opindex no-selinux -+@item --no-selinux -+This option causes @command{tar} not to store the current SELinux security -+context information in the archive and not to extract any SELinux information in -+an archive. -+ -+The @option{--no-selinux} option has no equivalent short option name. -+ -+@opindex acls -+@item --acls -+This option causes @command{tar} to store the current POSIX access control lists -+into the archive or restore POSIX ACLs from an archive. It also allows -+@command{tar} to show whether archived file contains ACLs when the verbose mode -+is active (@option{tar --acls -tvf} shows the symbol '+' after the permission -+characters in that case). Double-verbose mode allows @command{tar} to list -+contained POSIX ACLs (@command{tar --acls -tvvf archive.tar}), for printed -+examples @pxref{List Extended Attributes}. -+ -+This option implies the @option{--format=posix} when @command{tar} works in -+@option{--create} operation mode. -+ -+Warnings complaining that POSIX ACLs may not be written to a file system may be -+suppressed by the @option{--warning=no-xattr-write} option. -+ -+The @option{--acls} option has no equivalent short form. -+ -+@opindex no-acls -+@item --no-acls -+This option causes @command{tar} not to store the current POSIX ACL into the -+archive and not to extract any POSIX ACL information from an archive. -+ -+The @option{--no-acls} option has no equivalent short option name. -+ - @end table - - @node Portability -@@ -9441,7 +9718,7 @@ tar: ./one: Cannot hard link to `./jeden': No such file or directory - tar: Error exit delayed from previous errors - @end smallexample - --The reason for this behavior is that @command{tar} cannot seek back in -+The reason for this behaviour is that @command{tar} cannot seek back in - the archive to the previous member (in this case, @file{one}), to - extract it@footnote{There are plans to fix this in future releases.}. - If you wish to avoid such problems at the cost of a bigger archive, -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 0b9bd7a..4cf1459 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; - -@@ -253,6 +258,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; -@@ -707,6 +721,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); -@@ -727,6 +744,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 */ - -@@ -808,6 +831,8 @@ void checkpoint_run (bool do_write); - #define WARN_XDEV 0x00040000 - #define WARN_DECOMPRESS_PROGRAM 0x00080000 - -+#define WARN_XATTR_WRITE 0x00200000 -+ - /* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default - in verbose mode */ - #define WARN_VERBOSE_WARNINGS (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY|\ -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 aaea56e..8a7a6ad 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)) -@@ -673,6 +730,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 -@@ -733,12 +824,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); - } - } -@@ -854,7 +956,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; -@@ -864,6 +967,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; -@@ -934,6 +1041,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; - -@@ -950,8 +1059,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); -@@ -1091,6 +1210,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; -@@ -1525,6 +1651,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; -@@ -1539,6 +1672,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 7b62996..0ed1717 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, -@@ -340,7 +346,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; -@@ -525,6 +534,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 }, -@@ -2082,6 +2113,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; -@@ -2459,11 +2522,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; -@@ -2672,6 +2750,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) -@@ -2716,11 +2795,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 5d1bcab..b0b9884 100644 ---- a/src/warning.c -+++ b/src/warning.c -@@ -42,6 +42,7 @@ static char const *const warning_args[] = { - "unknown-keyword", - "xdev", - "decompress-program", -+ "xattr-write", - NULL - }; - -@@ -66,7 +67,8 @@ static int warning_types[] = { - WARN_UNKNOWN_CAST, - WARN_UNKNOWN_KEYWORD, - WARN_XDEV, -- WARN_DECOMPRESS_PROGRAM -+ WARN_DECOMPRESS_PROGRAM, -+ 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..6e26ace ---- /dev/null -+++ b/src/xattrs.c -@@ -0,0 +1,705 @@ -+/* 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 "common.h" -+ -+#include "selinux-at.h" -+#include "xattr-at.h" -+ -+/* 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 -+ -+struct xattrs_mask_map -+{ -+ const char **masks; -+ int size; -+ int used; -+}; -+ -+/* list of fnmatch patterns */ -+static struct -+{ -+ /* lists of fnmatch patterns */ -+ struct xattrs_mask_map incl; -+ struct xattrs_mask_map excl; -+} xattrs_setup; -+ -+#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) -+{ -+ ptr += strcspn (ptr, ":,\n"); /* skip tag name. Ie. user/group/default/mask */ -+ -+ if (*ptr != ':') -+ return (ptr); /* error? no user/group field */ -+ ++ptr; -+ -+ ptr += strcspn (ptr, ":,\n"); /* skip user/group name */ -+ -+ if (*ptr != ':') -+ return (ptr); /* error? no perms field */ -+ ++ptr; -+ -+ ptr += strcspn (ptr, ":,\n"); /* skip perms */ -+ -+ if (*ptr != ':') -+ return (ptr); /* no extra fields */ -+ -+ 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. -+ We just skip all extra fields atm. */ -+static const char *fixup_extra_acl_fields (const char *ptr) -+{ -+ char *src = (char *)ptr; -+ char *dst = (char *)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; -+} -+ -+static void xattrs__acls_set (struct tar_stat_info const *st, -+ char const *file_name, int type, -+ const char *ptr, size_t len, bool def) -+{ /* "system.posix_acl_access" */ -+ 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 == (acl_t)NULL) -+ { -+ 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) -+{ /* "system.posix_acl_access" */ -+ char *val = NULL; -+ ssize_t len; -+ acl_t acl; -+ -+ if ((acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_ACCESS)) -+ == (acl_t)NULL) -+ { -+ if (errno != ENOTSUP) -+ call_arg_warn ("acl_get_file_at", file_name); -+ return; -+ } -+ -+ val = acl_to_text (acl, &len); -+ acl_free (acl); -+ -+ if (val == NULL) -+ { -+ call_arg_warn ("acl_to_text", file_name); -+ return; -+ } -+ -+ *ret_ptr = xstrdup (val); -+ *ret_len = len; -+ -+ acl_free (val); -+} -+ -+static void xattrs__acls_get_d (int parentfd, char const *file_name, -+ struct tar_stat_info *st, -+ char **ret_ptr, size_t *ret_len) -+{ /* "system.posix_acl_default" */ -+ char *val = NULL; -+ ssize_t len; -+ acl_t acl; -+ -+ if ((acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_DEFAULT)) -+ == (acl_t)NULL) -+ { -+ if (errno != ENOTSUP) -+ call_arg_warn ("acl_get_file_at", file_name); -+ return; -+ } -+ -+ val = acl_to_text (acl, &len); -+ acl_free (acl); -+ -+ if (val == NULL) -+ { -+ 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 mask_map_realloc (struct xattrs_mask_map *map) -+{ -+ if (map->size == 0) -+ { -+ map->size = 4; -+ map->masks = xmalloc (16 * sizeof (char *)); -+ return; -+ } -+ -+ if (map->size <= map->used) -+ { -+ map->size *= 2; -+ map->masks = xrealloc (map->masks, map->size * sizeof (char *)); -+ return; -+ } -+} -+ -+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); -+} -+ -+void xattrs_acls_get (int parentfd, char const *file_name, -+ struct tar_stat_info *st, int fd, int xisfile) -+{ -+ int err; -+ 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 -+ 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 -+ } -+} -+ -+/* 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 ssize_t xsz = 1024; -+ static char *xatrs = NULL; -+ ssize_t xret = -1; -+ -+ if (!xatrs) xatrs = xmalloc (xsz); -+ -+ while (((fd == 0) ? -+ ((xret = llistxattrat (parentfd, file_name, xatrs, xsz)) == -1) : -+ ((xret = flistxattr (fd, xatrs, xsz)) == -1)) && -+ (errno == ERANGE)) -+ { -+ xsz <<= 1; -+ xatrs = xrealloc (xatrs, xsz); -+ } -+ -+ if (xret == -1) -+ call_arg_warn ((fd == 0) ? "llistxattrat" : "flistxattr", file_name); -+ else -+ { -+ const char *attr = xatrs; -+ static ssize_t asz = 1024; -+ static char *val = NULL; -+ -+ if (!val) val = xmalloc (asz); -+ -+ 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)) -+ { -+ asz <<= 1; -+ val = xrealloc (val, asz); -+ } -+ -+ 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)); -+ } -+} -+ -+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 -+ } -+} -+ -+/* 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; -+} -+ -+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.", strlen ("user.")) == 0; -+ } -+} -+ -+static bool xattrs_kw_excluded (const char *kw, bool archiving) -+{ -+ if (!xattrs_setup.excl.size) -+ return false; -+ -+ return xattrs_matches_mask (kw, &xattrs_setup.excl); -+} -+ -+/* 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) -+{ -+ if (!xattrs_kw_included (kw, archiving)) -+ return true; -+ -+ return xattrs_kw_excluded (kw, archiving); -+} -+ -+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; -+ obstack_init (&stk); -+ int pref_len = strlen (prefix); -+ const char *oldstring = aclstring; -+ -+ if (!aclstring || !len) -+ return; -+ -+ int pos = 0; -+ 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'); -+ const char *toprint = obstack_finish (&stk); -+ -+ fprintf (stdlis, "%s", toprint); -+ -+ obstack_free (&stk, NULL); -+} -+ -+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 */ )) -+ continue; -+ *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 */ )) -+ continue; -+ fprintf (stdlis, " x: %lu %s\n", st->xattr_map[i].xval_len, keyword); -+ } -+ } -+} -diff --git a/src/xattrs.h b/src/xattrs.h -new file mode 100644 -index 0000000..0c08cd7 ---- /dev/null -+++ b/src/xattrs.h -@@ -0,0 +1,52 @@ -+#ifndef GUARD_XATTTRS_H -+#define GUARD_XATTTRS_H -+ -+/* 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. -+*/ -+ -+ -+/* 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..666297d 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 -@@ -448,7 +448,7 @@ xheader_write_global (struct xheader *xhdr) - - xheader_init (xhdr); - for (kp = keyword_global_override_list; kp; kp = kp->next) -- code_string (kp->value, kp->pattern, xhdr); -+ code_string (kp->value, kp->pattern, xhdr); - } - if (xhdr->stk) - { -@@ -460,6 +460,80 @@ 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; -+} -+ -+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 +547,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 +564,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 +584,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 +596,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; - } -@@ -1470,6 +1556,71 @@ 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 = NULL; -+ -+ xstr = xmemdup(arg, size + 1); -+ xheader_xattr_add(st, keyword + strlen("SCHILY.xattr."), xstr, size); -+ free(xstr); -+} -+ -+static void - sparse_major_coder (struct tar_stat_info const *st, char const *keyword, - struct xheader *xhdr, void const *data) - { -@@ -1506,53 +1657,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 +1712,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 119f1f3..b3c24dc 100644 ---- a/tests/Makefile.am -+++ b/tests/Makefile.am -@@ -169,7 +169,16 @@ 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\ -+ xattr/xattr01.at\ -+ xattr/xattr02.at\ -+ xattr/xattr03.at\ -+ xattr/xattr04.at\ -+ xattr/acls01.at\ -+ xattr/acls02.at\ -+ xattr/selnx01.at\ -+ xattr/selacl01.at\ -+ xattr/capabs_raw01.at - - TESTSUITE = $(srcdir)/testsuite - -diff --git a/tests/testsuite.at b/tests/testsuite.at -index 13f7506..3f02a52 100644 ---- a/tests/testsuite.at -+++ b/tests/testsuite.at -@@ -93,16 +93,81 @@ m4_define([AT_SORT_PREREQ],[ - test -z "`sort < /dev/null 2>&1`" || AT_SKIP_TEST - ]) - --dnl AT_UNPRIVILEGED_PREREQ - Skip test if running at root privileges --m4_define([AT_UNPRIVILEGED_PREREQ],[ -+m4_define([AT_IS_PRIVILEGED],[ - echo "test" > $[]$ - chmod 0 $[]$ - cat $[]$ > /dev/null 2>&1 - result=$? - rm -f $[]$ --test $result -eq 0 && AT_SKIP_TEST -+test $result -eq 0]) -+ -+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 - ]) - -+dnl AT_UNPRIVILEGED_PREREQ - Skip test if running at root privileges -+m4_append([AT_UNPRIVILEGED_PREREQ],[AT_IS_PRIVILEGED]) -+m4_append([AT_UNPRIVILEGED_PREREQ],[&& AT_SKIP_TEST]) -+ -+dnl AT_UNPRIVILEGED_PREREQ - Skip test if running at non-root privileges -+m4_append([AT_PRIVILEGED_PREREQ],[ AT_IS_PRIVILEGED ]) -+m4_append([AT_PRIVILEGED_PREREQ],[ || 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]) -@@ -270,3 +335,17 @@ m4_include([star/ustar-big-2g.at]) - m4_include([star/ustar-big-8g.at]) - - m4_include([star/pax-big-10g.at]) -+ -+m4_include([xattr/xattr01.at]) -+m4_include([xattr/xattr02.at]) -+m4_include([xattr/xattr03.at]) -+m4_include([xattr/xattr04.at]) -+ -+m4_include([xattr/acls01.at]) -+m4_include([xattr/acls02.at]) -+ -+m4_include([xattr/selnx01.at]) -+ -+m4_include([xattr/selacl01.at]) -+ -+m4_include([xattr/capabs_raw01.at]) -diff --git a/tests/xattr/acls01.at b/tests/xattr/acls01.at -new file mode 100644 -index 0000000..0149f2d ---- /dev/null -+++ b/tests/xattr/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/xattr/acls02.at b/tests/xattr/acls02.at -new file mode 100644 -index 0000000..2ee1c5f ---- /dev/null -+++ b/tests/xattr/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/xattr/capabs_raw01.at b/tests/xattr/capabs_raw01.at -new file mode 100644 -index 0000000..8eea0cf ---- /dev/null -+++ b/tests/xattr/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/xattr/selacl01.at b/tests/xattr/selacl01.at -new file mode 100644 -index 0000000..90d0c5b ---- /dev/null -+++ b/tests/xattr/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/xattr/selnx01.at b/tests/xattr/selnx01.at -new file mode 100644 -index 0000000..79f7267 ---- /dev/null -+++ b/tests/xattr/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/xattr/xattr01.at b/tests/xattr/xattr01.at -new file mode 100644 -index 0000000..fd960d5 ---- /dev/null -+++ b/tests/xattr/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/xattr/xattr02.at b/tests/xattr/xattr02.at -new file mode 100644 -index 0000000..3aae3f9 ---- /dev/null -+++ b/tests/xattr/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/xattr/xattr03.at b/tests/xattr/xattr03.at -new file mode 100644 -index 0000000..d834f9f ---- /dev/null -+++ b/tests/xattr/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/xattr/xattr04.at b/tests/xattr/xattr04.at -new file mode 100644 -index 0000000..31832af ---- /dev/null -+++ b/tests/xattr/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 --- -1.7.11.2 - diff --git a/tar-sigpipe.patch b/tar-sigpipe.patch deleted file mode 100644 index a4813f2..0000000 --- a/tar-sigpipe.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -urNp tar-1.24-orig/tests/testsuite.at tar-1.24/tests/testsuite.at ---- tar-1.24-orig/tests/testsuite.at 2010-10-27 18:00:59.792862595 +0200 -+++ tar-1.24/tests/testsuite.at 2010-10-27 18:02:06.441873697 +0200 -@@ -245,7 +245,7 @@ m4_include([remfiles01.at]) - m4_include([remfiles02.at]) - m4_include([remfiles03.at]) - --m4_include([sigpipe.at]) -+dnl m4_include([sigpipe.at]) - - m4_include([star/gtarfail.at]) - m4_include([star/gtarfail2.at]) diff --git a/tar.spec b/tar.spec index e3b1b01..07ff853 100644 --- a/tar.spec +++ b/tar.spec @@ -9,38 +9,58 @@ Release: 17%{?dist} License: GPLv3+ Group: Applications/Archiving URL: http://www.gnu.org/software/tar/ + Source0: ftp://ftp.gnu.org/pub/gnu/tar/tar-%{version}.tar.xz Source1: ftp://ftp.gnu.org/pub/gnu/tar/tar-%{version}.tar.xz.sig -#Manpage for tar and gtar, a bit modified help2man generated manpage +# Manpage for tar and gtar, a bit modified help2man generated manpage Source2: tar.1 -#Stop issuing lone zero block warnings + +# Stop issuing lone zero block warnings. +# ~> https://bugzilla.redhat.com/show_bug.cgi?id=135601 +# ~> downstream Patch1: tar-1.14-loneZeroWarning.patch -#Fix extracting sparse files to a filesystem like vfat, -#when ftruncate may fail to grow the size of a file.(#179507) + +# Fix extracting sparse files to a file system like vfat, when ftruncate may fail +# to grow the size of a file. +# ~> #179507, +# ~> http://lists.gnu.org/archive/html/bug-tar/2006-02/msg00000.html +# ~> still downtream (do we need this now? ftruncate & vfat works is now OK) Patch2: tar-1.15.1-vfatTruncate.patch -#change inclusion defaults of tar to "--wildcards --anchored -#--wildcards-match-slash" for compatibility reasons (#206841) -#Add support for selinux, acl and extended attributes -#Patch3: tar-1.24-xattrs.patch -Patch4: tar-1.17-wildcards.patch -#ignore errors from setting utime() for source file -#on read-only filesystem (#500742) -Patch5: tar-1.22-atime-rofs.patch -#oldarchive option was not working(#594044) -Patch6: tar-1.23-oldarchive.patch -#temporarily disable sigpipe.at patch (fails at build in koji, passes manually) -Patch7: tar-sigpipe.patch -#partially revert upstream commit 4bde4f3 (#717684) -Patch8: tar-1.24-openat-partial-revert.patch -# fix for bad cooperation of -C and -u options (#688567) -Patch9: tar-1.26-update-with-change-directory.patch -# fix rawhide buildfailure with undefined gets -Patch10: tar-1.26-stdio.in.patch -# Prepare gnulib for xattrs and apply xattrs & acls & selinux (#850291) -Patch11: tar-1.26-xattrs-gnulib-prepare.patch -Patch12: tar-1.26-xattrs.patch -# fix regression with --keep-old-files option (#799252) -Patch13: tar-1.26-add-skip-old-files-option.patch + +# Change inclusion defaults of tar to +# "--wildcards --anchored --wildcards-match-slash" for compatibility reasons. +# ~> #206841 +# ~> downstream (compatibility) +Patch3: tar-1.17-wildcards.patch + +# Ignore errors from setting utime() for source file on read-only file-system. +# ~> #500742 +# ~> http://lists.gnu.org/archive/html/bug-tar/2009-06/msg00016.html +# ~> still downstream +Patch4: tar-1.22-atime-rofs.patch + +# The --old-archive option was not working. +# ~> #594044 +# ~> http://lists.gnu.org/archive/html/bug-tar/2010-05/msg00015.html +# ~> upstream (2a61a37) +Patch5: tar-1.23-oldarchive.patch + +# Fix for bad cooperation of -C and -u options. +# ~> #688567 +# ~> http://lists.gnu.org/archive/html/bug-tar/2012-02/msg00007.html +# ~> still downstream +Patch6: tar-1.26-update-with-change-directory.patch + +# Fix rawhide build failure with undefined gets. +# ~> upstream (gnulib) +Patch7: tar-1.26-stdio.in.patch + +# Fix regression with --keep-old-files option. +# ~> #799252 +# ~> http://lists.gnu.org/archive/html/bug-tar/2011-11/msg00043.html +# ~> upstream (7a5a3708c) +Patch8: tar-1.26-add-skip-old-files-option.patch + # run "make check" by default %bcond_without check @@ -75,16 +95,12 @@ the rmt package. %setup -q %patch1 -p1 -b .loneZeroWarning %patch2 -p1 -b .vfatTruncate -%patch4 -p1 -b .wildcards -%patch5 -p1 -b .rofs -%patch6 -p1 -b .oldarchive -%patch7 -p1 -b .fail -%patch8 -p1 -b .openat -%patch9 -p1 -b .update_and_changedir -%patch10 -p1 -b .gets %{?_rawbuild} -%patch11 -p1 -b .xattrs_gnulib_prep -%patch12 -p1 -b .xattrs2 -%patch13 -p1 -b .skip-old-files +%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 autoreconf -v @@ -150,6 +166,10 @@ fi * Mon Feb 18 2013 Pavel Raiskup - 2:1.26-17 - add possibility to 'rpmbuild' without %%check phase - make the autoreconf phase verbose +- re-create older patches (avoid offset warnings during patching) +- remove patches which we don't need now (xattrs - will be updated, sigpipe - + test should work now, partial revert of *at() conversion was done because of + incompatible xattr patch) * Fri Feb 01 2013 Pavel Raiskup - 2:1.26-16 - make the info documentation more visible in manpage (#903666)