Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 287617 Details for
Bug 382067
app-arch/tar-1.26: add patch to support xattr
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch to add full xattr support to tar
tar-1.26-full-xattr.patch (text/plain), 29.96 KB, created by
Anthony Basile
on 2011-09-24 19:47:48 UTC
(
hide
)
Description:
Patch to add full xattr support to tar
Filename:
MIME Type:
Creator:
Anthony Basile
Created:
2011-09-24 19:47:48 UTC
Size:
29.96 KB
patch
obsolete
>diff --git a/configure.ac b/configure.ac >index db69cb8..2afa463 100644 >--- a/configure.ac >+++ b/configure.ac >@@ -223,6 +223,20 @@ AC_CHECK_TYPE(iconv_t,:, > #endif > ]) > >+AC_ARG_ENABLE(xattr, >+ AC_HELP_STRING([--enable-xattr], >+ [enable Extended Attribute support (disabled by default)]), >+ [xattr_enabled=$enableval], >+ [xattr_enabled=no]) >+ >+if test "x$xattr_enabled" = xyes; then >+ AC_CHECK_HEADERS(attr/xattr.h) >+ AC_CHECK_FUNCS(getxattr fgetxattr lgetxattr \ >+ setxattr fsetxattr lsetxattr \ >+ listxattr flistxattr llistxattr, >+ AC_DEFINE(HAVE_XATTRS,1,[Define if we have a working extended attributes]),) >+fi >+ > # Gettext. > AM_GNU_GETTEXT([external], [need-formatstring-macros]) > AM_GNU_GETTEXT_VERSION([0.16]) >diff --git a/doc/tar.texi b/doc/tar.texi >index db8f986..d861d12 100644 >--- a/doc/tar.texi >+++ b/doc/tar.texi >@@ -3002,6 +3002,10 @@ mechanism. > 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 and not to extract xattrs. @xref{Attributes}. >+ > @opsummary{no-wildcards} > @item --no-wildcards > Do not use wildcards. >@@ -3447,6 +3451,10 @@ 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 xattrs. @xref{Attributes}. >+ > @opsummary{wildcards} > @item --wildcards > Use wildcards when matching member names with patterns. >@@ -8659,6 +8667,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 +9303,20 @@ 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 the current extended attributes in >+the archive. >+ >+The @option{--xattrs} option has no equivalent short option name. >+ >+@opindex no-xattrs >+@item --no-xattrs >+This option causes @command{tar} not to store the current extended attributes in >+the archive and not to extract any extended attributes in an archive. >+ >+The @option{--no-xattrs} option has no equivalent short option name. >+ > @end table > > @node Portability >diff --git a/src/Makefile.am b/src/Makefile.am >index de310f4..27c28be 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) >diff --git a/src/common.h b/src/common.h >index 0b9bd7a..e4ee345 100644 >--- a/src/common.h >+++ b/src/common.h >@@ -253,6 +253,9 @@ GLOBAL int same_owner_option; > /* If positive, preserve permissions when extracting. */ > GLOBAL int same_permissions_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 +710,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 +733,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 */ > >diff --git a/src/create.c b/src/create.c >index 43b5a4c..7ed5d10 100644 >--- a/src/create.c >+++ b/src/create.c >@@ -936,6 +936,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; > } > >@@ -1711,6 +1726,11 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p) > bool ok; > struct stat final_stat; > >+ if (fd == 0) >+ xattrs_xattrs_get(st, p, -1); >+ else >+ xattrs_xattrs_get(st, p, fd); >+ > if (is_dir) > { > const char *tag_file_name; >@@ -1829,6 +1849,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(st, p, -1); >+ > block_ordinal = current_block_ordinal (); > st->stat.st_size = 0; /* force 0 size on symlink */ > header = start_header (st); >@@ -1847,11 +1869,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(st, p, -1); >+ } > else if (S_ISBLK (st->stat.st_mode)) >- type = BLKTYPE; >+ { >+ type = BLKTYPE; >+ xattrs_xattrs_get(st, p, -1); >+ } > else if (S_ISFIFO (st->stat.st_mode)) >- type = FIFOTYPE; >+ { >+ type = FIFOTYPE; >+ xattrs_xattrs_get(st, p, -1); >+ } > else if (S_ISSOCK (st->stat.st_mode)) > { > WARNOPT (WARN_FILE_IGNORED, >diff --git a/src/extract.c b/src/extract.c >index aaea56e..5c0a9c9 100644 >--- a/src/extract.c >+++ b/src/extract.c >@@ -97,6 +97,9 @@ struct delayed_set_stat > /* Directory that the name is relative to. */ > int change_dir; > >+ /* extended attributes*/ >+ size_t xattr_map_size; /* Size of the xattr map */ >+ struct xattr_array *xattr_map; > /* Length and contents of name. */ > size_t file_name_len; > char file_name[1]; >@@ -134,6 +137,9 @@ struct delayed_link > hard-linked together. */ > struct string_list *sources; > >+ size_t xattr_map_size; /* Size of the xattr map */ >+ struct xattr_array *xattr_map; >+ > /* The desired target of the desired link. */ > char target[1]; > }; >@@ -335,6 +341,8 @@ set_stat (char const *file_name, > utime_error (file_name); > } > >+ xattrs_xattrs_set(st, file_name, typeflag); >+ > if (0 < same_owner_option && ! interdir) > { > /* Some systems allow non-root users to give files away. Once this >@@ -431,6 +439,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)) >@@ -673,6 +688,31 @@ 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 layout. >+ 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; >+ 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 = mknod (file_name, mode ^ invert_permissions, 0); >+ while (status && maybe_recoverable ((char *)file_name, false, &interdir_made)); >+ xattrs_xattrs_set(st, file_name, typeflag); >+ *file_created = 1; >+ } >+ 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 +773,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); > } > } >@@ -854,6 +897,7 @@ extract_dir (char *file_name, int typeflag) > > static int > open_output_file (char const *file_name, int typeflag, mode_t mode, >+ int file_created, > mode_t *current_mode, mode_t *current_mode_mask) > { > int fd; >@@ -864,6 +908,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() failure */ >+ if (file_created) >+ openflag = openflag & ~O_EXCL; >+ > if (typeflag == CONTTYPE) > { > static int conttype_diagnosed; >@@ -934,6 +982,7 @@ 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,7 +999,17 @@ 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, >+ file_created, > ¤t_mode, ¤t_mode_mask)) > < 0) > { >@@ -1091,6 +1150,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; >@@ -1525,6 +1585,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; >@@ -1539,6 +1601,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); >diff --git a/src/list.c b/src/list.c >index cf2de09..6f52579 100644 >--- a/src/list.c >+++ b/src/list.c >@@ -604,6 +604,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); >diff --git a/src/tar.c b/src/tar.c >index 928cfdd..75510d8 100644 >--- a/src/tar.c >+++ b/src/tar.c >@@ -304,6 +304,7 @@ enum > NO_UNQUOTE_OPTION, > NO_WILDCARDS_MATCH_SLASH_OPTION, > NO_WILDCARDS_OPTION, >+ NO_XATTR_OPTION, > NULL_OPTION, > NUMERIC_OWNER_OPTION, > OCCURRENCE_OPTION, >@@ -340,7 +341,8 @@ enum > VOLNO_FILE_OPTION, > WARNING_OPTION, > WILDCARDS_MATCH_SLASH_OPTION, >- WILDCARDS_OPTION >+ WILDCARDS_OPTION, >+ XATTR_OPTION > }; > > const char *argp_program_version = "tar (" PACKAGE_NAME ") " VERSION; >@@ -516,6 +518,10 @@ static struct argp_option options[] = { > {"preserve-order", 's', 0, 0, > N_("sort names to extract to match archive"), GRID+1 }, > {"same-order", 0, 0, OPTION_ALIAS, NULL, GRID+1 }, >+ {"xattrs", XATTR_OPTION, 0, 0, >+ N_("Save the user/root xattrs to the archive"), GRID+1 }, >+ {"no-xattrs", NO_XATTR_OPTION, 0, 0, >+ N_("Don't extract the user/root xattrs from the archive"), GRID+1 }, > {"preserve", PRESERVE_OPTION, 0, 0, > N_("same as both -p and -s"), GRID+1 }, > {"delay-directory-restore", DELAY_DIRECTORY_RESTORE_OPTION, 0, 0, >@@ -2079,6 +2085,15 @@ 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 RECURSION_OPTION: > recursion_option = FNM_LEADING_DIR; > break; >@@ -2461,6 +2476,15 @@ decode_options (int argc, char **argv) > || subcommand_option != LIST_SUBCOMMAND)) > USAGE_ERROR ((0, 0, _("--pax-option can be used only on POSIX archives"))); > >+ /* star create's non-POSIX typed archives with xattr support, so allow the >+ extra headers */ >+ if ((xattrs_option > 0) >+ && archive_format != POSIX_FORMAT >+ && (subcommand_option != EXTRACT_SUBCOMMAND >+ || subcommand_option != DIFF_SUBCOMMAND >+ || subcommand_option != LIST_SUBCOMMAND)) >+ USAGE_ERROR ((0, 0, _("--xattrs can be used only on POSIX archives"))); >+ > /* If ready to unlink hierarchies, so we are for simpler files. */ > if (recursive_unlink_option) > old_files_option = UNLINK_FIRST_OLD_FILES; >@@ -2713,6 +2737,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); >diff --git a/src/tar.h b/src/tar.h >index ce9850c..955b18e 100644 >--- a/src/tar.h >+++ b/src/tar.h >@@ -276,6 +276,14 @@ struct xheader > uintmax_t string_length; > }; > >+/* Information about xattrs for a file. */ >+struct xattr_array >+ { >+ char *xkey; >+ char *xval_ptr; >+ size_t xval_len; >+ }; >+ > struct tar_stat_info > { > char *orig_file_name; /* name of file read from the archive header */ >@@ -287,6 +295,7 @@ struct tar_stat_info > > char *uname; /* user name of owner */ > char *gname; /* group name of owner */ >+ > struct stat stat; /* regular filesystem stat */ > > /* STAT doesn't always have access, data modification, and status >@@ -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; > >diff --git a/src/xattrs.c b/src/xattrs.c >new file mode 100644 >index 0000000..6a9950e >--- /dev/null >+++ b/src/xattrs.c >@@ -0,0 +1,181 @@ >+/* Create a tar archive. >+ >+ Copyright (C) 2006 Free Software Foundation, Inc. >+ >+ Written by James Antill, on 2006-07-27. >+ >+ This program is free software; you can redistribute it and/or modify it >+ under the terms of the GNU General Public License as published by the >+ Free Software Foundation; either version 2, or (at your option) any later >+ version. >+ >+ This program is distributed in the hope that it will be useful, but >+ WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General >+ Public License for more details. >+ >+ You should have received a copy of the GNU General Public License along >+ with this program; if not, write to the Free Software Foundation, Inc., >+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ >+ >+#include <system.h> >+ >+#include <quotearg.h> >+ >+#include "common.h" >+ >+ >+#ifndef HAVE_ATTR_XATTR_H >+# undef HAVE_XATTRS >+#endif >+ >+#ifdef HAVE_ATTR_XATTR_H >+# include <attr/xattr.h> >+#endif >+ >+ >+void xattrs_xattrs_get(struct tar_stat_info *st, char const *file_name, int fd) >+{ >+ if (xattrs_option > 0) >+ { /* get all xattrs ... this include security.* and system.* if >+ available. We filter them here, but we have to filter them >+ in xattrs_xattrs_set() anyway. >+ */ >+ static ssize_t xsz = 1024; >+ static char *xatrs = NULL; >+ ssize_t xret = -1; >+ >+#ifndef HAVE_XATTRS >+ static int done = 0; >+ if ((xattrs_option > 0) && !done) >+ WARN ((0, 0, _("Xattr support requested, but not available"))); >+ done = 1; >+#else >+ >+ if (!xatrs) xatrs = xmalloc (xsz); >+ >+ while (((fd == -1) ? >+ ((xret = llistxattr (file_name, xatrs, xsz)) == -1) : >+ ((xret = flistxattr (fd, xatrs, xsz)) == -1)) && >+ (errno == ERANGE)) >+ { >+ xsz <<= 1; >+ xatrs = xrealloc (xatrs, xsz); >+ } >+ >+ if (xret == -1) >+ call_arg_warn ((fd == -1) ? "llistxattrs" : "flistxattrs", file_name); >+ else >+ { >+ const char *attr = xatrs; >+ static ssize_t asz = 1024; >+ static char *val = NULL; >+ >+ if (!val) val = xmalloc (asz); >+ >+ while (xret > 0) >+ { >+ size_t len = strlen (attr); >+ ssize_t aret = 0; >+ >+ /* Archive all xattrs during creation, decide at extraction time >+ * which ones are of interest/use for the target filesystem. */ >+ while (((fd == -1) ? >+ ((aret = lgetxattr (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==-1) ? "lgetxattr" : "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) >+{ >+#ifdef HAVE_XATTRS >+ if (ptr) >+ { >+ const char *sysname = "setxattr"; >+ int ret = -1; >+ >+ if (typeflag != SYMTYPE) >+ ret = setxattr (file_name, attr, ptr, len, 0); >+ else >+ { >+ sysname = "lsetxattr"; >+ ret = lsetxattr (file_name, attr, ptr, len, 0); >+ } >+ >+ /* do not print warnings when SELinux is disabled */ >+ if ((ret == -1) && (errno != EPERM) && (errno != ENOTSUP)) >+ call_arg_error(sysname, file_name); >+ } >+#endif >+} >+ >+static char *skip_to_ext_fields(char *ptr) >+{ >+ ptr += strcspn(ptr, ":,\n"); /* skip tag name. Ie. user/group/default/mask */ >+ >+ if (*ptr != ':') >+ return (ptr); /* error? no user/group field */ >+ ++ptr; >+ >+ ptr += strcspn(ptr, ":,\n"); /* skip user/group name */ >+ >+ if (*ptr != ':') >+ return (ptr); /* error? no perms field */ >+ ++ptr; >+ >+ ptr += strcspn(ptr, ":,\n"); /* skip perms */ >+ >+ if (*ptr != ':') >+ return (ptr); /* no extra fields */ >+ >+ return (ptr); >+} >+ >+void xattrs_xattrs_set(struct tar_stat_info const *st, >+ char const *file_name, char typeflag) >+{ >+ if ((xattrs_option >= 0) && st->xattr_map_size) >+ { >+ size_t scan = 0; >+ >+#ifndef HAVE_XATTRS >+ static int done = 0; >+ if (!done) >+ WARN ((0, 0, _("Xattr support requested, but not available"))); >+ done = 1; >+#else >+ while (scan < st->xattr_map_size) >+ { >+ char *keyword = st->xattr_map[scan].xkey; >+ >+ /* assert (!memcpy (keyword, "SCHILY.xattr.", strlen("SCHILY.xattr."))); */ >+ keyword += strlen("SCHILY.xattr."); >+ >+ xattrs__fd_set (st, file_name, typeflag, keyword, >+ st->xattr_map[scan].xval_ptr, >+ st->xattr_map[scan].xval_len); >+ >+ ++scan; >+ } >+#endif >+ } >+} >diff --git a/src/xattrs.h b/src/xattrs.h >new file mode 100644 >index 0000000..7ffdce1 >--- /dev/null >+++ b/src/xattrs.h >@@ -0,0 +1,6 @@ >+ >+extern void xattrs_xattrs_get(struct tar_stat_info *st, >+ char const *file_name, int fd); >+ >+extern void xattrs_xattrs_set(struct tar_stat_info const *st, >+ char const *file_name, char typeflag); >diff --git a/src/xheader.c b/src/xheader.c >index 2284e97..557b3e5 100644 >--- a/src/xheader.c >+++ b/src/xheader.c >@@ -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."); >+ tmp = stpcpy (tmp, key); >+ >+ xheader_xattr__add (&st->xattr_map, &st->xattr_map_size, xkey, val, len); >+ >+ free (xkey); >+} >+ >+void xheader_xattr_copy(const struct tar_stat_info *st, >+ struct xattr_array **xattr_map, size_t *xattr_map_size) >+{ >+ size_t scan = 0; >+ >+ *xattr_map = NULL; >+ *xattr_map_size = 0; >+ >+ while (scan < st->xattr_map_size) >+ { >+ char *key = st->xattr_map[scan].xkey; >+ char *val = st->xattr_map[scan].xval_ptr; >+ size_t len = st->xattr_map[scan].xval_len; >+ >+ xheader_xattr__add(xattr_map, xattr_map_size, key, val, len); >+ >+ ++scan; >+ } >+} >+ > > /* 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; > }; > > /* 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,7 @@ 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 +589,7 @@ 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 +1548,27 @@ volume_filename_decoder (struct tar_stat_info *st, > } > > 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 +1605,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 +1660,14 @@ 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 }, >+ >+ /* xattrs use the star format. note we only save some variants... */ >+ { "SCHILY.xattr", xattr_coder, xattr_decoder, 0, true }, > >- { NULL, NULL, NULL, 0 } >+ { NULL, NULL, NULL, 0, false } > };
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 382067
:
285715
|
285767
| 287617 |
287623