3062 lines
95 KiB
Diff
3062 lines
95 KiB
Diff
|
From f661d5c38ec585f364e47a981ebada092936d38a Mon Sep 17 00:00:00 2001
|
|||
|
From: Pavel Raiskup <praiskup@redhat.com>
|
|||
|
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 <grp.h>])
|
|||
|
AC_CHECK_DECLS([getpwuid],,, [#include <pwd.h>])
|
|||
|
AC_CHECK_DECLS([time],,, [#include <time.h>])
|
|||
|
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 <system.h>
|
|||
|
+
|
|||
|
+#include <fnmatch.h>
|
|||
|
+#include <quotearg.h>
|
|||
|
+
|
|||
|
+#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 <sys/acl.h>
|
|||
|
+#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 <http://www.gnu.org/licenses/>.
|
|||
|
+#
|
|||
|
+# Test description:
|
|||
|
+#
|
|||
|
+# This is basic test for acl support.
|
|||
|
+
|
|||
|
+AT_SETUP([acls: basic functionality])
|
|||
|
+AT_KEYWORDS([xattrs acls acls01])
|
|||
|
+
|
|||
|
+AT_TAR_CHECK([
|
|||
|
+AT_XATTRS_UTILS_PREREQ
|
|||
|
+AT_ACLS_PREREQ
|
|||
|
+
|
|||
|
+mkdir dir
|
|||
|
+genfile --file dir/file
|
|||
|
+
|
|||
|
+MYNAME=$( id -un )
|
|||
|
+
|
|||
|
+setfacl -m u:$MYNAME:--x dir/file
|
|||
|
+setfacl -m u:$MYNAME:--x dir
|
|||
|
+
|
|||
|
+getfattr -h -m. -d dir dir/file > before
|
|||
|
+
|
|||
|
+tar --acls -cf archive.tar dir
|
|||
|
+rm -rf dir
|
|||
|
+
|
|||
|
+tar --acls -xf archive.tar
|
|||
|
+
|
|||
|
+getfattr -h -m. -d dir dir/file > after
|
|||
|
+
|
|||
|
+diff before after
|
|||
|
+test "$?" = 0
|
|||
|
+],
|
|||
|
+[0],
|
|||
|
+[])
|
|||
|
+
|
|||
|
+AT_CLEANUP
|
|||
|
diff --git a/tests/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 <http://www.gnu.org/licenses/>.
|
|||
|
+#
|
|||
|
+# Test description:
|
|||
|
+#
|
|||
|
+# This is basic test for acl support.
|
|||
|
+
|
|||
|
+AT_SETUP([acls: work with -C])
|
|||
|
+AT_KEYWORDS([xattrs acls acls02])
|
|||
|
+
|
|||
|
+AT_TAR_CHECK([
|
|||
|
+AT_XATTRS_UTILS_PREREQ
|
|||
|
+AT_ACLS_PREREQ
|
|||
|
+
|
|||
|
+mkdir dir
|
|||
|
+mkdir dir/subdir
|
|||
|
+genfile --file dir/subdir/file
|
|||
|
+
|
|||
|
+MYNAME=$( id -un )
|
|||
|
+
|
|||
|
+setfacl -m u:$MYNAME:--x dir/subdir
|
|||
|
+setfacl -m u:$MYNAME:--x dir/subdir/file
|
|||
|
+
|
|||
|
+cd dir
|
|||
|
+getfattr -h -m. -d subdir subdir/file > ../before
|
|||
|
+cd ..
|
|||
|
+
|
|||
|
+tar --acls -cf archive.tar -C dir subdir
|
|||
|
+rm -rf dir
|
|||
|
+
|
|||
|
+mkdir dir
|
|||
|
+tar --acls -xf archive.tar -C dir
|
|||
|
+
|
|||
|
+cd dir
|
|||
|
+getfattr -h -m. -d subdir subdir/file > ../after
|
|||
|
+cd ..
|
|||
|
+
|
|||
|
+diff before after
|
|||
|
+test "$?" = 0
|
|||
|
+],
|
|||
|
+[0],
|
|||
|
+[])
|
|||
|
+
|
|||
|
+AT_CLEANUP
|
|||
|
diff --git a/tests/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 <http://www.gnu.org/licenses/>.
|
|||
|
+#
|
|||
|
+# Test description: Test if file capabilities are archived/restored correctly
|
|||
|
+# using just the default xattr support (capabilities are stored/restored in
|
|||
|
+# binary format -> system dependant).
|
|||
|
+
|
|||
|
+AT_SETUP([capabilities: binary store/restore])
|
|||
|
+AT_KEYWORDS([xattrs capabilities capabs_raw01])
|
|||
|
+
|
|||
|
+AT_TAR_CHECK([
|
|||
|
+AT_PRIVILEGED_PREREQ
|
|||
|
+AT_XATTRS_PREREQ
|
|||
|
+AT_CAPABILITIES_UTILS_PREREQ
|
|||
|
+
|
|||
|
+mkdir dir
|
|||
|
+genfile --file dir/file
|
|||
|
+
|
|||
|
+setcap "= cap_chown=ei" dir/file
|
|||
|
+
|
|||
|
+# archive whole directory including binary xattrs
|
|||
|
+tar --xattrs -cf archive.tar dir
|
|||
|
+
|
|||
|
+# clear the directory
|
|||
|
+rm -rf dir
|
|||
|
+
|
|||
|
+# restore _all_ xattrs (not just the user.* domain)
|
|||
|
+tar --xattrs --xattrs-include='*' -xf archive.tar
|
|||
|
+
|
|||
|
+getcap dir/file
|
|||
|
+],
|
|||
|
+[0],
|
|||
|
+[dir/file = cap_chown+ei
|
|||
|
+])
|
|||
|
+
|
|||
|
+AT_CLEANUP
|
|||
|
diff --git a/tests/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 <http://www.gnu.org/licenses/>.
|
|||
|
+#
|
|||
|
+# Test description:
|
|||
|
+#
|
|||
|
+# This is basic test for support of extended attributes.
|
|||
|
+
|
|||
|
+AT_SETUP([acls/selinux: special files & fifos])
|
|||
|
+AT_KEYWORDS([xattrs selinux acls selacls01])
|
|||
|
+
|
|||
|
+AT_TAR_CHECK([
|
|||
|
+AT_PRIVILEGED_PREREQ
|
|||
|
+AT_XATTRS_UTILS_PREREQ
|
|||
|
+AT_SELINUX_PREREQ
|
|||
|
+AT_ACLS_PREREQ
|
|||
|
+
|
|||
|
+mkdir dir
|
|||
|
+mkfifo dir/fifo
|
|||
|
+MAJOR=$( stat /dev/urandom --printf="%t" )
|
|||
|
+MINOR=$( stat /dev/urandom --printf="%T" )
|
|||
|
+mknod dir/chartype c $MAJOR $MINOR
|
|||
|
+
|
|||
|
+# setup attributes
|
|||
|
+restorecon -R dir
|
|||
|
+chcon -h --user=system_u dir/fifo
|
|||
|
+chcon -h --user=system_u dir/chartype
|
|||
|
+setfacl -m u:$UID:--- dir/fifo
|
|||
|
+setfacl -m u:$UID:rwx dir/chartype
|
|||
|
+
|
|||
|
+getfacl dir/fifo >> before
|
|||
|
+getfattr -msecurity.selinux dir/chartype >> before
|
|||
|
+
|
|||
|
+tar --xattrs --selinux --acls -cf archive.tar dir
|
|||
|
+
|
|||
|
+mv dir olddir
|
|||
|
+
|
|||
|
+tar --xattrs --selinux --acls -xf archive.tar
|
|||
|
+
|
|||
|
+getfacl dir/fifo >> after
|
|||
|
+getfattr -msecurity.selinux dir/chartype >> after
|
|||
|
+
|
|||
|
+diff before after
|
|||
|
+echo separator
|
|||
|
+],
|
|||
|
+[0],
|
|||
|
+[separator
|
|||
|
+])
|
|||
|
+
|
|||
|
+AT_CLEANUP
|
|||
|
diff --git a/tests/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 <http://www.gnu.org/licenses/>.
|
|||
|
+#
|
|||
|
+# Test description:
|
|||
|
+#
|
|||
|
+# This is basic test for selinux support (store & restore).
|
|||
|
+
|
|||
|
+AT_SETUP([selinux: basic store/restore])
|
|||
|
+AT_KEYWORDS([xattrs selinux selnx01])
|
|||
|
+
|
|||
|
+AT_TAR_CHECK([
|
|||
|
+AT_XATTRS_UTILS_PREREQ
|
|||
|
+AT_SELINUX_PREREQ
|
|||
|
+
|
|||
|
+mkdir dir
|
|||
|
+genfile --file dir/file
|
|||
|
+ln -s file dir/link
|
|||
|
+
|
|||
|
+getfattr -h -d -msecurity.selinux dir dir/file dir/link > start
|
|||
|
+
|
|||
|
+restorecon -R dir
|
|||
|
+chcon -h --user=system_u dir
|
|||
|
+chcon -h --user=unconfined_u dir/file
|
|||
|
+chcon -h --user=system_u dir/link
|
|||
|
+
|
|||
|
+# archive whole directory including selinux contexts
|
|||
|
+tar --selinux -cf archive.tar dir
|
|||
|
+
|
|||
|
+# clear the directory
|
|||
|
+rm -rf dir
|
|||
|
+
|
|||
|
+# ================================================
|
|||
|
+# check if selinux contexts are correctly restored
|
|||
|
+
|
|||
|
+tar --selinux -xf archive.tar
|
|||
|
+
|
|||
|
+# archive for later debugging
|
|||
|
+cp archive.tar archive_origin.tar
|
|||
|
+
|
|||
|
+# check if selinux contexts were restored
|
|||
|
+getfattr -h -d dir dir/file dir/link -msecurity.selinux | \
|
|||
|
+ grep -v -e '^#' -e ^$ | cut -d: -f1
|
|||
|
+
|
|||
|
+# ===========================================================================
|
|||
|
+# check if selinux contexts are not restored when --selinux option is missing
|
|||
|
+
|
|||
|
+getfattr -h -d -msecurity.selinux dir dir/file dir/link > with_selinux
|
|||
|
+rm -rf dir
|
|||
|
+tar -xf archive.tar
|
|||
|
+getfattr -h -d -msecurity.selinux dir dir/file dir/link > without_selinux
|
|||
|
+
|
|||
|
+diff with_selinux without_selinux > diff_with_without
|
|||
|
+if test "$?" -eq "0"; then
|
|||
|
+ echo "selinux contexts probably restored while --selinux is off"
|
|||
|
+fi
|
|||
|
+
|
|||
|
+# =================================================================
|
|||
|
+# check if selinux is not archived when --selinux option is missing
|
|||
|
+
|
|||
|
+tar -cf archive.tar dir
|
|||
|
+
|
|||
|
+# clear the directory
|
|||
|
+rm -rf dir
|
|||
|
+
|
|||
|
+# restore (with --selinux)
|
|||
|
+tar --selinux -xf archive.tar dir
|
|||
|
+
|
|||
|
+getfattr -h -d -msecurity.selinux dir dir/file dir/link > final
|
|||
|
+diff start final > final_diff
|
|||
|
+if test "$?" -ne "0"; then
|
|||
|
+ echo "bad result"
|
|||
|
+fi
|
|||
|
+
|
|||
|
+],
|
|||
|
+[0],
|
|||
|
+[security.selinux="system_u
|
|||
|
+security.selinux="unconfined_u
|
|||
|
+security.selinux="system_u
|
|||
|
+])
|
|||
|
+
|
|||
|
+AT_CLEANUP
|
|||
|
diff --git a/tests/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 <http://www.gnu.org/licenses/>.
|
|||
|
+#
|
|||
|
+# Test description:
|
|||
|
+#
|
|||
|
+# This is basic test for support of extended attributes.
|
|||
|
+
|
|||
|
+AT_SETUP([xattrs: basic functionality])
|
|||
|
+AT_KEYWORDS([xattrs xattr01])
|
|||
|
+
|
|||
|
+AT_TAR_CHECK([
|
|||
|
+AT_XATTRS_PREREQ
|
|||
|
+mkdir dir
|
|||
|
+genfile --file dir/file
|
|||
|
+
|
|||
|
+setfattr -n user.test -v OurDirValue dir
|
|||
|
+setfattr -n user.test -v OurFileValue dir/file
|
|||
|
+
|
|||
|
+tar --xattrs -cf archive.tar dir
|
|||
|
+
|
|||
|
+rm -rf dir
|
|||
|
+tar --xattrs -xf archive.tar
|
|||
|
+
|
|||
|
+getfattr -h -d dir | grep -v -e '^#' -e ^$
|
|||
|
+getfattr -h -d dir/file | grep -v -e '^#' -e ^$
|
|||
|
+],
|
|||
|
+[0],
|
|||
|
+[user.test="OurDirValue"
|
|||
|
+user.test="OurFileValue"
|
|||
|
+])
|
|||
|
+
|
|||
|
+AT_CLEANUP
|
|||
|
diff --git a/tests/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 <http://www.gnu.org/licenses/>.
|
|||
|
+#
|
|||
|
+# Test description:
|
|||
|
+#
|
|||
|
+# Cooperation of the '-C' option and storing/restoring extended attributes.
|
|||
|
+
|
|||
|
+AT_SETUP([xattrs: change directory with -C option])
|
|||
|
+AT_KEYWORDS([xattrs xattr02])
|
|||
|
+
|
|||
|
+AT_TAR_CHECK([
|
|||
|
+AT_XATTRS_PREREQ
|
|||
|
+
|
|||
|
+mkdir dir
|
|||
|
+mkdir dir/subdir
|
|||
|
+mkdir dir/subdir/subsubdir
|
|||
|
+genfile --file dir/file1
|
|||
|
+genfile --file dir/subdir/file2
|
|||
|
+
|
|||
|
+setfattr -n user.test -v OurFile1Value dir/file1
|
|||
|
+setfattr -n user.test -v OurFile2Value dir/subdir/file2
|
|||
|
+setfattr -n user.test -v OurDirValue dir/subdir/subsubdir
|
|||
|
+
|
|||
|
+tar --xattrs -cf archive.tar -C dir file1 -C subdir file2 subsubdir
|
|||
|
+
|
|||
|
+rm -rf dir
|
|||
|
+
|
|||
|
+tar --xattrs -xf archive.tar
|
|||
|
+
|
|||
|
+getfattr -h -d file1 | grep -v -e '^#' -e ^$
|
|||
|
+getfattr -h -d file2 | grep -v -e '^#' -e ^$
|
|||
|
+getfattr -h -d subsubdir | grep -v -e '^#' -e ^$
|
|||
|
+],
|
|||
|
+[0],
|
|||
|
+[user.test="OurFile1Value"
|
|||
|
+user.test="OurFile2Value"
|
|||
|
+user.test="OurDirValue"
|
|||
|
+])
|
|||
|
+
|
|||
|
+AT_CLEANUP
|
|||
|
diff --git a/tests/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 <http://www.gnu.org/licenses/>.
|
|||
|
+#
|
|||
|
+# Test description:
|
|||
|
+#
|
|||
|
+# Setup of the trusted.* domain under privileged user.
|
|||
|
+
|
|||
|
+AT_SETUP([xattrs: trusted.* attributes])
|
|||
|
+AT_KEYWORDS([xattrs xattr03])
|
|||
|
+
|
|||
|
+AT_TAR_CHECK([
|
|||
|
+AT_PRIVILEGED_PREREQ
|
|||
|
+AT_XATTRS_PREREQ
|
|||
|
+
|
|||
|
+mkdir dir
|
|||
|
+mkdir dir/subdir
|
|||
|
+mkdir dir/subdir/subsubdir
|
|||
|
+genfile --file dir/file1
|
|||
|
+genfile --file dir/subdir/file2
|
|||
|
+
|
|||
|
+setfattr -n trusted.test -v OurFile1Value dir/file1
|
|||
|
+setfattr -n trusted.test -v OurFile2Value dir/subdir/file2
|
|||
|
+setfattr -n trusted.test -v OurDirValue dir/subdir/subsubdir
|
|||
|
+
|
|||
|
+tar --xattrs -cf archive.tar -C dir file1 -C subdir file2 subsubdir
|
|||
|
+
|
|||
|
+rm -rf dir
|
|||
|
+
|
|||
|
+tar --xattrs --xattrs-include=trusted* -xf archive.tar
|
|||
|
+
|
|||
|
+getfattr -mtrusted. -d file1 | grep -v -e '^#' -e ^$
|
|||
|
+getfattr -mtrusted. -d file2 | grep -v -e '^#' -e ^$
|
|||
|
+getfattr -mtrusted. -d subsubdir | grep -v -e '^#' -e ^$
|
|||
|
+],
|
|||
|
+[0],
|
|||
|
+[trusted.test="OurFile1Value"
|
|||
|
+trusted.test="OurFile2Value"
|
|||
|
+trusted.test="OurDirValue"
|
|||
|
+])
|
|||
|
+
|
|||
|
+AT_CLEANUP
|
|||
|
diff --git a/tests/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 <http://www.gnu.org/licenses/>.
|
|||
|
+#
|
|||
|
+# Test description: Test for the regression caused by tar update from 1.23 to
|
|||
|
+# 1.26, Red Hat xattr patch was not ready for open->openat conversion.
|
|||
|
+#
|
|||
|
+# Related commit 4bde4f3. See the bug: https://bugzilla.redhat.com/717684
|
|||
|
+
|
|||
|
+AT_SETUP([xattrs: s/open/openat/ regression])
|
|||
|
+AT_KEYWORDS([xattrs xattr04])
|
|||
|
+
|
|||
|
+AT_TAR_CHECK([
|
|||
|
+AT_XATTRS_PREREQ
|
|||
|
+
|
|||
|
+mkdir dir
|
|||
|
+mkdir output
|
|||
|
+genfile --file dir/file
|
|||
|
+
|
|||
|
+setfattr -n user.test -v value dir/file
|
|||
|
+
|
|||
|
+# archive whole directory including binary xattrs
|
|||
|
+tar --xattrs -cf archive.tar -C dir .
|
|||
|
+
|
|||
|
+tar --xattrs -xf archive.tar -C output
|
|||
|
+ret=$?
|
|||
|
+getfattr -h -d output/file | grep -v -e '^#' -e ^$
|
|||
|
+exit $ret
|
|||
|
+],
|
|||
|
+[0],
|
|||
|
+[user.test="value"
|
|||
|
+])
|
|||
|
+
|
|||
|
+AT_CLEANUP
|
|||
|
--
|
|||
|
1.7.11.2
|
|||
|
|