Browse Source

Provide functions for manipulating arrays of extended attributes

* src/common.h (xheader_xattr_free,xheader_xattr_copy): Remove protos.
(xattr_map_init,xattr_map_copy)
(xattr_map_add,xattr_map_free): New protos.
* src/tar.h (xattr_map): New struct.
(tar_stat_info): Replace xattr_map_size and xattr_map with one
field: xattr_map.
* src/xattrs.c (XATTRS_PREFIX,XATTRS_PREFIX_LEN): New defines.
(xheader_xattr_init,xattr_map_init)
(xattr_map_free,xattr_map_add)
(xheader_xattr_add,xattr_map_copy): New functions.
All uses changed.
* src/create.c (start_header): Update to use struct xattr_map.
* src/extract.c: Update to use struct xattr_map.
* src/tar.c: Likewise.
* src/xheader.c (xheader_xattr_init,xheader_xattr_free)
(xheader_xattr_add,xheader_xattr_copy): Remove.
(xattr_coder,xattr_decoder): Use xattr_map_ functions.
Sergey Poznyakoff 3 years ago
parent
commit
66262c10d1
7 changed files with 123 additions and 134 deletions
  1. 7 3
      src/common.h
  2. 3 8
      src/create.c
  3. 9 16
      src/extract.c
  4. 1 1
      src/tar.c
  5. 8 2
      src/tar.h
  6. 90 14
      src/xattrs.c
  7. 5 90
      src/xheader.c

+ 7 - 3
src/common.h

@@ -881,12 +881,16 @@ 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);
 
+void xattr_map_init (struct xattr_map *map);
+void xattr_map_copy (struct xattr_map *dst,
+		     const struct xattr_map *src);
+void xattr_map_add (struct xattr_map *map,
+		    const char *key, const char *val, size_t len);
+void xattr_map_free (struct xattr_map *xattr_map);
+
 /* Module system.c */
 
 void sys_detect_dev_null_output (void);

+ 3 - 8
src/create.c

@@ -966,14 +966,9 @@ start_header (struct tar_stat_info *st)
         xheader_store ("RHT.security.selinux", st, NULL);
       if (xattrs_option > 0)
         {
-          size_t scan_xattr = 0;
-          struct xattr_array *xattr_map = st->xattr_map;
-
-          while (scan_xattr < st->xattr_map_size)
-            {
-              xheader_store (xattr_map[scan_xattr].xkey, st, &scan_xattr);
-              ++scan_xattr;
-            }
+          size_t i;
+	  for (i = 0; i < st->xattr_map.xm_size; i++)
+	    xheader_store (st->xattr_map.xm_map[i].xkey, st, &i);
         }
     }
 

+ 9 - 16
src/extract.c

@@ -105,7 +105,7 @@ struct delayed_set_stat
     char *acls_d_ptr;
     size_t acls_d_len;
     size_t xattr_map_size;
-    struct xattr_array *xattr_map;
+    struct xattr_map xattr_map;
     /* Length and contents of name.  */
     size_t file_name_len;
     char *file_name;
@@ -155,8 +155,7 @@ struct delayed_link
     char *acls_d_ptr;
     size_t acls_d_len;
 
-    size_t xattr_map_size;
-    struct xattr_array *xattr_map;
+    struct xattr_map xattr_map;
 
     /* The desired target of the desired link.  */
     char target[1];
@@ -503,6 +502,7 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
 	  data->dev = st->stat.st_dev;
 	  data->ino = st->stat.st_ino;
 	}
+      xattr_map_init (&data->xattr_map);
     }
 
   data->mode = mode;
@@ -542,12 +542,7 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
       data->acls_d_len = 0;
     }
   if (st)
-    xheader_xattr_copy (st, &data->xattr_map, &data->xattr_map_size);
-  else
-    {
-      data->xattr_map = NULL;
-      data->xattr_map_size = 0;
-    }
+    xattr_map_copy (&data->xattr_map, &st->xattr_map);
   if (must_be_dot_or_slash (file_name))
     mark_after_links (data);
 }
@@ -595,7 +590,7 @@ static void
 free_delayed_set_stat (struct delayed_set_stat *data)
 {
   free (data->file_name);
-  xheader_xattr_free (data->xattr_map, data->xattr_map_size);
+  xattr_map_free (&data->xattr_map);
   free (data->cntx_name);
   free (data->acls_a_ptr);
   free (data->acls_d_ptr);
@@ -859,7 +854,7 @@ set_xattr (char const *file_name, struct tar_stat_info const *st,
 #ifdef HAVE_XATTRS
   bool interdir_made = false;
 
-  if ((xattrs_option > 0) && st->xattr_map_size)
+  if ((xattrs_option > 0) && st->xattr_map.xm_size)
     {
       mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;
 
@@ -957,7 +952,6 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
 	  sb.acls_d_ptr = data->acls_d_ptr;
 	  sb.acls_d_len = data->acls_d_len;
 	  sb.xattr_map = data->xattr_map;
-	  sb.xattr_map_size = data->xattr_map_size;
 	  set_stat (data->file_name, &sb,
 		    -1, current_mode, current_mode_mask,
 		    DIRTYPE, data->interdir, data->atflag);
@@ -1447,8 +1441,8 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made,
       p->acls_a_len = 0;
       p->acls_d_ptr = NULL;
       p->acls_d_len = 0;
-      xheader_xattr_copy (&current_stat_info, &p->xattr_map,
-			  &p->xattr_map_size);
+      xattr_map_init (&p->xattr_map);
+      xattr_map_copy (&p->xattr_map, &current_stat_info.xattr_map);
       strcpy (p->target, current_stat_info.link_name);
 
       if ((h = find_direct_ancestor (file_name)) != NULL)
@@ -1882,7 +1876,6 @@ apply_delayed_links (void)
                   st1.acls_d_ptr = ds->acls_d_ptr;
                   st1.acls_d_len = ds->acls_d_len;
                   st1.xattr_map = ds->xattr_map;
-                  st1.xattr_map_size = ds->xattr_map_size;
 		  set_stat (source, &st1, -1, 0, 0, SYMTYPE,
 			    false, AT_SYMLINK_NOFOLLOW);
 		  valid_source = source;
@@ -1897,7 +1890,7 @@ apply_delayed_links (void)
 	  sources = next;
 	}
 
-      xheader_xattr_free (ds->xattr_map, ds->xattr_map_size);
+      xattr_map_free (&ds->xattr_map);
       free (ds->cntx_name);
 
       {

+ 1 - 1
src/tar.c

@@ -2883,7 +2883,7 @@ void
 tar_stat_destroy (struct tar_stat_info *st)
 {
   tar_stat_close (st);
-  xheader_xattr_free (st->xattr_map, st->xattr_map_size);
+  xattr_map_free (&st->xattr_map);
   free (st->orig_file_name);
   free (st->file_name);
   free (st->link_name);

+ 8 - 2
src/tar.h

@@ -284,6 +284,13 @@ struct xattr_array
     size_t xval_len;
   };
 
+struct xattr_map
+{
+  struct xattr_array *xm_map;
+  size_t xm_size;   /* Size of the xattr map */
+  size_t xm_max;    /* Max. number of entries in xattr_map */
+};
+
 struct tar_stat_info
 {
   char *orig_file_name;     /* name of file read from the archive header */
@@ -334,8 +341,7 @@ struct tar_stat_info
                                processed pax header parsing.  Following 'path'
                                header (lower priority) will be ignored. */
 
-  size_t xattr_map_size;   /* Size of the xattr map */
-  struct xattr_array *xattr_map;
+  struct xattr_map xattr_map;
 
   /* Extended headers */
   struct xheader xhdr;

+ 90 - 14
src/xattrs.c

@@ -30,6 +30,83 @@
 #include "xattr-at.h"
 #include "selinux-at.h"
 
+#define XATTRS_PREFIX "SCHILY.xattr."
+#define XATTRS_PREFIX_LEN (sizeof XATTRS_PREFIX - 1)
+
+void
+xheader_xattr_init (struct tar_stat_info *st)
+{
+  xattr_map_init (&st->xattr_map);
+
+  st->acls_a_ptr = NULL;
+  st->acls_a_len = 0;
+  st->acls_d_ptr = NULL;
+  st->acls_d_len = 0;
+  st->cntx_name = NULL;
+}
+
+void
+xattr_map_init (struct xattr_map *map)
+{
+  memset (map, 0, sizeof *map);
+}
+
+void
+xattr_map_free (struct xattr_map *xattr_map)
+{
+  size_t i;
+
+  for (i = 0; i < xattr_map->xm_size; i++)
+    {
+      free (xattr_map->xm_map[i].xkey);
+      free (xattr_map->xm_map[i].xval_ptr);
+    }
+  free (xattr_map->xm_map);
+}
+
+void
+xattr_map_add (struct xattr_map *map,
+	       const char *key, const char *val, size_t len)
+{
+  struct xattr_array *p;
+  
+  if (map->xm_size == map->xm_max)
+    map->xm_map = x2nrealloc (map->xm_map, &map->xm_max,
+			      sizeof (map->xm_map[0]));
+  p = &map->xm_map[map->xm_size];
+  p->xkey = xstrdup (key);
+  p->xval_ptr = xmemdup (val, len + 1);
+  p->xval_len = len;
+  map->xm_size++;
+}
+
+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 (XATTRS_PREFIX_LEN + klen + 1);
+  char *tmp = xkey;
+
+  tmp = stpcpy (tmp, XATTRS_PREFIX);
+  stpcpy (tmp, key);
+
+  xattr_map_add (&st->xattr_map, xkey, val, len);
+
+  free (xkey);
+}
+
+void
+xattr_map_copy (struct xattr_map *dst, const struct xattr_map *src)
+{
+  size_t i;
+
+  for (i = 0; i < src->xm_size; i++)
+    xattr_map_add (dst, src->xm_map[i].xkey,
+		   src->xm_map[i].xval_ptr,
+		   src->xm_map[i].xval_len);
+}
+
 struct xattrs_mask_map
 {
   const char **masks;
@@ -678,15 +755,14 @@ xattrs_xattrs_set (struct tar_stat_info const *st,
         WARN ((0, 0, _("XATTR support is not available")));
       done = 1;
 #else
-      size_t scan = 0;
+      size_t i;
 
-      if (!st->xattr_map_size)
+      if (!st->xattr_map.xm_size)
         return;
 
-      for (; scan < st->xattr_map_size; ++scan)
+      for (i = 0; i < st->xattr_map.xm_size; i++)
         {
-          char *keyword = st->xattr_map[scan].xkey;
-          keyword += strlen ("SCHILY.xattr.");
+          char *keyword = st->xattr_map.xm_map[i].xkey + XATTRS_PREFIX_LEN;
 
           /* TODO: this 'later_run' workaround is temporary solution -> once
              capabilities should become fully supported by it's API and there
@@ -703,8 +779,8 @@ xattrs_xattrs_set (struct tar_stat_info const *st,
             continue;
 
           xattrs__fd_set (st, file_name, typeflag, keyword,
-                          st->xattr_map[scan].xval_ptr,
-                          st->xattr_map[scan].xval_len);
+                          st->xattr_map.xm_map[i].xval_ptr,
+                          st->xattr_map.xm_map[i].xval_len);
         }
 #endif
     }
@@ -728,10 +804,10 @@ xattrs_print_char (struct tar_stat_info const *st, char *output)
       output[1] = 0;
     }
 
-  if (xattrs_option > 0 && st->xattr_map_size)
-    for (i = 0; i < st->xattr_map_size; ++i)
+  if (xattrs_option > 0 && st->xattr_map.xm_size)
+    for (i = 0; i < st->xattr_map.xm_size; ++i)
       {
-        char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr.");
+        char *keyword = st->xattr_map.xm_map[i].xkey + XATTRS_PREFIX_LEN;
         if (!xattrs_masked_out (keyword, false /* like extracting */ ))
 	  {
 	    *output = '*';
@@ -768,16 +844,16 @@ xattrs_print (struct tar_stat_info const *st)
     }
 
   /* xattrs */
-  if (xattrs_option > 0 && st->xattr_map_size)
+  if (xattrs_option > 0 && st->xattr_map.xm_size)
     {
       int i;
 
-      for (i = 0; i < st->xattr_map_size; ++i)
+      for (i = 0; i < st->xattr_map.xm_size; ++i)
         {
-          char *keyword = st->xattr_map[i].xkey + strlen ("SCHILY.xattr.");
+          char *keyword = st->xattr_map.xm_map[i].xkey + XATTRS_PREFIX_LEN;
           if (!xattrs_masked_out (keyword, false /* like extracting */ ))
 	    fprintf (stdlis, "  x: %lu %s\n",
-		     (unsigned long) st->xattr_map[i].xval_len, keyword);
+		     (unsigned long) st->xattr_map.xm_map[i].xval_len, keyword);
         }
     }
 }

+ 5 - 90
src/xheader.c

@@ -492,48 +492,6 @@ xheader_forbid_global (void)
     USAGE_ERROR ((0, 0, _("can't update global extended header record")));
 }
 
-void
-xheader_xattr_init (struct tar_stat_info *st)
-{
-  st->xattr_map = NULL;
-  st->xattr_map_size = 0;
-
-  st->acls_a_ptr = NULL;
-  st->acls_a_len = 0;
-  st->acls_d_ptr = NULL;
-  st->acls_d_len = 0;
-  st->cntx_name = NULL;
-}
-
-void
-xheader_xattr_free (struct xattr_array *xattr_map, size_t xattr_map_size)
-{
-  size_t scan = 0;
-
-  while (scan < xattr_map_size)
-    {
-      free (xattr_map[scan].xkey);
-      free (xattr_map[scan].xval_ptr);
-
-      ++scan;
-    }
-  free (xattr_map);
-}
-
-static void
-xheader_xattr__add (struct xattr_array **xattr_map,
-		    size_t *xattr_map_size,
-		    const char *key, const char *val, size_t len)
-{
-  size_t pos = (*xattr_map_size)++;
-
-  *xattr_map = xrealloc (*xattr_map,
-                         *xattr_map_size * sizeof(struct xattr_array));
-  (*xattr_map)[pos].xkey = xstrdup (key);
-  (*xattr_map)[pos].xval_ptr = xmemdup (val, len + 1);
-  (*xattr_map)[pos].xval_len = len;
-}
-
 /* This is reversal function for xattr_encode_keyword.  See comment for
    xattr_encode_keyword() for more info. */
 static void
@@ -571,44 +529,6 @@ xattr_decode_keyword (char *keyword)
       kpl++;
     }
 }
-
-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 */
 
@@ -1705,31 +1625,26 @@ 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;
+  size_t n = *(size_t *)data;
   xheader_print_n (xhdr, keyword,
-                   xattr_map[*off].xval_ptr, xattr_map[*off].xval_len);
+		   st->xattr_map.xm_map[n].xval_ptr,
+		   st->xattr_map.xm_map[n].xval_len);
 }
 
 static void
 xattr_decoder (struct tar_stat_info *st,
                char const *keyword, char const *arg, size_t size)
 {
-  char *xstr, *xkey;
+  char *xkey;
   
   /* copy keyword */
   xkey = xstrdup (keyword);
 
-  /* copy value */
-  xstr = xmalloc (size + 1);
-  memcpy (xstr, arg, size + 1); /* separator included, for GNU tar '\n' */;
-
   xattr_decode_keyword (xkey);
 
-  xheader_xattr_add (st, xkey + strlen ("SCHILY.xattr."), xstr, size);
+  xattr_map_add (&st->xattr_map, xkey, arg, size);
 
   free (xkey);
-  free (xstr);
 }
 
 static void