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