]> Dogcows Code - chaz/tar/blobdiff - src/xheader.c
(GNU.sparse.name): New variable for storing sparse file name.
[chaz/tar] / src / xheader.c
index 029bebf3b5eb55b53eb10e3836dcc777be472b1d..3eb1505890f68b207c5c1a66d2f3b306521239af 100644 (file)
@@ -1,6 +1,6 @@
 /* POSIX extended headers for tar.
 
-   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006 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
@@ -157,7 +157,7 @@ xheader_list_destroy (struct keyword_list **root)
 static void
 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 implemented"), kw));
 }
 
 static void
@@ -225,15 +225,17 @@ xheader_set_option (char *string)
                               to the result of the basename
                               utility on the translated file name.
      %p                       The process ID of the pax process.
+     %n                       The value of the 3rd argument.  
      %%                       A '%' character. */
 
-static char *
-xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
+char *
+xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
 {
   char *buf;
   size_t len = strlen (fmt);
   char *q;
   const char *p;
+  char *dirp = NULL;
   char *dir = NULL;
   char *base = NULL;
   char pidbuf[UINTMAX_STRSIZE_BOUND];
@@ -252,9 +254,10 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
        case 'd':
          if (st)
            {
-             dir = safer_name_suffix (dir_name (st->orig_file_name),
-                                      false, absolute_names_option);
-             len += strlen (dir) - 1;
+             if (!dirp)
+               dirp = dir_name (st->orig_file_name);
+             dir = safer_name_suffix (dirp, false, absolute_names_option);
+             len += strlen (dir) - 2;
            }
          break;
 
@@ -262,21 +265,18 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
          if (st)
            {
              base = base_name (st->orig_file_name);
-             len += strlen (base) - 1;
+             len += strlen (base) - 2;
            }
          break;
 
        case 'p':
          pptr = umaxtostr (getpid (), pidbuf);
-         len += pidbuf + sizeof pidbuf - 1 - pptr - 1;
+         len += pidbuf + sizeof pidbuf - 1 - pptr - 2;
          break;
 
        case 'n':
-         if (allow_n)
-           {
-             nptr = umaxtostr (global_header_count + 1, nbuf);
-             len += nbuf + sizeof nbuf - 1 - nptr - 1;
-           }
+         nptr = umaxtostr (n, nbuf);
+         len += nbuf + sizeof nbuf - 1 - nptr - 2;
          break;
        }
       p++;
@@ -316,6 +316,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
                {
                  q = stpcpy (q, nptr);
                  p += 2;
+                 break;
                }
              /* else fall through */
 
@@ -329,6 +330,8 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
        *q++ = *p++;
     }
 
+  free (dirp);
+  
   /* Do not allow it to end in a slash */
   while (q > buf && ISSLASH (q[-1]))
     q--;
@@ -341,7 +344,7 @@ xheader_xhdr_name (struct tar_stat_info *st)
 {
   if (!exthdr_name)
     assign_string (&exthdr_name, "%d/PaxHeaders.%p/%f");
-  return xheader_format_name (st, exthdr_name, false);
+  return xheader_format_name (st, exthdr_name, 0);
 }
 
 #define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n"
@@ -361,7 +364,7 @@ xheader_ghdr_name (void)
       strcat(globexthdr_name, GLOBAL_HEADER_TEMPLATE);
     }
 
-  return xheader_format_name (NULL, globexthdr_name, true);
+  return xheader_format_name (NULL, globexthdr_name, global_header_count + 1);
 }
 
 void
@@ -396,6 +399,9 @@ xheader_write (char type, char *name, struct xheader *xhdr)
     }
   while (size > 0);
   xheader_destroy (xhdr);
+
+  if (type == XGLTYPE)
+    global_header_count++;
 }
 
 void
@@ -414,7 +420,6 @@ xheader_write_global (void)
   xheader_write (XGLTYPE, name = xheader_ghdr_name (),
                 &extended_header);
   free (name);
-  global_header_count++;
 }
 
 \f
@@ -424,7 +429,7 @@ struct xhdr_tab
 {
   char const *keyword;
   void (*coder) (struct tar_stat_info const *, char const *,
-                struct xheader *, void *data);
+                struct xheader *, void const *data);
   void (*decoder) (struct tar_stat_info *, char const *, size_t);
   bool protect;
 };
@@ -615,7 +620,8 @@ extended_header_init (void)
 }
 
 void
-xheader_store (char const *keyword, struct tar_stat_info const *st, void *data)
+xheader_store (char const *keyword, struct tar_stat_info const *st,
+              void const *data)
 {
   struct xhdr_tab const *t;
 
@@ -742,7 +748,7 @@ xheader_string_add (char const *s)
 
 void
 xheader_string_end (char const *keyword)
-{  
+{
   size_t len;
   size_t p;
   size_t n = 0;
@@ -753,9 +759,9 @@ xheader_string_end (char const *keyword)
   if (extended_header.buffer)
     return;
   extended_header_init ();
-  
+
   len = strlen (keyword) + string_length + 3; /* ' ' + '=' + '\n' */
-  
+
   do
     {
       p = n;
@@ -830,8 +836,15 @@ code_time (struct timespec t, char const *keyword, struct xheader *xhdr)
   xheader_print (xhdr, keyword, code_timespec (t, buf));
 }
 
-static bool
-decode_time (struct timespec *ts, char const *arg, char const *keyword)
+enum decode_time_status
+  {
+    decode_time_success,
+    decode_time_range,
+    decode_time_bad_header
+  };
+
+static enum decode_time_status
+_decode_time (struct timespec *ts, char const *arg, char const *keyword)
 {
   time_t s;
   unsigned long int ns = 0;
@@ -847,21 +860,21 @@ decode_time (struct timespec *ts, char const *arg, char const *keyword)
        {
          intmax_t i = strtoimax (arg, &arg_lim, 10);
          if (TYPE_SIGNED (time_t) ? i < TYPE_MINIMUM (time_t) : i < 0)
-           goto out_of_range;
+           return decode_time_range;
          s = i;
        }
       else
        {
          uintmax_t i = strtoumax (arg, &arg_lim, 10);
          if (TYPE_MAXIMUM (time_t) < i)
-           goto out_of_range;
+           return decode_time_range;
          s = i;
        }
 
       p = arg_lim;
 
       if (errno == ERANGE)
-       goto out_of_range;
+       return decode_time_range;
 
       if (*p == '.')
        {
@@ -889,7 +902,7 @@ decode_time (struct timespec *ts, char const *arg, char const *keyword)
              if (ns != 0)
                {
                  if (s == TYPE_MINIMUM (time_t))
-                   goto out_of_range;
+                   return decode_time_range;
                  s--;
                  ns = BILLION - ns;
                }
@@ -900,20 +913,34 @@ decode_time (struct timespec *ts, char const *arg, char const *keyword)
        {
          ts->tv_sec = s;
          ts->tv_nsec = ns;
-         return true;
+         return decode_time_success;
        }
     }
 
-  ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
-         keyword, arg));
-  return false;
+  return decode_time_bad_header;
+}
 
- out_of_range:
-  out_of_range_header (keyword, arg, - (uintmax_t) TYPE_MINIMUM (time_t),
-                      TYPE_MAXIMUM (time_t));
-  return false;
+static bool
+decode_time (struct timespec *ts, char const *arg, char const *keyword)
+{
+  switch (_decode_time (ts, arg, keyword))
+    {
+    case decode_time_success:
+      return true;
+    case decode_time_bad_header:
+      ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
+             keyword, arg));
+      return false;
+    case decode_time_range:
+      out_of_range_header (keyword, arg, - (uintmax_t) TYPE_MINIMUM (time_t),
+                          TYPE_MAXIMUM (time_t));
+      return false;
+    }
+  return true;
 }
 
+  
+
 static void
 code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
 {
@@ -950,7 +977,7 @@ static void
 dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)),
             char const *keyword __attribute__ ((unused)),
             struct xheader *xhdr __attribute__ ((unused)),
-            void *data __attribute__ ((unused)))
+            void const *data __attribute__ ((unused)))
 {
 }
 
@@ -963,7 +990,7 @@ dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)),
 
 static void
 atime_coder (struct tar_stat_info const *st, char const *keyword,
-            struct xheader *xhdr, void *data __attribute__ ((unused)))
+            struct xheader *xhdr, void const *data __attribute__ ((unused)))
 {
   code_time (st->atime, keyword, xhdr);
 }
@@ -979,7 +1006,7 @@ atime_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 gid_coder (struct tar_stat_info const *st, char const *keyword,
-          struct xheader *xhdr, void *data __attribute__ ((unused)))
+          struct xheader *xhdr, void const *data __attribute__ ((unused)))
 {
   code_num (st->stat.st_gid, keyword, xhdr);
 }
@@ -995,7 +1022,7 @@ gid_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 gname_coder (struct tar_stat_info const *st, char const *keyword,
-            struct xheader *xhdr, void *data __attribute__ ((unused)))
+            struct xheader *xhdr, void const *data __attribute__ ((unused)))
 {
   code_string (st->gname, keyword, xhdr);
 }
@@ -1009,7 +1036,7 @@ gname_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 linkpath_coder (struct tar_stat_info const *st, char const *keyword,
-               struct xheader *xhdr, void *data __attribute__ ((unused)))
+               struct xheader *xhdr, void const *data __attribute__ ((unused)))
 {
   code_string (st->link_name, keyword, xhdr);
 }
@@ -1023,7 +1050,7 @@ linkpath_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 ctime_coder (struct tar_stat_info const *st, char const *keyword,
-            struct xheader *xhdr, void *data __attribute__ ((unused)))
+            struct xheader *xhdr, void const *data __attribute__ ((unused)))
 {
   code_time (st->ctime, keyword, xhdr);
 }
@@ -1039,7 +1066,7 @@ ctime_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 mtime_coder (struct tar_stat_info const *st, char const *keyword,
-            struct xheader *xhdr, void *data __attribute__ ((unused)))
+            struct xheader *xhdr, void const *data __attribute__ ((unused)))
 {
   code_time (st->mtime, keyword, xhdr);
 }
@@ -1055,7 +1082,7 @@ mtime_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 path_coder (struct tar_stat_info const *st, char const *keyword,
-           struct xheader *xhdr, void *data __attribute__ ((unused)))
+           struct xheader *xhdr, void const *data __attribute__ ((unused)))
 {
   code_string (st->file_name, keyword, xhdr);
 }
@@ -1071,7 +1098,7 @@ path_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 size_coder (struct tar_stat_info const *st, char const *keyword,
-           struct xheader *xhdr, void *data __attribute__ ((unused)))
+           struct xheader *xhdr, void const *data __attribute__ ((unused)))
 {
   code_num (st->stat.st_size, keyword, xhdr);
 }
@@ -1087,7 +1114,7 @@ size_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 uid_coder (struct tar_stat_info const *st, char const *keyword,
-          struct xheader *xhdr, void *data __attribute__ ((unused)))
+          struct xheader *xhdr, void const *data __attribute__ ((unused)))
 {
   code_num (st->stat.st_uid, keyword, xhdr);
 }
@@ -1103,7 +1130,7 @@ uid_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 uname_coder (struct tar_stat_info const *st, char const *keyword,
-            struct xheader *xhdr, void *data __attribute__ ((unused)))
+            struct xheader *xhdr, void const *data __attribute__ ((unused)))
 {
   code_string (st->uname, keyword, xhdr);
 }
@@ -1117,7 +1144,7 @@ uname_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 sparse_size_coder (struct tar_stat_info const *st, char const *keyword,
-            struct xheader *xhdr, void *data)
+            struct xheader *xhdr, void const *data)
 {
   size_coder (st, keyword, xhdr, data);
 }
@@ -1134,7 +1161,7 @@ sparse_size_decoder (struct tar_stat_info *st, char const *arg,
 static void
 sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword,
                        struct xheader *xhdr,
-                       void *data __attribute__ ((unused)))
+                       void const *data __attribute__ ((unused)))
 {
   code_num (st->sparse_map_avail, keyword, xhdr);
 }
@@ -1154,9 +1181,9 @@ sparse_numblocks_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 sparse_offset_coder (struct tar_stat_info const *st, char const *keyword,
-                    struct xheader *xhdr, void *data)
+                    struct xheader *xhdr, void const *data)
 {
-  size_t *pi = data;
+  size_t const *pi = data;
   code_num (st->sparse_map[*pi].offset, keyword, xhdr);
 }
 
@@ -1177,9 +1204,9 @@ sparse_offset_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 sparse_numbytes_coder (struct tar_stat_info const *st, char const *keyword,
-                      struct xheader *xhdr, void *data)
+                      struct xheader *xhdr, void const *data)
 {
-  size_t *pi = data;
+  size_t const *pi = data;
   code_num (st->sparse_map[*pi].numbytes, keyword, xhdr);
 }
 
@@ -1204,14 +1231,14 @@ sparse_map_decoder (struct tar_stat_info *st, char const *arg,
 {
   int offset = 1;
   static char *keyword = "GNU.sparse.map";
-  
+
   st->sparse_map_avail = 0;
   while (1)
     {
       uintmax_t u;
       char *delim;
       struct sp_array e;
-      
+
       if (!ISDIGIT (*arg))
        {
          ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
@@ -1243,11 +1270,11 @@ sparse_map_decoder (struct tar_stat_info *st, char const *arg,
          else
            {
              ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
-                     "GNU.sparse.numbytes", arg));
+                     keyword, arg));
              return;
            }
        }
-           
+
       offset = !offset;
 
       if (*delim == 0)
@@ -1271,7 +1298,7 @@ sparse_map_decoder (struct tar_stat_info *st, char const *arg,
 
 static void
 dumpdir_coder (struct tar_stat_info const *st, char const *keyword,
-              struct xheader *xhdr, void *data)
+              struct xheader *xhdr, void const *data)
 {
   xheader_print_n (xhdr, keyword, data, dumpdir_size (data));
 }
@@ -1284,6 +1311,60 @@ dumpdir_decoder (struct tar_stat_info *st, char const *arg,
   memcpy (st->dumpdir, arg, size);
 }
 
+static void
+volume_label_coder (struct tar_stat_info const *st, char const *keyword,
+                   struct xheader *xhdr, void const *data)
+{
+  code_string (data, keyword, xhdr);
+}
+
+static void
+volume_label_decoder (struct tar_stat_info *st, char const *arg, size_t size)
+{
+  decode_string (&volume_label, arg);
+}
+
+static void
+volume_size_coder (struct tar_stat_info const *st, char const *keyword,
+                  struct xheader *xhdr, void const *data)
+{
+  off_t v = *(off_t*)data;
+  code_num (v, keyword, xhdr);
+}
+
+static void
+volume_size_decoder (struct tar_stat_info *st, char const *arg, size_t size)
+{
+  uintmax_t u;
+  if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), "GNU.volume.size"))
+    continued_file_size = u;
+}
+
+/* FIXME: Merge with volume_size_coder */
+static void
+volume_offset_coder (struct tar_stat_info const *st, char const *keyword,
+                    struct xheader *xhdr, void const *data)
+{
+  off_t v = *(off_t*)data;
+  code_num (v, keyword, xhdr);
+}
+
+static void
+volume_offset_decoder (struct tar_stat_info *st, char const *arg, size_t size)
+{
+  uintmax_t u;
+  if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), "GNU.volume.offset"))
+    continued_file_offset = u;
+}
+
+static void
+volume_filename_decoder (struct tar_stat_info *st, char const *arg,
+                        size_t size)
+{
+  decode_string (&continued_file_name, arg);
+}
+  
+
 struct xhdr_tab const xhdr_tab[] = {
   { "atime",   atime_coder,    atime_decoder,    false },
   { "comment", dummy_coder,    dummy_decoder,    false },
@@ -1302,7 +1383,9 @@ struct xhdr_tab const xhdr_tab[] = {
   { "GNU.sparse.size",       sparse_size_coder, sparse_size_decoder, true },
   { "GNU.sparse.numblocks",  sparse_numblocks_coder, sparse_numblocks_decoder,
     true },
-  /* tar 1.14 - 1.15.1 keywords. Multiplse instances of these appeared in 'x'
+  { "GNU.sparse.name",       path_coder, path_decoder,
+    true },
+  /* 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." */
@@ -1316,12 +1399,10 @@ struct xhdr_tab const xhdr_tab[] = {
 
   { "GNU.dumpdir",           dumpdir_coder, dumpdir_decoder,
     true },
-  
-#if 0 /* GNU private keywords (not yet implemented) */
 
-  /* Keeps the tape/volume header. May be present only in the global headers.
+  /* Keeps the tape/volume label. May be present only in the global headers.
      Equivalent to GNUTYPE_VOLHDR.  */
-  { "GNU.volume.header", volume_header_coder, volume_header_decoder, false },
+  { "GNU.volume.label", volume_label_coder, volume_label_decoder, true },
 
   /* These may be present in a first global header of the archive.
      They provide the same functionality as GNUTYPE_MULTIVOL header.
@@ -1329,9 +1410,10 @@ struct xhdr_tab const xhdr_tab[] = {
      otherwise kept in the size field of a multivolume header.  The
      GNU.volume.offset keeps the offset of the start of this volume,
      otherwise kept in oldgnu_header.offset.  */
-  { "GNU.volume.size", volume_size_coder, volume_size_decoder, false },
-  { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, false },
-#endif
+  { "GNU.volume.filename", volume_label_coder, volume_filename_decoder,
+    true },
+  { "GNU.volume.size", volume_size_coder, volume_size_decoder, true },
+  { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, true },
 
   { NULL, NULL, NULL, false }
 };
This page took 0.041214 seconds and 4 git commands to generate.