+++ /dev/null
---- tar-1.17/configure.xattrs 2007-06-08 10:36:00.000000000 +0200
-+++ tar-1.17/configure 2007-06-27 17:18:14.000000000 +0200
-@@ -514,19 +514,29 @@ else
- as_mkdir_p=false
- fi
-
--# Find out whether ``test -x'' works. Don't use a zero-byte file, as
--# systems may use methods other than mode bits to determine executability.
--cat >conf$$.file <<_ASEOF
--#! /bin/sh
--exit 0
--_ASEOF
--chmod +x conf$$.file
--if test -x conf$$.file >/dev/null 2>&1; then
-- as_executable_p="test -x"
-+if test -x / >/dev/null 2>&1; then
-+ as_test_x='test -x'
- else
-- as_executable_p=:
-+ if ls -dL / >/dev/null 2>&1; then
-+ as_ls_L_option=L
-+ else
-+ as_ls_L_option=
-+ fi
-+ as_test_x='
-+ eval sh -c '\''
-+ if test -d "$1"; then
-+ test -d "$1/.";
-+ else
-+ case $1 in
-+ -*)set "./$1";;
-+ esac;
-+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
-+ ???[sx]*):;;*)false;;esac;fi
-+ '\'' sh
-+ '
- fi
--rm -f conf$$.file
-+as_executable_p=$as_test_x
-+
-
- # Sed expression to map a string onto a valid CPP name.
- as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-@@ -1925,6 +1935,9 @@ ac_header_list="$ac_header_list sys/tpri
- ac_header_list="$ac_header_list sys/tape.h"
- ac_header_list="$ac_header_list unistd.h"
- ac_header_list="$ac_header_list locale.h"
-+ac_header_list="$ac_header_list selinux/selinux.h"
-+ac_header_list="$ac_header_list attr/xattr.h"
-+ac_header_list="$ac_header_list sys/acl.h"
- ac_func_list="$ac_func_list flockfile"
- ac_func_list="$ac_func_list funlockfile"
- ac_header_list="$ac_header_list features.h"
-@@ -34101,6 +34114,251 @@ _ACEOF
- fi
- done
-
-+
-+for ac_func in getxattr fgetxattr lgetxattr \
-+ setxattr fsetxattr lsetxattr \
-+ listxattr flistxattr llistxattr
-+do
-+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
-+ echo $ECHO_N "(cached) $ECHO_C" >&6
-+else
-+ cat >conftest.$ac_ext <<_ACEOF
-+/* confdefs.h. */
-+_ACEOF
-+cat confdefs.h >>conftest.$ac_ext
-+cat >>conftest.$ac_ext <<_ACEOF
-+/* end confdefs.h. */
-+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
-+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
-+#define $ac_func innocuous_$ac_func
-+
-+/* System header to define __stub macros and hopefully few prototypes,
-+ which can conflict with char $ac_func (); below.
-+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-+ <limits.h> exists even on freestanding compilers. */
-+
-+#ifdef __STDC__
-+# include <limits.h>
-+#else
-+# include <assert.h>
-+#endif
-+
-+#undef $ac_func
-+
-+/* Override any GCC internal prototype to avoid an error.
-+ Use char because int might match the return type of a GCC
-+ builtin and then its argument prototype would still apply. */
-+#ifdef __cplusplus
-+extern "C"
-+#endif
-+char $ac_func ();
-+/* The GNU C library defines this for functions which it implements
-+ to always fail with ENOSYS. Some functions are actually named
-+ something starting with __ and the normal name is an alias. */
-+#if defined __stub_$ac_func || defined __stub___$ac_func
-+choke me
-+#endif
-+
-+int
-+main ()
-+{
-+return $ac_func ();
-+ ;
-+ return 0;
-+}
-+_ACEOF
-+rm -f conftest.$ac_objext conftest$ac_exeext
-+if { (ac_try="$ac_link"
-+case "(($ac_try" in
-+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-+ *) ac_try_echo=$ac_try;;
-+esac
-+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-+ (eval "$ac_link") 2>conftest.er1
-+ ac_status=$?
-+ grep -v '^ *+' conftest.er1 >conftest.err
-+ rm -f conftest.er1
-+ cat conftest.err >&5
-+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
-+ (exit $ac_status); } && {
-+ test -z "$ac_c_werror_flag" ||
-+ test ! -s conftest.err
-+ } && test -s conftest$ac_exeext &&
-+ $as_test_x conftest$ac_exeext; then
-+ eval "$as_ac_var=yes"
-+else
-+ echo "$as_me: failed program was:" >&5
-+sed 's/^/| /' conftest.$ac_ext >&5
-+
-+ eval "$as_ac_var=no"
-+fi
-+
-+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-+ conftest$ac_exeext conftest.$ac_ext
-+fi
-+ac_res=`eval echo '${'$as_ac_var'}'`
-+ { echo "$as_me:$LINENO: result: $ac_res" >&5
-+echo "${ECHO_T}$ac_res" >&6; }
-+if test `eval echo '${'$as_ac_var'}'` = yes; then
-+ cat >>confdefs.h <<_ACEOF
-+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-+_ACEOF
-+
-+cat >>confdefs.h <<\_ACEOF
-+#define HAVE_XATTRS
-+_ACEOF
-+
-+fi
-+done
-+
-+
-+{ echo "$as_me:$LINENO: checking for getfilecon in -lselinux" >&5
-+echo $ECHO_N "checking for getfilecon in -lselinux... $ECHO_C" >&6; }
-+if test "${ac_cv_lib_selinux_getfilecon+set}" = set; then
-+ echo $ECHO_N "(cached) $ECHO_C" >&6
-+else
-+ ac_check_lib_save_LIBS=$LIBS
-+LIBS="-lselinux $LIBS"
-+cat >conftest.$ac_ext <<_ACEOF
-+/* confdefs.h. */
-+_ACEOF
-+cat confdefs.h >>conftest.$ac_ext
-+cat >>conftest.$ac_ext <<_ACEOF
-+/* end confdefs.h. */
-+
-+/* Override any GCC internal prototype to avoid an error.
-+ Use char because int might match the return type of a GCC
-+ builtin and then its argument prototype would still apply. */
-+#ifdef __cplusplus
-+extern "C"
-+#endif
-+char getfilecon ();
-+int
-+main ()
-+{
-+return getfilecon ();
-+ ;
-+ return 0;
-+}
-+_ACEOF
-+rm -f conftest.$ac_objext conftest$ac_exeext
-+if { (ac_try="$ac_link"
-+case "(($ac_try" in
-+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-+ *) ac_try_echo=$ac_try;;
-+esac
-+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-+ (eval "$ac_link") 2>conftest.er1
-+ ac_status=$?
-+ grep -v '^ *+' conftest.er1 >conftest.err
-+ rm -f conftest.er1
-+ cat conftest.err >&5
-+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
-+ (exit $ac_status); } && {
-+ test -z "$ac_c_werror_flag" ||
-+ test ! -s conftest.err
-+ } && test -s conftest$ac_exeext &&
-+ $as_test_x conftest$ac_exeext; then
-+ ac_cv_lib_selinux_getfilecon=yes
-+else
-+ echo "$as_me: failed program was:" >&5
-+sed 's/^/| /' conftest.$ac_ext >&5
-+
-+ ac_cv_lib_selinux_getfilecon=no
-+fi
-+
-+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-+ conftest$ac_exeext conftest.$ac_ext
-+LIBS=$ac_check_lib_save_LIBS
-+fi
-+{ echo "$as_me:$LINENO: result: $ac_cv_lib_selinux_getfilecon" >&5
-+echo "${ECHO_T}$ac_cv_lib_selinux_getfilecon" >&6; }
-+if test $ac_cv_lib_selinux_getfilecon = yes; then
-+ cat >>confdefs.h <<_ACEOF
-+#define HAVE_LIBSELINUX 1
-+_ACEOF
-+
-+ LIBS="-lselinux $LIBS"
-+
-+fi
-+
-+
-+{ echo "$as_me:$LINENO: checking for acl_get_fd in -lacl" >&5
-+echo $ECHO_N "checking for acl_get_fd in -lacl... $ECHO_C" >&6; }
-+if test "${ac_cv_lib_acl_acl_get_fd+set}" = set; then
-+ echo $ECHO_N "(cached) $ECHO_C" >&6
-+else
-+ ac_check_lib_save_LIBS=$LIBS
-+LIBS="-lacl $LIBS"
-+cat >conftest.$ac_ext <<_ACEOF
-+/* confdefs.h. */
-+_ACEOF
-+cat confdefs.h >>conftest.$ac_ext
-+cat >>conftest.$ac_ext <<_ACEOF
-+/* end confdefs.h. */
-+
-+/* Override any GCC internal prototype to avoid an error.
-+ Use char because int might match the return type of a GCC
-+ builtin and then its argument prototype would still apply. */
-+#ifdef __cplusplus
-+extern "C"
-+#endif
-+char acl_get_fd ();
-+int
-+main ()
-+{
-+return acl_get_fd ();
-+ ;
-+ return 0;
-+}
-+_ACEOF
-+rm -f conftest.$ac_objext conftest$ac_exeext
-+if { (ac_try="$ac_link"
-+case "(($ac_try" in
-+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-+ *) ac_try_echo=$ac_try;;
-+esac
-+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-+ (eval "$ac_link") 2>conftest.er1
-+ ac_status=$?
-+ grep -v '^ *+' conftest.er1 >conftest.err
-+ rm -f conftest.er1
-+ cat conftest.err >&5
-+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
-+ (exit $ac_status); } && {
-+ test -z "$ac_c_werror_flag" ||
-+ test ! -s conftest.err
-+ } && test -s conftest$ac_exeext &&
-+ $as_test_x conftest$ac_exeext; then
-+ ac_cv_lib_acl_acl_get_fd=yes
-+else
-+ echo "$as_me: failed program was:" >&5
-+sed 's/^/| /' conftest.$ac_ext >&5
-+
-+ ac_cv_lib_acl_acl_get_fd=no
-+fi
-+
-+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-+ conftest$ac_exeext conftest.$ac_ext
-+LIBS=$ac_check_lib_save_LIBS
-+fi
-+{ echo "$as_me:$LINENO: result: $ac_cv_lib_acl_acl_get_fd" >&5
-+echo "${ECHO_T}$ac_cv_lib_acl_acl_get_fd" >&6; }
-+if test $ac_cv_lib_acl_acl_get_fd = yes; then
-+ cat >>confdefs.h <<_ACEOF
-+#define HAVE_LIBACL 1
-+_ACEOF
-+
-+ LIBS="-lacl $LIBS"
-+
-+fi
-+
-+
-+
-+
- { echo "$as_me:$LINENO: checking whether getgrgid is declared" >&5
- echo $ECHO_N "checking whether getgrgid is declared... $ECHO_C" >&6; }
- if test "${ac_cv_have_decl_getgrgid+set}" = set; then
---- tar-1.17/configure.ac.xattrs 2007-06-08 10:28:04.000000000 +0200
-+++ tar-1.17/configure.ac 2007-06-27 17:10:56.000000000 +0200
-@@ -40,7 +40,7 @@ AC_CHECK_HEADERS_ONCE(fcntl.h linux/fd.h
- sys/param.h sys/device.h sys/filio.h sys/gentape.h \
- sys/inet.h sys/io/trioctl.h \
- sys/mtio.h sys/time.h sys/tprintf.h sys/tape.h \
-- unistd.h locale.h)
-+ unistd.h locale.h selinux/selinux.h attr/xattr.h sys/acl.h)
-
- AC_CHECK_HEADERS([sys/buf.h], [], [],
- [#if HAVE_SYS_PARAM_H
-@@ -88,6 +88,13 @@ gl_INIT
- tar_PAXUTILS
-
- AC_CHECK_FUNCS(fsync getdtablesize lstat mkfifo readlink strerror symlink setlocale utimes)
-+AC_CHECK_FUNCS(getxattr fgetxattr lgetxattr \
-+ setxattr fsetxattr lsetxattr \
-+ listxattr flistxattr llistxattr,
-+ AC_DEFINE(HAVE_XATTRS,,[Define if we have a working extended attributes]),)
-+AC_CHECK_LIB(selinux, getfilecon)
-+AC_CHECK_LIB(acl, acl_get_fd)
-+
- AC_CHECK_DECLS([getgrgid],,, [#include <grp.h>])
- AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
- AC_CHECK_DECLS([time],,, [#include <time.h>])
-@@ -203,6 +210,8 @@ AC_DEFINE_UNQUOTED(DEFAULT_QUOTING_STYLE
- # Iconv
- AM_ICONV
- AC_CHECK_HEADERS(iconv.h)
-+AC_CHECK_HEADERS(selinux/selinux.h)
-+AC_CHECK_HEADERS(attr/xattr.h)
- AC_CHECK_TYPE(iconv_t,:,
- AC_DEFINE(iconv_t, int,
- [Conversion descriptor type]),
---- tar-1.17/doc/tar.texi.xattrs 2007-06-08 10:25:19.000000000 +0200
-+++ tar-1.17/doc/tar.texi 2007-06-27 17:10:56.000000000 +0200
-@@ -7845,6 +7845,8 @@ implementation able to read @samp{ustar}
- 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{}.
-@@ -8333,6 +8335,51 @@ It is equivalent to @option{--same-permi
- @FIXME{I do not see the purpose of such an option. (Neither I. FP.)
- Neither do I. --Sergey}
-
-+@opindex acls
-+@item --acls
-+This option causes @command{tar} to store the current ACL in the archive.
-+
-+The @option{--acls} option has no equivalent short option name.
-+
-+@opindex selinux
-+@item --selinux
-+This option causes @command{tar} to store the current SELinux security context
-+information in the archive.
-+
-+The @option{--selinux} option has no equivalent short option name.
-+
-+@opindex xattrs
-+@item --xattrs
-+This option causes @command{tar} to store the current extended attributes in
-+the archive. This option also enables @option{--acls} and @option{--selinux} if
-+they haven't been set already.
-+
-+The @option{--xattrs} option has no equivalent short option name.
-+
-+@opindex no-acls
-+@item --no-acls
-+This option causes @command{tar} not to store the current ACL in the archive
-+and not to extract any ACL information in an archive.
-+
-+The @option{--acls} 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{--selinux} option has no equivalent short option name.
-+
-+@opindex xattrs
-+@item --xattrs
-+This option causes @command{tar} not to store the current extended attributes in
-+the archive and not to extract any extended attributes in an archive. This
-+option also enables @option{--acls} and @option{--selinux} if
-+they haven't been set already.
-+
-+The @option{--xattrs} option has no equivalent short option name.
-+
- @end table
-
- @node Portability
---- tar-1.17/src/Makefile.in.xattrs 2007-06-08 10:35:58.000000000 +0200
-+++ tar-1.17/src/Makefile.in 2007-06-27 17:11:28.000000000 +0200
-@@ -1,8 +1,8 @@
--# Makefile.in generated by automake 1.10a from Makefile.am.
-+# Makefile.in generated by automake 1.10 from Makefile.am.
- # @configure_input@
-
- # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
--# 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
-+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
- # This Makefile.in 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.
-@@ -22,9 +22,8 @@
-
- VPATH = @srcdir@
- pkgdatadir = $(datadir)/@PACKAGE@
--pkgincludedir = $(includedir)/@PACKAGE@
- pkglibdir = $(libdir)/@PACKAGE@
--pkglibexecdir = $(libexecdir)/@PACKAGE@
-+pkgincludedir = $(includedir)/@PACKAGE@
- am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
- install_sh_DATA = $(install_sh) -c -m 644
- install_sh_PROGRAM = $(install_sh) -c
-@@ -134,12 +133,13 @@ am_tar_OBJECTS = buffer.$(OBJEXT) compar
- incremen.$(OBJEXT) list.$(OBJEXT) misc.$(OBJEXT) \
- names.$(OBJEXT) sparse.$(OBJEXT) system.$(OBJEXT) \
- tar.$(OBJEXT) transform.$(OBJEXT) update.$(OBJEXT) \
-- utf8.$(OBJEXT)
-+ utf8.$(OBJEXT) xattrs.$(OBJEXT)
- tar_OBJECTS = $(am_tar_OBJECTS)
- am__DEPENDENCIES_1 =
- am__DEPENDENCIES_2 = ../lib/libtar.a $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
--tar_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-+tar_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
-+ $(am__DEPENDENCIES_1)
- DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
- depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
- am__depfiles_maybe = depfiles
-@@ -459,7 +459,7 @@ sysconfdir = @sysconfdir@
- target_alias = @target_alias@
- top_builddir = @top_builddir@
- top_srcdir = @top_srcdir@
--noinst_HEADERS = arith.h common.h tar.h
-+noinst_HEADERS = arith.h common.h tar.h xattrs.h
- tar_SOURCES = \
- buffer.c\
- compare.c\
-@@ -476,11 +476,12 @@ tar_SOURCES = \
- tar.c\
- transform.c\
- update.c\
-- utf8.c
-+ utf8.c\
-+ xattrs.c
-
- INCLUDES = -I$(top_srcdir)/lib -I../ -I../lib
- LDADD = ../lib/libtar.a $(LIBINTL) $(LIBICONV)
--tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
-+tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME)
- all: all-am
-
- .SUFFIXES:
-@@ -578,6 +579,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform.Po@am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update.Po@am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8.Po@am__quote@
-+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xattrs.Po@am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xheader.Po@am__quote@
-
- .c.o:
---- tar-1.17/src/common.h.xattrs 2007-06-08 10:14:42.000000000 +0200
-+++ tar-1.17/src/common.h 2007-06-27 17:10:56.000000000 +0200
-@@ -255,6 +255,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;
-@@ -666,6 +675,9 @@ extern char *output_start;
-
- void update_archive (void);
-
-+/* Module attrs.c. */
-+#include "xattrs.h"
-+
- /* Module xheader.c. */
-
- void xheader_init (struct xheader *xhdr);
-@@ -687,6 +699,12 @@ bool xheader_string_end (struct xheader
- 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 */
-
---- /dev/null 2007-06-25 09:32:25.472134050 +0200
-+++ tar-1.17/src/xattrs.c 2007-06-27 17:10:56.000000000 +0200
-@@ -0,0 +1,457 @@
-+/* Create a tar archive.
-+
-+ Copyright (C) 2006 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 <system.h>
-+
-+#include <quotearg.h>
-+
-+#include "common.h"
-+
-+
-+#ifndef HAVE_SELINUX_SELINUX_H
-+# undef HAVE_LIBSELINUX
-+#endif
-+
-+#ifndef HAVE_ATTR_XATTR_H
-+# undef HAVE_XATTRS
-+#endif
-+
-+#ifndef HAVE_SYS_ACL_H
-+# undef HAVE_LIBACL
-+#endif
-+
-+#ifdef HAVE_SELINUX_SELINUX_H
-+# include <selinux/selinux.h>
-+#endif
-+
-+#ifdef HAVE_ATTR_XATTR_H
-+# include <attr/xattr.h>
-+#endif
-+
-+#ifdef HAVE_SYS_ACL_H
-+# include <sys/acl.h>
-+#endif
-+
-+
-+#if 0 /* unused by xattr's atm. */
-+static void xattrs__fd_get(struct tar_stat_info *st,
-+ char const *file_name, int fd, const char *attr,
-+ char **ret_ptr, size_t *ret_len)
-+{
-+#ifdef HAVE_XATTRS
-+ static ssize_t asz = 1024;
-+ ssize_t ret = 0;
-+ static char *val = NULL;
-+
-+ if (!val) val = xmalloc (asz);
-+
-+ while (((ret = fgetxattr (fd, attr, val, asz)) == -1) &&
-+ (errno == ERANGE))
-+ {
-+ asz <<= 1;
-+ val = xrealloc (val, asz);
-+ }
-+
-+ if (ret != -1)
-+ {
-+ *ret_ptr = xmemdup (val, ret);
-+ *ret_len = ret;
-+ }
-+ else if (errno != ENOATTR)
-+ call_arg_warn ("fgetxattr", file_name);
-+#endif
-+}
-+#endif
-+
-+static void xattrs__acls_get_a(struct tar_stat_info *st,
-+ char const *file_name, int fd,
-+ char **ret_ptr, size_t *ret_len)
-+{ /* "system.posix_acl_access" */
-+#ifdef HAVE_LIBACL
-+ char *val = NULL;
-+ acl_t acl;
-+
-+ if (fd != -1)
-+ {
-+ if ((acl = acl_get_fd (fd)) == (acl_t)NULL)
-+ {
-+ if (errno != ENOTSUP)
-+ call_arg_warn ("acl_get_fd", file_name);
-+ return;
-+ }
-+ }
-+ else if ((acl = acl_get_file (file_name, ACL_TYPE_ACCESS)) == (acl_t)NULL)
-+ {
-+ if (errno != ENOTSUP)
-+ call_arg_warn ("acl_get_file", file_name);
-+ return;
-+ }
-+
-+
-+ val = acl_to_text(acl, NULL);
-+ acl_free (acl);
-+
-+ if (val == NULL)
-+ {
-+ call_arg_warn ("acl_to_text", file_name);
-+ return;
-+ }
-+
-+ *ret_ptr = xstrdup (val);
-+ *ret_len = strlen (val);
-+
-+ acl_free (val);
-+#endif
-+}
-+
-+static void xattrs__acls_get_d(struct tar_stat_info *st,
-+ char const *file_name,
-+ char **ret_ptr, size_t *ret_len)
-+{ /* "system.posix_acl_default" */
-+#ifdef HAVE_LIBACL
-+ char *val = NULL;
-+ acl_t acl;
-+
-+ if ((acl = acl_get_file (file_name, ACL_TYPE_DEFAULT)) == (acl_t)NULL)
-+ {
-+ if (errno != ENOTSUP)
-+ call_arg_warn ("acl_get_file", file_name);
-+ return;
-+ }
-+
-+ val = acl_to_text(acl, NULL);
-+ acl_free (acl);
-+
-+ if (val == NULL)
-+ {
-+ call_arg_warn ("acl_to_text", file_name);
-+ return;
-+ }
-+
-+ *ret_ptr = xstrdup (val);
-+ *ret_len = strlen (val);
-+
-+ acl_free (val);
-+#endif
-+}
-+
-+void xattrs_acls_get(struct tar_stat_info *st, char const *file_name, int fd,
-+ int xisfile)
-+{
-+ if (acls_option > 0)
-+ {
-+ xattrs__acls_get_a (st, file_name, fd,
-+ &st->acls_a_ptr, &st->acls_a_len);
-+ if (!xisfile)
-+ xattrs__acls_get_d (st, file_name,
-+ &st->acls_d_ptr, &st->acls_d_len);
-+ }
-+}
-+
-+void xattrs_selinux_get(struct tar_stat_info *st, char const *file_name, int fd)
-+{
-+#ifdef HAVE_LIBSELINUX
-+ if (selinux_context_option > 0)
-+ if (fd == -1)
-+ {
-+ if (lgetfilecon (file_name, &st->cntx_name) == -1)
-+ call_arg_warn ("lgetfilecon", file_name);
-+ }
-+ else if (fgetfilecon (fd, &st->cntx_name) == -1)
-+ call_arg_warn ("fgetfilecon", file_name);
-+#endif
-+}
-+
-+void xattrs_xattrs_get(struct tar_stat_info *st, char const *file_name, int fd)
-+{
-+#ifdef HAVE_XATTRS
-+ if (xattrs_option > 0)
-+ { /* get all xattrs ... this include security.* and system.* if
-+ available. We filter them here, but we have to filter them
-+ in xattrs_xattrs_set() anyway.
-+ */
-+ static ssize_t xsz = 1024;
-+ static char *xatrs = NULL;
-+ ssize_t xret = -1;
-+
-+ if (!xatrs) xatrs = xmalloc (xsz);
-+
-+ while (((fd == -1) ?
-+ ((xret = listxattr (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 == -1) ? "listxattrs" : "flistxattrs", 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;
-+
-+ if (strncmp (attr, "user.", strlen("user.")) &&
-+ strncmp (attr, "trusted.", strlen("trusted.")))
-+ goto next_attr; /* only store normal xattrs */
-+
-+ while (((fd == -1) ?
-+ ((aret = getxattr (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 ("fgetxattr", file_name);
-+
-+ next_attr:
-+ 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)
-+{
-+#ifdef HAVE_XATTRS
-+ if (ptr)
-+ {
-+ const char *sysname = "setxattr";
-+ int ret = -1;
-+
-+ if (typeflag != SYMTYPE)
-+ ret = setxattr (file_name, attr, ptr, len, 0);
-+ else
-+ {
-+ sysname = "lsetxattr";
-+ ret = lsetxattr (file_name, attr, ptr, len, 0);
-+ }
-+
-+ if ((ret == -1) && (errno == EPERM))
-+ call_arg_warn(sysname, file_name);
-+ else if ((ret == -1) && (errno != EOPNOTSUPP))
-+ call_arg_error(sysname, file_name);
-+ }
-+#endif
-+}
-+
-+/* convert unix permissions into an ACL ... needed due to "default" ACLs */
-+#ifdef HAVE_LIBACL
-+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));
-+}
-+#endif
-+
-+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)
-+{ /* "system.posix_acl_access" */
-+#ifdef HAVE_LIBACL
-+ 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 (file_name, type, acl) == -1)
-+ {
-+ if (errno != ENOTSUP)
-+ call_arg_warn ("acl_set_file", file_name);
-+ }
-+ acl_free (acl);
-+#endif
-+}
-+
-+void xattrs_acls_set(struct tar_stat_info const *st,
-+ char const *file_name, char typeflag)
-+{
-+ if ((acls_option >= 0) && (typeflag != SYMTYPE))
-+ {
-+#ifdef HAVE_LIBACL
-+ xattrs__acls_set (st, file_name, ACL_TYPE_ACCESS,
-+ st->acls_a_ptr, st->acls_a_len);
-+ if (S_ISDIR (st->stat.st_mode))
-+ xattrs__acls_set (st, file_name, ACL_TYPE_DEFAULT,
-+ st->acls_d_ptr, st->acls_d_len);
-+#endif
-+ }
-+}
-+
-+void xattrs_selinux_set(struct tar_stat_info const *st,
-+ char const *file_name, char typeflag)
-+{
-+#ifdef HAVE_LIBSELINUX
-+ if ((selinux_context_option >= 0) && st->cntx_name)
-+ {
-+ const char *sysname = "setfilecon";
-+ int ret = -1;
-+
-+ if (typeflag != SYMTYPE)
-+ ret = setfilecon (file_name, st->cntx_name);
-+ else
-+ {
-+ sysname = "lsetfilecon";
-+ ret = lsetfilecon (file_name, st->cntx_name);
-+ }
-+
-+ if ((ret == -1) && (errno == EPERM))
-+ call_arg_warn(sysname, file_name);
-+ else if ((ret == -1) && (errno != EOPNOTSUPP))
-+ call_arg_error(sysname, file_name);
-+ }
-+#endif
-+}
-+
-+void xattrs_xattrs_set(struct tar_stat_info const *st,
-+ char const *file_name, char typeflag)
-+{
-+#ifdef HAVE_XATTRS
-+ if ((xattrs_option >= 0) && st->xattr_map_size)
-+ {
-+ size_t scan = 0;
-+
-+ while (scan < st->xattr_map_size)
-+ {
-+ char *keyword = st->xattr_map[scan].xkey;
-+
-+ /* assert (!memcpy (keyword, "SCHILY.xattr.", strlen("SCHILY.xattr."))); */
-+ keyword += strlen("SCHILY.xattr.");
-+
-+ if (strncmp (keyword, "user.", strlen("user.")) &&
-+ strncmp (keyword, "trusted.", strlen("trusted.")))
-+ continue; /* don't try and set anything but normal xattrs */
-+
-+ /* should we ignore trusted.* EPERM errors when not root ? */
-+ xattrs__fd_set (st, file_name, typeflag, keyword,
-+ st->xattr_map[scan].xval_ptr,
-+ st->xattr_map[scan].xval_len);
-+
-+ ++scan;
-+ }
-+ }
-+#endif
-+}
-+
---- tar-1.17/src/tar.c.xattrs 2007-06-01 12:17:10.000000000 +0200
-+++ tar-1.17/src/tar.c 2007-06-27 17:10:56.000000000 +0200
-@@ -247,7 +247,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,
- CHECKPOINT_OPTION,
-@@ -271,6 +272,7 @@ enum
- MODE_OPTION,
- MTIME_OPTION,
- NEWER_MTIME_OPTION,
-+ NO_ACLS_OPTION,
- NO_ANCHORED_OPTION,
- NO_DELAY_DIRECTORY_RESTORE_OPTION,
- NO_IGNORE_CASE_OPTION,
-@@ -280,9 +282,11 @@ enum
- NO_RECURSION_OPTION,
- NO_SAME_OWNER_OPTION,
- NO_SAME_PERMISSIONS_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,
-@@ -304,6 +308,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,
-@@ -321,7 +326,8 @@ enum
- VERSION_OPTION,
- VOLNO_FILE_OPTION,
- WILDCARDS_MATCH_SLASH_OPTION,
-- WILDCARDS_OPTION
-+ WILDCARDS_OPTION,
-+ XATTR_OPTION
- };
-
- const char *argp_program_version = "tar (" PACKAGE_NAME ") " VERSION;
-@@ -453,6 +459,10 @@ static struct argp_option options[] = {
- {NULL, 0, NULL, 0,
- N_("Handling of file attributes:"), GRID },
-
-+ {"acls", ACLS_OPTION, 0, 0,
-+ N_("Save the ACLs to the archive"), GRID+1 },
-+ {"no-acls", NO_ACLS_OPTION, 0, 0,
-+ N_("Don't extract the ACLs from the archive"), GRID+1 },
- {"owner", OWNER_OPTION, N_("NAME"), 0,
- N_("force NAME as owner for added files"), GRID+1 },
- {"group", GROUP_OPTION, N_("NAME"), 0,
-@@ -483,6 +493,14 @@ static struct argp_option options[] = {
- {"preserve-order", 's', 0, 0,
- N_("sort names to extract to match archive"), GRID+1 },
- {"same-order", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
-+ {"selinux", SELINUX_CONTEXT_OPTION, 0, 0,
-+ N_("Save the SELinux context to the archive"), GRID+1 },
-+ {"no-selinux", NO_SELINUX_CONTEXT_OPTION, 0, 0,
-+ N_("Don't extract the SELinux context from the archive"), GRID+1 },
-+ {"xattrs", XATTR_OPTION, 0, 0,
-+ N_("Save the user/root xattrs to the archive"), GRID+1 },
-+ {"no-xattrs", NO_XATTR_OPTION, 0, 0,
-+ N_("Don't extract the user/root xattrs from the archive"), GRID+1 },
- {"preserve", PRESERVE_OPTION, 0, 0,
- N_("same as both -p and -s"), GRID+1 },
- {"delay-directory-restore", DELAY_DIRECTORY_RESTORE_OPTION, 0, 0,
-@@ -1805,6 +1823,37 @@ parse_opt (int key, char *arg, struct ar
- 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");
-+ if (!acls_option) acls_option = 1;
-+ if (!selinux_context_option) selinux_context_option = 1;
-+ xattrs_option = 1;
-+ break;
-+
-+ case NO_XATTR_OPTION:
-+ if (!acls_option) acls_option = -1;
-+ if (!selinux_context_option) selinux_context_option = -1;
-+ xattrs_option = -1;
-+ break;
-+
- case RECURSION_OPTION:
- recursion_option = FNM_LEADING_DIR;
- break;
-@@ -2200,6 +2249,29 @@ decode_options (int argc, char **argv)
- || subcommand_option != LIST_SUBCOMMAND))
- USAGE_ERROR ((0, 0, _("--pax-option can be used only on POSIX archives")));
-
-+ /* star create's non-POSIX typed archives with xattr support, so allow the
-+ extra headers */
-+ if ((acls_option > 0)
-+ && archive_format != POSIX_FORMAT
-+ && (subcommand_option != EXTRACT_SUBCOMMAND
-+ || subcommand_option != DIFF_SUBCOMMAND
-+ || subcommand_option != LIST_SUBCOMMAND))
-+ USAGE_ERROR ((0, 0, _("--acls can be used only on POSIX archives")));
-+
-+ if ((selinux_context_option > 0)
-+ && archive_format != POSIX_FORMAT
-+ && (subcommand_option != EXTRACT_SUBCOMMAND
-+ || subcommand_option != DIFF_SUBCOMMAND
-+ || subcommand_option != LIST_SUBCOMMAND))
-+ USAGE_ERROR ((0, 0, _("--selinux can be used only on POSIX archives")));
-+
-+ if ((xattrs_option > 0)
-+ && archive_format != POSIX_FORMAT
-+ && (subcommand_option != EXTRACT_SUBCOMMAND
-+ || subcommand_option != DIFF_SUBCOMMAND
-+ || subcommand_option != LIST_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;
-@@ -2401,11 +2473,15 @@ tar_stat_init (struct tar_stat_info *st)
- void
- tar_stat_destroy (struct tar_stat_info *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);
---- tar-1.17/src/xheader.c.xattrs 2007-06-01 12:17:10.000000000 +0200
-+++ tar-1.17/src/xheader.c 2007-06-27 17:10:56.000000000 +0200
-@@ -419,6 +419,74 @@ xheader_write_global (struct xheader *xh
- free (name);
- }
-
-+void xheader_xattr_init(struct tar_stat_info *st)
-+{
-+ st->xattr_map = NULL;
-+ st->xattr_map_size = 0;
-+}
-+
-+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.");
-+ tmp = 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;
-+ }
-+}
-+
- \f
- /* General Interface */
-
-@@ -429,6 +497,7 @@ struct xhdr_tab
- struct xheader *, void const *data);
- void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);
- bool protect;
-+ bool prefix;
- };
-
- /* This declaration must be extern, because ISO C99 section 6.9.2
-@@ -445,8 +514,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;
- }
-
-@@ -456,7 +534,7 @@ xheader_protected_pattern_p (const char
- struct xhdr_tab const *p;
-
- for (p = xhdr_tab; p->keyword; p++)
-- if (p->protect && fnmatch (pattern, p->keyword, 0) == 0)
-+ if (!p->prefix && p->protect && fnmatch (pattern, p->keyword, 0) == 0)
- return true;
- return false;
- }
-@@ -467,7 +545,7 @@ xheader_protected_keyword_p (const char
- struct xhdr_tab const *p;
-
- for (p = xhdr_tab; p->keyword; p++)
-- if (p->protect && strcmp (p->keyword, keyword) == 0)
-+ if (!p->prefix && p->protect && strcmp (p->keyword, keyword) == 0)
- return true;
- return false;
- }
-@@ -1419,6 +1497,71 @@ volume_filename_decoder (struct tar_stat
- }
-
- 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)
- {
-@@ -1455,18 +1598,18 @@ sparse_minor_decoder (struct tar_stat_in
- }
-
- struct xhdr_tab const xhdr_tab[] = {
-- { "atime", atime_coder, atime_decoder, false },
-- { "comment", dummy_coder, dummy_decoder, false },
-- { "charset", dummy_coder, dummy_decoder, false },
-- { "ctime", ctime_coder, ctime_decoder, false },
-- { "gid", gid_coder, gid_decoder, false },
-- { "gname", gname_coder, gname_decoder, false },
-- { "linkpath", linkpath_coder, linkpath_decoder, false },
-- { "mtime", mtime_coder, mtime_decoder, false },
-- { "path", path_coder, path_decoder, false },
-- { "size", size_coder, size_decoder, false },
-- { "uid", uid_coder, uid_decoder, false },
-- { "uname", uname_coder, uname_decoder, false },
-+ { "atime", atime_coder, atime_decoder, false, false },
-+ { "comment", dummy_coder, dummy_decoder, false, false },
-+ { "charset", dummy_coder, dummy_decoder, false, false },
-+ { "ctime", ctime_coder, ctime_decoder, false, false },
-+ { "gid", gid_coder, gid_decoder, false, false },
-+ { "gname", gname_coder, gname_decoder, false, false },
-+ { "linkpath", linkpath_coder, linkpath_decoder, false, false },
-+ { "mtime", mtime_coder, mtime_decoder, false, false },
-+ { "path", path_coder, path_decoder, false, false },
-+ { "size", size_coder, size_decoder, false, false },
-+ { "uid", uid_coder, uid_decoder, false, false },
-+ { "uname", uname_coder, uname_decoder, false, false },
-
- /* Sparse file handling */
- { "GNU.sparse.name", path_coder, path_decoder,
-@@ -1481,25 +1624,25 @@ struct xhdr_tab const xhdr_tab[] = {
- true },
-
- /* tar 1.14 - 1.15.90 keywords. */
-- { "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true },
-+ { "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true, 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,
-- true },
-+ true, false },
- { "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder,
-- true },
-+ true, 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, false },
-+ sparse_map_decoder, false, false },
-
- { "GNU.dumpdir", dumpdir_coder, dumpdir_decoder,
-- true },
-+ true, 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, true },
-+ { "GNU.volume.label", volume_label_coder, volume_label_decoder, true, false },
-
- /* These may be present in a first global header of the archive.
- They provide the same functionality as GNUTYPE_MULTIVOL header.
-@@ -1508,9 +1651,38 @@ 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,
-- true },
-- { "GNU.volume.size", volume_size_coder, volume_size_decoder, true },
-- { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, true },
--
-+ true, false },
-+ { "GNU.volume.size", volume_size_coder, volume_size_decoder, true, false },
-+ { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder,
-+ true, 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, false, false },
-+
-+ /* ACLs, use the star format... */
-+ { "SCHILY.acl.access",
-+ xattr_acls_a_coder, xattr_acls_a_decoder, false, false },
-+
-+ { "SCHILY.acl.default",
-+ xattr_acls_d_coder, xattr_acls_d_decoder, false, false },
-+
-+ /* FIXME: These are compat. for FC-6 ... we shipped a tar using the generic
-+ header names by accident. */
-+ { "SCHILY.xattr.security.selinux",
-+ xattr_selinux_coder, xattr_selinux_decoder, false, false },
-+ { "SCHILY.xattr.system.posix_acl_access",
-+ xattr_acls_a_coder, xattr_acls_a_decoder, false, false },
-+ { "SCHILY.xattr.system.posix_acl_default",
-+ xattr_acls_d_coder, xattr_acls_d_decoder, false, false },
-+
-+ /* xattr's, use the star format note we only save the user/trusted varients... */
-+ { "SCHILY.xattr.user", xattr_coder, xattr_decoder, false, true },
-+ { "SCHILY.xattr.trusted", xattr_coder, xattr_decoder, false, true },
-+
-+ /* ignore everything else in the xattr namespaces... */
-+ { "SCHILY.xattr", dummy_coder, dummy_decoder, false, true },
-+
- { NULL, NULL, NULL, false }
- };
---- tar-1.17/src/list.c.xattrs 2007-06-27 17:10:56.000000000 +0200
-+++ tar-1.17/src/list.c 2007-06-27 17:10:56.000000000 +0200
-@@ -567,6 +567,13 @@ decode_header (union block *header, stru
- assign_string (&stat_info->gname,
- header->header.gname[0] ? header->header.gname : NULL);
-
-+ stat_info->acls_a_ptr = NULL;
-+ stat_info->acls_a_len = 0;
-+ stat_info->acls_d_ptr = NULL;
-+ stat_info->acls_d_len = 0;
-+ stat_info->cntx_name = NULL;
-+ xheader_xattr_init(stat_info);
-+
- if (format == OLDGNU_FORMAT && incremental_option)
- {
- stat_info->atime.tv_sec = TIME_FROM_HEADER (header->oldgnu_header.atime);
---- tar-1.17/src/Makefile.am.xattrs 2006-12-05 08:37:59.000000000 +0100
-+++ tar-1.17/src/Makefile.am 2007-06-27 17:10:56.000000000 +0200
-@@ -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\
- compare.c\
-@@ -37,10 +37,11 @@ tar_SOURCES = \
- tar.c\
- transform.c\
- update.c\
-- utf8.c
-+ utf8.c\
-+ xattrs.c
-
- INCLUDES = -I$(top_srcdir)/lib -I../ -I../lib
-
- LDADD = ../lib/libtar.a $(LIBINTL) $(LIBICONV)
-
--tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
-+tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME)
---- tar-1.17/src/create.c.xattrs 2007-06-01 12:17:10.000000000 +0200
-+++ tar-1.17/src/create.c 2007-06-27 17:10:56.000000000 +0200
-@@ -24,6 +24,7 @@
- #include <quotearg.h>
-
- #include "common.h"
-+
- #include <hash.h>
-
- struct link
-@@ -942,6 +943,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;
- }
-
-@@ -1570,6 +1595,10 @@ dump_file0 (struct tar_stat_info *st, co
- open_diag (p);
- return;
- }
-+
-+ xattrs_acls_get(st, p, fd, !is_dir);
-+ xattrs_selinux_get(st, p, fd);
-+ xattrs_xattrs_get(st, p, fd);
- }
-
- if (is_dir)
---- /dev/null 2007-06-25 09:32:25.472134050 +0200
-+++ tar-1.17/src/xattrs.h 2007-06-27 17:10:56.000000000 +0200
-@@ -0,0 +1,14 @@
-+
-+extern void xattrs_acls_get(struct tar_stat_info *st,
-+ char const *file_name, int fd, int xisfile);
-+extern void xattrs_selinux_get(struct tar_stat_info *st,
-+ char const *file_name, int fd);
-+extern void xattrs_xattrs_get(struct tar_stat_info *st,
-+ char const *file_name, 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);
---- tar-1.17/src/extract.c.xattrs 2007-06-08 10:14:42.000000000 +0200
-+++ tar-1.17/src/extract.c 2007-06-27 17:10:56.000000000 +0200
-@@ -69,6 +69,13 @@ struct delayed_set_stat
- mode_t invert_permissions;
- enum permstatus permstatus;
- bool after_links;
-+ 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; /* Size of the xattr map */
-+ struct xattr_array *xattr_map;
- char file_name[1];
- };
-
-@@ -96,6 +103,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; /* Size of the xattr map */
-+ struct xattr_array *xattr_map;
-+
- /* The desired target of the desired link. */
- char target[1];
- };
-@@ -276,6 +295,10 @@ set_stat (char const *file_name,
- give files away. */
- }
-
-+ xattrs_acls_set(st, file_name, typeflag);
-+ xattrs_selinux_set(st, file_name, typeflag);
-+ xattrs_xattrs_set(st, file_name, typeflag);
-+
- if (0 < same_owner_option && permstatus != INTERDIR_PERMSTATUS)
- {
- /* When lchown exists, it should be used to change the attributes of
-@@ -352,6 +375,23 @@ delay_set_stat (char const *file_name, s
- data->invert_permissions = invert_permissions;
- data->permstatus = permstatus;
- data->after_links = 0;
-+ data->cntx_name = NULL;
-+ assign_string (&data->cntx_name, st->cntx_name);
-+ if (st->acls_a_ptr)
-+ data->acls_a_ptr = xmemdup(st->acls_a_ptr, st->acls_a_len);
-+ else
-+ {
-+ data->acls_a_ptr = NULL;
-+ data->acls_a_len = 0;
-+ }
-+ if (st->acls_d_ptr)
-+ data->acls_d_ptr = xmemdup(st->acls_d_ptr, st->acls_d_len);
-+ else
-+ {
-+ data->acls_d_ptr = NULL;
-+ data->acls_d_len = 0;
-+ }
-+ xheader_xattr_copy (st, &data->xattr_map, &data->xattr_map_size);
- strcpy (data->file_name, file_name);
- delayed_set_stat_head = data;
- }
-@@ -599,11 +639,22 @@ apply_nonancestor_delayed_set_stat (char
- st.stat.st_gid = data->gid;
- st.atime = data->atime;
- st.mtime = data->mtime;
-+ st.cntx_name = data->cntx_name;
-+ st.acls_a_ptr = data->acls_a_ptr;
-+ st.acls_a_len = data->acls_a_len;
-+ st.acls_d_ptr = data->acls_d_ptr;
-+ st.acls_d_len = data->acls_d_len;
-+ st.xattr_map = data->xattr_map;
-+ st.xattr_map_size = data->xattr_map_size;
- set_stat (data->file_name, &st, cur_info,
- data->invert_permissions, data->permstatus, DIRTYPE);
- }
-
- 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);
- }
- }
-@@ -882,6 +933,13 @@ create_placeholder_file (char *file_name
- + strlen (file_name) + 1);
- p->sources->next = 0;
- strcpy (p->sources->string, file_name);
-+ p->cntx_name = NULL;
-+ p->acls_a_ptr = NULL;
-+ p->acls_a_len = 0;
-+ p->acls_d_ptr = NULL;
-+ p->acls_d_len = 0;
-+ p->xattr_map = NULL;
-+ p->xattr_map_size = 0;
- strcpy (p->target, current_stat_info.link_name);
-
- h = delayed_set_stat_head;
-@@ -1291,6 +1349,13 @@ apply_delayed_links (void)
- struct tar_stat_info st1;
- st1.stat.st_uid = ds->uid;
- st1.stat.st_gid = ds->gid;
-+ 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, NULL, 0, 0, SYMTYPE);
- valid_source = source;
- }
---- tar-1.17/src/tar.h.xattrs 2007-06-01 12:17:10.000000000 +0200
-+++ tar-1.17/src/tar.h 2007-06-27 17:10:56.000000000 +0200
-@@ -276,6 +276,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 +295,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 +326,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;
-