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