Updated
[debian/tar] / src / xheader.c
1 /* POSIX extended headers for tar.
2
3    Copyright (C) 2003, 2004 Free Software Foundation, Inc.
4
5    This program is free software; you can redistribute it and/or modify it
6    under the terms of the GNU General Public License as published by the
7    Free Software Foundation; either version 2, or (at your option) any later
8    version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
13    Public License for more details.
14
15    You should have received a copy of the GNU General Public License along
16    with this program; if not, write to the Free Software Foundation, Inc.,
17    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18
19 #include "system.h"
20
21 #include <fnmatch.h>
22 #include <hash.h>
23 #include <quotearg.h>
24 #include <stpcpy.h>
25 #include <xstrtol.h>
26
27 #include "common.h"
28
29 #define obstack_chunk_alloc xmalloc
30 #define obstack_chunk_free free
31 #include <obstack.h>
32
33 #include <fnmatch.h>
34
35 static bool xheader_protected_pattern_p (char const *pattern);
36 static bool xheader_protected_keyword_p (char const *keyword);
37 static void xheader_set_single_keyword (char *) __attribute__ ((noreturn));
38
39 /* Used by xheader_finish() */
40 static void code_string (char const *string, char const *keyword,
41                          struct xheader *xhdr);
42 static void extended_header_init (void);
43
44 /* Number of global headers written so far. */
45 static size_t global_header_count;
46 /* FIXME: Possibly it should be reset after changing the volume.
47    POSIX %n specification says that it is expanded to the sequence
48    number of current global header in *the* archive. However, for
49    multi-volume archives this will yield duplicate header names
50    in different volumes, which I'd like to avoid. The best way
51    to solve this would be to use per-archive header count as required
52    by POSIX *and* set globexthdr.name to, say,
53    $TMPDIR/GlobalHead.%p.$NUMVOLUME.%n.
54
55    However it should wait until buffer.c is finally rewritten */
56
57 \f
58 /* Keyword options */
59
60 struct keyword_list
61 {
62   struct keyword_list *next;
63   char *pattern;
64   char *value;
65 };
66
67
68 /* List of keyword patterns set by delete= option */
69 static struct keyword_list *keyword_pattern_list;
70
71 /* List of keyword/value pairs set by `keyword=value' option */
72 static struct keyword_list *keyword_global_override_list;
73
74 /* List of keyword/value pairs set by `keyword:=value' option */
75 static struct keyword_list *keyword_override_list;
76
77 /* List of keyword/value pairs decoded from the last 'g' type header */
78 static struct keyword_list *global_header_override_list;
79
80 /* Template for the name field of an 'x' type header */
81 static char *exthdr_name;
82
83 /* Template for the name field of a 'g' type header */
84 static char *globexthdr_name;
85
86 static bool
87 xheader_keyword_deleted_p (const char *kw)
88 {
89   struct keyword_list *kp;
90
91   for (kp = keyword_pattern_list; kp; kp = kp->next)
92     if (fnmatch (kp->pattern, kw, 0) == 0)
93       return true;
94   return false;
95 }
96
97 static bool
98 xheader_keyword_override_p (const char *keyword)
99 {
100   struct keyword_list *kp;
101
102   for (kp = keyword_override_list; kp; kp = kp->next)
103     if (strcmp (kp->pattern, keyword) == 0)
104       return true;
105   return false;
106 }
107
108 static void
109 xheader_list_append (struct keyword_list **root, char const *kw,
110                      char const *value)
111 {
112   struct keyword_list *kp = xmalloc (sizeof *kp);
113   kp->pattern = xstrdup (kw);
114   kp->value = value ? xstrdup (value) : NULL;
115   kp->next = *root;
116   *root = kp;
117 }
118
119 static void
120 xheader_list_destroy (struct keyword_list **root)
121 {
122   if (root)
123     {
124       struct keyword_list *kw = *root;
125       while (kw)
126         {
127           struct keyword_list *next = kw->next;
128           free (kw->pattern);
129           free (kw->value);
130           free (kw);
131           kw = next;
132         }
133       *root = NULL;
134     }
135 }
136
137 static void
138 xheader_set_single_keyword (char *kw)
139 {
140   USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet imlemented"), kw));
141 }
142
143 static void
144 xheader_set_keyword_equal (char *kw, char *eq)
145 {
146   bool global = true;
147   char *p = eq;
148
149   if (eq[-1] == ':')
150     {
151       p--;
152       global = false;
153     }
154
155   while (p > kw && isspace (*p))
156     p--;
157
158   *p = 0;
159
160   for (p = eq + 1; *p && isspace (*p); p++)
161     ;
162
163   if (strcmp (kw, "delete") == 0)
164     {
165       if (xheader_protected_pattern_p (p))
166         USAGE_ERROR ((0, 0, _("Pattern %s cannot be used"), p));
167       xheader_list_append (&keyword_pattern_list, p, NULL);
168     }
169   else if (strcmp (kw, "exthdr.name") == 0)
170     assign_string (&exthdr_name, p);
171   else if (strcmp (kw, "globexthdr.name") == 0)
172     assign_string (&globexthdr_name, p);
173   else
174     {
175       if (xheader_protected_keyword_p (kw))
176         USAGE_ERROR ((0, 0, _("Keyword %s cannot be overridden"), kw));
177       if (global)
178         xheader_list_append (&keyword_global_override_list, kw, p);
179       else
180         xheader_list_append (&keyword_override_list, kw, p);
181     }
182 }
183
184 void
185 xheader_set_option (char *string)
186 {
187   char *token;
188   for (token = strtok (string, ","); token; token = strtok (NULL, ","))
189     {
190       char *p = strchr (token, '=');
191       if (!p)
192         xheader_set_single_keyword (token);
193       else
194         xheader_set_keyword_equal (token, p);
195     }
196 }
197
198 static void
199 to_decimal (uintmax_t value, char *where, size_t size)
200 {
201   size_t i = 0, j;
202
203   where[i++] = 0;
204   do
205     {
206       where[i++] = '0' + value % 10;
207       value /= 10;
208     }
209   while (i < size && value);
210   for (j = 0, i--; j < i; j++, i--)
211     {
212       char c = where[j];
213       where[j] = where[i];
214       where[i] = c;
215     }
216 }
217
218 /*
219     string Includes:          Replaced By:
220      %d                       The directory name of the file,
221                               equivalent to the result of the
222                               dirname utility on the translated
223                               pathname.
224      %f                       The filename of the file, equivalent
225                               to the result of the basename
226                               utility on the translated pathname.
227      %p                       The process ID of the pax process.
228      %%                       A '%' character. */
229
230 static char *
231 xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
232 {
233   char *buf;
234   size_t len = strlen (fmt);
235   char *q;
236   const char *p;
237   char *dir = NULL;
238   char *base = NULL;
239   char pidbuf[64];
240   char nbuf[64];
241
242   for (p = fmt; *p && (p = strchr (p, '%')); )
243     {
244       switch (p[1])
245         {
246         case '%':
247           len--;
248           break;
249
250         case 'd':
251           if (st)
252             {
253               dir = safer_name_suffix (dir_name (st->orig_file_name), false);
254               len += strlen (dir) - 1;
255             }
256           break;
257
258         case 'f':
259           if (st)
260             {
261               base = base_name (st->orig_file_name);
262               len += strlen (base) - 1;
263             }
264           break;
265
266         case 'p':
267           to_decimal (getpid (), pidbuf, sizeof pidbuf);
268           len += strlen (pidbuf) - 1;
269           break;
270
271         case 'n':
272           if (allow_n)
273             {
274               to_decimal (global_header_count + 1, pidbuf, sizeof pidbuf);
275               len += strlen (nbuf) - 1;
276             }
277           break;
278         }
279       p++;
280     }
281
282   buf = xmalloc (len + 1);
283   for (q = buf, p = fmt; *p; )
284     {
285       if (*p == '%')
286         {
287           switch (p[1])
288             {
289             case '%':
290               *q++ = *p++;
291               p++;
292               break;
293
294             case 'd':
295               if (dir)
296                 q = stpcpy (q, dir);
297               p += 2;
298               break;
299
300             case 'f':
301               if (base)
302                 q = stpcpy (q, base);
303               p += 2;
304               break;
305
306             case 'p':
307               q = stpcpy (q, pidbuf);
308               p += 2;
309               break;
310
311             case 'n':
312               if (allow_n)
313                 {
314                   q = stpcpy (q, nbuf);
315                   p += 2;
316                 }
317               /* else fall through */
318
319             default:
320               *q++ = *p++;
321               if (*p)
322                 *q++ = *p++;
323             }
324         }
325       else
326         *q++ = *p++;
327     }
328
329   /* Do not allow it to end in a slash */
330   while (q > buf && ISSLASH (q[-1]))
331     q--;
332   *q = 0;
333   return buf;
334 }
335
336 char *
337 xheader_xhdr_name (struct tar_stat_info *st)
338 {
339   if (!exthdr_name)
340     assign_string (&exthdr_name, "%d/PaxHeaders.%p/%f");
341   return xheader_format_name (st, exthdr_name, false);
342 }
343
344 #define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n"
345
346 char *
347 xheader_ghdr_name (void)
348 {
349   if (!globexthdr_name)
350     {
351       size_t len;
352       const char *tmp = getenv ("TMPDIR");
353       if (!tmp)
354         tmp = "/tmp";
355       len = strlen (tmp) + sizeof (GLOBAL_HEADER_TEMPLATE); /* Includes nul */
356       globexthdr_name = xmalloc (len);
357       strcpy(globexthdr_name, tmp);
358       strcat(globexthdr_name, GLOBAL_HEADER_TEMPLATE);
359     }
360
361   return xheader_format_name (NULL, globexthdr_name, true);
362 }
363
364 void
365 xheader_write (char type, char *name, struct xheader *xhdr)
366 {
367   union block *header;
368   size_t size;
369   char *p;
370
371   size = xhdr->size;
372   header = start_private_header (name, size);
373   header->header.typeflag = type;
374
375   simple_finish_header (header);
376
377   p = xhdr->buffer;
378
379   do
380     {
381       size_t len;
382
383       header = find_next_block ();
384       len = BLOCKSIZE;
385       if (len > size)
386         len = size;
387       memcpy (header->buffer, p, len);
388       if (len < BLOCKSIZE)
389         memset (header->buffer + len, 0, BLOCKSIZE - len);
390       p += len;
391       size -= len;
392       set_next_block_after (header);
393     }
394   while (size > 0);
395   xheader_destroy (xhdr);
396 }
397
398 void
399 xheader_write_global (void)
400 {
401   char *name;
402   struct keyword_list *kp;
403
404   if (!keyword_global_override_list)
405     return;
406
407   extended_header_init ();
408   for (kp = keyword_global_override_list; kp; kp = kp->next)
409     code_string (kp->value, kp->pattern, &extended_header);
410   xheader_finish (&extended_header);
411   xheader_write (XGLTYPE, name = xheader_ghdr_name (),
412                  &extended_header);
413   free (name);
414   global_header_count++;
415 }
416
417 \f
418 /* General Interface */
419
420 struct xhdr_tab
421 {
422   char const *keyword;
423   void (*coder) (struct tar_stat_info const *, char const *,
424                  struct xheader *, void *data);
425   void (*decoder) (struct tar_stat_info *, char const *);
426   bool protect;
427 };
428
429 /* This declaration must be extern, because ISO C99 section 6.9.2
430    prohibits a tentative definition that has both internal linkage and
431    incomplete type.  If we made it static, we'd have to declare its
432    size which would be a maintenance pain; if we put its initializer
433    here, we'd need a boatload of forward declarations, which would be
434    even more of a pain.  */
435 extern struct xhdr_tab const xhdr_tab[];
436
437 static struct xhdr_tab const *
438 locate_handler (char const *keyword)
439 {
440   struct xhdr_tab const *p;
441
442   for (p = xhdr_tab; p->keyword; p++)
443     if (strcmp (p->keyword, keyword) == 0)
444       return p;
445   return NULL;
446 }
447
448 static bool
449 xheader_protected_pattern_p (const char *pattern)
450 {
451   struct xhdr_tab const *p;
452
453   for (p = xhdr_tab; p->keyword; p++)
454     if (p->protect && fnmatch (pattern, p->keyword, 0) == 0)
455       return true;
456   return false;
457 }
458
459 static bool
460 xheader_protected_keyword_p (const char *keyword)
461 {
462   struct xhdr_tab const *p;
463
464   for (p = xhdr_tab; p->keyword; p++)
465     if (p->protect && strcmp (p->keyword, keyword) == 0)
466       return true;
467   return false;
468 }
469
470 /* Decodes a single extended header record. Advances P to the next
471    record.
472    Returns true on success, false otherwise. */
473 static bool
474 decode_record (char **p,
475                void (*handler) (void *, char const *, char const *),
476                void *data)
477 {
478   size_t len;
479   char const *keyword;
480   char *start = *p;
481   char endc;
482
483   if (**p == 0)
484     return false;
485
486   len = strtoul (*p, p, 10);
487   if (**p != ' ')
488     {
489       ERROR ((0, 0,
490        _("Malformed extended header: missing whitespace after the length")));
491       return false;
492     }
493
494   keyword = ++*p;
495   for (;*p < start + len; ++*p)
496     if (**p == '=')
497       break;
498
499   if (**p != '=')
500     {
501       ERROR ((0, 0, _("Malformed extended header: missing equal sign")));
502       return false;
503     }
504
505   **p = 0;
506
507   endc = start[len-1];
508   start[len-1] = 0;
509
510   handler (data, keyword, *p + 1);
511
512   start[len-1] = endc;
513   **p = '=';
514   *p = &start[len];
515   return true;
516 }
517
518 static void
519 run_override_list (struct keyword_list *kp, struct tar_stat_info *st)
520 {
521   for (; kp; kp = kp->next)
522     {
523       struct xhdr_tab const *t = locate_handler (kp->pattern);
524       if (t)
525         t->decoder (st, kp->value);
526     }
527 }
528
529 static void
530 decx (void *data, char const *keyword, char const *value)
531 {
532   struct xhdr_tab const *t;
533   struct tar_stat_info *st = data;
534
535   if (xheader_keyword_deleted_p (keyword)
536       || xheader_keyword_override_p (keyword))
537     return;
538
539   t = locate_handler (keyword);
540   if (t)
541     t->decoder (st, value);
542 }
543
544 void
545 xheader_decode (struct tar_stat_info *st)
546 {
547   run_override_list (keyword_global_override_list, st);
548   run_override_list (global_header_override_list, st);
549
550   if (extended_header.size)
551     {
552       char *p = extended_header.buffer + BLOCKSIZE;
553       char *endp = &extended_header.buffer[extended_header.size-1];
554
555       while (p < endp)
556         if (!decode_record (&p, decx, st))
557           break;
558     }
559   run_override_list (keyword_override_list, st);
560 }
561
562 static void
563 decg (void *data, char const *keyword, char const *value)
564 {
565   struct keyword_list **kwl = data;
566   xheader_list_append (kwl, keyword, value);
567 }
568
569 void
570 xheader_decode_global (void)
571 {
572   if (extended_header.size)
573     {
574       char *p = extended_header.buffer + BLOCKSIZE;
575       char *endp = &extended_header.buffer[extended_header.size-1];
576
577       xheader_list_destroy (&global_header_override_list);
578       while (p < endp)
579         if (!decode_record (&p, decg, &global_header_override_list))
580           break;
581     }
582 }
583
584 static void
585 extended_header_init (void)
586 {
587   if (!extended_header.stk)
588     {
589       extended_header.stk = xmalloc (sizeof *extended_header.stk);
590       obstack_init (extended_header.stk);
591     }
592 }
593
594 void
595 xheader_store (char const *keyword, struct tar_stat_info const *st, void *data)
596 {
597   struct xhdr_tab const *t;
598
599   if (extended_header.buffer)
600     return;
601   t = locate_handler (keyword);
602   if (!t)
603     return;
604   if (xheader_keyword_deleted_p (keyword)
605       || xheader_keyword_override_p (keyword))
606     return;
607   extended_header_init ();
608   t->coder (st, keyword, &extended_header, data);
609 }
610
611 void
612 xheader_read (union block *p, size_t size)
613 {
614   size_t j = 0;
615   size_t nblocks;
616
617   free (extended_header.buffer);
618   size += BLOCKSIZE;
619   extended_header.size = size;
620   nblocks = (size + BLOCKSIZE - 1) / BLOCKSIZE;
621   extended_header.buffer = xmalloc (size + 1);
622
623   do
624     {
625       size_t len = size;
626
627       if (len > BLOCKSIZE)
628         len = BLOCKSIZE;
629
630       memcpy (&extended_header.buffer[j], p->buffer, len);
631       set_next_block_after (p);
632
633       p = find_next_block ();
634
635       j += len;
636       size -= len;
637     }
638   while (size > 0);
639 }
640
641 static size_t
642 format_uintmax (uintmax_t val, char *buf, size_t s)
643 {
644   if (!buf)
645     {
646       s = 0;
647       do
648         s++;
649       while ((val /= 10) != 0);
650     }
651   else
652     {
653       char *p = buf + s - 1;
654
655       do
656         {
657           *p-- = val % 10 + '0';
658         }
659       while ((val /= 10) != 0);
660
661       while (p >= buf)
662         *p-- = '0';
663     }
664   return s;
665 }
666
667 static void
668 xheader_print (struct xheader *xhdr, char const *keyword, char const *value)
669 {
670   size_t len = strlen (keyword) + strlen (value) + 3; /* ' ' + '=' + '\n' */
671   size_t p, n = 0;
672   char nbuf[100];
673
674   do
675     {
676       p = n;
677       n = format_uintmax (len + p, NULL, 0);
678     }
679   while (n != p);
680
681   format_uintmax (len + n, nbuf, n);
682   obstack_grow (xhdr->stk, nbuf, n);
683   obstack_1grow (xhdr->stk, ' ');
684   obstack_grow (xhdr->stk, keyword, strlen (keyword));
685   obstack_1grow (xhdr->stk, '=');
686   obstack_grow (xhdr->stk, value, strlen (value));
687   obstack_1grow (xhdr->stk, '\n');
688 }
689
690 void
691 xheader_finish (struct xheader *xhdr)
692 {
693   struct keyword_list *kp;
694
695   for (kp = keyword_override_list; kp; kp = kp->next)
696     code_string (kp->value, kp->pattern, xhdr);
697
698   obstack_1grow (xhdr->stk, 0);
699   xhdr->buffer = obstack_finish (xhdr->stk);
700   xhdr->size = strlen (xhdr->buffer);
701 }
702
703 void
704 xheader_destroy (struct xheader *xhdr)
705 {
706   if (xhdr->stk)
707     {
708       obstack_free (xhdr->stk, NULL);
709       free (xhdr->stk);
710       xhdr->stk = NULL;
711     }
712   else
713     free (xhdr->buffer);
714   xhdr->buffer = 0;
715   xhdr->size = 0;
716 }
717
718 \f
719 /* Implementations */
720 static void
721 code_string (char const *string, char const *keyword, struct xheader *xhdr)
722 {
723   char *outstr;
724   if (!utf8_convert (true, string, &outstr))
725     {
726       /* FIXME: report error */
727       outstr = xstrdup (string);
728     }
729   xheader_print (xhdr, keyword, outstr);
730   free (outstr);
731 }
732
733 static void
734 decode_string (char **string, char const *arg)
735 {
736   if (*string)
737     {
738       free (*string);
739       *string = NULL;
740     }
741   if (!utf8_convert (false, arg, string))
742     {
743       /* FIXME: report error and act accordingly to --pax invalid=UTF-8 */
744       assign_string (string, arg);
745     }
746 }
747
748 static void
749 code_time (time_t t, unsigned long nano,
750            char const *keyword, struct xheader *xhdr)
751 {
752   char sbuf[200];
753   size_t s = format_uintmax (t, NULL, 0);
754   if (s + 11 >= sizeof sbuf)
755     return;
756   format_uintmax (t, sbuf, s);
757   sbuf[s++] = '.';
758   s += format_uintmax (nano, sbuf + s, 9);
759   sbuf[s] = 0;
760   xheader_print (xhdr, keyword, sbuf);
761 }
762
763 static void
764 decode_time (char const *arg, time_t *secs, unsigned long *nsecs)
765 {
766   uintmax_t u;
767   char *p;
768   if (xstrtoumax (arg, &p, 10, &u, "") == LONGINT_OK)
769     {
770       *secs = u;
771       if (*p == '.' && xstrtoumax (p+1, NULL, 10, &u, "") == LONGINT_OK)
772         *nsecs = u;
773     }
774 }
775
776 static void
777 code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
778 {
779   char sbuf[100];
780   size_t s = format_uintmax (value, NULL, 0);
781   format_uintmax (value, sbuf, s);
782   sbuf[s] = 0;
783   xheader_print (xhdr, keyword, sbuf);
784 }
785
786 static void
787 dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)),
788              char const *keyword __attribute__ ((unused)),
789              struct xheader *xhdr __attribute__ ((unused)),
790              void *data __attribute__ ((unused)))
791 {
792 }
793
794 static void
795 dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)),
796                char const *arg __attribute__ ((unused)))
797 {
798 }
799
800 static void
801 atime_coder (struct tar_stat_info const *st, char const *keyword,
802              struct xheader *xhdr, void *data __attribute__ ((unused)))
803 {
804   code_time (st->stat.st_atime, st->atime_nsec, keyword, xhdr);
805 }
806
807 static void
808 atime_decoder (struct tar_stat_info *st, char const *arg)
809 {
810   decode_time (arg, &st->stat.st_atime, &st->atime_nsec);
811 }
812
813 static void
814 gid_coder (struct tar_stat_info const *st, char const *keyword,
815            struct xheader *xhdr, void *data __attribute__ ((unused)))
816 {
817   code_num (st->stat.st_gid, keyword, xhdr);
818 }
819
820 static void
821 gid_decoder (struct tar_stat_info *st, char const *arg)
822 {
823   uintmax_t u;
824   if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
825     st->stat.st_gid = u;
826 }
827
828 static void
829 gname_coder (struct tar_stat_info const *st, char const *keyword,
830              struct xheader *xhdr, void *data __attribute__ ((unused)))
831 {
832   code_string (st->gname, keyword, xhdr);
833 }
834
835 static void
836 gname_decoder (struct tar_stat_info *st, char const *arg)
837 {
838   decode_string (&st->gname, arg);
839 }
840
841 static void
842 linkpath_coder (struct tar_stat_info const *st, char const *keyword,
843                 struct xheader *xhdr, void *data __attribute__ ((unused)))
844 {
845   code_string (st->link_name, keyword, xhdr);
846 }
847
848 static void
849 linkpath_decoder (struct tar_stat_info *st, char const *arg)
850 {
851   decode_string (&st->link_name, arg);
852 }
853
854 static void
855 ctime_coder (struct tar_stat_info const *st, char const *keyword,
856              struct xheader *xhdr, void *data __attribute__ ((unused)))
857 {
858   code_time (st->stat.st_ctime, st->ctime_nsec, keyword, xhdr);
859 }
860
861 static void
862 ctime_decoder (struct tar_stat_info *st, char const *arg)
863 {
864   decode_time (arg, &st->stat.st_ctime, &st->ctime_nsec);
865 }
866
867 static void
868 mtime_coder (struct tar_stat_info const *st, char const *keyword,
869              struct xheader *xhdr, void *data __attribute__ ((unused)))
870 {
871   code_time (st->stat.st_mtime, st->mtime_nsec, keyword, xhdr);
872 }
873
874 static void
875 mtime_decoder (struct tar_stat_info *st, char const *arg)
876 {
877   decode_time (arg, &st->stat.st_mtime, &st->mtime_nsec);
878 }
879
880 static void
881 path_coder (struct tar_stat_info const *st, char const *keyword,
882             struct xheader *xhdr, void *data __attribute__ ((unused)))
883 {
884   code_string (st->file_name, keyword, xhdr);
885 }
886
887 static void
888 path_decoder (struct tar_stat_info *st, char const *arg)
889 {
890   decode_string (&st->orig_file_name, arg);
891   decode_string (&st->file_name, arg);
892   st->had_trailing_slash = strip_trailing_slashes (st->file_name);
893 }
894
895 static void
896 size_coder (struct tar_stat_info const *st, char const *keyword,
897             struct xheader *xhdr, void *data __attribute__ ((unused)))
898 {
899   code_num (st->stat.st_size, keyword, xhdr);
900 }
901
902 static void
903 size_decoder (struct tar_stat_info *st, char const *arg)
904 {
905   uintmax_t u;
906   if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
907     st->archive_file_size = st->stat.st_size = u;
908 }
909
910 static void
911 uid_coder (struct tar_stat_info const *st, char const *keyword,
912            struct xheader *xhdr, void *data __attribute__ ((unused)))
913 {
914   code_num (st->stat.st_uid, keyword, xhdr);
915 }
916
917 static void
918 uid_decoder (struct tar_stat_info *st, char const *arg)
919 {
920   uintmax_t u;
921   if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
922     st->stat.st_uid = u;
923 }
924
925 static void
926 uname_coder (struct tar_stat_info const *st, char const *keyword,
927              struct xheader *xhdr, void *data __attribute__ ((unused)))
928 {
929   code_string (st->uname, keyword, xhdr);
930 }
931
932 static void
933 uname_decoder (struct tar_stat_info *st, char const *arg)
934 {
935   decode_string (&st->uname, arg);
936 }
937
938 static void
939 sparse_size_coder (struct tar_stat_info const *st, char const *keyword,
940              struct xheader *xhdr, void *data)
941 {
942   size_coder (st, keyword, xhdr, data);
943 }
944
945 static void
946 sparse_size_decoder (struct tar_stat_info *st, char const *arg)
947 {
948   uintmax_t u;
949   if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
950     st->stat.st_size = u;
951 }
952
953 static void
954 sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword,
955                         struct xheader *xhdr,
956                         void *data __attribute__ ((unused)))
957 {
958   code_num (st->sparse_map_avail, keyword, xhdr);
959 }
960
961 static void
962 sparse_numblocks_decoder (struct tar_stat_info *st, char const *arg)
963 {
964   uintmax_t u;
965   if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
966     {
967       st->sparse_map_size = u;
968       st->sparse_map = calloc(st->sparse_map_size, sizeof(st->sparse_map[0]));
969       st->sparse_map_avail = 0;
970     }
971 }
972
973 static void
974 sparse_offset_coder (struct tar_stat_info const *st, char const *keyword,
975                      struct xheader *xhdr, void *data)
976 {
977   size_t i = *(size_t*)data;
978   code_num (st->sparse_map[i].offset, keyword, xhdr);
979 }
980
981 static void
982 sparse_offset_decoder (struct tar_stat_info *st, char const *arg)
983 {
984   uintmax_t u;
985   if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
986     st->sparse_map[st->sparse_map_avail].offset = u;
987 }
988
989 static void
990 sparse_numbytes_coder (struct tar_stat_info const *st, char const *keyword,
991                      struct xheader *xhdr, void *data)
992 {
993   size_t i = *(size_t*)data;
994   code_num (st->sparse_map[i].numbytes, keyword, xhdr);
995 }
996
997 static void
998 sparse_numbytes_decoder (struct tar_stat_info *st, char const *arg)
999 {
1000   uintmax_t u;
1001   if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
1002     {
1003       if (st->sparse_map_avail == st->sparse_map_size)
1004         {
1005           st->sparse_map_size *= 2;
1006           st->sparse_map = xrealloc (st->sparse_map,
1007                                      st->sparse_map_size
1008                                      * sizeof st->sparse_map[0]);
1009         }
1010       st->sparse_map[st->sparse_map_avail++].numbytes = u;
1011     }
1012 }
1013
1014 struct xhdr_tab const xhdr_tab[] = {
1015   { "atime",    atime_coder,    atime_decoder,    false },
1016   { "comment",  dummy_coder,    dummy_decoder,    false },
1017   { "charset",  dummy_coder,    dummy_decoder,    false },
1018   { "ctime",    ctime_coder,    ctime_decoder,    false },
1019   { "gid",      gid_coder,      gid_decoder,      false },
1020   { "gname",    gname_coder,    gname_decoder,    false },
1021   { "linkpath", linkpath_coder, linkpath_decoder, false },
1022   { "mtime",    mtime_coder,    mtime_decoder,    false },
1023   { "path",     path_coder,     path_decoder,     false },
1024   { "size",     size_coder,     size_decoder,     false },
1025   { "uid",      uid_coder,      uid_decoder,      false },
1026   { "uname",    uname_coder,    uname_decoder,    false },
1027
1028   /* Sparse file handling */
1029   { "GNU.sparse.size",       sparse_size_coder, sparse_size_decoder, true },
1030   { "GNU.sparse.numblocks",  sparse_numblocks_coder, sparse_numblocks_decoder,
1031     true },
1032   { "GNU.sparse.offset",     sparse_offset_coder, sparse_offset_decoder,
1033     true },
1034   { "GNU.sparse.numbytes",   sparse_numbytes_coder, sparse_numbytes_decoder,
1035     true },
1036
1037 #if 0 /* GNU private keywords (not yet implemented) */
1038
1039   /* The next directory entry actually contains the names of files
1040      that were in the directory at the time the dump was made.
1041      Supersedes GNUTYPE_DUMPDIR header type.  */
1042   { "GNU.dump.name",  dump_name_coder, dump_name_decoder, false },
1043   { "GNU.dump.status", dump_status_coder, dump_status_decoder, false },
1044
1045   /* Keeps the tape/volume header. May be present only in the global headers.
1046      Equivalent to GNUTYPE_VOLHDR.  */
1047   { "GNU.volume.header", volume_header_coder, volume_header_decoder, false },
1048
1049   /* These may be present in a first global header of the archive.
1050      They provide the same functionality as GNUTYPE_MULTIVOL header.
1051      The GNU.volume.size keeps the real_s_sizeleft value, which is
1052      otherwise kept in the size field of a multivolume header.  The
1053      GNU.volume.offset keeps the offset of the start of this volume,
1054      otherwise kept in oldgnu_header.offset.  */
1055   { "GNU.volume.size", volume_size_coder, volume_size_decoder, false },
1056   { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, false },
1057 #endif
1058
1059   { NULL, NULL, NULL, false }
1060 };