Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 382067 | Differences between
and this patch

Collapse All | Expand All

(-)a/configure.ac (+14 lines)
Lines 223-228 AC_CHECK_TYPE(iconv_t,:, Link Here
223
#endif
223
#endif
224
])
224
])
225
225
226
AC_ARG_ENABLE(xattr,
227
  AC_HELP_STRING([--enable-xattr],
228
    [enable Extended Attribute support (disabled by default)]),
229
  [xattr_enabled=$enableval],
230
  [xattr_enabled=no])
231
232
if test "x$xattr_enabled" = xyes; then
233
  AC_CHECK_HEADERS(attr/xattr.h)
234
  AC_CHECK_FUNCS(getxattr  fgetxattr  lgetxattr \
235
                 setxattr  fsetxattr  lsetxattr \
236
                 listxattr flistxattr llistxattr,
237
                 AC_DEFINE(HAVE_XATTRS,1,[Define if we have a working extended attributes]),)
238
fi
239
226
# Gettext.
240
# Gettext.
227
AM_GNU_GETTEXT([external], [need-formatstring-macros])
241
AM_GNU_GETTEXT([external], [need-formatstring-macros])
228
AM_GNU_GETTEXT_VERSION([0.16])
242
AM_GNU_GETTEXT_VERSION([0.16])
(-)a/doc/tar.texi (+24 lines)
Lines 3002-3007 mechanism. Link Here
3002
Treat all input file or member names literally, do not interpret
3002
Treat all input file or member names literally, do not interpret
3003
escape sequences.  @xref{input name quoting}.
3003
escape sequences.  @xref{input name quoting}.
3004
3004
3005
@opsummary{no-xattrs}
3006
@item --no-xattrs
3007
Causes @command{tar} not to store and not to extract xattrs.  @xref{Attributes}.
3008
3005
@opsummary{no-wildcards}
3009
@opsummary{no-wildcards}
3006
@item --no-wildcards
3010
@item --no-wildcards
3007
Do not use wildcards.
3011
Do not use wildcards.
Lines 3447-3452 Enable or disable warning messages identified by @var{keyword}. The Link Here
3447
messages are suppressed if @var{keyword} is prefixed with @samp{no-}.
3451
messages are suppressed if @var{keyword} is prefixed with @samp{no-}.
3448
@xref{warnings}.
3452
@xref{warnings}.
3449
3453
3454
@opsummary{xattrs}
3455
@item --xattrs
3456
Causes @command{tar} to store xattrs.  @xref{Attributes}.
3457
3450
@opsummary{wildcards}
3458
@opsummary{wildcards}
3451
@item --wildcards
3459
@item --wildcards
3452
Use wildcards when matching member names with patterns.
3460
Use wildcards when matching member names with patterns.
Lines 8659-8664 implementation able to read @samp{ustar} archives will be able to read Link Here
8659
most @samp{posix} archives as well, with the only exception that any
8667
most @samp{posix} archives as well, with the only exception that any
8660
additional information (such as long file names etc.) will in such
8668
additional information (such as long file names etc.) will in such
8661
case be extracted as plain text files along with the files it refers to.
8669
case be extracted as plain text files along with the files it refers to.
8670
This is the only format that can store ACLs, SELinux context and extended
8671
attributes.
8662
8672
8663
This archive format will be the default format for future versions
8673
This archive format will be the default format for future versions
8664
of @GNUTAR{}.
8674
of @GNUTAR{}.
Lines 9293-9298 Same as both @option{--same-permissions} and @option{--same-order}. Link Here
9293
9303
9294
This option is deprecated, and will be removed in @GNUTAR{} version 1.23.
9304
This option is deprecated, and will be removed in @GNUTAR{} version 1.23.
9295
9305
9306
@opindex xattrs
9307
@item --xattrs
9308
This option causes @command{tar} to store the current extended attributes in
9309
the archive.
9310
9311
The @option{--xattrs} option has no equivalent short option name.
9312
9313
@opindex no-xattrs
9314
@item --no-xattrs
9315
This option causes @command{tar} not to store the current extended attributes in
9316
the archive and not to extract any extended attributes in an archive.
9317
9318
The @option{--no-xattrs} option has no equivalent short option name.
9319
9296
@end table
9320
@end table
9297
9321
9298
@node Portability
9322
@node Portability
(-)a/src/Makefile.am (-3 / +4 lines)
Lines 20-26 Link Here
20
20
21
bin_PROGRAMS = tar
21
bin_PROGRAMS = tar
22
22
23
noinst_HEADERS = arith.h common.h tar.h
23
noinst_HEADERS = arith.h common.h tar.h xattrs.h
24
tar_SOURCES = \
24
tar_SOURCES = \
25
 buffer.c\
25
 buffer.c\
26
 checkpoint.c\
26
 checkpoint.c\
Lines 42-51 tar_SOURCES = \ Link Here
42
 unlink.c\
42
 unlink.c\
43
 update.c\
43
 update.c\
44
 utf8.c\
44
 utf8.c\
45
 warning.c
45
 warning.c\
46
 xattrs.c
46
47
47
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
48
INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
48
49
49
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
50
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
50
51
51
tar_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS)
52
tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS)
(-)a/src/common.h (+12 lines)
Lines 253-258 GLOBAL int same_owner_option; Link Here
253
/* If positive, preserve permissions when extracting.  */
253
/* If positive, preserve permissions when extracting.  */
254
GLOBAL int same_permissions_option;
254
GLOBAL int same_permissions_option;
255
255
256
/* If positive, save the user and root xattrs.  */
257
GLOBAL int xattrs_option;
258
256
/* When set, strip the given number of file name components from the file name
259
/* When set, strip the given number of file name components from the file name
257
   before extracting */
260
   before extracting */
258
GLOBAL size_t strip_name_components;
261
GLOBAL size_t strip_name_components;
Lines 707-712 extern char *output_start; Link Here
707
710
708
void update_archive (void);
711
void update_archive (void);
709
712
713
/* Module attrs.c.  */
714
#include "xattrs.h"
715
710
/* Module xheader.c.  */
716
/* Module xheader.c.  */
711
717
712
void xheader_decode (struct tar_stat_info *stat);
718
void xheader_decode (struct tar_stat_info *stat);
Lines 727-732 bool xheader_string_end (struct xheader *xhdr, char const *keyword); Link Here
727
bool xheader_keyword_deleted_p (const char *kw);
733
bool xheader_keyword_deleted_p (const char *kw);
728
char *xheader_format_name (struct tar_stat_info *st, const char *fmt,
734
char *xheader_format_name (struct tar_stat_info *st, const char *fmt,
729
			   size_t n);
735
			   size_t n);
736
void xheader_xattr_init(struct tar_stat_info *st);
737
void xheader_xattr_free(struct xattr_array *vals, size_t sz);
738
void xheader_xattr_copy(const struct tar_stat_info *st,
739
                        struct xattr_array **vals, size_t *sz);
740
void xheader_xattr_add(struct tar_stat_info *st,
741
                       const char *key, const char *val, size_t len);
730
742
731
/* Module system.c */
743
/* Module system.c */
732
744
(-)a/src/create.c (-3 / +34 lines)
Lines 936-941 start_header (struct tar_stat_info *st) Link Here
936
      GNAME_TO_CHARS (st->gname, header->header.gname);
936
      GNAME_TO_CHARS (st->gname, header->header.gname);
937
    }
937
    }
938
938
939
  if (archive_format == POSIX_FORMAT)
940
    {
941
      if (xattrs_option > 0)
942
        {
943
          size_t scan_xattr = 0;
944
          struct xattr_array *xattr_map = st->xattr_map;
945
946
          while (scan_xattr < st->xattr_map_size)
947
            {
948
              xheader_store (xattr_map[scan_xattr].xkey, st, &scan_xattr);
949
              ++scan_xattr;
950
            }
951
        }
952
    }
953
939
  return header;
954
  return header;
940
}
955
}
941
956
Lines 1711-1716 dump_file0 (struct tar_stat_info *st, char const *name, char const *p) Link Here
1711
      bool ok;
1726
      bool ok;
1712
      struct stat final_stat;
1727
      struct stat final_stat;
1713
1728
1729
      if (fd == 0)
1730
        xattrs_xattrs_get(st, p, -1);
1731
      else
1732
        xattrs_xattrs_get(st, p, fd);
1733
1714
      if (is_dir)
1734
      if (is_dir)
1715
	{
1735
	{
1716
	  const char *tag_file_name;
1736
	  const char *tag_file_name;
Lines 1829-1834 dump_file0 (struct tar_stat_info *st, char const *name, char const *p) Link Here
1829
      if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT) < size)
1849
      if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT) < size)
1830
	write_long_link (st);
1850
	write_long_link (st);
1831
1851
1852
      xattrs_xattrs_get(st, p, -1);
1853
1832
      block_ordinal = current_block_ordinal ();
1854
      block_ordinal = current_block_ordinal ();
1833
      st->stat.st_size = 0;	/* force 0 size on symlink */
1855
      st->stat.st_size = 0;	/* force 0 size on symlink */
1834
      header = start_header (st);
1856
      header = start_header (st);
Lines 1847-1857 dump_file0 (struct tar_stat_info *st, char const *name, char const *p) Link Here
1847
    }
1869
    }
1848
#endif
1870
#endif
1849
  else if (S_ISCHR (st->stat.st_mode))
1871
  else if (S_ISCHR (st->stat.st_mode))
1850
    type = CHRTYPE;
1872
    {
1873
      type = CHRTYPE;
1874
      xattrs_xattrs_get(st, p, -1);
1875
    }
1851
  else if (S_ISBLK (st->stat.st_mode))
1876
  else if (S_ISBLK (st->stat.st_mode))
1852
    type = BLKTYPE;
1877
    {
1878
      type = BLKTYPE;
1879
      xattrs_xattrs_get(st, p, -1);
1880
    }
1853
  else if (S_ISFIFO (st->stat.st_mode))
1881
  else if (S_ISFIFO (st->stat.st_mode))
1854
    type = FIFOTYPE;
1882
    {
1883
      type = FIFOTYPE;
1884
      xattrs_xattrs_get(st, p, -1);
1885
    }
1855
  else if (S_ISSOCK (st->stat.st_mode))
1886
  else if (S_ISSOCK (st->stat.st_mode))
1856
    {
1887
    {
1857
      WARNOPT (WARN_FILE_IGNORED,
1888
      WARNOPT (WARN_FILE_IGNORED,
(-)a/src/extract.c (+64 lines)
Lines 97-102 struct delayed_set_stat Link Here
97
    /* Directory that the name is relative to.  */
97
    /* Directory that the name is relative to.  */
98
    int change_dir;
98
    int change_dir;
99
99
100
    /* extended attributes*/
101
    size_t xattr_map_size;   /* Size of the xattr map */
102
    struct xattr_array *xattr_map;
100
    /* Length and contents of name.  */
103
    /* Length and contents of name.  */
101
    size_t file_name_len;
104
    size_t file_name_len;
102
    char file_name[1];
105
    char file_name[1];
Lines 134-139 struct delayed_link Link Here
134
       hard-linked together.  */
137
       hard-linked together.  */
135
    struct string_list *sources;
138
    struct string_list *sources;
136
139
140
    size_t xattr_map_size;   /* Size of the xattr map */
141
    struct xattr_array *xattr_map;
142
137
    /* The desired target of the desired link.  */
143
    /* The desired target of the desired link.  */
138
    char target[1];
144
    char target[1];
139
  };
145
  };
Lines 335-340 set_stat (char const *file_name, Link Here
335
	utime_error (file_name);
341
	utime_error (file_name);
336
    }
342
    }
337
343
344
  xattrs_xattrs_set(st, file_name, typeflag);
345
338
  if (0 < same_owner_option && ! interdir)
346
  if (0 < same_owner_option && ! interdir)
339
    {
347
    {
340
      /* Some systems allow non-root users to give files away.  Once this
348
      /* Some systems allow non-root users to give files away.  Once this
Lines 431-436 delay_set_stat (char const *file_name, struct tar_stat_info const *st, Link Here
431
  data->atflag = atflag;
439
  data->atflag = atflag;
432
  data->after_links = 0;
440
  data->after_links = 0;
433
  data->change_dir = chdir_current;
441
  data->change_dir = chdir_current;
442
  if (st)
443
    xheader_xattr_copy (st, &data->xattr_map, &data->xattr_map_size);
444
  else
445
    {
446
      data->xattr_map = NULL;
447
      data->xattr_map_size = 0;
448
    }
434
  strcpy (data->file_name, file_name);
449
  strcpy (data->file_name, file_name);
435
  delayed_set_stat_head = data;
450
  delayed_set_stat_head = data;
436
  if (must_be_dot_or_slash (file_name))
451
  if (must_be_dot_or_slash (file_name))
Lines 673-678 maybe_recoverable (char *file_name, bool regular, bool *interdir_made) Link Here
673
  return RECOVER_NO;
688
  return RECOVER_NO;
674
}
689
}
675
690
691
/* Restore stat extended attributes (xattr) for FILE_NAME, using information
692
   given in *ST.  Restore before extraction because they may affect layout.
693
   If not restoring permissions, invert the
694
   INVERT_PERMISSIONS bits from the file's current permissions.
695
   TYPEFLAG specifies the type of the file.
696
   FILE_CREATED indicates set_xattr has created the file */
697
static int
698
set_xattr (char const *file_name, struct tar_stat_info const *st,
699
	   mode_t invert_permissions, char typeflag, int *file_created)
700
{
701
  int status = 0;
702
  bool interdir_made = false;
703
704
  if ((xattrs_option >= 0) && st->xattr_map_size) {
705
    mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;
706
707
    do
708
      status = mknod (file_name, mode ^ invert_permissions, 0);
709
    while (status && maybe_recoverable ((char *)file_name, false, &interdir_made));
710
    xattrs_xattrs_set(st, file_name, typeflag);
711
    *file_created = 1;
712
  }
713
  return(status);
714
}
715
676
/* Fix the statuses of all directories whose statuses need fixing, and
716
/* Fix the statuses of all directories whose statuses need fixing, and
677
   which are not ancestors of FILE_NAME.  If AFTER_LINKS is
717
   which are not ancestors of FILE_NAME.  If AFTER_LINKS is
678
   nonzero, do this for all such directories; otherwise, stop at the
718
   nonzero, do this for all such directories; otherwise, stop at the
Lines 733-744 apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links) Link Here
733
	  sb.stat.st_gid = data->gid;
773
	  sb.stat.st_gid = data->gid;
734
	  sb.atime = data->atime;
774
	  sb.atime = data->atime;
735
	  sb.mtime = data->mtime;
775
	  sb.mtime = data->mtime;
776
	  sb.xattr_map = data->xattr_map;
777
	  sb.xattr_map_size = data->xattr_map_size;
736
	  set_stat (data->file_name, &sb,
778
	  set_stat (data->file_name, &sb,
737
		    -1, current_mode, current_mode_mask,
779
		    -1, current_mode, current_mode_mask,
738
		    DIRTYPE, data->interdir, data->atflag);
780
		    DIRTYPE, data->interdir, data->atflag);
739
	}
781
	}
740
782
741
      delayed_set_stat_head = data->next;
783
      delayed_set_stat_head = data->next;
784
      xheader_xattr_free (data->xattr_map, data->xattr_map_size);
742
      free (data);
785
      free (data);
743
    }
786
    }
744
}
787
}
Lines 854-859 extract_dir (char *file_name, int typeflag) Link Here
854
897
855
static int
898
static int
856
open_output_file (char const *file_name, int typeflag, mode_t mode,
899
open_output_file (char const *file_name, int typeflag, mode_t mode,
900
                  int file_created,
857
		  mode_t *current_mode, mode_t *current_mode_mask)
901
		  mode_t *current_mode, mode_t *current_mode_mask)
858
{
902
{
859
  int fd;
903
  int fd;
Lines 864-869 open_output_file (char const *file_name, int typeflag, mode_t mode, Link Here
864
		     ? O_TRUNC | (dereference_option ? 0 : O_NOFOLLOW)
908
		     ? O_TRUNC | (dereference_option ? 0 : O_NOFOLLOW)
865
		     : O_EXCL));
909
		     : O_EXCL));
866
910
911
  /* File might be created in set_xattr. So clear O_EXCL to avoid open() failure */
912
  if (file_created)
913
    openflag = openflag & ~O_EXCL;
914
867
  if (typeflag == CONTTYPE)
915
  if (typeflag == CONTTYPE)
868
    {
916
    {
869
      static int conttype_diagnosed;
917
      static int conttype_diagnosed;
Lines 934-939 extract_file (char *file_name, int typeflag) Link Here
934
  bool interdir_made = false;
982
  bool interdir_made = false;
935
  mode_t mode = (current_stat_info.stat.st_mode & MODE_RWX
983
  mode_t mode = (current_stat_info.stat.st_mode & MODE_RWX
936
		 & ~ (0 < same_owner_option ? S_IRWXG | S_IRWXO : 0));
984
		 & ~ (0 < same_owner_option ? S_IRWXG | S_IRWXO : 0));
985
  mode_t invert_permissions = 0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
937
  mode_t current_mode = 0;
986
  mode_t current_mode = 0;
938
  mode_t current_mode_mask = 0;
987
  mode_t current_mode_mask = 0;
939
988
Lines 950-956 extract_file (char *file_name, int typeflag) Link Here
950
    }
999
    }
951
  else
1000
  else
952
    {
1001
    {
1002
      int file_created = 0;
1003
      if (set_xattr (file_name, &current_stat_info, invert_permissions,
1004
		     typeflag, &file_created))
1005
        {
1006
          skip_member ();
1007
          open_error (file_name);
1008
          return 1;
1009
        }
1010
953
      while ((fd = open_output_file (file_name, typeflag, mode,
1011
      while ((fd = open_output_file (file_name, typeflag, mode,
1012
                                     file_created,
954
				     &current_mode, &current_mode_mask))
1013
				     &current_mode, &current_mode_mask))
955
	     < 0)
1014
	     < 0)
956
	{
1015
	{
Lines 1091-1096 create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made) Link Here
1091
			    + strlen (file_name) + 1);
1150
			    + strlen (file_name) + 1);
1092
      p->sources->next = 0;
1151
      p->sources->next = 0;
1093
      strcpy (p->sources->string, file_name);
1152
      strcpy (p->sources->string, file_name);
1153
      xheader_xattr_copy (&current_stat_info, &p->xattr_map, &p->xattr_map_size);
1094
      strcpy (p->target, current_stat_info.link_name);
1154
      strcpy (p->target, current_stat_info.link_name);
1095
1155
1096
      h = delayed_set_stat_head;
1156
      h = delayed_set_stat_head;
Lines 1525-1530 apply_delayed_links (void) Link Here
1525
		  st1.stat.st_gid = ds->gid;
1585
		  st1.stat.st_gid = ds->gid;
1526
		  st1.atime = ds->atime;
1586
		  st1.atime = ds->atime;
1527
		  st1.mtime = ds->mtime;
1587
		  st1.mtime = ds->mtime;
1588
                  st1.xattr_map = ds->xattr_map;
1589
                  st1.xattr_map_size = ds->xattr_map_size;
1528
		  set_stat (source, &st1, -1, 0, 0, SYMTYPE,
1590
		  set_stat (source, &st1, -1, 0, 0, SYMTYPE,
1529
			    false, AT_SYMLINK_NOFOLLOW);
1591
			    false, AT_SYMLINK_NOFOLLOW);
1530
		  valid_source = source;
1592
		  valid_source = source;
Lines 1539-1544 apply_delayed_links (void) Link Here
1539
	  sources = next;
1601
	  sources = next;
1540
	}
1602
	}
1541
1603
1604
   xheader_xattr_free (ds->xattr_map, ds->xattr_map_size);
1605
1542
      {
1606
      {
1543
	struct delayed_link *next = ds->next;
1607
	struct delayed_link *next = ds->next;
1544
	free (ds);
1608
	free (ds);
(-)a/src/list.c (+2 lines)
Lines 604-609 decode_header (union block *header, struct tar_stat_info *stat_info, Link Here
604
  assign_string (&stat_info->gname,
604
  assign_string (&stat_info->gname,
605
		 header->header.gname[0] ? header->header.gname : NULL);
605
		 header->header.gname[0] ? header->header.gname : NULL);
606
606
607
  xheader_xattr_init(stat_info);
608
607
  if (format == OLDGNU_FORMAT && incremental_option)
609
  if (format == OLDGNU_FORMAT && incremental_option)
608
    {
610
    {
609
      stat_info->atime.tv_sec = TIME_FROM_HEADER (header->oldgnu_header.atime);
611
      stat_info->atime.tv_sec = TIME_FROM_HEADER (header->oldgnu_header.atime);
(-)a/src/tar.c (-1 / +26 lines)
Lines 304-309 enum Link Here
304
  NO_UNQUOTE_OPTION,
304
  NO_UNQUOTE_OPTION,
305
  NO_WILDCARDS_MATCH_SLASH_OPTION,
305
  NO_WILDCARDS_MATCH_SLASH_OPTION,
306
  NO_WILDCARDS_OPTION,
306
  NO_WILDCARDS_OPTION,
307
  NO_XATTR_OPTION,
307
  NULL_OPTION,
308
  NULL_OPTION,
308
  NUMERIC_OWNER_OPTION,
309
  NUMERIC_OWNER_OPTION,
309
  OCCURRENCE_OPTION,
310
  OCCURRENCE_OPTION,
Lines 340-346 enum Link Here
340
  VOLNO_FILE_OPTION,
341
  VOLNO_FILE_OPTION,
341
  WARNING_OPTION,
342
  WARNING_OPTION,
342
  WILDCARDS_MATCH_SLASH_OPTION,
343
  WILDCARDS_MATCH_SLASH_OPTION,
343
  WILDCARDS_OPTION
344
  WILDCARDS_OPTION,
345
  XATTR_OPTION
344
};
346
};
345
347
346
const char *argp_program_version = "tar (" PACKAGE_NAME ") " VERSION;
348
const char *argp_program_version = "tar (" PACKAGE_NAME ") " VERSION;
Lines 516-521 static struct argp_option options[] = { Link Here
516
  {"preserve-order", 's', 0, 0,
518
  {"preserve-order", 's', 0, 0,
517
   N_("sort names to extract to match archive"), GRID+1 },
519
   N_("sort names to extract to match archive"), GRID+1 },
518
  {"same-order", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
520
  {"same-order", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
521
  {"xattrs", XATTR_OPTION, 0, 0,
522
   N_("Save the user/root xattrs to the archive"), GRID+1 },
523
  {"no-xattrs", NO_XATTR_OPTION, 0, 0,
524
   N_("Don't extract the user/root xattrs from the archive"), GRID+1 },
519
  {"preserve", PRESERVE_OPTION, 0, 0,
525
  {"preserve", PRESERVE_OPTION, 0, 0,
520
   N_("same as both -p and -s"), GRID+1 },
526
   N_("same as both -p and -s"), GRID+1 },
521
  {"delay-directory-restore", DELAY_DIRECTORY_RESTORE_OPTION, 0, 0,
527
  {"delay-directory-restore", DELAY_DIRECTORY_RESTORE_OPTION, 0, 0,
Lines 2079-2084 parse_opt (int key, char *arg, struct argp_state *state) Link Here
2079
      same_permissions_option = -1;
2085
      same_permissions_option = -1;
2080
      break;
2086
      break;
2081
2087
2088
    case XATTR_OPTION:
2089
      set_archive_format ("posix");
2090
      xattrs_option = 1;
2091
      break;
2092
2093
    case NO_XATTR_OPTION:
2094
      xattrs_option = -1;
2095
      break;
2096
2082
    case RECURSION_OPTION:
2097
    case RECURSION_OPTION:
2083
      recursion_option = FNM_LEADING_DIR;
2098
      recursion_option = FNM_LEADING_DIR;
2084
      break;
2099
      break;
Lines 2461-2466 decode_options (int argc, char **argv) Link Here
2461
	  || subcommand_option != LIST_SUBCOMMAND))
2476
	  || subcommand_option != LIST_SUBCOMMAND))
2462
    USAGE_ERROR ((0, 0, _("--pax-option can be used only on POSIX archives")));
2477
    USAGE_ERROR ((0, 0, _("--pax-option can be used only on POSIX archives")));
2463
2478
2479
  /* star create's non-POSIX typed archives with xattr support, so allow the
2480
     extra headers */
2481
  if ((xattrs_option > 0)
2482
      && archive_format != POSIX_FORMAT
2483
      && (subcommand_option != EXTRACT_SUBCOMMAND
2484
	  || subcommand_option != DIFF_SUBCOMMAND
2485
	  || subcommand_option != LIST_SUBCOMMAND))
2486
    USAGE_ERROR ((0, 0, _("--xattrs can be used only on POSIX archives")));
2487
2464
  /* If ready to unlink hierarchies, so we are for simpler files.  */
2488
  /* If ready to unlink hierarchies, so we are for simpler files.  */
2465
  if (recursive_unlink_option)
2489
  if (recursive_unlink_option)
2466
    old_files_option = UNLINK_FIRST_OLD_FILES;
2490
    old_files_option = UNLINK_FIRST_OLD_FILES;
Lines 2713-2718 void Link Here
2713
tar_stat_destroy (struct tar_stat_info *st)
2737
tar_stat_destroy (struct tar_stat_info *st)
2714
{
2738
{
2715
  tar_stat_close (st);
2739
  tar_stat_close (st);
2740
  xheader_xattr_free (st->xattr_map, st->xattr_map_size);
2716
  free (st->orig_file_name);
2741
  free (st->orig_file_name);
2717
  free (st->file_name);
2742
  free (st->file_name);
2718
  free (st->link_name);
2743
  free (st->link_name);
(-)a/src/tar.h (+12 lines)
Lines 276-281 struct xheader Link Here
276
  uintmax_t string_length;
276
  uintmax_t string_length;
277
};
277
};
278
278
279
/* Information about xattrs for a file.  */
280
struct xattr_array
281
  {
282
    char *xkey;
283
    char *xval_ptr;
284
    size_t xval_len;
285
  };
286
279
struct tar_stat_info
287
struct tar_stat_info
280
{
288
{
281
  char *orig_file_name;     /* name of file read from the archive header */
289
  char *orig_file_name;     /* name of file read from the archive header */
Lines 287-292 struct tar_stat_info Link Here
287
295
288
  char          *uname;     /* user name of owner */
296
  char          *uname;     /* user name of owner */
289
  char          *gname;     /* group name of owner */
297
  char          *gname;     /* group name of owner */
298
290
  struct stat   stat;       /* regular filesystem stat */
299
  struct stat   stat;       /* regular filesystem stat */
291
300
292
  /* STAT doesn't always have access, data modification, and status
301
  /* STAT doesn't always have access, data modification, and status
Lines 309-314 struct tar_stat_info Link Here
309
  size_t sparse_map_size;   /* Size of the sparse map */
318
  size_t sparse_map_size;   /* Size of the sparse map */
310
  struct sp_array *sparse_map;
319
  struct sp_array *sparse_map;
311
320
321
  size_t xattr_map_size;   /* Size of the xattr map */
322
  struct xattr_array *xattr_map;
323
312
  /* Extended headers */
324
  /* Extended headers */
313
  struct xheader xhdr;
325
  struct xheader xhdr;
314
326
(-)a/src/xattrs.c (+181 lines)
Line 0 Link Here
1
/* Create a tar archive.
2
3
   Copyright (C) 2006 Free Software Foundation, Inc.
4
5
   Written by James Antill, on 2006-07-27.
6
7
   This program is free software; you can redistribute it and/or modify it
8
   under the terms of the GNU General Public License as published by the
9
   Free Software Foundation; either version 2, or (at your option) any later
10
   version.
11
12
   This program is distributed in the hope that it will be useful, but
13
   WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15
   Public License for more details.
16
17
   You should have received a copy of the GNU General Public License along
18
   with this program; if not, write to the Free Software Foundation, Inc.,
19
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
20
21
#include <system.h>
22
23
#include <quotearg.h>
24
25
#include "common.h"
26
27
28
#ifndef HAVE_ATTR_XATTR_H
29
# undef HAVE_XATTRS
30
#endif
31
32
#ifdef HAVE_ATTR_XATTR_H
33
# include <attr/xattr.h>
34
#endif
35
36
37
void xattrs_xattrs_get(struct tar_stat_info *st, char const *file_name, int fd)
38
{
39
  if (xattrs_option > 0)
40
    { /* get all xattrs ... this include security.* and system.* if
41
         available. We filter them here, but we have to filter them
42
         in xattrs_xattrs_set() anyway.
43
      */
44
      static ssize_t xsz = 1024;
45
      static char *xatrs = NULL;
46
      ssize_t xret = -1;
47
48
#ifndef HAVE_XATTRS
49
      static int done = 0;
50
      if ((xattrs_option > 0) && !done)
51
          WARN ((0, 0, _("Xattr support requested, but not available")));
52
      done = 1;
53
#else
54
55
      if (!xatrs) xatrs = xmalloc (xsz);
56
57
      while (((fd == -1) ?
58
              ((xret = llistxattr (file_name, xatrs, xsz)) == -1) :
59
              ((xret = flistxattr (fd, xatrs, xsz)) == -1)) &&
60
             (errno == ERANGE))
61
        {
62
          xsz <<= 1;
63
          xatrs = xrealloc (xatrs, xsz);
64
        }
65
66
      if (xret == -1)
67
        call_arg_warn ((fd == -1) ? "llistxattrs" : "flistxattrs", file_name);
68
      else
69
        {
70
          const char *attr = xatrs;
71
          static ssize_t asz = 1024;
72
          static char *val = NULL;
73
74
          if (!val) val = xmalloc (asz);
75
76
          while (xret > 0)
77
            {
78
              size_t len = strlen (attr);
79
              ssize_t aret = 0;
80
81
              /* Archive all xattrs during creation, decide at extraction time
82
               * which ones are of interest/use for the target filesystem. */
83
              while (((fd == -1) ?
84
                      ((aret = lgetxattr (file_name, attr, val, asz)) == -1) :
85
                      ((aret = fgetxattr (fd, attr, val, asz)) == -1)) &&
86
                     (errno == ERANGE))
87
                {
88
                  asz <<= 1;
89
                  val = xrealloc (val, asz);
90
                }
91
92
              if (aret != -1)
93
                xheader_xattr_add (st, attr, val, aret);
94
              else if (errno != ENOATTR)
95
                call_arg_warn ((fd==-1) ? "lgetxattr" : "fgetxattr", file_name);
96
97
              attr += len + 1;
98
              xret -= len + 1;
99
            }
100
        }
101
#endif
102
    }
103
}
104
105
static void xattrs__fd_set(struct tar_stat_info const *st,
106
                           char const *file_name, char typeflag,
107
                           const char *attr,
108
                           const char *ptr, size_t len)
109
{
110
#ifdef HAVE_XATTRS
111
  if (ptr)
112
    {
113
      const char *sysname = "setxattr";
114
      int ret = -1;
115
116
      if (typeflag != SYMTYPE)
117
        ret = setxattr (file_name, attr, ptr, len, 0);
118
      else
119
        {
120
          sysname = "lsetxattr";
121
          ret = lsetxattr (file_name, attr, ptr, len, 0);
122
        }
123
124
      /* do not print warnings when SELinux is disabled */
125
      if ((ret == -1) && (errno != EPERM) && (errno != ENOTSUP))
126
        call_arg_error(sysname, file_name);
127
    }
128
#endif
129
}
130
131
static char *skip_to_ext_fields(char *ptr)
132
{
133
  ptr += strcspn(ptr, ":,\n"); /* skip tag name. Ie. user/group/default/mask */
134
135
  if (*ptr != ':')
136
    return (ptr); /* error? no user/group field */
137
  ++ptr;
138
139
  ptr += strcspn(ptr, ":,\n"); /* skip user/group name */
140
141
  if (*ptr != ':')
142
    return (ptr); /* error? no perms field */
143
  ++ptr;
144
145
  ptr += strcspn(ptr, ":,\n"); /* skip perms */
146
147
  if (*ptr != ':')
148
    return (ptr); /* no extra fields */
149
150
  return (ptr);
151
}
152
153
void xattrs_xattrs_set(struct tar_stat_info const *st,
154
                       char const *file_name, char typeflag)
155
{
156
  if ((xattrs_option >= 0) && st->xattr_map_size)
157
    {
158
      size_t scan = 0;
159
160
#ifndef HAVE_XATTRS
161
      static int done = 0;
162
      if (!done)
163
          WARN ((0, 0, _("Xattr support requested, but not available")));
164
      done = 1;
165
#else
166
      while (scan < st->xattr_map_size)
167
        {
168
          char *keyword = st->xattr_map[scan].xkey;
169
170
          /* assert (!memcpy (keyword, "SCHILY.xattr.", strlen("SCHILY.xattr."))); */
171
          keyword += strlen("SCHILY.xattr.");
172
173
          xattrs__fd_set (st, file_name, typeflag, keyword,
174
                          st->xattr_map[scan].xval_ptr,
175
                          st->xattr_map[scan].xval_len);
176
177
          ++scan;
178
        }
179
#endif
180
    }
181
}
(-)a/src/xattrs.h (+6 lines)
Line 0 Link Here
1
2
extern void xattrs_xattrs_get(struct tar_stat_info *st,
3
                              char const *file_name, int fd);
4
5
extern void xattrs_xattrs_set(struct tar_stat_info const *st,
6
                              char const *file_name, char typeflag);
(-)a/src/xheader.c (-31 / +133 lines)
Lines 460-465 xheader_write_global (struct xheader *xhdr) Link Here
460
    }
460
    }
461
}
461
}
462
462
463
void xheader_xattr_init(struct tar_stat_info *st)
464
{
465
  st->xattr_map = NULL;
466
  st->xattr_map_size = 0;
467
}
468
469
void xheader_xattr_free(struct xattr_array *xattr_map, size_t xattr_map_size)
470
{
471
  size_t scan = 0;
472
473
  while (scan < xattr_map_size)
474
    {
475
      free (xattr_map[scan].xkey);
476
      free (xattr_map[scan].xval_ptr);
477
478
      ++scan;
479
    }
480
  free (xattr_map);
481
}
482
483
static void xheader_xattr__add(struct xattr_array **xattr_map,
484
                               size_t *xattr_map_size,
485
                               const char *key, const char *val, size_t len)
486
{
487
  size_t pos = (*xattr_map_size)++;
488
489
  *xattr_map = xrealloc (*xattr_map,
490
                         *xattr_map_size * sizeof(struct xattr_array));
491
  (*xattr_map)[pos].xkey = xstrdup (key);
492
  (*xattr_map)[pos].xval_ptr = xmemdup (val, len + 1);
493
  (*xattr_map)[pos].xval_len = len;
494
}
495
496
void xheader_xattr_add(struct tar_stat_info *st,
497
                       const char *key, const char *val, size_t len)
498
{
499
  size_t klen = strlen (key);
500
  char *xkey = xmalloc (strlen("SCHILY.xattr.") + klen + 1);
501
  char *tmp = xkey;
502
503
  tmp = stpcpy (tmp, "SCHILY.xattr.");
504
  tmp = stpcpy (tmp, key);
505
506
  xheader_xattr__add (&st->xattr_map, &st->xattr_map_size, xkey, val, len);
507
508
  free (xkey);
509
}
510
511
void xheader_xattr_copy(const struct tar_stat_info *st,
512
                        struct xattr_array **xattr_map, size_t *xattr_map_size)
513
{
514
  size_t scan = 0;
515
516
  *xattr_map = NULL;
517
  *xattr_map_size = 0;
518
519
  while (scan < st->xattr_map_size)
520
    {
521
      char  *key = st->xattr_map[scan].xkey;
522
      char  *val = st->xattr_map[scan].xval_ptr;
523
      size_t len = st->xattr_map[scan].xval_len;
524
525
      xheader_xattr__add(xattr_map, xattr_map_size, key, val, len);
526
527
      ++scan;
528
    }
529
}
530
463
531
464
/* General Interface */
532
/* General Interface */
465
533
Lines 473-478 struct xhdr_tab Link Here
473
		 struct xheader *, void const *data);
541
		 struct xheader *, void const *data);
474
  void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);
542
  void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);
475
  int flags;
543
  int flags;
544
  bool prefix;
476
};
545
};
477
546
478
/* This declaration must be extern, because ISO C99 section 6.9.2
547
/* This declaration must be extern, because ISO C99 section 6.9.2
Lines 489-496 locate_handler (char const *keyword) Link Here
489
  struct xhdr_tab const *p;
558
  struct xhdr_tab const *p;
490
559
491
  for (p = xhdr_tab; p->keyword; p++)
560
  for (p = xhdr_tab; p->keyword; p++)
492
    if (strcmp (p->keyword, keyword) == 0)
561
    if (p->prefix)
493
      return p;
562
      {
563
        if (strncmp (p->keyword, keyword, strlen(p->keyword)) == 0)
564
          return p;
565
      }
566
  else
567
      {
568
        if (strcmp (p->keyword, keyword) == 0)
569
          return p;
570
      }
571
494
  return NULL;
572
  return NULL;
495
}
573
}
496
574
Lines 500-506 xheader_protected_pattern_p (const char *pattern) Link Here
500
  struct xhdr_tab const *p;
578
  struct xhdr_tab const *p;
501
579
502
  for (p = xhdr_tab; p->keyword; p++)
580
  for (p = xhdr_tab; p->keyword; p++)
503
    if ((p->flags & XHDR_PROTECTED) && fnmatch (pattern, p->keyword, 0) == 0)
581
    if (!p->prefix && (p->flags & XHDR_PROTECTED) && fnmatch (pattern, p->keyword, 0) == 0)
504
      return true;
582
      return true;
505
  return false;
583
  return false;
506
}
584
}
Lines 511-517 xheader_protected_keyword_p (const char *keyword) Link Here
511
  struct xhdr_tab const *p;
589
  struct xhdr_tab const *p;
512
590
513
  for (p = xhdr_tab; p->keyword; p++)
591
  for (p = xhdr_tab; p->keyword; p++)
514
    if ((p->flags & XHDR_PROTECTED) && strcmp (p->keyword, keyword) == 0)
592
    if (!p->prefix && (p->flags & XHDR_PROTECTED) && strcmp (p->keyword, keyword) == 0)
515
      return true;
593
      return true;
516
  return false;
594
  return false;
517
}
595
}
Lines 1470-1475 volume_filename_decoder (struct tar_stat_info *st, Link Here
1470
}
1548
}
1471
1549
1472
static void
1550
static void
1551
xattr_coder (struct tar_stat_info const *st , char const *keyword,
1552
             struct xheader *xhdr, void const *data)
1553
{
1554
  struct xattr_array *xattr_map = st->xattr_map;
1555
  const size_t *off = data;
1556
  xheader_print_n (xhdr, keyword,
1557
                   xattr_map[*off].xval_ptr, xattr_map[*off].xval_len);
1558
}
1559
1560
static void
1561
xattr_decoder (struct tar_stat_info *st,
1562
               char const *keyword, char const *arg, size_t size)
1563
{
1564
  char *xstr = NULL;
1565
1566
  xstr = xmemdup(arg, size + 1);
1567
  xheader_xattr_add(st, keyword + strlen("SCHILY.xattr."), xstr, size);
1568
  free(xstr);
1569
}
1570
1571
static void
1473
sparse_major_coder (struct tar_stat_info const *st, char const *keyword,
1572
sparse_major_coder (struct tar_stat_info const *st, char const *keyword,
1474
		    struct xheader *xhdr, void const *data)
1573
		    struct xheader *xhdr, void const *data)
1475
{
1574
{
Lines 1506-1558 sparse_minor_decoder (struct tar_stat_info *st, Link Here
1506
}
1605
}
1507
1606
1508
struct xhdr_tab const xhdr_tab[] = {
1607
struct xhdr_tab const xhdr_tab[] = {
1509
  { "atime",	atime_coder,	atime_decoder,	  0 },
1608
  { "atime",   atime_coder,    atime_decoder,    0, false },
1510
  { "comment",	dummy_coder,	dummy_decoder,	  0 },
1609
  { "comment", dummy_coder,    dummy_decoder,    0, false },
1511
  { "charset",	dummy_coder,	dummy_decoder,	  0 },
1610
  { "charset", dummy_coder,    dummy_decoder,    0, false },
1512
  { "ctime",	ctime_coder,	ctime_decoder,	  0 },
1611
  { "ctime",   ctime_coder,    ctime_decoder,    0, false },
1513
  { "gid",	gid_coder,	gid_decoder,	  0 },
1612
  { "gid",     gid_coder,      gid_decoder,      0, false },
1514
  { "gname",	gname_coder,	gname_decoder,	  0 },
1613
  { "gname",   gname_coder,    gname_decoder,    0, false },
1515
  { "linkpath", linkpath_coder, linkpath_decoder, 0 },
1614
  { "linkpath", linkpath_coder, linkpath_decoder, 0, false },
1516
  { "mtime",	mtime_coder,	mtime_decoder,	  0 },
1615
  { "mtime",   mtime_coder,    mtime_decoder,    0, false },
1517
  { "path",	path_coder,	path_decoder,	  0 },
1616
  { "path",    path_coder,     path_decoder,     0, false },
1518
  { "size",	size_coder,	size_decoder,	  0 },
1617
  { "size",    size_coder,     size_decoder,     0, false },
1519
  { "uid",	uid_coder,	uid_decoder,	  0 },
1618
  { "uid",     uid_coder,      uid_decoder,      0, false },
1520
  { "uname",	uname_coder,	uname_decoder,	  0 },
1619
  { "uname",   uname_coder,    uname_decoder,    0, false },
1521
1620
1522
  /* Sparse file handling */
1621
  /* Sparse file handling */
1523
  { "GNU.sparse.name",       path_coder, path_decoder,
1622
  { "GNU.sparse.name",       path_coder, path_decoder,
1524
    XHDR_PROTECTED },
1623
    XHDR_PROTECTED, false },
1525
  { "GNU.sparse.major",      sparse_major_coder, sparse_major_decoder,
1624
  { "GNU.sparse.major",      sparse_major_coder, sparse_major_decoder,
1526
    XHDR_PROTECTED },
1625
    XHDR_PROTECTED, false },
1527
  { "GNU.sparse.minor",      sparse_minor_coder, sparse_minor_decoder,
1626
  { "GNU.sparse.minor",      sparse_minor_coder, sparse_minor_decoder,
1528
    XHDR_PROTECTED },
1627
    XHDR_PROTECTED, false },
1529
  { "GNU.sparse.realsize",   sparse_size_coder, sparse_size_decoder,
1628
  { "GNU.sparse.realsize",   sparse_size_coder, sparse_size_decoder,
1530
    XHDR_PROTECTED },
1629
    XHDR_PROTECTED, false },
1531
  { "GNU.sparse.numblocks",  sparse_numblocks_coder, sparse_numblocks_decoder,
1630
  { "GNU.sparse.numblocks",  sparse_numblocks_coder, sparse_numblocks_decoder,
1532
    XHDR_PROTECTED },
1631
    XHDR_PROTECTED, false },
1533
1632
1534
  /* tar 1.14 - 1.15.90 keywords. */
1633
  /* tar 1.14 - 1.15.90 keywords. */
1535
  { "GNU.sparse.size",       sparse_size_coder, sparse_size_decoder,
1634
  { "GNU.sparse.size",       sparse_size_coder, sparse_size_decoder,
1536
    XHDR_PROTECTED },
1635
    XHDR_PROTECTED, false },
1537
  /* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
1636
  /* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
1538
     headers, and each of them was meaningful. It confilcted with POSIX specs,
1637
     headers, and each of them was meaningful. It confilcted with POSIX specs,
1539
     which requires that "when extended header records conflict, the last one
1638
     which requires that "when extended header records conflict, the last one
1540
     given in the header shall take precedence." */
1639
     given in the header shall take precedence." */
1541
  { "GNU.sparse.offset",     sparse_offset_coder, sparse_offset_decoder,
1640
  { "GNU.sparse.offset",     sparse_offset_coder, sparse_offset_decoder,
1542
    XHDR_PROTECTED },
1641
    XHDR_PROTECTED, false },
1543
  { "GNU.sparse.numbytes",   sparse_numbytes_coder, sparse_numbytes_decoder,
1642
  { "GNU.sparse.numbytes",   sparse_numbytes_coder, sparse_numbytes_decoder,
1544
    XHDR_PROTECTED },
1643
    XHDR_PROTECTED, false },
1545
  /* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
1644
  /* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
1546
  { "GNU.sparse.map",        NULL /* Unused, see pax_dump_header() */,
1645
  { "GNU.sparse.map",        NULL /* Unused, see pax_dump_header() */,
1547
    sparse_map_decoder, 0 },
1646
    sparse_map_decoder, 0, false },
1548
1647
1549
  { "GNU.dumpdir",           dumpdir_coder, dumpdir_decoder,
1648
  { "GNU.dumpdir",           dumpdir_coder, dumpdir_decoder,
1550
    XHDR_PROTECTED },
1649
    XHDR_PROTECTED, false },
1551
1650
1552
  /* Keeps the tape/volume label. May be present only in the global headers.
1651
  /* Keeps the tape/volume label. May be present only in the global headers.
1553
     Equivalent to GNUTYPE_VOLHDR.  */
1652
     Equivalent to GNUTYPE_VOLHDR.  */
1554
  { "GNU.volume.label", volume_label_coder, volume_label_decoder,
1653
  { "GNU.volume.label", volume_label_coder, volume_label_decoder,
1555
    XHDR_PROTECTED | XHDR_GLOBAL },
1654
    XHDR_PROTECTED | XHDR_GLOBAL, false },
1556
1655
1557
  /* These may be present in a first global header of the archive.
1656
  /* These may be present in a first global header of the archive.
1558
     They provide the same functionality as GNUTYPE_MULTIVOL header.
1657
     They provide the same functionality as GNUTYPE_MULTIVOL header.
Lines 1561-1571 struct xhdr_tab const xhdr_tab[] = { Link Here
1561
     GNU.volume.offset keeps the offset of the start of this volume,
1660
     GNU.volume.offset keeps the offset of the start of this volume,
1562
     otherwise kept in oldgnu_header.offset.  */
1661
     otherwise kept in oldgnu_header.offset.  */
1563
  { "GNU.volume.filename", volume_label_coder, volume_filename_decoder,
1662
  { "GNU.volume.filename", volume_label_coder, volume_filename_decoder,
1564
    XHDR_PROTECTED | XHDR_GLOBAL },
1663
    XHDR_PROTECTED | XHDR_GLOBAL, false },
1565
  { "GNU.volume.size", volume_size_coder, volume_size_decoder,
1664
  { "GNU.volume.size", volume_size_coder, volume_size_decoder,
1566
    XHDR_PROTECTED | XHDR_GLOBAL },
1665
    XHDR_PROTECTED | XHDR_GLOBAL, false },
1567
  { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder,
1666
  { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder,
1568
    XHDR_PROTECTED | XHDR_GLOBAL },
1667
    XHDR_PROTECTED | XHDR_GLOBAL, false },
1668
1669
  /* xattrs use the star format.  note we only save some variants... */
1670
  { "SCHILY.xattr", xattr_coder, xattr_decoder, 0, true },
1569
1671
1570
  { NULL, NULL, NULL, 0 }
1672
  { NULL, NULL, NULL, 0, false }
1571
};
1673
};

Return to bug 382067