Bladeren bron

Use keywords from the global headers.
Correctly handle UTF-8 conversions.
(xheader_list_destroy): New function.
(xheader_set_single_keyword,xheader_set_keyword_equal): Added
missing gettext markers
(decode_record): Rewritten using caller-provided handler and
data closure.

Sergey Poznyakoff 21 jaren geleden
bovenliggende
commit
b8754a37c7
1 gewijzigde bestanden met toevoegingen van 109 en 31 verwijderingen
  1. 109 31
      src/xheader.c

+ 109 - 31
src/xheader.c

@@ -62,12 +62,19 @@ struct keyword_list
 
 
 /* List of keyword patterns set by delete= option */
 /* List of keyword patterns set by delete= option */
 static struct keyword_list *keyword_pattern_list;
 static struct keyword_list *keyword_pattern_list;
+
 /* List of keyword/value pairs set by `keyword=value' option */
 /* List of keyword/value pairs set by `keyword=value' option */
 static struct keyword_list *keyword_global_override_list;
 static struct keyword_list *keyword_global_override_list;
+
 /* List of keyword/value pairs set by `keyword:=value' option */
 /* List of keyword/value pairs set by `keyword:=value' option */
 static struct keyword_list *keyword_override_list;
 static struct keyword_list *keyword_override_list;
+
+/* List of keyword/value pairs decoded from the last 'g' type header */
+static struct keyword_list *global_header_override_list;
+
 /* Template for the name field of an 'x' type header */
 /* Template for the name field of an 'x' type header */
 static char *exthdr_name;
 static char *exthdr_name;
+
 /* Template for the name field of a 'g' type header */
 /* Template for the name field of a 'g' type header */
 static char *globexthdr_name;
 static char *globexthdr_name;
 
 
@@ -94,7 +101,8 @@ xheader_keyword_override_p (const char *keyword)
 }
 }
 
 
 void
 void
-xheader_list_append (struct keyword_list **root, char *kw, char *value)
+xheader_list_append (struct keyword_list **root, char const *kw,
+		     char const *value)
 {
 {
   struct keyword_list *kp = xmalloc (sizeof *kp);
   struct keyword_list *kp = xmalloc (sizeof *kp);
   kp->pattern = xstrdup (kw);
   kp->pattern = xstrdup (kw);
@@ -103,10 +111,29 @@ xheader_list_append (struct keyword_list **root, char *kw, char *value)
   *root = kp;
   *root = kp;
 }
 }
 
 
+void
+xheader_list_destroy (struct keyword_list **root)
+{
+  if (root)
+    {
+      struct keyword_list *kw = *root;
+      while (kw)
+	{
+	  struct keyword_list *next = kw->next;
+	  free (kw->pattern);
+	  free (kw->value);
+	  free (kw);
+	  kw = next;
+	}
+      *root = NULL;
+    }
+}
+	  
+  
 void
 void
 xheader_set_single_keyword (char *kw)
 xheader_set_single_keyword (char *kw)
 {
 {
-  USAGE_ERROR ((0, 0, "Keyword %s is unknown or not yet imlemented", kw));
+  USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet imlemented"), kw));
 }
 }
 
 
 void
 void
@@ -132,7 +159,7 @@ xheader_set_keyword_equal (char *kw, char *eq)
   if (strcmp (kw, "delete") == 0)
   if (strcmp (kw, "delete") == 0)
     {
     {
       if (xheader_protected_pattern_p (p))
       if (xheader_protected_pattern_p (p))
-	USAGE_ERROR ((0, 0, "Pattern %s cannot be used", p));
+	USAGE_ERROR ((0, 0, _("Pattern %s cannot be used"), p));
       xheader_list_append (&keyword_pattern_list, p, NULL);
       xheader_list_append (&keyword_pattern_list, p, NULL);
     }
     }
   else if (strcmp (kw, "exthdr.name") == 0)
   else if (strcmp (kw, "exthdr.name") == 0)
@@ -142,7 +169,7 @@ xheader_set_keyword_equal (char *kw, char *eq)
   else
   else
     {
     {
       if (xheader_protected_keyword_p (kw))
       if (xheader_protected_keyword_p (kw))
-	USAGE_ERROR ((0, 0, "Keyword %s cannot be overridden", kw));
+	USAGE_ERROR ((0, 0, _("Keyword %s cannot be overridden"), kw));
       if (global)
       if (global)
 	xheader_list_append (&keyword_global_override_list, kw, p);
 	xheader_list_append (&keyword_global_override_list, kw, p);
       else
       else
@@ -423,13 +450,14 @@ xheader_protected_keyword_p (const char *keyword)
    record.
    record.
    Returns true on success, false otherwise. */
    Returns true on success, false otherwise. */
 static bool
 static bool
-decode_record (char **p, struct tar_stat_info *st)
+decode_record (char **p,
+	       void (*handler) (void *, char const *, char const *),
+	       void *data)
 {
 {
   size_t len;
   size_t len;
   char const *keyword;
   char const *keyword;
-  char *eqp;
   char *start = *p;
   char *start = *p;
-  struct xhdr_tab const *t;
+  char endc;
 
 
   if (**p == 0)
   if (**p == 0)
     return false;
     return false;
@@ -453,26 +481,15 @@ decode_record (char **p, struct tar_stat_info *st)
       return false;
       return false;
     }
     }
 
 
-  eqp = *p;
   **p = 0;
   **p = 0;
 
 
-  if (xheader_keyword_deleted_p (keyword)
-      || xheader_keyword_override_p (keyword))
-    return true;
-  t = locate_handler (keyword);
-  if (t)
-    {
-      char endc;
-      char *value;
+  endc = start[len-1];
+  start[len-1] = 0;
 
 
-      value = ++*p;
+  handler (data, keyword, *p + 1);
 
 
-      endc = start[len-1];
-      start[len-1] = 0;
-      t->decoder (st, value);
-      start[len-1] = endc;
-    }
-  *eqp = '=';
+  start[len-1] = endc;
+  **p = '=';
   *p = &start[len];
   *p = &start[len];
   return true;
   return true;
 }
 }
@@ -488,10 +505,26 @@ run_override_list (struct keyword_list *kp, struct tar_stat_info *st)
     }
     }
 }
 }
 
 
+static void
+decx (void *data, char const *keyword, char const *value)
+{
+  struct xhdr_tab const *t;
+  struct tar_stat_info *st = data;
+
+  if (xheader_keyword_deleted_p (keyword)
+      || xheader_keyword_override_p (keyword))
+    return;
+  
+  t = locate_handler (keyword);
+  if (t)
+    t->decoder (st, value);
+}
+
 void
 void
 xheader_decode (struct tar_stat_info *st)
 xheader_decode (struct tar_stat_info *st)
 {
 {
   run_override_list (keyword_global_override_list, st);
   run_override_list (keyword_global_override_list, st);
+  run_override_list (global_header_override_list, st);
   
   
   if (extended_header.size)
   if (extended_header.size)
     {
     {
@@ -499,12 +532,34 @@ xheader_decode (struct tar_stat_info *st)
       char *endp = &extended_header.buffer[extended_header.size-1];
       char *endp = &extended_header.buffer[extended_header.size-1];
       
       
       while (p < endp)
       while (p < endp)
-	if (!decode_record (&p, st))
+	if (!decode_record (&p, decx, st))
 	  break;
 	  break;
     }
     }
   run_override_list (keyword_override_list, st);
   run_override_list (keyword_override_list, st);
 }
 }
 
 
+static void
+decg (void *data, char const *keyword, char const *value)
+{
+  struct keyword_list **kwl = data;
+  xheader_list_append (kwl, keyword, value);
+}
+
+void
+xheader_decode_global ()
+{
+  if (extended_header.size)
+    {
+      char *p = extended_header.buffer + BLOCKSIZE;
+      char *endp = &extended_header.buffer[extended_header.size-1];
+
+      xheader_list_destroy (&global_header_override_list);
+      while (p < endp)
+	if (!decode_record (&p, decg, &global_header_override_list))
+	  break;
+    }
+}
+
 static void
 static void
 extended_header_init ()
 extended_header_init ()
 {
 {
@@ -645,7 +700,29 @@ xheader_destroy (struct xheader *xhdr)
 static void
 static void
 code_string (char const *string, char const *keyword, struct xheader *xhdr)
 code_string (char const *string, char const *keyword, struct xheader *xhdr)
 {
 {
-  xheader_print (xhdr, keyword, string);
+  char *outstr;
+  if (!utf8_convert (true, string, &outstr))
+    {
+      /* FIXME: report error */
+      outstr = xstrdup (string);
+    }
+  xheader_print (xhdr, keyword, outstr);
+  free (outstr);
+}
+
+static void
+decode_string (char **string, char const *arg)
+{
+  if (*string)
+    {
+      free (*string);
+      *string = NULL;
+    }
+  if (!utf8_convert (false, arg, string))
+    {
+      /* FIXME: report error and act accordingly to --pax invalid=UTF-8 */
+      assign_string (string, arg);
+    }
 }
 }
 
 
 static void
 static void
@@ -735,7 +812,7 @@ gname_coder (struct tar_stat_info const *st, char const *keyword,
 static void
 static void
 gname_decoder (struct tar_stat_info *st, char const *arg)
 gname_decoder (struct tar_stat_info *st, char const *arg)
 {
 {
-  assign_string (&st->gname, arg);
+  decode_string (&st->gname, arg);
 }
 }
 
 
 static void
 static void
@@ -748,7 +825,7 @@ linkpath_coder (struct tar_stat_info const *st, char const *keyword,
 static void
 static void
 linkpath_decoder (struct tar_stat_info *st, char const *arg)
 linkpath_decoder (struct tar_stat_info *st, char const *arg)
 {
 {
-  assign_string (&st->link_name, arg);
+  decode_string (&st->link_name, arg);
 }
 }
 
 
 static void
 static void
@@ -787,8 +864,8 @@ path_coder (struct tar_stat_info const *st, char const *keyword,
 static void
 static void
 path_decoder (struct tar_stat_info *st, char const *arg)
 path_decoder (struct tar_stat_info *st, char const *arg)
 {
 {
-  assign_string (&st->orig_file_name, arg);
-  assign_string (&st->file_name, arg);
+  decode_string (&st->orig_file_name, arg);
+  decode_string (&st->file_name, arg);
   st->had_trailing_slash = strip_trailing_slashes (st->file_name);
   st->had_trailing_slash = strip_trailing_slashes (st->file_name);
 }
 }
 
 
@@ -832,7 +909,7 @@ uname_coder (struct tar_stat_info const *st, char const *keyword,
 static void
 static void
 uname_decoder (struct tar_stat_info *st, char const *arg)
 uname_decoder (struct tar_stat_info *st, char const *arg)
 {
 {
-  assign_string (&st->uname, arg);
+  decode_string (&st->uname, arg);
 }
 }
 
 
 static void
 static void
@@ -938,7 +1015,8 @@ struct xhdr_tab const xhdr_tab[] = {
   /* The next directory entry actually contains the names of files
   /* The next directory entry actually contains the names of files
      that were in the directory at the time the dump was made.
      that were in the directory at the time the dump was made.
      Supersedes GNUTYPE_DUMPDIR header type.  */
      Supersedes GNUTYPE_DUMPDIR header type.  */
-  { "GNU.dumpdir",  dumpdir_coder, dumpdir_decoder },
+  { "GNU.dump.name",  dump_name_coder, dump_name_decoder },
+  { "GNU.dump.status", dump_status_coder, dump_status_decoder },
 
 
   /* Keeps the tape/volume header. May be present only in the global headers.
   /* Keeps the tape/volume header. May be present only in the global headers.
      Equivalent to GNUTYPE_VOLHDR.  */
      Equivalent to GNUTYPE_VOLHDR.  */