1 /* POSIX extended headers for tar.
3 Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
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
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.
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 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
31 static bool xheader_protected_pattern_p (char const *pattern
);
32 static bool xheader_protected_keyword_p (char const *keyword
);
33 static void xheader_set_single_keyword (char *) __attribute__ ((noreturn
));
35 /* Used by xheader_finish() */
36 static void code_string (char const *string
, char const *keyword
,
37 struct xheader
*xhdr
);
38 static void extended_header_init (void);
40 /* Number of global headers written so far. */
41 static size_t global_header_count
;
42 /* FIXME: Possibly it should be reset after changing the volume.
43 POSIX %n specification says that it is expanded to the sequence
44 number of current global header in *the* archive. However, for
45 multi-volume archives this will yield duplicate header names
46 in different volumes, which I'd like to avoid. The best way
47 to solve this would be to use per-archive header count as required
48 by POSIX *and* set globexthdr.name to, say,
49 $TMPDIR/GlobalHead.%p.$NUMVOLUME.%n.
51 However it should wait until buffer.c is finally rewritten */
54 /* Interface functions to obstacks */
57 x_obstack_grow (struct xheader
*xhdr
, const char *ptr
, size_t length
)
59 obstack_grow (xhdr
->stk
, ptr
, length
);
64 x_obstack_1grow (struct xheader
*xhdr
, char c
)
66 obstack_1grow (xhdr
->stk
, c
);
71 x_obstack_blank (struct xheader
*xhdr
, size_t length
)
73 obstack_blank (xhdr
->stk
, length
);
82 struct keyword_list
*next
;
88 /* List of keyword patterns set by delete= option */
89 static struct keyword_list
*keyword_pattern_list
;
91 /* List of keyword/value pairs set by `keyword=value' option */
92 static struct keyword_list
*keyword_global_override_list
;
94 /* List of keyword/value pairs set by `keyword:=value' option */
95 static struct keyword_list
*keyword_override_list
;
97 /* List of keyword/value pairs decoded from the last 'g' type header */
98 static struct keyword_list
*global_header_override_list
;
100 /* Template for the name field of an 'x' type header */
101 static char *exthdr_name
;
103 /* Template for the name field of a 'g' type header */
104 static char *globexthdr_name
;
107 xheader_keyword_deleted_p (const char *kw
)
109 struct keyword_list
*kp
;
111 for (kp
= keyword_pattern_list
; kp
; kp
= kp
->next
)
112 if (fnmatch (kp
->pattern
, kw
, 0) == 0)
118 xheader_keyword_override_p (const char *keyword
)
120 struct keyword_list
*kp
;
122 for (kp
= keyword_override_list
; kp
; kp
= kp
->next
)
123 if (strcmp (kp
->pattern
, keyword
) == 0)
129 xheader_list_append (struct keyword_list
**root
, char const *kw
,
132 struct keyword_list
*kp
= xmalloc (sizeof *kp
);
133 kp
->pattern
= xstrdup (kw
);
134 kp
->value
= value
? xstrdup (value
) : NULL
;
140 xheader_list_destroy (struct keyword_list
**root
)
144 struct keyword_list
*kw
= *root
;
147 struct keyword_list
*next
= kw
->next
;
158 xheader_set_single_keyword (char *kw
)
160 USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet imlemented"), kw
));
164 xheader_set_keyword_equal (char *kw
, char *eq
)
175 while (p
> kw
&& isspace (*p
))
180 for (p
= eq
+ 1; *p
&& isspace (*p
); p
++)
183 if (strcmp (kw
, "delete") == 0)
185 if (xheader_protected_pattern_p (p
))
186 USAGE_ERROR ((0, 0, _("Pattern %s cannot be used"), quote (p
)));
187 xheader_list_append (&keyword_pattern_list
, p
, NULL
);
189 else if (strcmp (kw
, "exthdr.name") == 0)
190 assign_string (&exthdr_name
, p
);
191 else if (strcmp (kw
, "globexthdr.name") == 0)
192 assign_string (&globexthdr_name
, p
);
195 if (xheader_protected_keyword_p (kw
))
196 USAGE_ERROR ((0, 0, _("Keyword %s cannot be overridden"), kw
));
198 xheader_list_append (&keyword_global_override_list
, kw
, p
);
200 xheader_list_append (&keyword_override_list
, kw
, p
);
205 xheader_set_option (char *string
)
208 for (token
= strtok (string
, ","); token
; token
= strtok (NULL
, ","))
210 char *p
= strchr (token
, '=');
212 xheader_set_single_keyword (token
);
214 xheader_set_keyword_equal (token
, p
);
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
224 %f The filename of the file, equivalent
225 to the result of the basename
226 utility on the translated file name.
227 %p The process ID of the pax process.
228 %n The value of the 3rd argument.
229 %% A '%' character. */
232 xheader_format_name (struct tar_stat_info
*st
, const char *fmt
, size_t n
)
235 size_t len
= strlen (fmt
);
241 char pidbuf
[UINTMAX_STRSIZE_BOUND
];
243 char nbuf
[UINTMAX_STRSIZE_BOUND
];
244 char const *nptr
= NULL
;
246 for (p
= fmt
; *p
&& (p
= strchr (p
, '%')); )
258 dirp
= dir_name (st
->orig_file_name
);
259 dir
= safer_name_suffix (dirp
, false, absolute_names_option
);
260 len
+= strlen (dir
) - 2;
267 base
= base_name (st
->orig_file_name
);
268 len
+= strlen (base
) - 2;
273 pptr
= umaxtostr (getpid (), pidbuf
);
274 len
+= pidbuf
+ sizeof pidbuf
- 1 - pptr
- 2;
278 nptr
= umaxtostr (n
, nbuf
);
279 len
+= nbuf
+ sizeof nbuf
- 1 - nptr
- 2;
285 buf
= xmalloc (len
+ 1);
286 for (q
= buf
, p
= fmt
; *p
; )
305 q
= stpcpy (q
, base
);
310 q
= stpcpy (q
, pptr
);
317 q
= stpcpy (q
, nptr
);
321 /* else fall through */
335 /* Do not allow it to end in a slash */
336 while (q
> buf
&& ISSLASH (q
[-1]))
343 xheader_xhdr_name (struct tar_stat_info
*st
)
346 assign_string (&exthdr_name
, "%d/PaxHeaders.%p/%f");
347 return xheader_format_name (st
, exthdr_name
, 0);
350 #define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n"
353 xheader_ghdr_name (void)
355 if (!globexthdr_name
)
358 const char *tmp
= getenv ("TMPDIR");
361 len
= strlen (tmp
) + sizeof (GLOBAL_HEADER_TEMPLATE
); /* Includes nul */
362 globexthdr_name
= xmalloc (len
);
363 strcpy(globexthdr_name
, tmp
);
364 strcat(globexthdr_name
, GLOBAL_HEADER_TEMPLATE
);
367 return xheader_format_name (NULL
, globexthdr_name
, global_header_count
+ 1);
371 xheader_write (char type
, char *name
, struct xheader
*xhdr
)
377 if (multi_volume_option
)
379 /* Estimate the total size of the extended header and, in case
380 if XHDTYPE, the ustar header following it, and make sure that
381 these fit into the current volume */
382 size_t hblocks
= 1 + (extended_header
.size
+ BLOCKSIZE
- 1) / BLOCKSIZE
;
385 multi_volume_fixup (hblocks
);
389 header
= start_private_header (name
, size
);
390 header
->header
.typeflag
= type
;
392 simple_finish_header (header
);
400 header
= find_next_block ();
404 memcpy (header
->buffer
, p
, len
);
406 memset (header
->buffer
+ len
, 0, BLOCKSIZE
- len
);
409 set_next_block_after (header
);
412 xheader_destroy (xhdr
);
415 global_header_count
++;
418 /* SIZE is guaranteed to be divisible by BLOCKSIZE */
420 xheader_eof (size_t size
)
428 name
= xheader_ghdr_name ();
429 header
= start_private_header (name
, size
);
430 header
->header
.typeflag
= XGLTYPE
;
432 simple_finish_header (header
);
439 header
= find_next_block ();
443 memset (header
->buffer
, 0, len
);
447 sprintf (header
->buffer
, "%d GNU.volume.eof=", size
);
450 set_next_block_after (header
);
453 header
->buffer
[BLOCKSIZE
-1] = '\n';
457 xheader_write_global (void)
460 struct keyword_list
*kp
;
462 if (!keyword_global_override_list
)
465 extended_header_init ();
466 for (kp
= keyword_global_override_list
; kp
; kp
= kp
->next
)
467 code_string (kp
->value
, kp
->pattern
, &extended_header
);
468 xheader_finish (&extended_header
);
469 xheader_write (XGLTYPE
, name
= xheader_ghdr_name (),
475 /* General Interface */
480 void (*coder
) (struct tar_stat_info
const *, char const *,
481 struct xheader
*, void const *data
);
482 void (*decoder
) (struct tar_stat_info
*, char const *, size_t);
486 /* This declaration must be extern, because ISO C99 section 6.9.2
487 prohibits a tentative definition that has both internal linkage and
488 incomplete type. If we made it static, we'd have to declare its
489 size which would be a maintenance pain; if we put its initializer
490 here, we'd need a boatload of forward declarations, which would be
491 even more of a pain. */
492 extern struct xhdr_tab
const xhdr_tab
[];
494 static struct xhdr_tab
const *
495 locate_handler (char const *keyword
)
497 struct xhdr_tab
const *p
;
499 for (p
= xhdr_tab
; p
->keyword
; p
++)
500 if (strcmp (p
->keyword
, keyword
) == 0)
506 xheader_protected_pattern_p (const char *pattern
)
508 struct xhdr_tab
const *p
;
510 for (p
= xhdr_tab
; p
->keyword
; p
++)
511 if (p
->protect
&& fnmatch (pattern
, p
->keyword
, 0) == 0)
517 xheader_protected_keyword_p (const char *keyword
)
519 struct xhdr_tab
const *p
;
521 for (p
= xhdr_tab
; p
->keyword
; p
++)
522 if (p
->protect
&& strcmp (p
->keyword
, keyword
) == 0)
527 /* Decode a single extended header record, advancing *PTR to the next record.
528 Return true on success, false otherwise. */
530 decode_record (char **ptr
,
531 void (*handler
) (void *, char const *, char const *, size_t),
536 unsigned long int len
;
540 size_t len_max
= extended_header
.buffer
+ extended_header
.size
- start
;
542 while (*p
== ' ' || *p
== '\t')
548 ERROR ((0, 0, _("Malformed extended header: missing length")));
553 len
= strtoul (p
, &len_lim
, 10);
557 int len_len
= len_lim
- p
;
558 ERROR ((0, 0, _("Extended header length %*s is out of range"),
565 for (p
= len_lim
; *p
== ' ' || *p
== '\t'; p
++)
570 _("Malformed extended header: missing blank after length")));
576 if (! (p
&& p
< nextp
))
578 ERROR ((0, 0, _("Malformed extended header: missing equal sign")));
582 if (nextp
[-1] != '\n')
584 ERROR ((0, 0, _("Malformed extended header: missing newline")));
588 *p
= nextp
[-1] = '\0';
589 handler (data
, keyword
, p
+ 1, nextp
- p
- 2); /* '=' + trailing '\n' */
597 run_override_list (struct keyword_list
*kp
, struct tar_stat_info
*st
)
599 for (; kp
; kp
= kp
->next
)
601 struct xhdr_tab
const *t
= locate_handler (kp
->pattern
);
603 t
->decoder (st
, kp
->value
, strlen (kp
->value
));
608 decx (void *data
, char const *keyword
, char const *value
, size_t size
)
610 struct xhdr_tab
const *t
;
611 struct tar_stat_info
*st
= data
;
613 if (xheader_keyword_deleted_p (keyword
)
614 || xheader_keyword_override_p (keyword
))
617 t
= locate_handler (keyword
);
619 t
->decoder (st
, value
, size
);
621 ERROR((0, 0, _("Ignoring unknown extended header keyword `%s'"),
626 xheader_decode (struct tar_stat_info
*st
)
628 run_override_list (keyword_global_override_list
, st
);
629 run_override_list (global_header_override_list
, st
);
631 if (extended_header
.size
)
633 char *p
= extended_header
.buffer
+ BLOCKSIZE
;
634 while (decode_record (&p
, decx
, st
))
637 run_override_list (keyword_override_list
, st
);
641 decg (void *data
, char const *keyword
, char const *value
,
642 size_t size
__attribute__((unused
)))
644 struct keyword_list
**kwl
= data
;
645 xheader_list_append (kwl
, keyword
, value
);
649 xheader_decode_global (void)
651 if (extended_header
.size
)
653 char *p
= extended_header
.buffer
+ BLOCKSIZE
;
655 xheader_list_destroy (&global_header_override_list
);
656 while (decode_record (&p
, decg
, &global_header_override_list
))
662 extended_header_init (void)
664 if (!extended_header
.stk
)
666 extended_header
.stk
= xmalloc (sizeof *extended_header
.stk
);
667 obstack_init (extended_header
.stk
);
672 xheader_save (struct xheader
*xhdr
)
674 *xhdr
= extended_header
;
675 memset (&extended_header
, 0, sizeof extended_header
);
679 xheader_restore (struct xheader
*xhdr
)
681 xheader_destroy (&extended_header
);
682 extended_header
= *xhdr
;
686 xheader_store (char const *keyword
, struct tar_stat_info
const *st
,
689 struct xhdr_tab
const *t
;
691 if (extended_header
.buffer
)
693 t
= locate_handler (keyword
);
696 if (xheader_keyword_deleted_p (keyword
)
697 || xheader_keyword_override_p (keyword
))
699 extended_header_init ();
700 t
->coder (st
, keyword
, &extended_header
, data
);
704 xheader_read (union block
*p
, size_t size
)
709 free (extended_header
.buffer
);
711 extended_header
.size
= size
;
712 nblocks
= (size
+ BLOCKSIZE
- 1) / BLOCKSIZE
;
713 extended_header
.buffer
= xmalloc (size
+ 1);
714 extended_header
.buffer
[size
] = '\0';
723 memcpy (&extended_header
.buffer
[j
], p
->buffer
, len
);
724 set_next_block_after (p
);
726 p
= find_next_block ();
735 xheader_print_n (struct xheader
*xhdr
, char const *keyword
,
736 char const *value
, size_t vsize
)
738 size_t len
= strlen (keyword
) + vsize
+ 3; /* ' ' + '=' + '\n' */
741 char nbuf
[UINTMAX_STRSIZE_BOUND
];
747 np
= umaxtostr (len
+ p
, nbuf
);
748 n
= nbuf
+ sizeof nbuf
- 1 - np
;
752 x_obstack_grow (xhdr
, np
, n
);
753 x_obstack_1grow (xhdr
, ' ');
754 x_obstack_grow (xhdr
, keyword
, strlen (keyword
));
755 x_obstack_1grow (xhdr
, '=');
756 x_obstack_grow (xhdr
, value
, vsize
);
757 x_obstack_1grow (xhdr
, '\n');
761 xheader_print (struct xheader
*xhdr
, char const *keyword
, char const *value
)
763 xheader_print_n (xhdr
, keyword
, value
, strlen (value
));
767 xheader_finish (struct xheader
*xhdr
)
769 struct keyword_list
*kp
;
771 for (kp
= keyword_override_list
; kp
; kp
= kp
->next
)
772 code_string (kp
->value
, kp
->pattern
, xhdr
);
774 xhdr
->buffer
= obstack_finish (xhdr
->stk
);
778 xheader_destroy (struct xheader
*xhdr
)
782 obstack_free (xhdr
->stk
, NULL
);
793 /* Buildable strings */
794 static uintmax_t string_length
;
797 xheader_string_begin ()
803 xheader_string_add (char const *s
)
805 if (extended_header
.buffer
)
807 extended_header_init ();
808 string_length
+= strlen (s
);
809 x_obstack_grow (&extended_header
, s
, strlen (s
));
813 xheader_string_end (char const *keyword
)
818 char nbuf
[UINTMAX_STRSIZE_BOUND
];
822 if (extended_header
.buffer
)
824 extended_header_init ();
826 len
= strlen (keyword
) + string_length
+ 3; /* ' ' + '=' + '\n' */
831 np
= umaxtostr (len
+ p
, nbuf
);
832 n
= nbuf
+ sizeof nbuf
- 1 - np
;
836 p
= strlen (keyword
) + n
+ 2;
837 x_obstack_blank (&extended_header
, p
);
838 x_obstack_1grow (&extended_header
, '\n');
839 cp
= obstack_next_free (extended_header
.stk
) - string_length
- p
- 1;
840 memmove (cp
+ p
, cp
, string_length
);
841 cp
= stpcpy (cp
, np
);
843 cp
= stpcpy (cp
, keyword
);
848 /* Implementations */
851 out_of_range_header (char const *keyword
, char const *value
,
852 uintmax_t minus_minval
, uintmax_t maxval
)
854 char minval_buf
[UINTMAX_STRSIZE_BOUND
+ 1];
855 char maxval_buf
[UINTMAX_STRSIZE_BOUND
];
856 char *minval_string
= umaxtostr (minus_minval
, minval_buf
+ 1);
857 char *maxval_string
= umaxtostr (maxval
, maxval_buf
);
859 *--minval_string
= '-';
861 /* TRANSLATORS: The first %s is the pax extended header keyword
862 (atime, gid, etc.). */
863 ERROR ((0, 0, _("Extended header %s=%s is out of range %s..%s"),
864 keyword
, value
, minval_string
, maxval_string
));
868 code_string (char const *string
, char const *keyword
, struct xheader
*xhdr
)
871 if (!utf8_convert (true, string
, &outstr
))
873 /* FIXME: report error */
874 outstr
= xstrdup (string
);
876 xheader_print (xhdr
, keyword
, outstr
);
881 decode_string (char **string
, char const *arg
)
888 if (!utf8_convert (false, arg
, string
))
890 /* FIXME: report error and act accordingly to --pax invalid=UTF-8 */
891 assign_string (string
, arg
);
896 code_time (struct timespec t
, char const *keyword
, struct xheader
*xhdr
)
898 char buf
[TIMESPEC_STRSIZE_BOUND
];
899 xheader_print (xhdr
, keyword
, code_timespec (t
, buf
));
903 decode_time (struct timespec
*ts
, char const *arg
, char const *keyword
)
906 unsigned long int ns
= 0;
909 bool negative
= *arg
== '-';
913 if (ISDIGIT (arg
[negative
]))
917 intmax_t i
= strtoimax (arg
, &arg_lim
, 10);
918 if (TYPE_SIGNED (time_t) ? i
< TYPE_MINIMUM (time_t) : i
< 0)
924 uintmax_t i
= strtoumax (arg
, &arg_lim
, 10);
925 if (TYPE_MAXIMUM (time_t) < i
)
938 bool trailing_nonzero
= false;
940 while (ISDIGIT (*++p
))
941 if (digits
< LOG10_BILLION
)
943 ns
= 10 * ns
+ (*p
- '0');
947 trailing_nonzero
|= *p
!= '0';
949 while (digits
++ < LOG10_BILLION
)
954 /* Convert "-1.10000000000001" to s == -2, ns == 89999999.
955 I.e., truncate time stamps towards minus infinity while
956 converting them to internal form. */
957 ns
+= trailing_nonzero
;
960 if (s
== TYPE_MINIMUM (time_t))
976 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
981 out_of_range_header (keyword
, arg
, - (uintmax_t) TYPE_MINIMUM (time_t),
982 TYPE_MAXIMUM (time_t));
987 code_num (uintmax_t value
, char const *keyword
, struct xheader
*xhdr
)
989 char sbuf
[UINTMAX_STRSIZE_BOUND
];
990 xheader_print (xhdr
, keyword
, umaxtostr (value
, sbuf
));
994 decode_num (uintmax_t *num
, char const *arg
, uintmax_t maxval
,
1000 if (! (ISDIGIT (*arg
)
1001 && (errno
= 0, u
= strtoumax (arg
, &arg_lim
, 10), !*arg_lim
)))
1003 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
1008 if (! (u
<= maxval
&& errno
!= ERANGE
))
1010 out_of_range_header (keyword
, arg
, 0, maxval
);
1019 dummy_coder (struct tar_stat_info
const *st
__attribute__ ((unused
)),
1020 char const *keyword
__attribute__ ((unused
)),
1021 struct xheader
*xhdr
__attribute__ ((unused
)),
1022 void const *data
__attribute__ ((unused
)))
1027 dummy_decoder (struct tar_stat_info
*st
__attribute__ ((unused
)),
1028 char const *arg
__attribute__ ((unused
)),
1029 size_t size
__attribute__((unused
)))
1034 atime_coder (struct tar_stat_info
const *st
, char const *keyword
,
1035 struct xheader
*xhdr
, void const *data
__attribute__ ((unused
)))
1037 code_time (st
->atime
, keyword
, xhdr
);
1041 atime_decoder (struct tar_stat_info
*st
, char const *arg
,
1042 size_t size
__attribute__((unused
)))
1045 if (decode_time (&ts
, arg
, "atime"))
1050 gid_coder (struct tar_stat_info
const *st
, char const *keyword
,
1051 struct xheader
*xhdr
, void const *data
__attribute__ ((unused
)))
1053 code_num (st
->stat
.st_gid
, keyword
, xhdr
);
1057 gid_decoder (struct tar_stat_info
*st
, char const *arg
,
1058 size_t size
__attribute__((unused
)))
1061 if (decode_num (&u
, arg
, TYPE_MAXIMUM (gid_t
), "gid"))
1062 st
->stat
.st_gid
= u
;
1066 gname_coder (struct tar_stat_info
const *st
, char const *keyword
,
1067 struct xheader
*xhdr
, void const *data
__attribute__ ((unused
)))
1069 code_string (st
->gname
, keyword
, xhdr
);
1073 gname_decoder (struct tar_stat_info
*st
, char const *arg
,
1074 size_t size
__attribute__((unused
)))
1076 decode_string (&st
->gname
, arg
);
1080 linkpath_coder (struct tar_stat_info
const *st
, char const *keyword
,
1081 struct xheader
*xhdr
, void const *data
__attribute__ ((unused
)))
1083 code_string (st
->link_name
, keyword
, xhdr
);
1087 linkpath_decoder (struct tar_stat_info
*st
, char const *arg
,
1088 size_t size
__attribute__((unused
)))
1090 decode_string (&st
->link_name
, arg
);
1094 ctime_coder (struct tar_stat_info
const *st
, char const *keyword
,
1095 struct xheader
*xhdr
, void const *data
__attribute__ ((unused
)))
1097 code_time (st
->ctime
, keyword
, xhdr
);
1101 ctime_decoder (struct tar_stat_info
*st
, char const *arg
,
1102 size_t size
__attribute__((unused
)))
1105 if (decode_time (&ts
, arg
, "ctime"))
1110 mtime_coder (struct tar_stat_info
const *st
, char const *keyword
,
1111 struct xheader
*xhdr
, void const *data
__attribute__ ((unused
)))
1113 code_time (st
->mtime
, keyword
, xhdr
);
1117 mtime_decoder (struct tar_stat_info
*st
, char const *arg
,
1118 size_t size
__attribute__((unused
)))
1121 if (decode_time (&ts
, arg
, "mtime"))
1126 path_coder (struct tar_stat_info
const *st
, char const *keyword
,
1127 struct xheader
*xhdr
, void const *data
__attribute__ ((unused
)))
1129 code_string (st
->file_name
, keyword
, xhdr
);
1133 path_decoder (struct tar_stat_info
*st
, char const *arg
,
1134 size_t size
__attribute__((unused
)))
1136 decode_string (&st
->orig_file_name
, arg
);
1137 decode_string (&st
->file_name
, arg
);
1138 st
->had_trailing_slash
= strip_trailing_slashes (st
->file_name
);
1142 size_coder (struct tar_stat_info
const *st
, char const *keyword
,
1143 struct xheader
*xhdr
, void const *data
__attribute__ ((unused
)))
1145 code_num (st
->stat
.st_size
, keyword
, xhdr
);
1149 size_decoder (struct tar_stat_info
*st
, char const *arg
,
1150 size_t size
__attribute__((unused
)))
1153 if (decode_num (&u
, arg
, TYPE_MAXIMUM (off_t
), "size"))
1154 st
->stat
.st_size
= u
;
1158 uid_coder (struct tar_stat_info
const *st
, char const *keyword
,
1159 struct xheader
*xhdr
, void const *data
__attribute__ ((unused
)))
1161 code_num (st
->stat
.st_uid
, keyword
, xhdr
);
1165 uid_decoder (struct tar_stat_info
*st
, char const *arg
,
1166 size_t size
__attribute__((unused
)))
1169 if (decode_num (&u
, arg
, TYPE_MAXIMUM (uid_t
), "uid"))
1170 st
->stat
.st_uid
= u
;
1174 uname_coder (struct tar_stat_info
const *st
, char const *keyword
,
1175 struct xheader
*xhdr
, void const *data
__attribute__ ((unused
)))
1177 code_string (st
->uname
, keyword
, xhdr
);
1181 uname_decoder (struct tar_stat_info
*st
, char const *arg
,
1182 size_t size
__attribute__((unused
)))
1184 decode_string (&st
->uname
, arg
);
1188 sparse_size_coder (struct tar_stat_info
const *st
, char const *keyword
,
1189 struct xheader
*xhdr
, void const *data
)
1191 size_coder (st
, keyword
, xhdr
, data
);
1195 sparse_size_decoder (struct tar_stat_info
*st
, char const *arg
,
1196 size_t size
__attribute__((unused
)))
1199 if (decode_num (&u
, arg
, TYPE_MAXIMUM (off_t
), "GNU.sparse.size"))
1200 st
->stat
.st_size
= u
;
1204 sparse_numblocks_coder (struct tar_stat_info
const *st
, char const *keyword
,
1205 struct xheader
*xhdr
,
1206 void const *data
__attribute__ ((unused
)))
1208 code_num (st
->sparse_map_avail
, keyword
, xhdr
);
1212 sparse_numblocks_decoder (struct tar_stat_info
*st
, char const *arg
,
1213 size_t size
__attribute__((unused
)))
1216 if (decode_num (&u
, arg
, SIZE_MAX
, "GNU.sparse.numblocks"))
1218 st
->sparse_map_size
= u
;
1219 st
->sparse_map
= xcalloc (u
, sizeof st
->sparse_map
[0]);
1220 st
->sparse_map_avail
= 0;
1225 sparse_offset_coder (struct tar_stat_info
const *st
, char const *keyword
,
1226 struct xheader
*xhdr
, void const *data
)
1228 size_t const *pi
= data
;
1229 code_num (st
->sparse_map
[*pi
].offset
, keyword
, xhdr
);
1233 sparse_offset_decoder (struct tar_stat_info
*st
, char const *arg
,
1234 size_t size
__attribute__((unused
)))
1237 if (decode_num (&u
, arg
, TYPE_MAXIMUM (off_t
), "GNU.sparse.offset"))
1239 if (st
->sparse_map_avail
< st
->sparse_map_size
)
1240 st
->sparse_map
[st
->sparse_map_avail
].offset
= u
;
1242 ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
1243 "GNU.sparse.offset", arg
));
1248 sparse_numbytes_coder (struct tar_stat_info
const *st
, char const *keyword
,
1249 struct xheader
*xhdr
, void const *data
)
1251 size_t const *pi
= data
;
1252 code_num (st
->sparse_map
[*pi
].numbytes
, keyword
, xhdr
);
1256 sparse_numbytes_decoder (struct tar_stat_info
*st
, char const *arg
,
1257 size_t size
__attribute__((unused
)))
1260 if (decode_num (&u
, arg
, SIZE_MAX
, "GNU.sparse.numbytes"))
1262 if (st
->sparse_map_avail
< st
->sparse_map_size
)
1263 st
->sparse_map
[st
->sparse_map_avail
++].numbytes
= u
;
1265 ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
1266 "GNU.sparse.numbytes", arg
));
1271 sparse_map_decoder (struct tar_stat_info
*st
, char const *arg
,
1272 size_t size
__attribute__((unused
)))
1275 static char *keyword
= "GNU.sparse.map";
1277 st
->sparse_map_avail
= 0;
1284 if (!ISDIGIT (*arg
))
1286 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
1292 u
= strtoumax (arg
, &delim
, 10);
1296 if (!(u
== e
.offset
&& errno
!= ERANGE
))
1298 out_of_range_header (keyword
, arg
, 0, TYPE_MAXIMUM (off_t
));
1305 if (!(u
== e
.numbytes
&& errno
!= ERANGE
))
1307 out_of_range_header (keyword
, arg
, 0, TYPE_MAXIMUM (size_t));
1310 if (st
->sparse_map_avail
< st
->sparse_map_size
)
1311 st
->sparse_map
[st
->sparse_map_avail
++] = e
;
1314 ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
1315 "GNU.sparse.numbytes", arg
));
1324 else if (*delim
!= ',')
1327 _("Malformed extended header: invalid %s: unexpected delimiter %c"),
1337 _("Malformed extended header: invalid %s: odd number of values"),
1342 dumpdir_coder (struct tar_stat_info
const *st
, char const *keyword
,
1343 struct xheader
*xhdr
, void const *data
)
1345 xheader_print_n (xhdr
, keyword
, data
, dumpdir_size (data
));
1349 dumpdir_decoder (struct tar_stat_info
*st
, char const *arg
,
1352 st
->dumpdir
= xmalloc (size
);
1353 memcpy (st
->dumpdir
, arg
, size
);
1357 volume_label_coder (struct tar_stat_info
const *st
, char const *keyword
,
1358 struct xheader
*xhdr
, void const *data
)
1360 code_string (data
, keyword
, xhdr
);
1364 volume_label_decoder (struct tar_stat_info
*st
, char const *arg
, size_t size
)
1366 decode_string (&volume_label
, arg
);
1370 volume_size_coder (struct tar_stat_info
const *st
, char const *keyword
,
1371 struct xheader
*xhdr
, void const *data
)
1373 off_t v
= *(off_t
*)data
;
1374 code_num (v
, keyword
, xhdr
);
1378 volume_size_decoder (struct tar_stat_info
*st
, char const *arg
, size_t size
)
1381 if (decode_num (&u
, arg
, TYPE_MAXIMUM (uintmax_t), "GNU.volume.size"))
1382 continued_file_size
= u
;
1385 /* FIXME: Merge with volume_size_coder */
1387 volume_offset_coder (struct tar_stat_info
const *st
, char const *keyword
,
1388 struct xheader
*xhdr
, void const *data
)
1390 off_t v
= *(off_t
*)data
;
1391 code_num (v
, keyword
, xhdr
);
1395 volume_offset_decoder (struct tar_stat_info
*st
, char const *arg
, size_t size
)
1398 if (decode_num (&u
, arg
, TYPE_MAXIMUM (uintmax_t), "GNU.volume.offset"))
1399 continued_file_offset
= u
;
1403 volume_filename_decoder (struct tar_stat_info
*st
, char const *arg
,
1406 decode_string (&continued_file_name
, arg
);
1410 struct xhdr_tab
const xhdr_tab
[] = {
1411 { "atime", atime_coder
, atime_decoder
, false },
1412 { "comment", dummy_coder
, dummy_decoder
, false },
1413 { "charset", dummy_coder
, dummy_decoder
, false },
1414 { "ctime", ctime_coder
, ctime_decoder
, false },
1415 { "gid", gid_coder
, gid_decoder
, false },
1416 { "gname", gname_coder
, gname_decoder
, false },
1417 { "linkpath", linkpath_coder
, linkpath_decoder
, false },
1418 { "mtime", mtime_coder
, mtime_decoder
, false },
1419 { "path", path_coder
, path_decoder
, false },
1420 { "size", size_coder
, size_decoder
, false },
1421 { "uid", uid_coder
, uid_decoder
, false },
1422 { "uname", uname_coder
, uname_decoder
, false },
1424 /* Sparse file handling */
1425 { "GNU.sparse.size", sparse_size_coder
, sparse_size_decoder
, true },
1426 { "GNU.sparse.numblocks", sparse_numblocks_coder
, sparse_numblocks_decoder
,
1428 /* tar 1.14 - 1.15.1 keywords. Multiplse instances of these appeared in 'x'
1429 headers, and each of them was meaningful. It confilcted with POSIX specs,
1430 which requires that "when extended header records conflict, the last one
1431 given in the header shall take precedence." */
1432 { "GNU.sparse.offset", sparse_offset_coder
, sparse_offset_decoder
,
1434 { "GNU.sparse.numbytes", sparse_numbytes_coder
, sparse_numbytes_decoder
,
1436 /* tar >=1.16 keyword, introduced to remove the above-mentioned conflict. */
1437 { "GNU.sparse.map", NULL
/* Unused, see pax_dump_header() */,
1438 sparse_map_decoder
, false },
1440 { "GNU.dumpdir", dumpdir_coder
, dumpdir_decoder
,
1443 /* Keeps the tape/volume label. May be present only in the global headers.
1444 Equivalent to GNUTYPE_VOLHDR. */
1445 { "GNU.volume.label", volume_label_coder
, volume_label_decoder
, true },
1447 /* These may be present in a first global header of the archive.
1448 They provide the same functionality as GNUTYPE_MULTIVOL header.
1449 The GNU.volume.size keeps the real_s_sizeleft value, which is
1450 otherwise kept in the size field of a multivolume header. The
1451 GNU.volume.offset keeps the offset of the start of this volume,
1452 otherwise kept in oldgnu_header.offset. */
1453 { "GNU.volume.filename", volume_label_coder
, volume_filename_decoder
,
1455 { "GNU.volume.size", volume_size_coder
, volume_size_decoder
, true },
1456 { "GNU.volume.offset", volume_offset_coder
, volume_offset_decoder
, true },
1458 { NULL
, NULL
, NULL
, false }