]> Dogcows Code - chaz/tar/blob - src/xheader.c
Silent a cc warning
[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 /* The archived (effective) file size is always set directly in tar header
760 field, possibly overridden by "size" extended header - in both cases,
761 result is now decoded in st->stat.st_size */
762 st->archive_file_size = st->stat.st_size;
763
764 /* The real file size (given by stat()) may be redefined for sparse
765 files in "GNU.sparse.realsize" extended header */
766 if (st->real_size_set)
767 st->stat.st_size = st->real_size;
768 }
769
770 static void
771 decg (void *data, char const *keyword, char const *value,
772 size_t size __attribute__((unused)))
773 {
774 struct keyword_list **kwl = data;
775 struct xhdr_tab const *tab = locate_handler (keyword);
776 if (tab && (tab->flags & XHDR_GLOBAL))
777 tab->decoder (data, keyword, value, size);
778 else
779 xheader_list_append (kwl, keyword, value);
780 }
781
782 void
783 xheader_decode_global (struct xheader *xhdr)
784 {
785 if (xhdr->size)
786 {
787 char *p = xhdr->buffer + BLOCKSIZE;
788
789 xheader_list_destroy (&global_header_override_list);
790 while (decode_record (xhdr, &p, decg, &global_header_override_list))
791 continue;
792 }
793 }
794
795 static void
796 xheader_init (struct xheader *xhdr)
797 {
798 if (!xhdr->stk)
799 {
800 xhdr->stk = xmalloc (sizeof *xhdr->stk);
801 obstack_init (xhdr->stk);
802 }
803 }
804
805 void
806 xheader_store (char const *keyword, struct tar_stat_info *st,
807 void const *data)
808 {
809 struct xhdr_tab const *t;
810
811 if (st->xhdr.buffer)
812 return;
813 t = locate_handler (keyword);
814 if (!t || !t->coder)
815 return;
816 if (xheader_keyword_deleted_p (keyword))
817 return;
818 xheader_init (&st->xhdr);
819 if (!xheader_keyword_override_p (keyword))
820 t->coder (st, keyword, &st->xhdr, data);
821 }
822
823 void
824 xheader_read (struct xheader *xhdr, union block *p, off_t size)
825 {
826 size_t j = 0;
827
828 if (size < 0)
829 size = 0; /* Already diagnosed. */
830
831 if (SIZE_MAX - BLOCKSIZE <= size)
832 xalloc_die ();
833
834 size += BLOCKSIZE;
835 xhdr->size = size;
836 xhdr->buffer = xmalloc (size + 1);
837 xhdr->buffer[size] = '\0';
838
839 do
840 {
841 size_t len = size;
842
843 if (len > BLOCKSIZE)
844 len = BLOCKSIZE;
845
846 if (!p)
847 FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
848
849 memcpy (&xhdr->buffer[j], p->buffer, len);
850 set_next_block_after (p);
851
852 p = find_next_block ();
853
854 j += len;
855 size -= len;
856 }
857 while (size > 0);
858 }
859
860 /* xattr_encode_keyword() substitutes '=' ~~> '%3D' and '%' ~~> '%25'
861 in extended attribute keywords. This is needed because the '=' character
862 has special purpose in extended attribute header - it splits keyword and
863 value part of header. If there was the '=' occurrence allowed inside
864 keyword, there would be no unambiguous way how to decode this extended
865 attribute.
866
867 (http://lists.gnu.org/archive/html/bug-tar/2012-10/msg00017.html)
868 */
869 static char *
870 xattr_encode_keyword(const char *keyword)
871 {
872 static char *encode_buffer = NULL;
873 static size_t encode_buffer_size = 0;
874 size_t bp; /* keyword/buffer pointers */
875
876 if (!encode_buffer)
877 {
878 encode_buffer_size = 256;
879 encode_buffer = xmalloc (encode_buffer_size);
880 }
881 else
882 *encode_buffer = 0;
883
884 for (bp = 0; *keyword != 0; ++bp, ++keyword)
885 {
886 char c = *keyword;
887
888 if (bp + 2 /* enough for URL encoding also.. */ >= encode_buffer_size)
889 {
890 encode_buffer = x2realloc (encode_buffer, &encode_buffer_size);
891 }
892
893 if (c == '%')
894 {
895 strcpy (encode_buffer + bp, "%25");
896 bp += 2;
897 }
898 else if (c == '=')
899 {
900 strcpy (encode_buffer + bp, "%3D");
901 bp += 2;
902 }
903 else
904 encode_buffer[bp] = c;
905 }
906
907 encode_buffer[bp] = 0;
908
909 return encode_buffer;
910 }
911
912 static void
913 xheader_print_n (struct xheader *xhdr, char const *keyword,
914 char const *value, size_t vsize)
915 {
916 size_t p;
917 size_t n = 0;
918 char nbuf[UINTMAX_STRSIZE_BOUND];
919 char const *np;
920 size_t len, klen;
921
922 keyword = xattr_encode_keyword (keyword);
923 klen = strlen (keyword);
924 len = klen + vsize + 3; /* ' ' + '=' + '\n' */
925
926 do
927 {
928 p = n;
929 np = umaxtostr (len + p, nbuf);
930 n = nbuf + sizeof nbuf - 1 - np;
931 }
932 while (n != p);
933
934 x_obstack_grow (xhdr, np, n);
935 x_obstack_1grow (xhdr, ' ');
936 x_obstack_grow (xhdr, keyword, klen);
937 x_obstack_1grow (xhdr, '=');
938 x_obstack_grow (xhdr, value, vsize);
939 x_obstack_1grow (xhdr, '\n');
940 }
941
942 static void
943 xheader_print (struct xheader *xhdr, char const *keyword, char const *value)
944 {
945 xheader_print_n (xhdr, keyword, value, strlen (value));
946 }
947
948 void
949 xheader_finish (struct xheader *xhdr)
950 {
951 struct keyword_list *kp;
952
953 for (kp = keyword_override_list; kp; kp = kp->next)
954 code_string (kp->value, kp->pattern, xhdr);
955
956 xhdr->buffer = obstack_finish (xhdr->stk);
957 }
958
959 void
960 xheader_destroy (struct xheader *xhdr)
961 {
962 if (xhdr->stk)
963 {
964 obstack_free (xhdr->stk, NULL);
965 free (xhdr->stk);
966 xhdr->stk = NULL;
967 }
968 else
969 free (xhdr->buffer);
970 xhdr->buffer = 0;
971 xhdr->size = 0;
972 }
973
974 \f
975 /* Buildable strings */
976
977 void
978 xheader_string_begin (struct xheader *xhdr)
979 {
980 xhdr->string_length = 0;
981 }
982
983 void
984 xheader_string_add (struct xheader *xhdr, char const *s)
985 {
986 if (xhdr->buffer)
987 return;
988 xheader_init (xhdr);
989 xhdr->string_length += strlen (s);
990 x_obstack_grow (xhdr, s, strlen (s));
991 }
992
993 bool
994 xheader_string_end (struct xheader *xhdr, char const *keyword)
995 {
996 uintmax_t len;
997 uintmax_t p;
998 uintmax_t n = 0;
999 size_t size;
1000 char nbuf[UINTMAX_STRSIZE_BOUND];
1001 char const *np;
1002 char *cp;
1003
1004 if (xhdr->buffer)
1005 return false;
1006 xheader_init (xhdr);
1007
1008 len = strlen (keyword) + xhdr->string_length + 3; /* ' ' + '=' + '\n' */
1009
1010 do
1011 {
1012 p = n;
1013 np = umaxtostr (len + p, nbuf);
1014 n = nbuf + sizeof nbuf - 1 - np;
1015 }
1016 while (n != p);
1017
1018 p = strlen (keyword) + n + 2;
1019 size = p;
1020 if (size != p)
1021 {
1022 ERROR ((0, 0,
1023 _("Generated keyword/value pair is too long (keyword=%s, length=%s)"),
1024 keyword, nbuf));
1025 obstack_free (xhdr->stk, obstack_finish (xhdr->stk));
1026 return false;
1027 }
1028 x_obstack_blank (xhdr, p);
1029 x_obstack_1grow (xhdr, '\n');
1030 cp = (char*) obstack_next_free (xhdr->stk) - xhdr->string_length - p - 1;
1031 memmove (cp + p, cp, xhdr->string_length);
1032 cp = stpcpy (cp, np);
1033 *cp++ = ' ';
1034 cp = stpcpy (cp, keyword);
1035 *cp++ = '=';
1036 return true;
1037 }
1038
1039 \f
1040 /* Implementations */
1041
1042 static void
1043 out_of_range_header (char const *keyword, char const *value,
1044 intmax_t minval, uintmax_t maxval)
1045 {
1046 char minval_buf[INT_BUFSIZE_BOUND (intmax_t)];
1047 char maxval_buf[UINTMAX_STRSIZE_BOUND];
1048 char *minval_string = imaxtostr (minval, minval_buf);
1049 char *maxval_string = umaxtostr (maxval, maxval_buf);
1050
1051 /* TRANSLATORS: The first %s is the pax extended header keyword
1052 (atime, gid, etc.). */
1053 ERROR ((0, 0, _("Extended header %s=%s is out of range %s..%s"),
1054 keyword, value, minval_string, maxval_string));
1055 }
1056
1057 static void
1058 code_string (char const *string, char const *keyword, struct xheader *xhdr)
1059 {
1060 char *outstr;
1061 if (!utf8_convert (true, string, &outstr))
1062 {
1063 /* FIXME: report error */
1064 outstr = xstrdup (string);
1065 }
1066 xheader_print (xhdr, keyword, outstr);
1067 free (outstr);
1068 }
1069
1070 static void
1071 decode_string (char **string, char const *arg)
1072 {
1073 if (*string)
1074 {
1075 free (*string);
1076 *string = NULL;
1077 }
1078 if (!utf8_convert (false, arg, string))
1079 {
1080 /* FIXME: report error and act accordingly to --pax invalid=UTF-8 */
1081 assign_string (string, arg);
1082 }
1083 }
1084
1085 static void
1086 code_time (struct timespec t, char const *keyword, struct xheader *xhdr)
1087 {
1088 char buf[TIMESPEC_STRSIZE_BOUND];
1089 xheader_print (xhdr, keyword, code_timespec (t, buf));
1090 }
1091
1092 static bool
1093 decode_time (struct timespec *ts, char const *arg, char const *keyword)
1094 {
1095 char *arg_lim;
1096 struct timespec t = decode_timespec (arg, &arg_lim, true);
1097
1098 if (! valid_timespec (t))
1099 {
1100 if (arg < arg_lim && !*arg_lim)
1101 out_of_range_header (keyword, arg, TYPE_MINIMUM (time_t),
1102 TYPE_MAXIMUM (time_t));
1103 else
1104 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
1105 keyword, arg));
1106 return false;
1107 }
1108
1109 *ts = t;
1110 return true;
1111 }
1112
1113 static void
1114 code_signed_num (uintmax_t value, char const *keyword,
1115 intmax_t minval, uintmax_t maxval, struct xheader *xhdr)
1116 {
1117 char sbuf[SYSINT_BUFSIZE];
1118 xheader_print (xhdr, keyword, sysinttostr (value, minval, maxval, sbuf));
1119 }
1120
1121 static void
1122 code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
1123 {
1124 code_signed_num (value, keyword, 0, UINTMAX_MAX, xhdr);
1125 }
1126
1127 static bool
1128 decode_signed_num (intmax_t *num, char const *arg,
1129 intmax_t minval, uintmax_t maxval,
1130 char const *keyword)
1131 {
1132 char *arg_lim;
1133 intmax_t u = strtosysint (arg, &arg_lim, minval, maxval);
1134
1135 if (errno == EINVAL || *arg_lim)
1136 {
1137 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
1138 keyword, arg));
1139 return false;
1140 }
1141
1142 if (errno == ERANGE)
1143 {
1144 out_of_range_header (keyword, arg, minval, maxval);
1145 return false;
1146 }
1147
1148 *num = u;
1149 return true;
1150 }
1151
1152 static bool
1153 decode_num (uintmax_t *num, char const *arg, uintmax_t maxval,
1154 char const *keyword)
1155 {
1156 intmax_t i;
1157 if (! decode_signed_num (&i, arg, 0, maxval, keyword))
1158 return false;
1159 *num = i;
1160 return true;
1161 }
1162
1163 static void
1164 dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)),
1165 char const *keyword __attribute__ ((unused)),
1166 struct xheader *xhdr __attribute__ ((unused)),
1167 void const *data __attribute__ ((unused)))
1168 {
1169 }
1170
1171 static void
1172 dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)),
1173 char const *keyword __attribute__ ((unused)),
1174 char const *arg __attribute__ ((unused)),
1175 size_t size __attribute__((unused)))
1176 {
1177 }
1178
1179 static void
1180 atime_coder (struct tar_stat_info const *st, char const *keyword,
1181 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1182 {
1183 code_time (st->atime, keyword, xhdr);
1184 }
1185
1186 static void
1187 atime_decoder (struct tar_stat_info *st,
1188 char const *keyword,
1189 char const *arg,
1190 size_t size __attribute__((unused)))
1191 {
1192 struct timespec ts;
1193 if (decode_time (&ts, arg, keyword))
1194 st->atime = ts;
1195 }
1196
1197 static void
1198 gid_coder (struct tar_stat_info const *st, char const *keyword,
1199 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1200 {
1201 code_signed_num (st->stat.st_gid, keyword,
1202 TYPE_MINIMUM (gid_t), TYPE_MAXIMUM (gid_t), xhdr);
1203 }
1204
1205 static void
1206 gid_decoder (struct tar_stat_info *st,
1207 char const *keyword,
1208 char const *arg,
1209 size_t size __attribute__((unused)))
1210 {
1211 intmax_t u;
1212 if (decode_signed_num (&u, arg, TYPE_MINIMUM (gid_t),
1213 TYPE_MAXIMUM (gid_t), keyword))
1214 st->stat.st_gid = u;
1215 }
1216
1217 static void
1218 gname_coder (struct tar_stat_info const *st, char const *keyword,
1219 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1220 {
1221 code_string (st->gname, keyword, xhdr);
1222 }
1223
1224 static void
1225 gname_decoder (struct tar_stat_info *st,
1226 char const *keyword __attribute__((unused)),
1227 char const *arg,
1228 size_t size __attribute__((unused)))
1229 {
1230 decode_string (&st->gname, arg);
1231 }
1232
1233 static void
1234 linkpath_coder (struct tar_stat_info const *st, char const *keyword,
1235 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1236 {
1237 code_string (st->link_name, keyword, xhdr);
1238 }
1239
1240 static void
1241 linkpath_decoder (struct tar_stat_info *st,
1242 char const *keyword __attribute__((unused)),
1243 char const *arg,
1244 size_t size __attribute__((unused)))
1245 {
1246 decode_string (&st->link_name, arg);
1247 }
1248
1249 static void
1250 ctime_coder (struct tar_stat_info const *st, char const *keyword,
1251 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1252 {
1253 code_time (st->ctime, keyword, xhdr);
1254 }
1255
1256 static void
1257 ctime_decoder (struct tar_stat_info *st,
1258 char const *keyword,
1259 char const *arg,
1260 size_t size __attribute__((unused)))
1261 {
1262 struct timespec ts;
1263 if (decode_time (&ts, arg, keyword))
1264 st->ctime = ts;
1265 }
1266
1267 static void
1268 mtime_coder (struct tar_stat_info const *st, char const *keyword,
1269 struct xheader *xhdr, void const *data)
1270 {
1271 struct timespec const *mtime = data;
1272 code_time (mtime ? *mtime : st->mtime, keyword, xhdr);
1273 }
1274
1275 static void
1276 mtime_decoder (struct tar_stat_info *st,
1277 char const *keyword,
1278 char const *arg,
1279 size_t size __attribute__((unused)))
1280 {
1281 struct timespec ts;
1282 if (decode_time (&ts, arg, keyword))
1283 st->mtime = ts;
1284 }
1285
1286 static void
1287 path_coder (struct tar_stat_info const *st, char const *keyword,
1288 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1289 {
1290 code_string (st->file_name, keyword, xhdr);
1291 }
1292
1293 static void
1294 path_decoder (struct tar_stat_info *st,
1295 char const *keyword __attribute__((unused)),
1296 char const *arg,
1297 size_t size __attribute__((unused)))
1298 {
1299 decode_string (&st->orig_file_name, arg);
1300 decode_string (&st->file_name, arg);
1301 st->had_trailing_slash = strip_trailing_slashes (st->file_name);
1302 }
1303
1304 static void
1305 size_coder (struct tar_stat_info const *st, char const *keyword,
1306 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1307 {
1308 code_num (st->stat.st_size, keyword, xhdr);
1309 }
1310
1311 static void
1312 size_decoder (struct tar_stat_info *st,
1313 char const *keyword,
1314 char const *arg,
1315 size_t size __attribute__((unused)))
1316 {
1317 uintmax_t u;
1318 if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
1319 st->stat.st_size = u;
1320 }
1321
1322 static void
1323 uid_coder (struct tar_stat_info const *st, char const *keyword,
1324 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1325 {
1326 code_signed_num (st->stat.st_uid, keyword,
1327 TYPE_MINIMUM (uid_t), TYPE_MAXIMUM (uid_t), xhdr);
1328 }
1329
1330 static void
1331 uid_decoder (struct tar_stat_info *st,
1332 char const *keyword,
1333 char const *arg,
1334 size_t size __attribute__((unused)))
1335 {
1336 intmax_t u;
1337 if (decode_signed_num (&u, arg, TYPE_MINIMUM (uid_t),
1338 TYPE_MAXIMUM (uid_t), keyword))
1339 st->stat.st_uid = u;
1340 }
1341
1342 static void
1343 uname_coder (struct tar_stat_info const *st, char const *keyword,
1344 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1345 {
1346 code_string (st->uname, keyword, xhdr);
1347 }
1348
1349 static void
1350 uname_decoder (struct tar_stat_info *st,
1351 char const *keyword __attribute__((unused)),
1352 char const *arg,
1353 size_t size __attribute__((unused)))
1354 {
1355 decode_string (&st->uname, arg);
1356 }
1357
1358 static void
1359 sparse_size_coder (struct tar_stat_info const *st, char const *keyword,
1360 struct xheader *xhdr, void const *data)
1361 {
1362 size_coder (st, keyword, xhdr, data);
1363 }
1364
1365 static void
1366 sparse_size_decoder (struct tar_stat_info *st,
1367 char const *keyword,
1368 char const *arg,
1369 size_t size __attribute__((unused)))
1370 {
1371 uintmax_t u;
1372 if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
1373 {
1374 st->real_size_set = 1;
1375 st->real_size = u;
1376 }
1377 }
1378
1379 static void
1380 sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword,
1381 struct xheader *xhdr,
1382 void const *data __attribute__ ((unused)))
1383 {
1384 code_num (st->sparse_map_avail, keyword, xhdr);
1385 }
1386
1387 static void
1388 sparse_numblocks_decoder (struct tar_stat_info *st,
1389 char const *keyword,
1390 char const *arg,
1391 size_t size __attribute__((unused)))
1392 {
1393 uintmax_t u;
1394 if (decode_num (&u, arg, SIZE_MAX, keyword))
1395 {
1396 st->sparse_map_size = u;
1397 st->sparse_map = xcalloc (u, sizeof st->sparse_map[0]);
1398 st->sparse_map_avail = 0;
1399 }
1400 }
1401
1402 static void
1403 sparse_offset_coder (struct tar_stat_info const *st, char const *keyword,
1404 struct xheader *xhdr, void const *data)
1405 {
1406 size_t const *pi = data;
1407 code_num (st->sparse_map[*pi].offset, keyword, xhdr);
1408 }
1409
1410 static void
1411 sparse_offset_decoder (struct tar_stat_info *st,
1412 char const *keyword,
1413 char const *arg,
1414 size_t size __attribute__((unused)))
1415 {
1416 uintmax_t u;
1417 if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
1418 {
1419 if (st->sparse_map_avail < st->sparse_map_size)
1420 st->sparse_map[st->sparse_map_avail].offset = u;
1421 else
1422 ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
1423 "GNU.sparse.offset", arg));
1424 }
1425 }
1426
1427 static void
1428 sparse_numbytes_coder (struct tar_stat_info const *st, char const *keyword,
1429 struct xheader *xhdr, void const *data)
1430 {
1431 size_t const *pi = data;
1432 code_num (st->sparse_map[*pi].numbytes, keyword, xhdr);
1433 }
1434
1435 static void
1436 sparse_numbytes_decoder (struct tar_stat_info *st,
1437 char const *keyword,
1438 char const *arg,
1439 size_t size __attribute__((unused)))
1440 {
1441 uintmax_t u;
1442 if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
1443 {
1444 if (st->sparse_map_avail < st->sparse_map_size)
1445 st->sparse_map[st->sparse_map_avail++].numbytes = u;
1446 else
1447 ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
1448 keyword, arg));
1449 }
1450 }
1451
1452 static void
1453 sparse_map_decoder (struct tar_stat_info *st,
1454 char const *keyword,
1455 char const *arg,
1456 size_t size __attribute__((unused)))
1457 {
1458 int offset = 1;
1459
1460 st->sparse_map_avail = 0;
1461 while (1)
1462 {
1463 intmax_t u;
1464 char *delim;
1465 struct sp_array e;
1466
1467 if (!ISDIGIT (*arg))
1468 {
1469 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
1470 keyword, arg));
1471 return;
1472 }
1473
1474 errno = 0;
1475 u = strtoimax (arg, &delim, 10);
1476 if (TYPE_MAXIMUM (off_t) < u)
1477 {
1478 u = TYPE_MAXIMUM (off_t);
1479 errno = ERANGE;
1480 }
1481 if (offset)
1482 {
1483 e.offset = u;
1484 if (errno == ERANGE)
1485 {
1486 out_of_range_header (keyword, arg, 0, TYPE_MAXIMUM (off_t));
1487 return;
1488 }
1489 }
1490 else
1491 {
1492 e.numbytes = u;
1493 if (errno == ERANGE)
1494 {
1495 out_of_range_header (keyword, arg, 0, TYPE_MAXIMUM (off_t));
1496 return;
1497 }
1498 if (st->sparse_map_avail < st->sparse_map_size)
1499 st->sparse_map[st->sparse_map_avail++] = e;
1500 else
1501 {
1502 ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
1503 keyword, arg));
1504 return;
1505 }
1506 }
1507
1508 offset = !offset;
1509
1510 if (*delim == 0)
1511 break;
1512 else if (*delim != ',')
1513 {
1514 ERROR ((0, 0,
1515 _("Malformed extended header: invalid %s: unexpected delimiter %c"),
1516 keyword, *delim));
1517 return;
1518 }
1519
1520 arg = delim + 1;
1521 }
1522
1523 if (!offset)
1524 ERROR ((0, 0,
1525 _("Malformed extended header: invalid %s: odd number of values"),
1526 keyword));
1527 }
1528
1529 static void
1530 dumpdir_coder (struct tar_stat_info const *st, char const *keyword,
1531 struct xheader *xhdr, void const *data)
1532 {
1533 xheader_print_n (xhdr, keyword, data, dumpdir_size (data));
1534 }
1535
1536 static void
1537 dumpdir_decoder (struct tar_stat_info *st,
1538 char const *keyword __attribute__((unused)),
1539 char const *arg,
1540 size_t size)
1541 {
1542 st->dumpdir = xmalloc (size);
1543 memcpy (st->dumpdir, arg, size);
1544 }
1545
1546 static void
1547 volume_label_coder (struct tar_stat_info const *st, char const *keyword,
1548 struct xheader *xhdr, void const *data)
1549 {
1550 code_string (data, keyword, xhdr);
1551 }
1552
1553 static void
1554 volume_label_decoder (struct tar_stat_info *st,
1555 char const *keyword __attribute__((unused)),
1556 char const *arg,
1557 size_t size __attribute__((unused)))
1558 {
1559 decode_string (&volume_label, arg);
1560 }
1561
1562 static void
1563 volume_size_coder (struct tar_stat_info const *st, char const *keyword,
1564 struct xheader *xhdr, void const *data)
1565 {
1566 off_t const *v = data;
1567 code_num (*v, keyword, xhdr);
1568 }
1569
1570 static void
1571 volume_size_decoder (struct tar_stat_info *st,
1572 char const *keyword,
1573 char const *arg, size_t size)
1574 {
1575 uintmax_t u;
1576 if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
1577 continued_file_size = u;
1578 }
1579
1580 /* FIXME: Merge with volume_size_coder */
1581 static void
1582 volume_offset_coder (struct tar_stat_info const *st, char const *keyword,
1583 struct xheader *xhdr, void const *data)
1584 {
1585 off_t const *v = data;
1586 code_num (*v, keyword, xhdr);
1587 }
1588
1589 static void
1590 volume_offset_decoder (struct tar_stat_info *st,
1591 char const *keyword,
1592 char const *arg, size_t size)
1593 {
1594 uintmax_t u;
1595 if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
1596 continued_file_offset = u;
1597 }
1598
1599 static void
1600 volume_filename_decoder (struct tar_stat_info *st,
1601 char const *keyword __attribute__((unused)),
1602 char const *arg,
1603 size_t size __attribute__((unused)))
1604 {
1605 decode_string (&continued_file_name, arg);
1606 }
1607
1608 static void
1609 xattr_selinux_coder (struct tar_stat_info const *st, char const *keyword,
1610 struct xheader *xhdr, void const *data)
1611 {
1612 code_string (st->cntx_name, keyword, xhdr);
1613 }
1614
1615 static void
1616 xattr_selinux_decoder (struct tar_stat_info *st,
1617 char const *keyword, char const *arg, size_t size)
1618 {
1619 decode_string (&st->cntx_name, arg);
1620 }
1621
1622 static void
1623 xattr_acls_a_coder (struct tar_stat_info const *st , char const *keyword,
1624 struct xheader *xhdr, void const *data)
1625 {
1626 xheader_print_n (xhdr, keyword, st->acls_a_ptr, st->acls_a_len);
1627 }
1628
1629 static void
1630 xattr_acls_a_decoder (struct tar_stat_info *st,
1631 char const *keyword, char const *arg, size_t size)
1632 {
1633 st->acls_a_ptr = xmemdup (arg, size + 1);
1634 st->acls_a_len = size;
1635 }
1636
1637 static void
1638 xattr_acls_d_coder (struct tar_stat_info const *st , char const *keyword,
1639 struct xheader *xhdr, void const *data)
1640 {
1641 xheader_print_n (xhdr, keyword, st->acls_d_ptr, st->acls_d_len);
1642 }
1643
1644 static void
1645 xattr_acls_d_decoder (struct tar_stat_info *st,
1646 char const *keyword, char const *arg, size_t size)
1647 {
1648 st->acls_d_ptr = xmemdup (arg, size + 1);
1649 st->acls_d_len = size;
1650 }
1651
1652 static void
1653 xattr_coder (struct tar_stat_info const *st, char const *keyword,
1654 struct xheader *xhdr, void const *data)
1655 {
1656 struct xattr_array *xattr_map = st->xattr_map;
1657 const size_t *off = data;
1658 xheader_print_n (xhdr, keyword,
1659 xattr_map[*off].xval_ptr, xattr_map[*off].xval_len);
1660 }
1661
1662 static void
1663 xattr_decoder (struct tar_stat_info *st,
1664 char const *keyword, char const *arg, size_t size)
1665 {
1666 char *xstr, *xkey;
1667
1668 /* copy keyword */
1669 size_t klen_raw = strlen (keyword);
1670 xkey = alloca (klen_raw + 1);
1671 memcpy (xkey, keyword, klen_raw + 1) /* including null-terminating */;
1672
1673 /* copy value */
1674 xstr = alloca (size + 1);
1675 memcpy (xstr, arg, size + 1); /* separator included, for GNU tar '\n' */;
1676
1677 xattr_decode_keyword (xkey);
1678
1679 xheader_xattr_add (st, xkey + strlen("SCHILY.xattr."), xstr, size);
1680 }
1681
1682 static void
1683 sparse_major_coder (struct tar_stat_info const *st, char const *keyword,
1684 struct xheader *xhdr, void const *data)
1685 {
1686 code_num (st->sparse_major, keyword, xhdr);
1687 }
1688
1689 static void
1690 sparse_major_decoder (struct tar_stat_info *st,
1691 char const *keyword,
1692 char const *arg,
1693 size_t size)
1694 {
1695 uintmax_t u;
1696 if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
1697 st->sparse_major = u;
1698 }
1699
1700 static void
1701 sparse_minor_coder (struct tar_stat_info const *st, char const *keyword,
1702 struct xheader *xhdr, void const *data)
1703 {
1704 code_num (st->sparse_minor, keyword, xhdr);
1705 }
1706
1707 static void
1708 sparse_minor_decoder (struct tar_stat_info *st,
1709 char const *keyword,
1710 char const *arg,
1711 size_t size)
1712 {
1713 uintmax_t u;
1714 if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
1715 st->sparse_minor = u;
1716 }
1717
1718 struct xhdr_tab const xhdr_tab[] = {
1719 { "atime", atime_coder, atime_decoder, 0, false },
1720 { "comment", dummy_coder, dummy_decoder, 0, false },
1721 { "charset", dummy_coder, dummy_decoder, 0, false },
1722 { "ctime", ctime_coder, ctime_decoder, 0, false },
1723 { "gid", gid_coder, gid_decoder, 0, false },
1724 { "gname", gname_coder, gname_decoder, 0, false },
1725 { "linkpath", linkpath_coder, linkpath_decoder, 0, false },
1726 { "mtime", mtime_coder, mtime_decoder, 0, false },
1727 { "path", path_coder, path_decoder, 0, false },
1728 { "size", size_coder, size_decoder, 0, false },
1729 { "uid", uid_coder, uid_decoder, 0, false },
1730 { "uname", uname_coder, uname_decoder, 0, false },
1731
1732 /* Sparse file handling */
1733 { "GNU.sparse.name", path_coder, path_decoder,
1734 XHDR_PROTECTED, false },
1735 { "GNU.sparse.major", sparse_major_coder, sparse_major_decoder,
1736 XHDR_PROTECTED, false },
1737 { "GNU.sparse.minor", sparse_minor_coder, sparse_minor_decoder,
1738 XHDR_PROTECTED, false },
1739 { "GNU.sparse.realsize", sparse_size_coder, sparse_size_decoder,
1740 XHDR_PROTECTED, false },
1741 { "GNU.sparse.numblocks", sparse_numblocks_coder, sparse_numblocks_decoder,
1742 XHDR_PROTECTED, false },
1743
1744 /* tar 1.14 - 1.15.90 keywords. */
1745 { "GNU.sparse.size", sparse_size_coder, sparse_size_decoder,
1746 XHDR_PROTECTED, false },
1747 /* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
1748 headers, and each of them was meaningful. It confilcted with POSIX specs,
1749 which requires that "when extended header records conflict, the last one
1750 given in the header shall take precedence." */
1751 { "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder,
1752 XHDR_PROTECTED, false },
1753 { "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder,
1754 XHDR_PROTECTED, false },
1755 /* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
1756 { "GNU.sparse.map", NULL /* Unused, see pax_dump_header() */,
1757 sparse_map_decoder, 0, false },
1758
1759 { "GNU.dumpdir", dumpdir_coder, dumpdir_decoder,
1760 XHDR_PROTECTED, false },
1761
1762 /* Keeps the tape/volume label. May be present only in the global headers.
1763 Equivalent to GNUTYPE_VOLHDR. */
1764 { "GNU.volume.label", volume_label_coder, volume_label_decoder,
1765 XHDR_PROTECTED | XHDR_GLOBAL, false },
1766
1767 /* These may be present in a first global header of the archive.
1768 They provide the same functionality as GNUTYPE_MULTIVOL header.
1769 The GNU.volume.size keeps the real_s_sizeleft value, which is
1770 otherwise kept in the size field of a multivolume header. The
1771 GNU.volume.offset keeps the offset of the start of this volume,
1772 otherwise kept in oldgnu_header.offset. */
1773 { "GNU.volume.filename", volume_label_coder, volume_filename_decoder,
1774 XHDR_PROTECTED | XHDR_GLOBAL, false },
1775 { "GNU.volume.size", volume_size_coder, volume_size_decoder,
1776 XHDR_PROTECTED | XHDR_GLOBAL, false },
1777 { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder,
1778 XHDR_PROTECTED | XHDR_GLOBAL, false },
1779
1780 /* We get the SELinux value from filecon, so add a namespace for SELinux
1781 instead of storing it in SCHILY.xattr.* (which would be RAW). */
1782 { "RHT.security.selinux",
1783 xattr_selinux_coder, xattr_selinux_decoder, 0, false },
1784
1785 /* ACLs, use the star format... */
1786 { "SCHILY.acl.access",
1787 xattr_acls_a_coder, xattr_acls_a_decoder, 0, false },
1788
1789 { "SCHILY.acl.default",
1790 xattr_acls_d_coder, xattr_acls_d_decoder, 0, false },
1791
1792 /* We are storing all extended attributes using this rule even if some of them
1793 were stored by some previous rule (duplicates) -- we just have to make sure
1794 they are restored *only once* during extraction later on. */
1795 { "SCHILY.xattr", xattr_coder, xattr_decoder, 0, true },
1796
1797 { NULL, NULL, NULL, 0, false }
1798 };
This page took 0.108356 seconds and 4 git commands to generate.