]> Dogcows Code - chaz/tar/blob - src/xheader.c
build: new configure option --enable-gcc-warnings
[chaz/tar] / src / xheader.c
1 /* POSIX extended headers for tar.
2
3 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2012
4 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14 Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20 #include <system.h>
21
22 #include <fnmatch.h>
23 #include <hash.h>
24 #include <inttostr.h>
25 #include <quotearg.h>
26
27 #include "common.h"
28
29 static void xheader_init (struct xheader *xhdr);
30 static bool xheader_protected_pattern_p (char const *pattern);
31 static bool xheader_protected_keyword_p (char const *keyword);
32 static void xheader_set_single_keyword (char *) __attribute__ ((noreturn));
33
34 /* Used by xheader_finish() */
35 static void code_string (char const *string, char const *keyword,
36 struct xheader *xhdr);
37
38 /* Number of global headers written so far. */
39 static size_t global_header_count;
40 /* FIXME: Possibly it should be reset after changing the volume.
41 POSIX %n specification says that it is expanded to the sequence
42 number of current global header in *the* archive. However, for
43 multi-volume archives this will yield duplicate header names
44 in different volumes, which I'd like to avoid. The best way
45 to solve this would be to use per-archive header count as required
46 by POSIX *and* set globexthdr.name to, say,
47 $TMPDIR/GlobalHead.%p.$NUMVOLUME.%n.
48
49 However it should wait until buffer.c is finally rewritten */
50
51 \f
52 /* Interface functions to obstacks */
53
54 static void
55 x_obstack_grow (struct xheader *xhdr, const char *ptr, size_t length)
56 {
57 obstack_grow (xhdr->stk, ptr, length);
58 xhdr->size += length;
59 }
60
61 static void
62 x_obstack_1grow (struct xheader *xhdr, char c)
63 {
64 obstack_1grow (xhdr->stk, c);
65 xhdr->size++;
66 }
67
68 static void
69 x_obstack_blank (struct xheader *xhdr, size_t length)
70 {
71 obstack_blank (xhdr->stk, length);
72 xhdr->size += length;
73 }
74
75 \f
76 /* Keyword options */
77
78 struct keyword_list
79 {
80 struct keyword_list *next;
81 char *pattern;
82 char *value;
83 };
84
85
86 /* List of keyword patterns set by delete= option */
87 static struct keyword_list *keyword_pattern_list;
88
89 /* List of keyword/value pairs set by 'keyword=value' option */
90 static struct keyword_list *keyword_global_override_list;
91
92 /* List of keyword/value pairs set by 'keyword:=value' option */
93 static struct keyword_list *keyword_override_list;
94
95 /* List of keyword/value pairs decoded from the last 'g' type header */
96 static struct keyword_list *global_header_override_list;
97
98 /* Template for the name field of an 'x' type header */
99 static char *exthdr_name;
100
101 static char *exthdr_mtime_option;
102 static time_t exthdr_mtime;
103
104 /* Template for the name field of a 'g' type header */
105 static char *globexthdr_name;
106
107 static char *globexthdr_mtime_option;
108 static time_t globexthdr_mtime;
109
110 bool
111 xheader_keyword_deleted_p (const char *kw)
112 {
113 struct keyword_list *kp;
114
115 for (kp = keyword_pattern_list; kp; kp = kp->next)
116 if (fnmatch (kp->pattern, kw, 0) == 0)
117 return true;
118 return false;
119 }
120
121 static bool
122 xheader_keyword_override_p (const char *keyword)
123 {
124 struct keyword_list *kp;
125
126 for (kp = keyword_override_list; kp; kp = kp->next)
127 if (strcmp (kp->pattern, keyword) == 0)
128 return true;
129 return false;
130 }
131
132 static void
133 xheader_list_append (struct keyword_list **root, char const *kw,
134 char const *value)
135 {
136 struct keyword_list *kp = xmalloc (sizeof *kp);
137 kp->pattern = xstrdup (kw);
138 kp->value = value ? xstrdup (value) : NULL;
139 kp->next = *root;
140 *root = kp;
141 }
142
143 static void
144 xheader_list_destroy (struct keyword_list **root)
145 {
146 if (root)
147 {
148 struct keyword_list *kw = *root;
149 while (kw)
150 {
151 struct keyword_list *next = kw->next;
152 free (kw->pattern);
153 free (kw->value);
154 free (kw);
155 kw = next;
156 }
157 *root = NULL;
158 }
159 }
160
161 static void
162 xheader_set_single_keyword (char *kw)
163 {
164 USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet implemented"), kw));
165 }
166
167 static void
168 assign_time_option (char **sval, time_t *tval, const char *input)
169 {
170 uintmax_t u;
171 char *p;
172 time_t t = u = strtoumax (input, &p, 10);
173 if (t != u || *p || errno == ERANGE)
174 ERROR ((0, 0, _("Time stamp is out of allowed range")));
175 else
176 {
177 *tval = t;
178 assign_string (sval, input);
179 }
180 }
181
182 static void
183 xheader_set_keyword_equal (char *kw, char *eq)
184 {
185 bool global = true;
186 char *p = eq;
187
188 if (eq[-1] == ':')
189 {
190 p--;
191 global = false;
192 }
193
194 while (p > kw && isspace ((unsigned char) *p))
195 p--;
196
197 *p = 0;
198
199 for (p = eq + 1; *p && isspace ((unsigned char) *p); p++)
200 ;
201
202 if (strcmp (kw, "delete") == 0)
203 {
204 if (xheader_protected_pattern_p (p))
205 USAGE_ERROR ((0, 0, _("Pattern %s cannot be used"), quote (p)));
206 xheader_list_append (&keyword_pattern_list, p, NULL);
207 }
208 else if (strcmp (kw, "exthdr.name") == 0)
209 assign_string (&exthdr_name, p);
210 else if (strcmp (kw, "globexthdr.name") == 0)
211 assign_string (&globexthdr_name, p);
212 else if (strcmp (kw, "exthdr.mtime") == 0)
213 assign_time_option (&exthdr_mtime_option, &exthdr_mtime, p);
214 else if (strcmp (kw, "globexthdr.mtime") == 0)
215 assign_time_option (&globexthdr_mtime_option, &globexthdr_mtime, p);
216 else
217 {
218 if (xheader_protected_keyword_p (kw))
219 USAGE_ERROR ((0, 0, _("Keyword %s cannot be overridden"), kw));
220 if (global)
221 xheader_list_append (&keyword_global_override_list, kw, p);
222 else
223 xheader_list_append (&keyword_override_list, kw, p);
224 }
225 }
226
227 void
228 xheader_set_option (char *string)
229 {
230 char *token;
231 for (token = strtok (string, ","); token; token = strtok (NULL, ","))
232 {
233 char *p = strchr (token, '=');
234 if (!p)
235 xheader_set_single_keyword (token);
236 else
237 xheader_set_keyword_equal (token, p);
238 }
239 }
240
241 /*
242 string Includes: Replaced By:
243 %d The directory name of the file,
244 equivalent to the result of the
245 dirname utility on the translated
246 file name.
247 %f The filename of the file, equivalent
248 to the result of the basename
249 utility on the translated file name.
250 %p The process ID of the pax process.
251 %n The value of the 3rd argument.
252 %% A '%' character. */
253
254 char *
255 xheader_format_name (struct tar_stat_info *st, const char *fmt, size_t n)
256 {
257 char *buf;
258 size_t len = strlen (fmt);
259 char *q;
260 const char *p;
261 char *dirp = NULL;
262 char *dir = NULL;
263 char *base = NULL;
264 char pidbuf[UINTMAX_STRSIZE_BOUND];
265 char const *pptr = 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 xheader_write (XGLTYPE, name = xheader_ghdr_name (), time (NULL), 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 uintmax_t u;
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 errno = 0;
673 len = u = strtoumax (p, &len_lim, 10);
674 if (len != u || errno == ERANGE)
675 {
676 ERROR ((0, 0, _("Extended header length is out of allowed range")));
677 return false;
678 }
679
680 if (len_max < len)
681 {
682 int len_len = len_lim - p;
683 ERROR ((0, 0, _("Extended header length %*s is out of range"),
684 len_len, p));
685 return false;
686 }
687
688 nextp = start + len;
689
690 for (p = len_lim; *p == ' ' || *p == '\t'; p++)
691 continue;
692 if (p == len_lim)
693 {
694 ERROR ((0, 0,
695 _("Malformed extended header: missing blank after length")));
696 return false;
697 }
698
699 keyword = p;
700 p = strchr (p, '=');
701 if (! (p && p < nextp))
702 {
703 ERROR ((0, 0, _("Malformed extended header: missing equal sign")));
704 return false;
705 }
706
707 if (nextp[-1] != '\n')
708 {
709 ERROR ((0, 0, _("Malformed extended header: missing newline")));
710 return false;
711 }
712
713 *p = nextp[-1] = '\0';
714 handler (data, keyword, p + 1, nextp - p - 2); /* '=' + trailing '\n' */
715 *p = '=';
716 nextp[-1] = '\n';
717 *ptr = nextp;
718 return true;
719 }
720
721 static void
722 run_override_list (struct keyword_list *kp, struct tar_stat_info *st)
723 {
724 for (; kp; kp = kp->next)
725 {
726 struct xhdr_tab const *t = locate_handler (kp->pattern);
727 if (t)
728 t->decoder (st, t->keyword, kp->value, strlen (kp->value));
729 }
730 }
731
732 static void
733 decx (void *data, char const *keyword, char const *value, size_t size)
734 {
735 struct xhdr_tab const *t;
736 struct tar_stat_info *st = data;
737
738 if (xheader_keyword_deleted_p (keyword)
739 || xheader_keyword_override_p (keyword))
740 return;
741
742 t = locate_handler (keyword);
743 if (t)
744 t->decoder (st, keyword, value, size);
745 else
746 WARNOPT (WARN_UNKNOWN_KEYWORD,
747 (0, 0, _("Ignoring unknown extended header keyword '%s'"),
748 keyword));
749 }
750
751 void
752 xheader_decode (struct tar_stat_info *st)
753 {
754 run_override_list (keyword_global_override_list, st);
755 run_override_list (global_header_override_list, st);
756
757 if (st->xhdr.size)
758 {
759 char *p = st->xhdr.buffer + BLOCKSIZE;
760 while (decode_record (&st->xhdr, &p, decx, st))
761 continue;
762 }
763 run_override_list (keyword_override_list, st);
764 }
765
766 static void
767 decg (void *data, char const *keyword, char const *value,
768 size_t size __attribute__((unused)))
769 {
770 struct keyword_list **kwl = data;
771 struct xhdr_tab const *tab = locate_handler (keyword);
772 if (tab && (tab->flags & XHDR_GLOBAL))
773 tab->decoder (data, keyword, value, size);
774 else
775 xheader_list_append (kwl, keyword, value);
776 }
777
778 void
779 xheader_decode_global (struct xheader *xhdr)
780 {
781 if (xhdr->size)
782 {
783 char *p = xhdr->buffer + BLOCKSIZE;
784
785 xheader_list_destroy (&global_header_override_list);
786 while (decode_record (xhdr, &p, decg, &global_header_override_list))
787 continue;
788 }
789 }
790
791 static void
792 xheader_init (struct xheader *xhdr)
793 {
794 if (!xhdr->stk)
795 {
796 xhdr->stk = xmalloc (sizeof *xhdr->stk);
797 obstack_init (xhdr->stk);
798 }
799 }
800
801 void
802 xheader_store (char const *keyword, struct tar_stat_info *st,
803 void const *data)
804 {
805 struct xhdr_tab const *t;
806
807 if (st->xhdr.buffer)
808 return;
809 t = locate_handler (keyword);
810 if (!t || !t->coder)
811 return;
812 if (xheader_keyword_deleted_p (keyword)
813 || xheader_keyword_override_p (keyword))
814 return;
815 xheader_init (&st->xhdr);
816 t->coder (st, keyword, &st->xhdr, data);
817 }
818
819 void
820 xheader_read (struct xheader *xhdr, union block *p, size_t size)
821 {
822 size_t j = 0;
823
824 size += BLOCKSIZE;
825 xhdr->size = size;
826 xhdr->buffer = xmalloc (size + 1);
827 xhdr->buffer[size] = '\0';
828
829 do
830 {
831 size_t len = size;
832
833 if (len > BLOCKSIZE)
834 len = BLOCKSIZE;
835
836 if (!p)
837 FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
838
839 memcpy (&xhdr->buffer[j], p->buffer, len);
840 set_next_block_after (p);
841
842 p = find_next_block ();
843
844 j += len;
845 size -= len;
846 }
847 while (size > 0);
848 }
849
850 /* xattr_encode_keyword() substitutes '=' ~~> '%3D' and '%' ~~> '%25'
851 in extended attribute keywords. This is needed because the '=' character
852 has special purpose in extended attribute header - it splits keyword and
853 value part of header. If there was the '=' occurrence allowed inside
854 keyword, there would be no unambiguous way how to decode this extended
855 attribute.
856
857 (http://lists.gnu.org/archive/html/bug-tar/2012-10/msg00017.html)
858 */
859 static char *
860 xattr_encode_keyword(const char *keyword)
861 {
862 static char *encode_buffer = NULL;
863 static size_t encode_buffer_size = 0;
864 size_t bp; /* keyword/buffer pointers */
865
866 if (!encode_buffer)
867 {
868 encode_buffer_size = 256;
869 encode_buffer = xmalloc (encode_buffer_size);
870 }
871 else
872 *encode_buffer = 0;
873
874 for (bp = 0; *keyword != 0; ++bp, ++keyword)
875 {
876 char c = *keyword;
877
878 if (bp + 2 /* enough for URL encoding also.. */ >= encode_buffer_size)
879 {
880 encode_buffer = x2realloc (encode_buffer, &encode_buffer_size);
881 }
882
883 if (c == '%')
884 {
885 strcpy (encode_buffer + bp, "%25");
886 bp += 2;
887 }
888 else if (c == '=')
889 {
890 strcpy (encode_buffer + bp, "%3D");
891 bp += 2;
892 }
893 else
894 encode_buffer[bp] = c;
895 }
896
897 encode_buffer[bp] = 0;
898
899 return encode_buffer;
900 }
901
902 static void
903 xheader_print_n (struct xheader *xhdr, char const *keyword,
904 char const *value, size_t vsize)
905 {
906 size_t p;
907 size_t n = 0;
908 char nbuf[UINTMAX_STRSIZE_BOUND];
909 char const *np;
910 size_t len, klen;
911
912 keyword = xattr_encode_keyword (keyword);
913 klen = strlen (keyword);
914 len = klen + vsize + 3; /* ' ' + '=' + '\n' */
915
916 do
917 {
918 p = n;
919 np = umaxtostr (len + p, nbuf);
920 n = nbuf + sizeof nbuf - 1 - np;
921 }
922 while (n != p);
923
924 x_obstack_grow (xhdr, np, n);
925 x_obstack_1grow (xhdr, ' ');
926 x_obstack_grow (xhdr, keyword, klen);
927 x_obstack_1grow (xhdr, '=');
928 x_obstack_grow (xhdr, value, vsize);
929 x_obstack_1grow (xhdr, '\n');
930 }
931
932 static void
933 xheader_print (struct xheader *xhdr, char const *keyword, char const *value)
934 {
935 xheader_print_n (xhdr, keyword, value, strlen (value));
936 }
937
938 void
939 xheader_finish (struct xheader *xhdr)
940 {
941 struct keyword_list *kp;
942
943 for (kp = keyword_override_list; kp; kp = kp->next)
944 code_string (kp->value, kp->pattern, xhdr);
945
946 xhdr->buffer = obstack_finish (xhdr->stk);
947 }
948
949 void
950 xheader_destroy (struct xheader *xhdr)
951 {
952 if (xhdr->stk)
953 {
954 obstack_free (xhdr->stk, NULL);
955 free (xhdr->stk);
956 xhdr->stk = NULL;
957 }
958 else
959 free (xhdr->buffer);
960 xhdr->buffer = 0;
961 xhdr->size = 0;
962 }
963
964 \f
965 /* Buildable strings */
966
967 void
968 xheader_string_begin (struct xheader *xhdr)
969 {
970 xhdr->string_length = 0;
971 }
972
973 void
974 xheader_string_add (struct xheader *xhdr, char const *s)
975 {
976 if (xhdr->buffer)
977 return;
978 xheader_init (xhdr);
979 xhdr->string_length += strlen (s);
980 x_obstack_grow (xhdr, s, strlen (s));
981 }
982
983 bool
984 xheader_string_end (struct xheader *xhdr, char const *keyword)
985 {
986 uintmax_t len;
987 uintmax_t p;
988 uintmax_t n = 0;
989 size_t size;
990 char nbuf[UINTMAX_STRSIZE_BOUND];
991 char const *np;
992 char *cp;
993
994 if (xhdr->buffer)
995 return false;
996 xheader_init (xhdr);
997
998 len = strlen (keyword) + xhdr->string_length + 3; /* ' ' + '=' + '\n' */
999
1000 do
1001 {
1002 p = n;
1003 np = umaxtostr (len + p, nbuf);
1004 n = nbuf + sizeof nbuf - 1 - np;
1005 }
1006 while (n != p);
1007
1008 p = strlen (keyword) + n + 2;
1009 size = p;
1010 if (size != p)
1011 {
1012 ERROR ((0, 0,
1013 _("Generated keyword/value pair is too long (keyword=%s, length=%s)"),
1014 keyword, nbuf));
1015 obstack_free (xhdr->stk, obstack_finish (xhdr->stk));
1016 return false;
1017 }
1018 x_obstack_blank (xhdr, p);
1019 x_obstack_1grow (xhdr, '\n');
1020 cp = obstack_next_free (xhdr->stk) - xhdr->string_length - p - 1;
1021 memmove (cp + p, cp, xhdr->string_length);
1022 cp = stpcpy (cp, np);
1023 *cp++ = ' ';
1024 cp = stpcpy (cp, keyword);
1025 *cp++ = '=';
1026 return true;
1027 }
1028
1029 \f
1030 /* Implementations */
1031
1032 static void
1033 out_of_range_header (char const *keyword, char const *value,
1034 uintmax_t minus_minval, uintmax_t maxval)
1035 {
1036 char minval_buf[UINTMAX_STRSIZE_BOUND + 1];
1037 char maxval_buf[UINTMAX_STRSIZE_BOUND];
1038 char *minval_string = umaxtostr (minus_minval, minval_buf + 1);
1039 char *maxval_string = umaxtostr (maxval, maxval_buf);
1040 if (minus_minval)
1041 *--minval_string = '-';
1042
1043 /* TRANSLATORS: The first %s is the pax extended header keyword
1044 (atime, gid, etc.). */
1045 ERROR ((0, 0, _("Extended header %s=%s is out of range %s..%s"),
1046 keyword, value, minval_string, maxval_string));
1047 }
1048
1049 static void
1050 code_string (char const *string, char const *keyword, struct xheader *xhdr)
1051 {
1052 char *outstr;
1053 if (!utf8_convert (true, string, &outstr))
1054 {
1055 /* FIXME: report error */
1056 outstr = xstrdup (string);
1057 }
1058 xheader_print (xhdr, keyword, outstr);
1059 free (outstr);
1060 }
1061
1062 static void
1063 decode_string (char **string, char const *arg)
1064 {
1065 if (*string)
1066 {
1067 free (*string);
1068 *string = NULL;
1069 }
1070 if (!utf8_convert (false, arg, string))
1071 {
1072 /* FIXME: report error and act accordingly to --pax invalid=UTF-8 */
1073 assign_string (string, arg);
1074 }
1075 }
1076
1077 static void
1078 code_time (struct timespec t, char const *keyword, struct xheader *xhdr)
1079 {
1080 char buf[TIMESPEC_STRSIZE_BOUND];
1081 xheader_print (xhdr, keyword, code_timespec (t, buf));
1082 }
1083
1084 enum decode_time_status
1085 {
1086 decode_time_success,
1087 decode_time_range,
1088 decode_time_bad_header
1089 };
1090
1091 static enum decode_time_status
1092 _decode_time (struct timespec *ts, char const *arg, char const *keyword)
1093 {
1094 time_t s;
1095 unsigned long int ns = 0;
1096 char *p;
1097 char *arg_lim;
1098 bool negative = *arg == '-';
1099
1100 errno = 0;
1101
1102 if (ISDIGIT (arg[negative]))
1103 {
1104 if (negative)
1105 {
1106 intmax_t i = strtoimax (arg, &arg_lim, 10);
1107 if (TYPE_SIGNED (time_t) ? i < TYPE_MINIMUM (time_t) : i < 0)
1108 return decode_time_range;
1109 s = i;
1110 }
1111 else
1112 {
1113 uintmax_t i = strtoumax (arg, &arg_lim, 10);
1114 if (TYPE_MAXIMUM (time_t) < i)
1115 return decode_time_range;
1116 s = i;
1117 }
1118
1119 p = arg_lim;
1120
1121 if (errno == ERANGE)
1122 return decode_time_range;
1123
1124 if (*p == '.')
1125 {
1126 int digits = 0;
1127 bool trailing_nonzero = false;
1128
1129 while (ISDIGIT (*++p))
1130 if (digits < LOG10_BILLION)
1131 {
1132 ns = 10 * ns + (*p - '0');
1133 digits++;
1134 }
1135 else
1136 trailing_nonzero |= *p != '0';
1137
1138 while (digits++ < LOG10_BILLION)
1139 ns *= 10;
1140
1141 if (negative)
1142 {
1143 /* Convert "-1.10000000000001" to s == -2, ns == 89999999.
1144 I.e., truncate time stamps towards minus infinity while
1145 converting them to internal form. */
1146 ns += trailing_nonzero;
1147 if (ns != 0)
1148 {
1149 if (s == TYPE_MINIMUM (time_t))
1150 return decode_time_range;
1151 s--;
1152 ns = BILLION - ns;
1153 }
1154 }
1155 }
1156
1157 if (! *p)
1158 {
1159 ts->tv_sec = s;
1160 ts->tv_nsec = ns;
1161 return decode_time_success;
1162 }
1163 }
1164
1165 return decode_time_bad_header;
1166 }
1167
1168 static bool
1169 decode_time (struct timespec *ts, char const *arg, char const *keyword)
1170 {
1171 switch (_decode_time (ts, arg, keyword))
1172 {
1173 case decode_time_success:
1174 return true;
1175 case decode_time_bad_header:
1176 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
1177 keyword, arg));
1178 return false;
1179 case decode_time_range:
1180 out_of_range_header (keyword, arg, - (uintmax_t) TYPE_MINIMUM (time_t),
1181 TYPE_MAXIMUM (time_t));
1182 return false;
1183 }
1184 return true;
1185 }
1186
1187 static void
1188 code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
1189 {
1190 char sbuf[UINTMAX_STRSIZE_BOUND];
1191 xheader_print (xhdr, keyword, umaxtostr (value, sbuf));
1192 }
1193
1194 static bool
1195 decode_num (uintmax_t *num, char const *arg, uintmax_t maxval,
1196 char const *keyword)
1197 {
1198 uintmax_t u;
1199 char *arg_lim;
1200
1201 if (! (ISDIGIT (*arg)
1202 && (errno = 0, u = strtoumax (arg, &arg_lim, 10), !*arg_lim)))
1203 {
1204 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
1205 keyword, arg));
1206 return false;
1207 }
1208
1209 if (! (u <= maxval && errno != ERANGE))
1210 {
1211 out_of_range_header (keyword, arg, 0, maxval);
1212 return false;
1213 }
1214
1215 *num = u;
1216 return true;
1217 }
1218
1219 static void
1220 dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)),
1221 char const *keyword __attribute__ ((unused)),
1222 struct xheader *xhdr __attribute__ ((unused)),
1223 void const *data __attribute__ ((unused)))
1224 {
1225 }
1226
1227 static void
1228 dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)),
1229 char const *keyword __attribute__ ((unused)),
1230 char const *arg __attribute__ ((unused)),
1231 size_t size __attribute__((unused)))
1232 {
1233 }
1234
1235 static void
1236 atime_coder (struct tar_stat_info const *st, char const *keyword,
1237 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1238 {
1239 code_time (st->atime, keyword, xhdr);
1240 }
1241
1242 static void
1243 atime_decoder (struct tar_stat_info *st,
1244 char const *keyword,
1245 char const *arg,
1246 size_t size __attribute__((unused)))
1247 {
1248 struct timespec ts;
1249 if (decode_time (&ts, arg, keyword))
1250 st->atime = ts;
1251 }
1252
1253 static void
1254 gid_coder (struct tar_stat_info const *st, char const *keyword,
1255 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1256 {
1257 code_num (st->stat.st_gid, keyword, xhdr);
1258 }
1259
1260 static void
1261 gid_decoder (struct tar_stat_info *st,
1262 char const *keyword,
1263 char const *arg,
1264 size_t size __attribute__((unused)))
1265 {
1266 uintmax_t u;
1267 if (decode_num (&u, arg, TYPE_MAXIMUM (gid_t), keyword))
1268 st->stat.st_gid = u;
1269 }
1270
1271 static void
1272 gname_coder (struct tar_stat_info const *st, char const *keyword,
1273 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1274 {
1275 code_string (st->gname, keyword, xhdr);
1276 }
1277
1278 static void
1279 gname_decoder (struct tar_stat_info *st,
1280 char const *keyword __attribute__((unused)),
1281 char const *arg,
1282 size_t size __attribute__((unused)))
1283 {
1284 decode_string (&st->gname, arg);
1285 }
1286
1287 static void
1288 linkpath_coder (struct tar_stat_info const *st, char const *keyword,
1289 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1290 {
1291 code_string (st->link_name, keyword, xhdr);
1292 }
1293
1294 static void
1295 linkpath_decoder (struct tar_stat_info *st,
1296 char const *keyword __attribute__((unused)),
1297 char const *arg,
1298 size_t size __attribute__((unused)))
1299 {
1300 decode_string (&st->link_name, arg);
1301 }
1302
1303 static void
1304 ctime_coder (struct tar_stat_info const *st, char const *keyword,
1305 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1306 {
1307 code_time (st->ctime, keyword, xhdr);
1308 }
1309
1310 static void
1311 ctime_decoder (struct tar_stat_info *st,
1312 char const *keyword,
1313 char const *arg,
1314 size_t size __attribute__((unused)))
1315 {
1316 struct timespec ts;
1317 if (decode_time (&ts, arg, keyword))
1318 st->ctime = ts;
1319 }
1320
1321 static void
1322 mtime_coder (struct tar_stat_info const *st, char const *keyword,
1323 struct xheader *xhdr, void const *data)
1324 {
1325 struct timespec const *mtime = data;
1326 code_time (mtime ? *mtime : st->mtime, keyword, xhdr);
1327 }
1328
1329 static void
1330 mtime_decoder (struct tar_stat_info *st,
1331 char const *keyword,
1332 char const *arg,
1333 size_t size __attribute__((unused)))
1334 {
1335 struct timespec ts;
1336 if (decode_time (&ts, arg, keyword))
1337 st->mtime = ts;
1338 }
1339
1340 static void
1341 path_coder (struct tar_stat_info const *st, char const *keyword,
1342 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1343 {
1344 code_string (st->file_name, keyword, xhdr);
1345 }
1346
1347 static void
1348 path_decoder (struct tar_stat_info *st,
1349 char const *keyword __attribute__((unused)),
1350 char const *arg,
1351 size_t size __attribute__((unused)))
1352 {
1353 decode_string (&st->orig_file_name, arg);
1354 decode_string (&st->file_name, arg);
1355 st->had_trailing_slash = strip_trailing_slashes (st->file_name);
1356 }
1357
1358 static void
1359 size_coder (struct tar_stat_info const *st, char const *keyword,
1360 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1361 {
1362 code_num (st->stat.st_size, keyword, xhdr);
1363 }
1364
1365 static void
1366 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 st->stat.st_size = u;
1374 }
1375
1376 static void
1377 uid_coder (struct tar_stat_info const *st, char const *keyword,
1378 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1379 {
1380 code_num (st->stat.st_uid, keyword, xhdr);
1381 }
1382
1383 static void
1384 uid_decoder (struct tar_stat_info *st,
1385 char const *keyword,
1386 char const *arg,
1387 size_t size __attribute__((unused)))
1388 {
1389 uintmax_t u;
1390 if (decode_num (&u, arg, TYPE_MAXIMUM (uid_t), keyword))
1391 st->stat.st_uid = u;
1392 }
1393
1394 static void
1395 uname_coder (struct tar_stat_info const *st, char const *keyword,
1396 struct xheader *xhdr, void const *data __attribute__ ((unused)))
1397 {
1398 code_string (st->uname, keyword, xhdr);
1399 }
1400
1401 static void
1402 uname_decoder (struct tar_stat_info *st,
1403 char const *keyword __attribute__((unused)),
1404 char const *arg,
1405 size_t size __attribute__((unused)))
1406 {
1407 decode_string (&st->uname, arg);
1408 }
1409
1410 static void
1411 sparse_size_coder (struct tar_stat_info const *st, char const *keyword,
1412 struct xheader *xhdr, void const *data)
1413 {
1414 size_coder (st, keyword, xhdr, data);
1415 }
1416
1417 static void
1418 sparse_size_decoder (struct tar_stat_info *st,
1419 char const *keyword,
1420 char const *arg,
1421 size_t size __attribute__((unused)))
1422 {
1423 uintmax_t u;
1424 if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
1425 st->stat.st_size = u;
1426 }
1427
1428 static void
1429 sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword,
1430 struct xheader *xhdr,
1431 void const *data __attribute__ ((unused)))
1432 {
1433 code_num (st->sparse_map_avail, keyword, xhdr);
1434 }
1435
1436 static void
1437 sparse_numblocks_decoder (struct tar_stat_info *st,
1438 char const *keyword,
1439 char const *arg,
1440 size_t size __attribute__((unused)))
1441 {
1442 uintmax_t u;
1443 if (decode_num (&u, arg, SIZE_MAX, keyword))
1444 {
1445 st->sparse_map_size = u;
1446 st->sparse_map = xcalloc (u, sizeof st->sparse_map[0]);
1447 st->sparse_map_avail = 0;
1448 }
1449 }
1450
1451 static void
1452 sparse_offset_coder (struct tar_stat_info const *st, char const *keyword,
1453 struct xheader *xhdr, void const *data)
1454 {
1455 size_t const *pi = data;
1456 code_num (st->sparse_map[*pi].offset, keyword, xhdr);
1457 }
1458
1459 static void
1460 sparse_offset_decoder (struct tar_stat_info *st,
1461 char const *keyword,
1462 char const *arg,
1463 size_t size __attribute__((unused)))
1464 {
1465 uintmax_t u;
1466 if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
1467 {
1468 if (st->sparse_map_avail < st->sparse_map_size)
1469 st->sparse_map[st->sparse_map_avail].offset = u;
1470 else
1471 ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
1472 "GNU.sparse.offset", arg));
1473 }
1474 }
1475
1476 static void
1477 sparse_numbytes_coder (struct tar_stat_info const *st, char const *keyword,
1478 struct xheader *xhdr, void const *data)
1479 {
1480 size_t const *pi = data;
1481 code_num (st->sparse_map[*pi].numbytes, keyword, xhdr);
1482 }
1483
1484 static void
1485 sparse_numbytes_decoder (struct tar_stat_info *st,
1486 char const *keyword,
1487 char const *arg,
1488 size_t size __attribute__((unused)))
1489 {
1490 uintmax_t u;
1491 if (decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
1492 {
1493 if (st->sparse_map_avail < st->sparse_map_size)
1494 st->sparse_map[st->sparse_map_avail++].numbytes = u;
1495 else
1496 ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
1497 keyword, arg));
1498 }
1499 }
1500
1501 static void
1502 sparse_map_decoder (struct tar_stat_info *st,
1503 char const *keyword,
1504 char const *arg,
1505 size_t size __attribute__((unused)))
1506 {
1507 int offset = 1;
1508
1509 st->sparse_map_avail = 0;
1510 while (1)
1511 {
1512 uintmax_t u;
1513 char *delim;
1514 struct sp_array e;
1515
1516 if (!ISDIGIT (*arg))
1517 {
1518 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
1519 keyword, arg));
1520 return;
1521 }
1522
1523 errno = 0;
1524 u = strtoumax (arg, &delim, 10);
1525 if (offset)
1526 {
1527 e.offset = u;
1528 if (!(u == e.offset && errno != ERANGE))
1529 {
1530 out_of_range_header (keyword, arg, 0, TYPE_MAXIMUM (off_t));
1531 return;
1532 }
1533 }
1534 else
1535 {
1536 e.numbytes = u;
1537 if (!(u == e.numbytes && errno != ERANGE))
1538 {
1539 out_of_range_header (keyword, arg, 0, TYPE_MAXIMUM (off_t));
1540 return;
1541 }
1542 if (st->sparse_map_avail < st->sparse_map_size)
1543 st->sparse_map[st->sparse_map_avail++] = e;
1544 else
1545 {
1546 ERROR ((0, 0, _("Malformed extended header: excess %s=%s"),
1547 keyword, arg));
1548 return;
1549 }
1550 }
1551
1552 offset = !offset;
1553
1554 if (*delim == 0)
1555 break;
1556 else if (*delim != ',')
1557 {
1558 ERROR ((0, 0,
1559 _("Malformed extended header: invalid %s: unexpected delimiter %c"),
1560 keyword, *delim));
1561 return;
1562 }
1563
1564 arg = delim + 1;
1565 }
1566
1567 if (!offset)
1568 ERROR ((0, 0,
1569 _("Malformed extended header: invalid %s: odd number of values"),
1570 keyword));
1571 }
1572
1573 static void
1574 dumpdir_coder (struct tar_stat_info const *st, char const *keyword,
1575 struct xheader *xhdr, void const *data)
1576 {
1577 xheader_print_n (xhdr, keyword, data, dumpdir_size (data));
1578 }
1579
1580 static void
1581 dumpdir_decoder (struct tar_stat_info *st,
1582 char const *keyword __attribute__((unused)),
1583 char const *arg,
1584 size_t size)
1585 {
1586 st->dumpdir = xmalloc (size);
1587 memcpy (st->dumpdir, arg, size);
1588 }
1589
1590 static void
1591 volume_label_coder (struct tar_stat_info const *st, char const *keyword,
1592 struct xheader *xhdr, void const *data)
1593 {
1594 code_string (data, keyword, xhdr);
1595 }
1596
1597 static void
1598 volume_label_decoder (struct tar_stat_info *st,
1599 char const *keyword __attribute__((unused)),
1600 char const *arg,
1601 size_t size __attribute__((unused)))
1602 {
1603 decode_string (&volume_label, arg);
1604 }
1605
1606 static void
1607 volume_size_coder (struct tar_stat_info const *st, char const *keyword,
1608 struct xheader *xhdr, void const *data)
1609 {
1610 off_t const *v = data;
1611 code_num (*v, keyword, xhdr);
1612 }
1613
1614 static void
1615 volume_size_decoder (struct tar_stat_info *st,
1616 char const *keyword,
1617 char const *arg, size_t size)
1618 {
1619 uintmax_t u;
1620 if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
1621 continued_file_size = u;
1622 }
1623
1624 /* FIXME: Merge with volume_size_coder */
1625 static void
1626 volume_offset_coder (struct tar_stat_info const *st, char const *keyword,
1627 struct xheader *xhdr, void const *data)
1628 {
1629 off_t const *v = data;
1630 code_num (*v, keyword, xhdr);
1631 }
1632
1633 static void
1634 volume_offset_decoder (struct tar_stat_info *st,
1635 char const *keyword,
1636 char const *arg, size_t size)
1637 {
1638 uintmax_t u;
1639 if (decode_num (&u, arg, TYPE_MAXIMUM (uintmax_t), keyword))
1640 continued_file_offset = u;
1641 }
1642
1643 static void
1644 volume_filename_decoder (struct tar_stat_info *st,
1645 char const *keyword __attribute__((unused)),
1646 char const *arg,
1647 size_t size __attribute__((unused)))
1648 {
1649 decode_string (&continued_file_name, arg);
1650 }
1651
1652 static void
1653 xattr_selinux_coder (struct tar_stat_info const *st, char const *keyword,
1654 struct xheader *xhdr, void const *data)
1655 {
1656 code_string (st->cntx_name, keyword, xhdr);
1657 }
1658
1659 static void
1660 xattr_selinux_decoder (struct tar_stat_info *st,
1661 char const *keyword, char const *arg, size_t size)
1662 {
1663 decode_string (&st->cntx_name, arg);
1664 }
1665
1666 static void
1667 xattr_acls_a_coder (struct tar_stat_info const *st , char const *keyword,
1668 struct xheader *xhdr, void const *data)
1669 {
1670 xheader_print_n (xhdr, keyword, st->acls_a_ptr, st->acls_a_len);
1671 }
1672
1673 static void
1674 xattr_acls_a_decoder (struct tar_stat_info *st,
1675 char const *keyword, char const *arg, size_t size)
1676 {
1677 st->acls_a_ptr = xmemdup (arg, size + 1);
1678 st->acls_a_len = size;
1679 }
1680
1681 static void
1682 xattr_acls_d_coder (struct tar_stat_info const *st , char const *keyword,
1683 struct xheader *xhdr, void const *data)
1684 {
1685 xheader_print_n (xhdr, keyword, st->acls_d_ptr, st->acls_d_len);
1686 }
1687
1688 static void
1689 xattr_acls_d_decoder (struct tar_stat_info *st,
1690 char const *keyword, char const *arg, size_t size)
1691 {
1692 st->acls_d_ptr = xmemdup (arg, size + 1);
1693 st->acls_d_len = size;
1694 }
1695
1696 static void
1697 xattr_coder (struct tar_stat_info const *st, char const *keyword,
1698 struct xheader *xhdr, void const *data)
1699 {
1700 struct xattr_array *xattr_map = st->xattr_map;
1701 const size_t *off = data;
1702 xheader_print_n (xhdr, keyword,
1703 xattr_map[*off].xval_ptr, xattr_map[*off].xval_len);
1704 }
1705
1706 static void
1707 xattr_decoder (struct tar_stat_info *st,
1708 char const *keyword, char const *arg, size_t size)
1709 {
1710 char *xstr, *xkey;
1711
1712 /* copy keyword */
1713 size_t klen_raw = strlen (keyword);
1714 xkey = alloca (klen_raw + 1);
1715 memcpy (xkey, keyword, klen_raw + 1) /* including null-terminating */;
1716
1717 /* copy value */
1718 xstr = alloca (size + 1);
1719 memcpy (xstr, arg, size + 1); /* separator included, for GNU tar '\n' */;
1720
1721 xattr_decode_keyword (xkey);
1722
1723 xheader_xattr_add (st, xkey + strlen("SCHILY.xattr."), xstr, size);
1724 }
1725
1726 static void
1727 sparse_major_coder (struct tar_stat_info const *st, char const *keyword,
1728 struct xheader *xhdr, void const *data)
1729 {
1730 code_num (st->sparse_major, keyword, xhdr);
1731 }
1732
1733 static void
1734 sparse_major_decoder (struct tar_stat_info *st,
1735 char const *keyword,
1736 char const *arg,
1737 size_t size)
1738 {
1739 uintmax_t u;
1740 if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
1741 st->sparse_major = u;
1742 }
1743
1744 static void
1745 sparse_minor_coder (struct tar_stat_info const *st, char const *keyword,
1746 struct xheader *xhdr, void const *data)
1747 {
1748 code_num (st->sparse_minor, keyword, xhdr);
1749 }
1750
1751 static void
1752 sparse_minor_decoder (struct tar_stat_info *st,
1753 char const *keyword,
1754 char const *arg,
1755 size_t size)
1756 {
1757 uintmax_t u;
1758 if (decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
1759 st->sparse_minor = u;
1760 }
1761
1762 struct xhdr_tab const xhdr_tab[] = {
1763 { "atime", atime_coder, atime_decoder, 0, false },
1764 { "comment", dummy_coder, dummy_decoder, 0, false },
1765 { "charset", dummy_coder, dummy_decoder, 0, false },
1766 { "ctime", ctime_coder, ctime_decoder, 0, false },
1767 { "gid", gid_coder, gid_decoder, 0, false },
1768 { "gname", gname_coder, gname_decoder, 0, false },
1769 { "linkpath", linkpath_coder, linkpath_decoder, 0, false },
1770 { "mtime", mtime_coder, mtime_decoder, 0, false },
1771 { "path", path_coder, path_decoder, 0, false },
1772 { "size", size_coder, size_decoder, 0, false },
1773 { "uid", uid_coder, uid_decoder, 0, false },
1774 { "uname", uname_coder, uname_decoder, 0, false },
1775
1776 /* Sparse file handling */
1777 { "GNU.sparse.name", path_coder, path_decoder,
1778 XHDR_PROTECTED, false },
1779 { "GNU.sparse.major", sparse_major_coder, sparse_major_decoder,
1780 XHDR_PROTECTED, false },
1781 { "GNU.sparse.minor", sparse_minor_coder, sparse_minor_decoder,
1782 XHDR_PROTECTED, false },
1783 { "GNU.sparse.realsize", sparse_size_coder, sparse_size_decoder,
1784 XHDR_PROTECTED, false },
1785 { "GNU.sparse.numblocks", sparse_numblocks_coder, sparse_numblocks_decoder,
1786 XHDR_PROTECTED, false },
1787
1788 /* tar 1.14 - 1.15.90 keywords. */
1789 { "GNU.sparse.size", sparse_size_coder, sparse_size_decoder,
1790 XHDR_PROTECTED, false },
1791 /* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
1792 headers, and each of them was meaningful. It confilcted with POSIX specs,
1793 which requires that "when extended header records conflict, the last one
1794 given in the header shall take precedence." */
1795 { "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder,
1796 XHDR_PROTECTED, false },
1797 { "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder,
1798 XHDR_PROTECTED, false },
1799 /* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
1800 { "GNU.sparse.map", NULL /* Unused, see pax_dump_header() */,
1801 sparse_map_decoder, 0, false },
1802
1803 { "GNU.dumpdir", dumpdir_coder, dumpdir_decoder,
1804 XHDR_PROTECTED, false },
1805
1806 /* Keeps the tape/volume label. May be present only in the global headers.
1807 Equivalent to GNUTYPE_VOLHDR. */
1808 { "GNU.volume.label", volume_label_coder, volume_label_decoder,
1809 XHDR_PROTECTED | XHDR_GLOBAL, false },
1810
1811 /* These may be present in a first global header of the archive.
1812 They provide the same functionality as GNUTYPE_MULTIVOL header.
1813 The GNU.volume.size keeps the real_s_sizeleft value, which is
1814 otherwise kept in the size field of a multivolume header. The
1815 GNU.volume.offset keeps the offset of the start of this volume,
1816 otherwise kept in oldgnu_header.offset. */
1817 { "GNU.volume.filename", volume_label_coder, volume_filename_decoder,
1818 XHDR_PROTECTED | XHDR_GLOBAL, false },
1819 { "GNU.volume.size", volume_size_coder, volume_size_decoder,
1820 XHDR_PROTECTED | XHDR_GLOBAL, false },
1821 { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder,
1822 XHDR_PROTECTED | XHDR_GLOBAL, false },
1823
1824 /* We get the SELinux value from filecon, so add a namespace for SELinux
1825 instead of storing it in SCHILY.xattr.* (which would be RAW). */
1826 { "RHT.security.selinux",
1827 xattr_selinux_coder, xattr_selinux_decoder, 0, false },
1828
1829 /* ACLs, use the star format... */
1830 { "SCHILY.acl.access",
1831 xattr_acls_a_coder, xattr_acls_a_decoder, 0, false },
1832
1833 { "SCHILY.acl.default",
1834 xattr_acls_d_coder, xattr_acls_d_decoder, 0, false },
1835
1836 /* We are storing all extended attributes using this rule even if some of them
1837 were stored by some previous rule (duplicates) -- we just have to make sure
1838 they are restored *only once* during extraction later on. */
1839 { "SCHILY.xattr", xattr_coder, xattr_decoder, 0, true },
1840
1841 { NULL, NULL, NULL, 0, false }
1842 };
This page took 0.115655 seconds and 5 git commands to generate.