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