[tar] Allow to store extended attribute keywords containing '=' character

Pavel Raiskup praiskup at fedoraproject.org
Wed Oct 10 09:03:29 UTC 2012


commit 9989b8ed46702391a012ba08d6409707a5853f5c
Author: Pavel Raiskup <praiskup at redhat.com>
Date:   Tue Oct 9 14:20:22 2012 +0200

    Allow to store extended attribute keywords containing '=' character

 tar-1.26-xattrs-equal-sign.patch |  236 ++++++++++++++++++++++++++++++++++++++
 tar.spec                         |    4 +-
 2 files changed, 239 insertions(+), 1 deletions(-)
---
diff --git a/tar-1.26-xattrs-equal-sign.patch b/tar-1.26-xattrs-equal-sign.patch
new file mode 100644
index 0000000..60279da
--- /dev/null
+++ b/tar-1.26-xattrs-equal-sign.patch
@@ -0,0 +1,236 @@
+diff --git a/src/xheader.c b/src/xheader.c
+index e785248..de47388 100644
+--- a/src/xheader.c
++++ b/src/xheader.c
+@@ -499,6 +499,43 @@ static void xheader_xattr__add (struct xattr_array **xattr_map,
+   (*xattr_map)[pos].xval_len = len;
+ }
+ 
++/* This is reversal function for xattr_encode_keyword.  See comment for
++   xattr_encode_keyword() for more info. */
++static void xattr_decode_keyword (char *keyword)
++{
++  char *kpr, *kpl; /* keyword pointer left/right */
++  kpr = kpl = keyword;
++
++  for (;;)
++    {
++      if (*kpr == '%')
++        {
++          if (kpr[1] == '3' && kpr[2] == 'D')
++            {
++              *kpl = '=';
++              kpr += 3;
++              kpl ++;
++              continue;
++            }
++          else if (kpr[1] == '2' && kpr[2] == '5')
++            {
++              *kpl = '%';
++              kpr += 3;
++              kpl ++;
++              continue;
++            }
++        }
++
++      *kpl = *kpr;
++
++      if (*kpr == 0)
++        break;
++
++      kpr++;
++      kpl++;
++    }
++}
++
+ void xheader_xattr_add(struct tar_stat_info *st,
+                        const char *key, const char *val, size_t len)
+ {
+@@ -807,15 +844,70 @@ xheader_read (struct xheader *xhdr, union block *p, size_t size)
+   while (size > 0);
+ }
+ 
++/* xattr_encode_keyword() substitutes '=' ~~> '%3D' and '%' ~~> '%25'
++   in extended attribute keywords.  This is needed because the '=' character
++   has special purpose in extended attribute header - it splits keyword and
++   value part of header.  If there was the '=' occurrence allowed inside
++   keyword, there would be no unambiguous way how to decode this extended
++   attribute.
++
++   (http://lists.gnu.org/archive/html/bug-tar/2012-10/msg00017.html)
++ */
++static char *xattr_encode_keyword(const char *keyword)
++{
++  static char *encode_buffer = NULL;
++  static size_t encode_buffer_size = 0;
++  size_t bp; /* keyword/buffer pointers */
++
++  if (!encode_buffer)
++    {
++      encode_buffer_size = 256;
++      encode_buffer = xmalloc (encode_buffer_size);
++    }
++  else
++    *encode_buffer = 0;
++
++  for (bp = 0; *keyword != 0; ++bp, ++keyword)
++    {
++      char c = *keyword;
++
++      if (bp + 2 /* enough for URL encoding also.. */ >= encode_buffer_size)
++        {
++          encode_buffer = x2realloc (encode_buffer, &encode_buffer_size);
++        }
++
++      if (c == '%')
++        {
++          strcpy (encode_buffer + bp, "%25");
++          bp += 2;
++        }
++      else if (c == '=')
++        {
++          strcpy (encode_buffer + bp, "%3D");
++          bp += 2;
++        }
++      else
++        encode_buffer[bp] = c;
++    }
++
++  encode_buffer[bp] = 0;
++
++  return encode_buffer;
++}
++
+ static void
+ xheader_print_n (struct xheader *xhdr, char const *keyword,
+ 		 char const *value, size_t vsize)
+ {
+-  size_t len = strlen (keyword) + vsize + 3; /* ' ' + '=' + '\n' */
+   size_t p;
+   size_t n = 0;
+   char nbuf[UINTMAX_STRSIZE_BOUND];
+   char const *np;
++  size_t len, klen;
++
++  keyword = xattr_encode_keyword (keyword);
++  klen = strlen (keyword);
++  len = klen + vsize + 3; /* ' ' + '=' + '\n' */
+ 
+   do
+     {
+@@ -827,7 +919,7 @@ xheader_print_n (struct xheader *xhdr, char const *keyword,
+ 
+   x_obstack_grow (xhdr, np, n);
+   x_obstack_1grow (xhdr, ' ');
+-  x_obstack_grow (xhdr, keyword, strlen (keyword));
++  x_obstack_grow (xhdr, keyword, klen);
+   x_obstack_1grow (xhdr, '=');
+   x_obstack_grow (xhdr, value, vsize);
+   x_obstack_1grow (xhdr, '\n');
+@@ -1613,11 +1705,20 @@ static void
+ xattr_decoder (struct tar_stat_info *st,
+                char const *keyword, char const *arg, size_t size)
+ {
+-  char *xstr = NULL;
++  char *xstr, *xkey;
++
++  /* copy keyword */
++  size_t klen_raw = strlen (keyword);
++  xkey = alloca (klen_raw + 1);
++  memcpy (xkey, keyword, klen_raw + 1) /* including null-terminating */;
++
++  /* copy value */
++  xstr = alloca (size + 1);
++  memcpy (xstr, arg, size + 1); /* separator included, for GNU tar '\n' */;
++
++  xattr_decode_keyword (xkey);
+ 
+-  xstr = xmemdup(arg, size + 1);
+-  xheader_xattr_add(st, keyword + strlen("SCHILY.xattr."), xstr, size);
+-  free(xstr);
++  xheader_xattr_add (st, xkey + strlen("SCHILY.xattr."), xstr, size);
+ }
+ 
+ static void
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 88942b3..449bbb4 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -177,6 +177,7 @@ TESTSUITE_AT = \
+  xattr/xattr02.at\
+  xattr/xattr03.at\
+  xattr/xattr04.at\
++ xattr/xattr05.at\
+  xattr/acls01.at\
+  xattr/acls02.at\
+  xattr/selnx01.at\
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index 63be9f0..d943e1f 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -343,6 +343,7 @@ m4_include([xattr/xattr01.at])
+ m4_include([xattr/xattr02.at])
+ m4_include([xattr/xattr03.at])
+ m4_include([xattr/xattr04.at])
++m4_include([xattr/xattr05.at])
+ 
+ m4_include([xattr/acls01.at])
+ m4_include([xattr/acls02.at])
+diff --git a/tests/xattr/xattr05.at b/tests/xattr/xattr05.at
+new file mode 100644
+index 0000000..d36efbe
+--- /dev/null
++++ b/tests/xattr/xattr05.at
+@@ -0,0 +1,52 @@
++# Process this file with autom4te to create testsuite. -*- Autotest -*-
++#
++# Test suite for GNU tar.
++# Copyright (C) 2012 Free Software Foundation, Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3, or (at your option)
++# any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++#
++# Test description:  Test for archiving/extracting of extended attributes
++# having the '=' character in its keyword.
++#
++# Test for the regression caused by tar update from 1.23 to
++# 1.26, Red Hat xattr patch was not ready for open->openat conversion.
++#
++# Relevant mailing list thread:
++#
++# http://lists.gnu.org/archive/html/bug-tar/2012-10/msg00017.html
++
++AT_SETUP([xattrs: keywords with '=' and '%'])
++AT_KEYWORDS([xattrs xattr05])
++
++AT_TAR_CHECK([
++AT_XATTRS_PREREQ
++
++mkdir dir
++mkdir output
++genfile --file dir/file
++
++setfattr -n user.=NAME%3D= -v value dir/file
++getfattr -d dir/file | grep -v '# ' > before
++
++# archive whole directory including binary xattrs
++tar --xattrs -cf archive.tar -C dir .
++
++tar --xattrs -xf archive.tar -C output
++getfattr -d output/file | grep -v '# ' > after
++diff before after
++],
++[0],
++[])
++
++AT_CLEANUP
diff --git a/tar.spec b/tar.spec
index 7045f6f..e31c62f 100644
--- a/tar.spec
+++ b/tar.spec
@@ -5,7 +5,7 @@ Summary: A GNU file archiving program
 Name: tar
 Epoch: 2
 Version: 1.26
-Release: 12%{?dist}
+Release: 13%{?dist}
 License: GPLv3+
 Group: Applications/Archiving
 URL: http://www.gnu.org/software/tar/
@@ -39,6 +39,7 @@ Patch10: tar-1.26-stdio.in.patch
 # Prepare gnulib for xattrs and apply xattrs & acls & selinux (#850291)
 Patch11: tar-1.26-xattrs-gnulib-prepare.patch
 Patch12: tar-1.26-xattrs.patch
+Patch13: tar-1.26-xattrs-equal-sign.patch
 
 BuildRequires: autoconf automake texinfo gettext libacl-devel rsh
 # allow proper tests for extended attributes
@@ -76,6 +77,7 @@ the rmt package.
 %patch10 -p1 -b .gets  %{?_rawbuild}
 %patch11 -p1 -b .xattrs_gnulib_prep
 %patch12 -p1 -b .xattrs2
+%patch13 -p1 -b .xattrs-equal-sign
 
 autoreconf
 


More information about the scm-commits mailing list