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