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