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