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