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