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