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