Add basic suuport for extended attributes.
* src/Makefile.am: Add xattrs.[ch] * src/xattrs.c: New file. * src/xattrs.h: New file. * src/common.h (READ_LIKE_SUBCOMMAND): New define. (selinux_context_option, acls_option, xattrs_option): New globals. (xheader_xattr_init, xheader_xattr_free) (xheader_xattr_copy, xheader_xattr_add): New protos. (WARN_XATTR_WRITE): New mask. * src/create.c (start_header): Handle xattrs pairs if in POSIX format. (dump_file0): Handle extended attributes. * src/extract.c (delayed_set_stat,delayed_link) <xattr_map_size> <xattr_map>: New members. (set_xattr): New static function. (open_output_file): Accept an additional argument indicating whether the file has already been created. (set_stat,delay_set_stat) (apply_nonancestor_delayed_set_stat) (extract_file): Handle extended attributes. * src/list.c (decode_header, simple_print_header): Display extended attributes. * src/tar.c: New options --xattrs, --no-xattrs, --xattrs-include, --xattrs-exclude (tar_stat_destroy): Free the xattr_map storage. * src/tar.h (xattr_array): New struct. (tar_stat_info) <xattr_map_size, xattr_map>: New members. * src/warning.c: New warning control keyword "xattr-write". * src/xheader.c (xheader_xattr_init) (xheader_xattr_free, xheader_xattr_add) (xheader_xattr_copy): New functions. (struct xhdr_tab) <prefix>: New member. (locate_handler): Permit selecting the keyword based on its prefix. (xheader_protected_pattern_p) (xheader_protected_keyword_p): Likewise. (xattr_coder, xattr_decoder): New functions. (xhdr_tab): Reflect the changes to struct xhdr_tab. New keyword "SCHILY.xattr". * tests/Makefile.am: Add new tests. * tests/testsuite.at: Likewise. (AT_CHECK_UTIL, AT_XATTRS_UTILS_PREREQ) (AT_CAPABILITIES_UTILS_PREREQ, AT_XATTRS_PREREQ): New defuns. * tests/xattr01.at: New test. * tests/xattr02.at: New test. * tests/xattr03.at: New test. * tests/xattr04.at: New test. * tests/capabs_raw01.at: New test.
This commit is contained in:
committed by
Sergey Poznyakoff
parent
b997c90f9e
commit
696338043e
@@ -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)
|
||||
|
||||
28
src/common.h
28
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;
|
||||
|
||||
@@ -256,6 +261,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;
|
||||
@@ -714,6 +728,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);
|
||||
@@ -734,6 +751,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 */
|
||||
|
||||
@@ -815,6 +838,7 @@ void checkpoint_run (bool do_write);
|
||||
#define WARN_XDEV 0x00040000
|
||||
#define WARN_DECOMPRESS_PROGRAM 0x00080000
|
||||
#define WARN_EXISTING_FILE 0x00100000
|
||||
#define WARN_XATTR_WRITE 0x00200000
|
||||
|
||||
/* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default
|
||||
in verbose mode */
|
||||
|
||||
37
src/create.c
37
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.
|
||||
|
||||
@@ -943,6 +944,21 @@ start_header (struct tar_stat_info *st)
|
||||
GNAME_TO_CHARS (st->gname, header->header.gname);
|
||||
}
|
||||
|
||||
if (archive_format == POSIX_FORMAT)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1718,6 +1734,8 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
|
||||
bool ok;
|
||||
struct stat final_stat;
|
||||
|
||||
xattrs_xattrs_get (parentfd, name, st, fd);
|
||||
|
||||
if (is_dir)
|
||||
{
|
||||
const char *tag_file_name;
|
||||
@@ -1836,6 +1854,8 @@ 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_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);
|
||||
@@ -1854,11 +1874,20 @@ 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_xattrs_get (parentfd, name, st, 0);
|
||||
}
|
||||
else if (S_ISBLK (st->stat.st_mode))
|
||||
type = BLKTYPE;
|
||||
{
|
||||
type = BLKTYPE;
|
||||
xattrs_xattrs_get (parentfd, name, st, 0);
|
||||
}
|
||||
else if (S_ISFIFO (st->stat.st_mode))
|
||||
type = FIFOTYPE;
|
||||
{
|
||||
type = FIFOTYPE;
|
||||
xattrs_xattrs_get (parentfd, name, st, 0);
|
||||
}
|
||||
else if (S_ISSOCK (st->stat.st_mode))
|
||||
{
|
||||
WARNOPT (WARN_FILE_IGNORED,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -98,6 +99,9 @@ struct delayed_set_stat
|
||||
/* Directory that the name is relative to. */
|
||||
int change_dir;
|
||||
|
||||
/* extended attributes*/
|
||||
size_t xattr_map_size;
|
||||
struct xattr_array *xattr_map;
|
||||
/* Length and contents of name. */
|
||||
size_t file_name_len;
|
||||
char file_name[1];
|
||||
@@ -138,6 +142,9 @@ struct delayed_link
|
||||
hard-linked together. */
|
||||
struct string_list *sources;
|
||||
|
||||
size_t xattr_map_size;
|
||||
struct xattr_array *xattr_map;
|
||||
|
||||
/* The desired target of the desired link. */
|
||||
char target[1];
|
||||
};
|
||||
@@ -364,6 +371,10 @@ 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);
|
||||
}
|
||||
|
||||
/* For each entry H in the leading prefix of entries in HEAD that do
|
||||
@@ -435,6 +446,13 @@ 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;
|
||||
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))
|
||||
@@ -682,6 +700,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
|
||||
@@ -742,12 +794,15 @@ 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.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);
|
||||
}
|
||||
}
|
||||
@@ -863,7 +918,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;
|
||||
@@ -873,6 +929,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;
|
||||
@@ -944,6 +1004,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;
|
||||
|
||||
@@ -960,8 +1022,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);
|
||||
@@ -1101,6 +1173,7 @@ 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);
|
||||
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;
|
||||
@@ -1536,6 +1609,8 @@ apply_delayed_links (void)
|
||||
st1.stat.st_gid = ds->gid;
|
||||
st1.atime = ds->atime;
|
||||
st1.mtime = ds->mtime;
|
||||
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;
|
||||
@@ -1550,6 +1625,8 @@ apply_delayed_links (void)
|
||||
sources = next;
|
||||
}
|
||||
|
||||
xheader_xattr_free (ds->xattr_map, ds->xattr_map_size);
|
||||
|
||||
{
|
||||
struct delayed_link *next = ds->next;
|
||||
free (ds);
|
||||
|
||||
11
src/list.c
11
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.
|
||||
|
||||
@@ -604,6 +605,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);
|
||||
@@ -1064,7 +1067,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;
|
||||
@@ -1156,6 +1159,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);
|
||||
@@ -1301,6 +1307,7 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
|
||||
}
|
||||
}
|
||||
fflush (stdlis);
|
||||
xattrs_print (st);
|
||||
}
|
||||
|
||||
|
||||
|
||||
50
src/tar.c
50
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.
|
||||
|
||||
@@ -304,6 +305,7 @@ enum
|
||||
NO_UNQUOTE_OPTION,
|
||||
NO_WILDCARDS_MATCH_SLASH_OPTION,
|
||||
NO_WILDCARDS_OPTION,
|
||||
NO_XATTR_OPTION,
|
||||
NULL_OPTION,
|
||||
NUMERIC_OWNER_OPTION,
|
||||
OCCURRENCE_OPTION,
|
||||
@@ -341,7 +343,10 @@ enum
|
||||
VOLNO_FILE_OPTION,
|
||||
WARNING_OPTION,
|
||||
WILDCARDS_MATCH_SLASH_OPTION,
|
||||
WILDCARDS_OPTION
|
||||
WILDCARDS_OPTION,
|
||||
XATTR_OPTION,
|
||||
XATTR_EXCLUDE,
|
||||
XATTR_INCLUDE
|
||||
};
|
||||
|
||||
const char *argp_program_version = "tar (" PACKAGE_NAME ") " VERSION;
|
||||
@@ -530,6 +535,20 @@ 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 },
|
||||
#undef GRID
|
||||
|
||||
#define GRID 60
|
||||
{NULL, 0, NULL, 0,
|
||||
N_("Device selection and switching:"), GRID },
|
||||
@@ -2150,6 +2169,20 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
same_permissions_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;
|
||||
@@ -2527,11 +2560,16 @@ 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 when reading */
|
||||
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;
|
||||
@@ -2740,6 +2778,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)
|
||||
@@ -2784,6 +2823,7 @@ 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);
|
||||
|
||||
14
src/tar.h
14
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 */
|
||||
@@ -309,6 +318,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;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* This file is part of GNU tar.
|
||||
|
||||
Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 2009, 2012 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
@@ -43,6 +43,7 @@ static char const *const warning_args[] = {
|
||||
"xdev",
|
||||
"decompress-program",
|
||||
"existing-file",
|
||||
"xattr-write",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -68,7 +69,8 @@ static int warning_types[] = {
|
||||
WARN_UNKNOWN_KEYWORD,
|
||||
WARN_XDEV,
|
||||
WARN_DECOMPRESS_PROGRAM,
|
||||
WARN_EXISTING_FILE
|
||||
WARN_EXISTING_FILE,
|
||||
WARN_XATTR_WRITE
|
||||
};
|
||||
|
||||
ARGMATCH_VERIFY (warning_args, warning_types);
|
||||
|
||||
315
src/xattrs.c
Normal file
315
src/xattrs.c
Normal file
@@ -0,0 +1,315 @@
|
||||
/* 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 "xattr-at.h"
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
void xattrs_print (struct tar_stat_info const *st)
|
||||
{
|
||||
if (verbose_option < 3)
|
||||
return;
|
||||
|
||||
/* 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",
|
||||
(unsigned long) st->xattr_map[i].xval_len, keyword);
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/xattrs.h
Normal file
52
src/xattrs.h
Normal file
@@ -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 */
|
||||
171
src/xheader.c
171
src/xheader.c
@@ -1,7 +1,7 @@
|
||||
/* POSIX extended headers for tar.
|
||||
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software
|
||||
Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2012
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
@@ -460,6 +460,74 @@ xheader_write_global (struct xheader *xhdr)
|
||||
}
|
||||
}
|
||||
|
||||
void xheader_xattr_init (struct tar_stat_info *st)
|
||||
{
|
||||
st->xattr_map = NULL;
|
||||
st->xattr_map_size = 0;
|
||||
}
|
||||
|
||||
void xheader_xattr_free (struct xattr_array *xattr_map, size_t xattr_map_size)
|
||||
{
|
||||
size_t scan = 0;
|
||||
|
||||
while (scan < xattr_map_size)
|
||||
{
|
||||
free (xattr_map[scan].xkey);
|
||||
free (xattr_map[scan].xval_ptr);
|
||||
|
||||
++scan;
|
||||
}
|
||||
free (xattr_map);
|
||||
}
|
||||
|
||||
static void xheader_xattr__add (struct xattr_array **xattr_map,
|
||||
size_t *xattr_map_size,
|
||||
const char *key, const char *val, size_t len)
|
||||
{
|
||||
size_t pos = (*xattr_map_size)++;
|
||||
|
||||
*xattr_map = xrealloc (*xattr_map,
|
||||
*xattr_map_size * sizeof(struct xattr_array));
|
||||
(*xattr_map)[pos].xkey = xstrdup (key);
|
||||
(*xattr_map)[pos].xval_ptr = xmemdup (val, len + 1);
|
||||
(*xattr_map)[pos].xval_len = len;
|
||||
}
|
||||
|
||||
void xheader_xattr_add(struct tar_stat_info *st,
|
||||
const char *key, const char *val, size_t len)
|
||||
{
|
||||
size_t klen = strlen (key);
|
||||
char *xkey = xmalloc (strlen("SCHILY.xattr.") + klen + 1);
|
||||
char *tmp = xkey;
|
||||
|
||||
tmp = stpcpy (tmp, "SCHILY.xattr.");
|
||||
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 +541,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 +558,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 +578,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 +590,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;
|
||||
}
|
||||
@@ -1468,6 +1548,26 @@ volume_filename_decoder (struct tar_stat_info *st,
|
||||
{
|
||||
decode_string (&continued_file_name, arg);
|
||||
}
|
||||
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,
|
||||
@@ -1506,53 +1606,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 +1661,16 @@ 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 },
|
||||
|
||||
{ NULL, NULL, NULL, 0 }
|
||||
/* 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, false }
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Makefile for GNU tar regression tests.
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2003, 2004, 2005,
|
||||
# 2006, 2007, 2009 Free Software Foundation, Inc.
|
||||
# 2006, 2007, 2009, 2012 Free Software Foundation, Inc.
|
||||
|
||||
# François Pinard <pinard@iro.umontreal.ca>, 1988.
|
||||
# Sergey Poznyakoff <gray@mirddin.farlep.net>, 2004.
|
||||
@@ -173,7 +173,12 @@ TESTSUITE_AT = \
|
||||
star/multi-fail.at\
|
||||
star/ustar-big-2g.at\
|
||||
star/ustar-big-8g.at\
|
||||
star/pax-big-10g.at
|
||||
star/pax-big-10g.at\
|
||||
xattr01.at\
|
||||
xattr02.at\
|
||||
xattr03.at\
|
||||
xattr04.at\
|
||||
capabs_raw01.at
|
||||
|
||||
TESTSUITE = $(srcdir)/testsuite
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Process this file with autom4te to create testsuite. -*- Autotest -*-
|
||||
|
||||
# Test suite for GNU tar.
|
||||
# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Free Software
|
||||
# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010, 2012 Free Software
|
||||
# Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
@@ -117,6 +117,36 @@ m4_define([AT_TAR_MKHIER],[
|
||||
install-sh -d $1 >/dev/null dnl
|
||||
m4_if([$2],,,&& genfile --file [$1]/[$2]) || AT_SKIP_TEST])
|
||||
|
||||
dnl Skip test when utlity does not return expected return value
|
||||
m4_define([AT_CHECK_UTIL],[
|
||||
$1 &> /dev/null
|
||||
if test "$?" != $2; then
|
||||
AT_SKIP_TEST
|
||||
fi
|
||||
])
|
||||
|
||||
m4_define([AT_XATTRS_UTILS_PREREQ],[
|
||||
file=$( mktemp -p . )
|
||||
AT_CHECK_UTIL(setfattr -n user.test -v test $file,0)
|
||||
AT_CHECK_UTIL(getfattr $file,0)
|
||||
])
|
||||
m4_define([AT_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_include([sparsemvp.at])
|
||||
|
||||
AT_INIT
|
||||
@@ -284,3 +314,10 @@ m4_include([star/ustar-big-2g.at])
|
||||
m4_include([star/ustar-big-8g.at])
|
||||
|
||||
m4_include([star/pax-big-10g.at])
|
||||
|
||||
m4_include([xattr01.at])
|
||||
m4_include([xattr02.at])
|
||||
m4_include([xattr03.at])
|
||||
m4_include([xattr04.at])
|
||||
|
||||
m4_include([capabs_raw01.at])
|
||||
|
||||
Reference in New Issue
Block a user