source: trunk/essentials/app-arch/tar/src/xheader.c

Last change on this file was 3342, checked in by bird, 18 years ago

tar 1.16.1

File size: 35.6 KB
Line 
1/* POSIX extended headers for tar.
2
3 Copyright (C) 2003, 2004, 2005, 2006 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 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#include <system.h>
20
21#include <fnmatch.h>
22#include <hash.h>
23#include <inttostr.h>
24#include <quotearg.h>
25#include <stpcpy.h>
26
27#include "common.h"
28
29#include <fnmatch.h>
30
31static bool xheader_protected_pattern_p (char const *pattern);
32static bool xheader_protected_keyword_p (char const *keyword);
33static void xheader_set_single_keyword (char *) __attribute__ ((noreturn));
34
35/* Used by xheader_finish() */
36static void code_string (char const *string, char const *keyword,
37 struct xheader *xhdr);
38static void extended_header_init (void);
39
40/* Number of global headers written so far. */
41static 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.
50
51 However it should wait until buffer.c is finally rewritten */
52
53
54
55/* Interface functions to obstacks */
56
57static void
58x_obstack_grow (struct xheader *xhdr, const char *ptr, size_t length)
59{
60 obstack_grow (xhdr->stk, ptr, length);
61 xhdr->size += length;
62}
63
64static void
65x_obstack_1grow (struct xheader *xhdr, char c)
66{
67 obstack_1grow (xhdr->stk, c);
68 xhdr->size++;
69}
70
71static void
72x_obstack_blank (struct xheader *xhdr, size_t length)
73{
74 obstack_blank (xhdr->stk, length);
75 xhdr->size += length;
76}
77
78
79
80/* Keyword options */
81
82struct keyword_list
83{
84 struct keyword_list *next;
85 char *pattern;
86 char *value;
87};
88
89
90/* List of keyword patterns set by delete= option */
91static struct keyword_list *keyword_pattern_list;
92
93/* List of keyword/value pairs set by `keyword=value' option */
94static struct keyword_list *keyword_global_override_list;
95
96/* List of keyword/value pairs set by `keyword:=value' option */
97static struct keyword_list *keyword_override_list;
98
99/* List of keyword/value pairs decoded from the last 'g' type header */
100static struct keyword_list *global_header_override_list;
101
102/* Template for the name field of an 'x' type header */
103static char *exthdr_name;
104
105/* Template for the name field of a 'g' type header */
106static char *globexthdr_name;
107
108bool
109xheader_keyword_deleted_p (const char *kw)
110{
111 struct keyword_list *kp;
112
113 for (kp = keyword_pattern_list; kp; kp = kp->next)
114 if (fnmatch (kp->pattern, kw, 0) == 0)
115 return true;
116 return false;
117}
118
119static bool
120xheader_keyword_override_p (const char *keyword)
121{
122 struct keyword_list *kp;
123
124 for (kp = keyword_override_list; kp; kp = kp->next)
125 if (strcmp (kp->pattern, keyword) == 0)
126 return true;
127 return false;
128}
129
130static void
131xheader_list_append (struct keyword_list **root, char const *kw,
132 char const *value)
133{
134 struct keyword_list *kp = xmalloc (sizeof *kp);
135 kp->pattern = xstrdup (kw);
136 kp->value = value ? xstrdup (value) : NULL;
137 kp->next = *root;
138 *root = kp;
139}
140
141static void
142xheader_list_destroy (struct keyword_list **root)
143{
144 if (root)
145 {
146 struct keyword_list *kw = *root;
147 while (kw)
148 {
149 struct keyword_list *next = kw->next;
150 free (kw->pattern);
151 free (kw->value);
152 free (kw);
153 kw = next;
154 }
155 *root = NULL;
156 }
157}
158
159static void
160xheader_set_single_keyword (char *kw)
161{
162 USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet implemented"), kw));
163}
164
165static void
166xheader_set_keyword_equal (char *kw, char *eq)
167{
168 bool global = true;
169 char *p = eq;
170
171 if (eq[-1] == ':')
172 {
173 p--;
174 global = false;
175 }
176
177 while (p > kw && isspace (*p))
178 p--;
179
180 *p = 0;
181
182 for (p = eq + 1; *p && isspace (*p); p++)
183 ;
184
185 if (strcmp (kw, "delete") == 0)
186 {
187 if (xheader_protected_pattern_p (p))
188 USAGE_ERROR ((0, 0, _("Pattern %s cannot be used"), quote (p)));
189 xheader_list_append (&keyword_pattern_list, p, NULL);
190 }
191 else if (strcmp (kw, "exthdr.name") == 0)
192 assign_string (&exthdr_name, p);
193 else if (strcmp (kw, "globexthdr.name") == 0)
194 assign_string (&globexthdr_name, p);
195 else
196 {
197 if (xheader_protected_keyword_p (kw))
198 USAGE_ERROR ((0, 0, _("Keyword %s cannot be overridden"), kw));
199 if (global)
200 xheader_list_append (&keyword_global_override_list, kw, p);
201 else
202 xheader_list_append (&keyword_override_list, kw, p);
203 }
204}
205
206void
207xheader_set_option (char *string)
208{
209 char *token;
210 for (token = strtok (string, ","); token; token = strtok (NULL, ","))
211 {
212 char *p = strchr (token, '=');
213 if (!p)
214 xheader_set_single_keyword (token);
215 else
216 xheader_set_keyword_equal (token, p);
217 }
218}
219
220/*
221 string Includes: Replaced By:
222 %d The directory name of the file,
223 equivalent to the result of the
224 dirname utility on the translated
225 file name.
226 %f The filename of the file, equivalent
227 to the result of the basename
228 utility on the translated file name.
229 %p The process ID of the pax process.
230 %n The value of the 3rd argument.
231 %% A '%' character. */
232
233char *
234xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
235{
236 char *buf;
237 size_t len = strlen (fmt);
238 char *q;
239 const char *p;
240 char *dirp = NULL;
241 char *dir = NULL;
242 char *base = NULL;
243 char pidbuf[UINTMAX_STRSIZE_BOUND];
244 char const *pptr;
245 char nbuf[UINTMAX_STRSIZE_BOUND];
246 char const *nptr = NULL;
247
248 for (p = fmt; *p && (p = strchr (p, '%')); )
249 {
250 switch (p[1])
251 {
252 case '%':
253 len--;
254 break;
255
256 case 'd':
257 if (st)
258 {
259 if (!dirp)
260 dirp = dir_name (st->orig_file_name);
261 dir = safer_name_suffix (dirp, false, absolute_names_option);
262 len += strlen (dir) - 2;
263 }
264 break;
265
266 case 'f':
267 if (st)
268 {
269 base = last_component (st->orig_file_name);
270 len += strlen (base) - 2;
271 }
272 break;
273
274 case 'p':
275 pptr = umaxtostr (getpid (), pidbuf);
276 len += pidbuf + sizeof pidbuf - 1 - pptr - 2;
277 break;
278
279 case 'n':
280 nptr = umaxtostr (n, nbuf);
281 len += nbuf + sizeof nbuf - 1 - nptr - 2;
282 break;
283 }
284 p++;
285 }
286
287 buf = xmalloc (len + 1);
288 for (q = buf, p = fmt; *p; )
289 {
290 if (*p == '%')
291 {
292 switch (p[1])
293 {
294 case '%':
295 *q++ = *p++;
296 p++;
297 break;
298
299 case 'd':
300 if (dir)
301 q = stpcpy (q, dir);
302 p += 2;
303 break;
304
305 case 'f':
306 if (base)
307 q = stpcpy (q, base);
308 p += 2;
309 break;
310
311 case 'p':
312 q = stpcpy (q, pptr);
313 p += 2;
314 break;
315
316 case 'n':
317 if (nptr)
318 {
319 q = stpcpy (q, nptr);
320 p += 2;
321 break;
322 }
323 /* else fall through */
324
325 default:
326 *q++ = *p++;
327 if (*p)
328 *q++ = *p++;
329 }
330 }
331 else
332 *q++ = *p++;
333 }
334
335 free (dirp);
336
337 /* Do not allow it to end in a slash */
338 while (q > buf && ISSLASH (q[-1]))
339 q--;
340 *q = 0;
341 return buf;
342}
343
344char *
345xheader_xhdr_name (struct tar_stat_info *st)
346{
347 if (!exthdr_name)
348 assign_string (&exthdr_name, "%d/PaxHeaders.%p/%f");
349 return xheader_format_name (st, exthdr_name, 0);
350}
351
352#define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n"
353
354char *
355xheader_ghdr_name (void)
356{
357 if (!globexthdr_name)
358 {
359 size_t len;
360 const char *tmp = getenv ("TMPDIR");
361 if (!tmp)
362 tmp = "/tmp";
363 len = strlen (tmp) + sizeof (GLOBAL_HEADER_TEMPLATE); /* Includes nul */
364 globexthdr_name = xmalloc (len);
365 strcpy(globexthdr_name, tmp);
366 strcat(globexthdr_name, GLOBAL_HEADER_TEMPLATE);
367 }
368
369 return xheader_format_name (NULL, globexthdr_name, global_header_count + 1);
370}
371
372void
373xheader_write (char type, char *name, struct xheader *xhdr)
374{
375 union block *header;
376 size_t size;
377 char *p;
378
379 size = xhdr->size;
380 header = start_private_header (name, size);
381 header->header.typeflag = type;
382
383 simple_finish_header (header);
384
385 p = xhdr->buffer;
386
387 do
388 {
389 size_t len;
390
391 header = find_next_block ();
392 len = BLOCKSIZE;
393 if (len > size)
394 len = size;
395 memcpy (header->buffer, p, len);
396 if (len < BLOCKSIZE)
397 memset (header->buffer + len, 0, BLOCKSIZE - len);
398 p += len;
399 size -= len;
400 set_next_block_after (header);
401 }
402 while (size > 0);
403 xheader_destroy (xhdr);
404
405 if (type == XGLTYPE)
406 global_header_count++;
407}
408
409void
410xheader_write_global (void)
411{
412 char *name;
413 struct keyword_list *kp;
414
415 if (!keyword_global_override_list)
416 return;
417
418 extended_header_init ();
419 for (kp = keyword_global_override_list; kp; kp = kp->next)
420 code_string (kp->value, kp->pattern, &extended_header);
421 xheader_finish (&extended_header);
422 xheader_write (XGLTYPE, name = xheader_ghdr_name (),
423 &extended_header);
424 free (name);
425}
426
427
428
429/* General Interface */
430
431struct xhdr_tab
432{
433 char const *keyword;
434 void (*coder) (struct tar_stat_info const *, char const *,
435 struct xheader *, void const *data);
436 void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);
437 bool protect;
438};
439
440/* This declaration must be extern, because ISO C99 section 6.9.2
441 prohibits a tentative definition that has both internal linkage and
442 incomplete type. If we made it static, we'd have to declare its
443 size which would be a maintenance pain; if we put its initializer
444 here, we'd need a boatload of forward declarations, which would be
445 even more of a pain. */
446extern struct xhdr_tab const xhdr_tab[];
447
448static struct xhdr_tab const *
449locate_handler (char const *keyword)
450{
451 struct xhdr_tab const *p;
452
453 for (p = xhdr_tab; p->keyword; p++)
454 if (strcmp (p->keyword, keyword) == 0)
455 return p;
456 return NULL;
457}
458
459static bool
460xheader_protected_pattern_p (const char *pattern)
461{
462 struct xhdr_tab const *p;
463
464 for (p = xhdr_tab; p->keyword; p++)
465 if (p->protect && fnmatch (pattern, p->keyword, 0) == 0)
466 return true;
467 return false;
468}
469
470static bool
471xheader_protected_keyword_p (const char *keyword)
472{
473 struct xhdr_tab const *p;
474
475 for (p = xhdr_tab; p->keyword; p++)
476 if (p->protect && strcmp (p->keyword, keyword) == 0)
477 return true;
478 return false;
479}
480
481/* Decode a single extended header record, advancing *PTR to the next record.
482 Return true on success, false otherwise. */
483static bool
484decode_record (char **ptr,
485 void (*handler) (void *, char const *, char const *, size_t),
486 void *data)
487{
488 char *start = *ptr;
489 char *p = start;
490 uintmax_t u;
491 size_t len;
492 char *len_lim;
493 char const *keyword;
494 char *nextp;
495 size_t len_max = extended_header.buffer + extended_header.size - start;
496
497 while (*p == ' ' || *p == '\t')
498 p++;
499
500 if (! ISDIGIT (*p))
501 {
502 if (*p)
503 ERROR ((0, 0, _("Malformed extended header: missing length")));
504 return false;
505 }
506
507 errno = 0;
508 len = u = strtoumax (p, &len_lim, 10);
509 if (len != u || errno == ERANGE)
510 {
511 ERROR ((0, 0, _("Extended header length is out of allowed range")));
512 return false;
513 }
514
515 if (len_max < len)
516 {
517 int len_len = len_lim - p;
518 ERROR ((0, 0, _("Extended header length %*s is out of range"),
519 len_len, p));
520 return false;
521 }
522
523 nextp = start + len;
524
525 for (p = len_lim; *p == ' ' || *p == '\t'; p++)
526 continue;
527 if (p == len_lim)
528 {
529 ERROR ((0, 0,
530 _("Malformed extended header: missing blank after length")));
531 return false;
532 }
533
534 keyword = p;
535 p = strchr (p, '=');
536 if (! (p && p < nextp))
537 {
538 ERROR ((0, 0, _("Malformed extended header: missing equal sign")));
539 return false;
540 }
541
542 if (nextp[-1] != '\n')
543 {
544 ERROR ((0, 0, _("Malformed extended header: missing newline")));
545 return false;
546 }
547
548 *p = nextp[-1] = '\0';
549 handler (data, keyword, p + 1, nextp - p - 2); /* '=' + trailing '\n' */
550 *p = '=';
551 nextp[-1] = '\n';
552 *ptr = nextp;
553 return true;
554}
555
556static void
557run_override_list (struct keyword_list *kp, struct tar_stat_info *st)
558{
559 for (; kp; kp = kp->next)
560 {
561 struct xhdr_tab const *t = locate_handler (kp->pattern);
562 if (t)
563 t->decoder (st, t->keyword, kp->value, strlen (kp->value));
564 }
565}
566
567static void
568decx (void *data, char const *keyword, char const *value, size_t size)
569{
570 struct xhdr_tab const *t;
571 struct tar_stat_info *st = data;
572
573 if (xheader_keyword_deleted_p (keyword)
574 || xheader_keyword_override_p (keyword))
575 return;
576
577 t = locate_handler (keyword);
578 if (t)
579 t->decoder (st, keyword, value, size);
580 else
581 ERROR((0, 0, _("Ignoring unknown extended header keyword `%s'"),
582 keyword));
583}
584
585void
586xheader_decode (struct tar_stat_info *st)
587{
588 run_override_list (keyword_global_override_list, st);
589 run_override_list (global_header_override_list, st);
590
591 if (extended_header.size)
592 {
593 char *p = extended_header.buffer + BLOCKSIZE;
594 while (decode_record (&p, decx, st))
595 continue;
596 }
597 run_override_list (keyword_override_list, st);
598}
599
600static void
601decg (void *data, char const *keyword, char const *value,
602 size_t size __attribute__((unused)))
603{
604 struct keyword_list **kwl = data;
605 xheader_list_append (kwl, keyword, value);
606}
607
608void
609xheader_decode_global (void)
610{
611 if (extended_header.size)
612 {
613 char *p = extended_header.buffer + BLOCKSIZE;
614
615 xheader_list_destroy (&global_header_override_list);
616 while (decode_record (&p, decg, &global_header_override_list))
617 continue;
618 }
619}
620
621static void
622extended_header_init (void)
623{
624 if (!extended_header.stk)
625 {
626 extended_header.stk = xmalloc (sizeof *extended_header.stk);
627 obstack_init (extended_header.stk);
628 }
629}
630
631void
632xheader_store (char const *keyword, struct tar_stat_info const *st,
633 void const *data)
634{
635 struct xhdr_tab const *t;
636
637 if (extended_header.buffer)
638 return;
639 t = locate_handler (keyword);
640 if (!t || !t->coder)
641 return;
642 if (xheader_keyword_deleted_p (keyword)
643 || xheader_keyword_override_p (keyword))
644 return;
645 extended_header_init ();
646 t->coder (st, keyword, &extended_header, data);
647}
648
649void
650xheader_read (union block *p, size_t size)
651{
652 size_t j = 0;
653
654 free (extended_header.buffer);
655 size += BLOCKSIZE;
656 extended_header.size = size;
657 extended_header.buffer = xmalloc (size + 1);
658 extended_header.buffer[size] = '\0';
659
660 do
661 {
662 size_t len = size;
663
664 if (len > BLOCKSIZE)
665 len = BLOCKSIZE;
666
667 memcpy (&extended_header.buffer[j], p->buffer, len);
668 set_next_block_after (p);
669
670 p = find_next_block ();
671
672 j += len;
673 size -= len;
674 }
675 while (size > 0);
676}
677
678static void
679xheader_print_n (struct xheader *xhdr, char const *keyword,
680 char const *value, size_t vsize)
681{
682 size_t len = strlen (keyword) + vsize + 3; /* ' ' + '=' + '\n' */
683 size_t p;
684 size_t n = 0;
685 char nbuf[UINTMAX_STRSIZE_BOUND];
686 char const *np;
687
688 do
689 {
690 p = n;
691 np = umaxtostr (len + p, nbuf);
692 n = nbuf + sizeof nbuf - 1 - np;
693 }
694 while (n != p);
695
696 x_obstack_grow (xhdr, np, n);
697 x_obstack_1grow (xhdr, ' ');
698 x_obstack_grow (xhdr, keyword, strlen (keyword));
699 x_obstack_1grow (xhdr, '=');
700 x_obstack_grow (xhdr, value, vsize);
701 x_obstack_1grow (xhdr, '\n');
702}
703
704static void
705xheader_print (struct xheader *xhdr, char const *keyword, char const *value)
706{
707 xheader_print_n (xhdr, keyword, value, strlen (value));
708}
709
710void
711xheader_finish (struct xheader *xhdr)
712{
713 struct keyword_list *kp;
714
715 for (kp = keyword_override_list; kp; kp = kp->next)
716 code_string (kp->value, kp->pattern, xhdr);
717
718 xhdr->buffer = obstack_finish (xhdr->stk);
719}
720
721void
722xheader_destroy (struct xheader *xhdr)
723{
724 if (xhdr->stk)
725 {
726 obstack_free (xhdr->stk, NULL);
727 free (xhdr->stk);
728 xhdr->stk = NULL;
729 }
730 else
731 free (xhdr->buffer);
732 xhdr->buffer = 0;
733 xhdr->size = 0;
734}
735
736
737
738/* Buildable strings */
739static uintmax_t string_length;
740
741void
742xheader_string_begin ()
743{
744 string_length = 0;
745}
746
747void
748xheader_string_add (char const *s)
749{
750 if (extended_header.buffer)
751 return;
752 extended_header_init ();
753 string_length += strlen (s);
754 x_obstack_grow (&extended_header, s, strlen (s));
755}
756
757bool
758xheader_string_end (char const *keyword)
759{
760 uintmax_t len;
761 uintmax_t p;
762 uintmax_t n = 0;
763 size_t size;
764 char nbuf[UINTMAX_STRSIZE_BOUND];
765 char const *np;
766 char *cp;
767
768 if (extended_header.buffer)
769 return false;
770 extended_header_init ();
771
772 len = strlen (keyword) + string_length + 3; /* ' ' + '=' + '\n' */
773
774 do
775 {
776 p = n;
777 np = umaxtostr (len + p, nbuf);
778 n = nbuf + sizeof nbuf - 1 - np;
779 }
780 while (n != p);
781
782 p = strlen (keyword) + n + 2;
783 size = p;
784 if (size != p)
785 {
786 ERROR ((0, 0,
787 _("Generated keyword/value pair is too long (keyword=%s, length=%s)"),
788 keyword, nbuf));
789 obstack_free (extended_header.stk, obstack_finish (extended_header.stk));
790 return false;
791 }
792 x_obstack_blank (&extended_header, p);
793 x_obstack_1grow (&extended_header, '\n');
794 cp = obstack_next_free (extended_header.stk) - string_length - p - 1;
795 memmove (cp + p, cp, string_length);
796 cp = stpcpy (cp, np);
797 *cp++ = ' ';
798 cp = stpcpy (cp, keyword);
799 *cp++ = '=';
800 return true;
801}
802
803
804
805/* Implementations */
806
807static void
808out_of_range_header (char const *keyword, char const *value,
809 uintmax_t minus_minval, uintmax_t maxval)
810{
811 char minval_buf[UINTMAX_STRSIZE_BOUND + 1];
812 char maxval_buf[UINTMAX_STRSIZE_BOUND];
813 char *minval_string = umaxtostr (minus_minval, minval_buf + 1);
814 char *maxval_string = umaxtostr (maxval, maxval_buf);
815 if (minus_minval)
816 *--minval_string = '-';
817
818 /* TRANSLATORS: The first %s is the pax extended header keyword
819 (atime, gid, etc.). */
820 ERROR ((0, 0, _("Extended header %s=%s is out of range %s..%s"),
821 keyword, value, minval_string, maxval_string));
822}
823
824static void
825code_string (char const *string, char const *keyword, struct xheader *xhdr)
826{
827 char *outstr;
828 if (!utf8_convert (true, string, &outstr))
829 {
830 /* FIXME: report error */
831 outstr = xstrdup (string);
832 }
833 xheader_print (xhdr, keyword, outstr);
834 free (outstr);
835}
836
837static void
838decode_string (char **string, char const *arg)
839{
840 if (*string)
841 {
842 free (*string);
843 *string = NULL;
844 }
845 if (!utf8_convert (false, arg, string))
846 {
847 /* FIXME: report error and act accordingly to --pax invalid=UTF-8 */
848 assign_string (string, arg);
849 }
850}
851
852static void
853code_time (struct timespec t, char const *keyword, struct xheader *xhdr)
854{
855 char buf[TIMESPEC_STRSIZE_BOUND];
856 xheader_print (xhdr, keyword, code_timespec (t, buf));
857}
858
859enum decode_time_status
860 {
861 decode_time_success,
862 decode_time_range,
863 decode_time_bad_header
864 };
865
866static enum decode_time_status
867_decode_time (struct timespec *ts, char const *arg, char const *keyword)
868{
869 time_t s;
870 unsigned long int ns = 0;
871 char *p;
872 char *arg_lim;
873 bool negative = *arg == '-';
874
875 errno = 0;
876
877 if (ISDIGIT (arg[negative]))
878 {
879 if (negative)
880 {
881 intmax_t i = strtoimax (arg, &arg_lim, 10);
882 if (TYPE_SIGNED (time_t) ? i < TYPE_MINIMUM (time_t) : i < 0)
883 return decode_time_range;
884 s = i;
885 }
886 else
887 {
888 uintmax_t i = strtoumax (arg, &arg_lim, 10);
889 if (TYPE_MAXIMUM (time_t) < i)
890 return decode_time_range;
891 s = i;
892 }
893
894 p = arg_lim;
895
896 if (errno == ERANGE)
897 return decode_time_range;
898
899 if (*p == '.')
900 {
901 int digits = 0;
902 bool trailing_nonzero = false;
903
904 while (ISDIGIT (*++p))
905 if (digits < LOG10_BILLION)
906 {
907 ns = 10 * ns + (*p - '0');
908 digits++;
909 }
910 else
911 trailing_nonzero |= *p != '0';
912
913 while (digits++ < LOG10_BILLION)
914 ns *= 10;
915
916 if (negative)
917 {
918 /* Convert "-1.10000000000001" to s == -2, ns == 89999999.
919 I.e., truncate time stamps towards minus infinity while
920 converting them to internal form. */
921 ns += trailing_nonzero;
922 if (ns != 0)
923 {
924 if (s == TYPE_MINIMUM (time_t))
925 return decode_time_range;
926 s--;
927 ns = BILLION - ns;
928 }
929 }
930 }
931
932 if (! *p)
933 {
934 ts->tv_sec = s;
935 ts->tv_nsec = ns;
936 return decode_time_success;
937 }
938 }
939
940 return decode_time_bad_header;
941}
942
943static bool
944decode_time (struct timespec *ts, char const *arg, char const *keyword)
945{
946 switch (_decode_time (ts, arg, keyword))
947 {
948 case decode_time_success:
949 return true;
950 case decode_time_bad_header:
951 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
952 keyword, arg));
953 return false;
954 case decode_time_range:
955 out_of_range_header (keyword, arg, - (uintmax_t) TYPE_MINIMUM (time_t),
956 TYPE_MAXIMUM (time_t));
957 return false;
958 }
959 return true;
960}
961
962
963
964static void
965code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
966{
967 char sbuf[UINTMAX_STRSIZE_BOUND];
968 xheader_print (xhdr, keyword, umaxtostr (value, sbuf));
969}
970
971static bool
972decode_num (uintmax_t *num, char const *arg, uintmax_t maxval,
973 char const *keyword)
974{
975 uintmax_t u;
976 char *arg_lim;
977
978 if (! (ISDIGIT (*arg)
979 && (errno = 0, u = strtoumax (arg, &arg_lim, 10), !*arg_lim)))
980 {
981 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
982 keyword, arg));
983 return false;
984 }
985
986 if (! (u <= maxval && errno != ERANGE))
987 {
988 out_of_range_header (keyword, arg, 0, maxval);
989 return false;
990 }
991
992 *num = u;
993 return true;
994}
995
996static void
997dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)),
998 char const *keyword __attribute__ ((unused)),
999 struct xheader *xhdr __attribute__ ((unused)),
1000 void const *data __attribute__ ((unused)))
1001{
1002}
1003
1004static void
1005dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)),
1006 char const *keyword __attribute__ ((unused)),
1007 char const *arg __attribute__ ((unused)),
1008 size_t size __attribute__((unused)))
1009{
1010}
1011
1012static void
1013atime_coder (struct tar_stat_info const *st, char const *keyword,
1014 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1015{
1016 code_time (st->atime, keyword, xhdr);
1017}
1018
1019static void
1020atime_decoder (struct tar_stat_info *st,
1021 char const *keyword,
1022 char const *arg,
1023 size_t size __attribute__((unused)))
1024{
1025 struct timespec ts;
1026 if (decode_time (&ts, arg, keyword))
1027 st->atime = ts;
1028}
1029
1030static void
1031gid_coder (struct tar_stat_info const *st, char const *keyword,
1032 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1033{
1034 code_num (st->stat.st_gid, keyword, xhdr);
1035}
1036
1037static void
1038gid_decoder (struct tar_stat_info *st,
1039 char const *keyword,
1040 char const *arg,
1041 size_t size __attribute__((unused)))
1042{
1043 uintmax_t u;
1044 if (decode_num (&u, arg, TYPE_MAXIMUM (gid_t), keyword))
1045 st->stat.st_gid = u;
1046}
1047
1048static void
1049gname_coder (struct tar_stat_info const *st, char const *keyword,
1050 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1051{
1052 code_string (st->gname, keyword, xhdr);
1053}
1054
1055static void
1056gname_decoder (struct tar_stat_info *st,
1057 char const *keyword __attribute__((unused)),
1058 char const *arg,
1059 size_t size __attribute__((unused)))
1060{
1061 decode_string (&st->gname, arg);
1062}
1063
1064static void
1065linkpath_coder (struct tar_stat_info const *st, char const *keyword,
1066 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1067{
1068 code_string (st->link_name, keyword, xhdr);
1069}
1070
1071static void
1072linkpath_decoder (struct tar_stat_info *st,
1073 char const *keyword __attribute__((unused)),
1074 char const *arg,
1075 size_t size __attribute__((unused)))
1076{
1077 decode_string (&st->link_name, arg);
1078}
1079
1080static void
1081ctime_coder (struct tar_stat_info const *st, char const *keyword,
1082 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1083{
1084 code_time (st->ctime, keyword, xhdr);
1085}
1086
1087static void
1088ctime_decoder (struct tar_stat_info *st,
1089 char const *keyword,
1090 char const *arg,
1091 size_t size __attribute__((unused)))
1092{
1093 struct timespec ts;
1094 if (decode_time (&ts, arg, keyword))
1095 st->ctime = ts;
1096}
1097
1098static void
1099mtime_coder (struct tar_stat_info const *st, char const *keyword,
1100 struct xheader *xhdr, void const *data)
1101{
1102 const struct timespec mtime = data ? *(struct timespec *) data : st->mtime;
1103 code_time (mtime, keyword, xhdr);
1104}
1105
1106static void
1107mtime_decoder (struct tar_stat_info *st,
1108 char const *keyword,
1109 char const *arg,
1110 size_t size __attribute__((unused)))
1111{
1112 struct timespec ts;
1113 if (decode_time (&ts, arg, keyword))
1114 st->mtime = ts;
1115}
1116
1117static void
1118path_coder (struct tar_stat_info const *st, char const *keyword,
1119 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1120{
1121 code_string (st->file_name, keyword, xhdr);
1122}
1123
1124static void
1125path_decoder (struct tar_stat_info *st,
1126 char const *keyword __attribute__((unused)),
1127 char const *arg,
1128 size_t size __attribute__((unused)))
1129{
1130 decode_string (&st->orig_file_name, arg);
1131 decode_string (&st->file_name, arg);
1132 st->had_trailing_slash = strip_trailing_slashes (st->file_name);
1133}
1134
1135static void
1136size_coder (struct tar_stat_info const *st, char const *keyword,
1137 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1138{
1139 code_num (st->stat.st_size, keyword, xhdr);
1140}
1141
1142static void
1143size_decoder (struct tar_stat_info *st,
1144 char const *keyword,
1145 char const *arg,
1146 size_t size __attribute__((unused)))
1147{
1148 uintmax_t u;
1149 if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
1150 st->stat.st_size = u;
1151}
1152
1153static void
1154uid_coder (struct tar_stat_info const *st, char const *keyword,
1155 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1156{
1157 code_num (st->stat.st_uid, keyword, xhdr);
1158}
1159
1160static void
1161uid_decoder (struct tar_stat_info *st,
1162 char const *keyword,
1163 char const *arg,
1164 size_t size __attribute__((unused)))
1165{
1166 uintmax_t u;
1167 if (decode_num (&u, arg, TYPE_MAXIMUM (uid_t), keyword))
1168 st->stat.st_uid = u;
1169}
1170
1171static void
1172uname_coder (struct tar_stat_info const *st, char const *keyword,
1173 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1174{
1175 code_string (st->uname, keyword, xhdr);
1176}
1177
1178static void
1179uname_decoder (struct tar_stat_info *st,
1180 char const *keyword __attribute__((unused)),
1181 char const *arg,
1182 size_t size __attribute__((unused)))
1183{
1184 decode_string (&st->uname, arg);
1185}
1186
1187static void
1188sparse_size_coder (struct tar_stat_info const *st, char const *keyword,
1189 struct xheader *xhdr, void const *data)
1190{
1191 size_coder (st, keyword, xhdr, data);
1192}
1193
1194static void
1195sparse_size_decoder (struct tar_stat_info *st,
1196 char const *keyword,
1197 char const *arg,
1198 size_t size __attribute__((unused)))
1199{
1200 uintmax_t u;
1201 if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
1202 st->stat.st_size = u;
1203}
1204
1205static void
1206sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword,
1207 struct xheader *xhdr,
1208 void const *data __attribute__ ((unused)))
1209{
1210 code_num (st->sparse_map_avail, keyword, xhdr);
1211}
1212
1213static void
1214sparse_numblocks_decoder (struct tar_stat_info *st,
1215 char const *keyword,
1216 char const *arg,
1217 size_t size __attribute__((unused)))
1218{
1219 uintmax_t u;
1220 if (decode_num (&u, arg, SIZE_MAX, keyword))
1221 {
1222 st->sparse_map_size = u;
1223 st->sparse_map = xcalloc (u, sizeof st->sparse_map[0]);
1224 st->sparse_map_avail = 0;
1225 }
1226}
1227
1228static void
1229sparse_offset_coder (struct tar_stat_info const *st, char const *keyword,
1230 struct xheader *xhdr, void const *data)
1231{
1232 size_t const *pi = data;
1233 code_num (st->sparse_map[*pi].offset, keyword, xhdr);
1234}
1235
1236static void
1237sparse_offset_decoder (struct tar_stat_info *st,
1238 char const *keyword,
1239 char const *arg,
1240 size_t size __attribute__((unused)))
1241{
1242 uintmax_t u;
1243 if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
1244 {
1245 if (st->sparse_map_avail < st->sparse_map_size)
1246 st->sparse_map[st->sparse_map_avail].offset = u;
1247 else
1248 ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
1249 "GNU.sparse.offset", arg));
1250 }
1251}
1252
1253static void
1254sparse_numbytes_coder (struct tar_stat_info const *st, char const *keyword,
1255 struct xheader *xhdr, void const *data)
1256{
1257 size_t const *pi = data;
1258 code_num (st->sparse_map[*pi].numbytes, keyword, xhdr);
1259}
1260
1261static void
1262sparse_numbytes_decoder (struct tar_stat_info *st,
1263 char const *keyword,
1264 char const *arg,
1265 size_t size __attribute__((unused)))
1266{
1267 uintmax_t u;
1268 if (decode_num (&u, arg, SIZE_MAX, keyword))
1269 {
1270 if (st->sparse_map_avail < st->sparse_map_size)
1271 st->sparse_map[st->sparse_map_avail++].numbytes = u;
1272 else
1273 ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
1274 keyword, arg));
1275 }
1276}
1277
1278static void
1279sparse_map_decoder (struct tar_stat_info *st,
1280 char const *keyword,
1281 char const *arg,
1282 size_t size __attribute__((unused)))
1283{
1284 int offset = 1;
1285
1286 st->sparse_map_avail = 0;
1287 while (1)
1288 {
1289 uintmax_t u;
1290 char *delim;
1291 struct sp_array e;
1292
1293 if (!ISDIGIT (*arg))
1294 {
1295 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
1296 keyword, arg));
1297 return;
1298 }
1299
1300 errno = 0;
1301 u = strtoumax (arg, &delim, 10);
1302 if (offset)
1303 {
1304 e.offset = u;
1305 if (!(u == e.offset && errno != ERANGE))
1306 {
1307 out_of_range_header (keyword, arg, 0, TYPE_MAXIMUM (off_t));
1308 return;
1309 }
1310 }
1311 else
1312 {
1313 e.numbytes = u;
1314 if (!(u == e.numbytes && errno != ERANGE))
1315 {
1316 out_of_range_header (keyword, arg, 0, TYPE_MAXIMUM (size_t));
1317 return;
1318 }
1319 if (st->sparse_map_avail < st->sparse_map_size)
1320 st->sparse_map[st->sparse_map_avail++] = e;
1321 else
1322 {
1323 ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
1324 keyword, arg));
1325 return;
1326 }
1327 }
1328
1329 offset = !offset;
1330
1331 if (*delim == 0)
1332 break;
1333 else if (*delim != ',')
1334 {
1335 ERROR ((0, 0,
1336 _("Malformed extended header: invalid %s: unexpected delimiter %c"),
1337 keyword, *delim));
1338 return;
1339 }
1340
1341 arg = delim + 1;
1342 }
1343
1344 if (!offset)
1345 ERROR ((0, 0,
1346 _("Malformed extended header: invalid %s: odd number of values"),
1347 keyword));
1348}
1349
1350static void
1351dumpdir_coder (struct tar_stat_info const *st, char const *keyword,
1352 struct xheader *xhdr, void const *data)
1353{
1354 xheader_print_n (xhdr, keyword, data, dumpdir_size (data));
1355}
1356
1357static void
1358dumpdir_decoder (struct tar_stat_info *st,
1359 char const *keyword __attribute__((unused)),
1360 char const *arg,
1361 size_t size)
1362{
1363 st->dumpdir = xmalloc (size);
1364 memcpy (st->dumpdir, arg, size);
1365}
1366
1367static void
1368volume_label_coder (struct tar_stat_info const *st, char const *keyword,
1369 struct xheader *xhdr, void const *data)
1370{
1371 code_string (data, keyword, xhdr);
1372}
1373
1374static void
1375volume_label_decoder (struct tar_stat_info *st,
1376 char const *keyword __attribute__((unused)),
1377 char const *arg,
1378 size_t size __attribute__((unused)))
1379{
1380 decode_string (&volume_label, arg);
1381}
1382
1383static void
1384volume_size_coder (struct tar_stat_info const *st, char const *keyword,
1385 struct xheader *xhdr, void const *data)
1386{
1387 off_t v = *(off_t*)data;
1388 code_num (v, keyword, xhdr);
1389}
1390
1391static void
1392volume_size_decoder (struct tar_stat_info *st,
1393 char const *keyword,
1394 char const *arg, size_t size)
1395{
1396 uintmax_t u;
1397 if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
1398 continued_file_size = u;
1399}
1400
1401/* FIXME: Merge with volume_size_coder */
1402static void
1403volume_offset_coder (struct tar_stat_info const *st, char const *keyword,
1404 struct xheader *xhdr, void const *data)
1405{
1406 off_t v = *(off_t*)data;
1407 code_num (v, keyword, xhdr);
1408}
1409
1410static void
1411volume_offset_decoder (struct tar_stat_info *st,
1412 char const *keyword,
1413 char const *arg, size_t size)
1414{
1415 uintmax_t u;
1416 if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
1417 continued_file_offset = u;
1418}
1419
1420static void
1421volume_filename_decoder (struct tar_stat_info *st,
1422 char const *keyword __attribute__((unused)),
1423 char const *arg,
1424 size_t size __attribute__((unused)))
1425{
1426 decode_string (&continued_file_name, arg);
1427}
1428
1429static void
1430sparse_major_coder (struct tar_stat_info const *st, char const *keyword,
1431 struct xheader *xhdr, void const *data)
1432{
1433 code_num (st->sparse_major, keyword, xhdr);
1434}
1435
1436static void
1437sparse_major_decoder (struct tar_stat_info *st,
1438 char const *keyword,
1439 char const *arg,
1440 size_t size)
1441{
1442 uintmax_t u;
1443 if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
1444 st->sparse_major = u;
1445}
1446
1447static void
1448sparse_minor_coder (struct tar_stat_info const *st, char const *keyword,
1449 struct xheader *xhdr, void const *data)
1450{
1451 code_num (st->sparse_minor, keyword, xhdr);
1452}
1453
1454static void
1455sparse_minor_decoder (struct tar_stat_info *st,
1456 char const *keyword,
1457 char const *arg,
1458 size_t size)
1459{
1460 uintmax_t u;
1461 if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
1462 st->sparse_minor = u;
1463}
1464
1465struct xhdr_tab const xhdr_tab[] = {
1466 { "atime", atime_coder, atime_decoder, false },
1467 { "comment", dummy_coder, dummy_decoder, false },
1468 { "charset", dummy_coder, dummy_decoder, false },
1469 { "ctime", ctime_coder, ctime_decoder, false },
1470 { "gid", gid_coder, gid_decoder, false },
1471 { "gname", gname_coder, gname_decoder, false },
1472 { "linkpath", linkpath_coder, linkpath_decoder, false },
1473 { "mtime", mtime_coder, mtime_decoder, false },
1474 { "path", path_coder, path_decoder, false },
1475 { "size", size_coder, size_decoder, false },
1476 { "uid", uid_coder, uid_decoder, false },
1477 { "uname", uname_coder, uname_decoder, false },
1478
1479 /* Sparse file handling */
1480 { "GNU.sparse.name", path_coder, path_decoder,
1481 true },
1482 { "GNU.sparse.major", sparse_major_coder, sparse_major_decoder,
1483 true },
1484 { "GNU.sparse.minor", sparse_minor_coder, sparse_minor_decoder,
1485 true },
1486 { "GNU.sparse.realsize", sparse_size_coder, sparse_size_decoder,
1487 true },
1488 { "GNU.sparse.numblocks", sparse_numblocks_coder, sparse_numblocks_decoder,
1489 true },
1490
1491 /* tar 1.14 - 1.15.90 keywords. */
1492 { "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true },
1493 /* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
1494 headers, and each of them was meaningful. It confilcted with POSIX specs,
1495 which requires that "when extended header records conflict, the last one
1496 given in the header shall take precedence." */
1497 { "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder,
1498 true },
1499 { "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder,
1500 true },
1501 /* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
1502 { "GNU.sparse.map", NULL /* Unused, see pax_dump_header() */,
1503 sparse_map_decoder, false },
1504
1505 { "GNU.dumpdir", dumpdir_coder, dumpdir_decoder,
1506 true },
1507
1508 /* Keeps the tape/volume label. May be present only in the global headers.
1509 Equivalent to GNUTYPE_VOLHDR. */
1510 { "GNU.volume.label", volume_label_coder, volume_label_decoder, true },
1511
1512 /* These may be present in a first global header of the archive.
1513 They provide the same functionality as GNUTYPE_MULTIVOL header.
1514 The GNU.volume.size keeps the real_s_sizeleft value, which is
1515 otherwise kept in the size field of a multivolume header. The
1516 GNU.volume.offset keeps the offset of the start of this volume,
1517 otherwise kept in oldgnu_header.offset. */
1518 { "GNU.volume.filename", volume_label_coder, volume_filename_decoder,
1519 true },
1520 { "GNU.volume.size", volume_size_coder, volume_size_decoder, true },
1521 { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, true },
1522
1523 { NULL, NULL, NULL, false }
1524};
Note: See TracBrowser for help on using the repository browser.