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