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