]> Dogcows Code - chaz/tar/blob - src/xheader.c
Allow to store/extract '=' character in xattr keyword
[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 xheader_xattr_init (struct tar_stat_info *st)
464 {
465 st->xattr_map = NULL;
466 st->xattr_map_size = 0;
467
468 st->acls_a_ptr = NULL;
469 st->acls_a_len = 0;
470 st->acls_d_ptr = NULL;
471 st->acls_d_len = 0;
472 st->cntx_name = NULL;
473 }
474
475 void xheader_xattr_free (struct xattr_array *xattr_map, size_t xattr_map_size)
476 {
477 size_t scan = 0;
478
479 while (scan < xattr_map_size)
480 {
481 free (xattr_map[scan].xkey);
482 free (xattr_map[scan].xval_ptr);
483
484 ++scan;
485 }
486 free (xattr_map);
487 }
488
489 static void 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 xheader_xattr_add(struct tar_stat_info *st,
541 const char *key, const char *val, size_t len)
542 {
543 size_t klen = strlen (key);
544 char *xkey = xmalloc (strlen("SCHILY.xattr.") + klen + 1);
545 char *tmp = xkey;
546
547 tmp = stpcpy (tmp, "SCHILY.xattr.");
548 stpcpy (tmp, key);
549
550 xheader_xattr__add (&st->xattr_map, &st->xattr_map_size, xkey, val, len);
551
552 free (xkey);
553 }
554
555 void xheader_xattr_copy(const struct tar_stat_info *st,
556 struct xattr_array **xattr_map, size_t *xattr_map_size)
557 {
558 size_t scan = 0;
559
560 *xattr_map = NULL;
561 *xattr_map_size = 0;
562
563 while (scan < st->xattr_map_size)
564 {
565 char *key = st->xattr_map[scan].xkey;
566 char *val = st->xattr_map[scan].xval_ptr;
567 size_t len = st->xattr_map[scan].xval_len;
568
569 xheader_xattr__add(xattr_map, xattr_map_size, key, val, len);
570
571 ++scan;
572 }
573 }
574
575 \f
576 /* General Interface */
577
578 #define XHDR_PROTECTED 0x01
579 #define XHDR_GLOBAL 0x02
580
581 struct xhdr_tab
582 {
583 char const *keyword;
584 void (*coder) (struct tar_stat_info const *, char const *,
585 struct xheader *, void const *data);
586 void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);
587 int flags;
588 bool prefix; /* select handler comparing prefix only */
589 };
590
591 /* This declaration must be extern, because ISO C99 section 6.9.2
592 prohibits a tentative definition that has both internal linkage and
593 incomplete type. If we made it static, we'd have to declare its
594 size which would be a maintenance pain; if we put its initializer
595 here, we'd need a boatload of forward declarations, which would be
596 even more of a pain. */
597 extern struct xhdr_tab const xhdr_tab[];
598
599 static struct xhdr_tab const *
600 locate_handler (char const *keyword)
601 {
602 struct xhdr_tab const *p;
603
604 for (p = xhdr_tab; p->keyword; p++)
605 if (p->prefix)
606 {
607 if (strncmp (p->keyword, keyword, strlen(p->keyword)) == 0)
608 return p;
609 }
610 else
611 {
612 if (strcmp (p->keyword, keyword) == 0)
613 return p;
614 }
615
616 return NULL;
617 }
618
619 static bool
620 xheader_protected_pattern_p (const char *pattern)
621 {
622 struct xhdr_tab const *p;
623
624 for (p = xhdr_tab; p->keyword; p++)
625 if (!p->prefix && (p->flags & XHDR_PROTECTED)
626 && fnmatch (pattern, p->keyword, 0) == 0)
627 return true;
628 return false;
629 }
630
631 static bool
632 xheader_protected_keyword_p (const char *keyword)
633 {
634 struct xhdr_tab const *p;
635
636 for (p = xhdr_tab; p->keyword; p++)
637 if (!p->prefix && (p->flags & XHDR_PROTECTED)
638 && strcmp (p->keyword, keyword) == 0)
639 return true;
640 return false;
641 }
642
643 /* Decode a single extended header record, advancing *PTR to the next record.
644 Return true on success, false otherwise. */
645 static bool
646 decode_record (struct xheader *xhdr,
647 char **ptr,
648 void (*handler) (void *, char const *, char const *, size_t),
649 void *data)
650 {
651 char *start = *ptr;
652 char *p = start;
653 uintmax_t u;
654 size_t len;
655 char *len_lim;
656 char const *keyword;
657 char *nextp;
658 size_t len_max = xhdr->buffer + xhdr->size - start;
659
660 while (*p == ' ' || *p == '\t')
661 p++;
662
663 if (! ISDIGIT (*p))
664 {
665 if (*p)
666 ERROR ((0, 0, _("Malformed extended header: missing length")));
667 return false;
668 }
669
670 errno = 0;
671 len = u = strtoumax (p, &len_lim, 10);
672 if (len != u || errno == ERANGE)
673 {
674 ERROR ((0, 0, _("Extended header length is out of allowed range")));
675 return false;
676 }
677
678 if (len_max < len)
679 {
680 int len_len = len_lim - p;
681 ERROR ((0, 0, _("Extended header length %*s is out of range"),
682 len_len, p));
683 return false;
684 }
685
686 nextp = start + len;
687
688 for (p = len_lim; *p == ' ' || *p == '\t'; p++)
689 continue;
690 if (p == len_lim)
691 {
692 ERROR ((0, 0,
693 _("Malformed extended header: missing blank after length")));
694 return false;
695 }
696
697 keyword = p;
698 p = strchr (p, '=');
699 if (! (p && p < nextp))
700 {
701 ERROR ((0, 0, _("Malformed extended header: missing equal sign")));
702 return false;
703 }
704
705 if (nextp[-1] != '\n')
706 {
707 ERROR ((0, 0, _("Malformed extended header: missing newline")));
708 return false;
709 }
710
711 *p = nextp[-1] = '\0';
712 handler (data, keyword, p + 1, nextp - p - 2); /* '=' + trailing '\n' */
713 *p = '=';
714 nextp[-1] = '\n';
715 *ptr = nextp;
716 return true;
717 }
718
719 static void
720 run_override_list (struct keyword_list *kp, struct tar_stat_info *st)
721 {
722 for (; kp; kp = kp->next)
723 {
724 struct xhdr_tab const *t = locate_handler (kp->pattern);
725 if (t)
726 t->decoder (st, t->keyword, kp->value, strlen (kp->value));
727 }
728 }
729
730 static void
731 decx (void *data, char const *keyword, char const *value, size_t size)
732 {
733 struct xhdr_tab const *t;
734 struct tar_stat_info *st = data;
735
736 if (xheader_keyword_deleted_p (keyword)
737 || xheader_keyword_override_p (keyword))
738 return;
739
740 t = locate_handler (keyword);
741 if (t)
742 t->decoder (st, keyword, value, size);
743 else
744 WARNOPT (WARN_UNKNOWN_KEYWORD,
745 (0, 0, _("Ignoring unknown extended header keyword '%s'"),
746 keyword));
747 }
748
749 void
750 xheader_decode (struct tar_stat_info *st)
751 {
752 run_override_list (keyword_global_override_list, st);
753 run_override_list (global_header_override_list, st);
754
755 if (st->xhdr.size)
756 {
757 char *p = st->xhdr.buffer + BLOCKSIZE;
758 while (decode_record (&st->xhdr, &p, decx, st))
759 continue;
760 }
761 run_override_list (keyword_override_list, st);
762 }
763
764 static void
765 decg (void *data, char const *keyword, char const *value,
766 size_t size __attribute__((unused)))
767 {
768 struct keyword_list **kwl = data;
769 struct xhdr_tab const *tab = locate_handler (keyword);
770 if (tab && (tab->flags & XHDR_GLOBAL))
771 tab->decoder (data, keyword, value, size);
772 else
773 xheader_list_append (kwl, keyword, value);
774 }
775
776 void
777 xheader_decode_global (struct xheader *xhdr)
778 {
779 if (xhdr->size)
780 {
781 char *p = xhdr->buffer + BLOCKSIZE;
782
783 xheader_list_destroy (&global_header_override_list);
784 while (decode_record (xhdr, &p, decg, &global_header_override_list))
785 continue;
786 }
787 }
788
789 static void
790 xheader_init (struct xheader *xhdr)
791 {
792 if (!xhdr->stk)
793 {
794 xhdr->stk = xmalloc (sizeof *xhdr->stk);
795 obstack_init (xhdr->stk);
796 }
797 }
798
799 void
800 xheader_store (char const *keyword, struct tar_stat_info *st,
801 void const *data)
802 {
803 struct xhdr_tab const *t;
804
805 if (st->xhdr.buffer)
806 return;
807 t = locate_handler (keyword);
808 if (!t || !t->coder)
809 return;
810 if (xheader_keyword_deleted_p (keyword)
811 || xheader_keyword_override_p (keyword))
812 return;
813 xheader_init (&st->xhdr);
814 t->coder (st, keyword, &st->xhdr, data);
815 }
816
817 void
818 xheader_read (struct xheader *xhdr, union block *p, size_t size)
819 {
820 size_t j = 0;
821
822 size += BLOCKSIZE;
823 xhdr->size = size;
824 xhdr->buffer = xmalloc (size + 1);
825 xhdr->buffer[size] = '\0';
826
827 do
828 {
829 size_t len = size;
830
831 if (len > BLOCKSIZE)
832 len = BLOCKSIZE;
833
834 if (!p)
835 FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
836
837 memcpy (&xhdr->buffer[j], p->buffer, len);
838 set_next_block_after (p);
839
840 p = find_next_block ();
841
842 j += len;
843 size -= len;
844 }
845 while (size > 0);
846 }
847
848 /* xattr_encode_keyword() substitutes '=' ~~> '%3D' and '%' ~~> '%25'
849 in extended attribute keywords. This is needed because the '=' character
850 has special purpose in extended attribute header - it splits keyword and
851 value part of header. If there was the '=' occurrence allowed inside
852 keyword, there would be no unambiguous way how to decode this extended
853 attribute.
854
855 (http://lists.gnu.org/archive/html/bug-tar/2012-10/msg00017.html)
856 */
857 static char *
858 xattr_encode_keyword(const char *keyword)
859 {
860 static char *encode_buffer = NULL;
861 static size_t encode_buffer_size = 0;
862 size_t bp; /* keyword/buffer pointers */
863
864 if (!encode_buffer)
865 {
866 encode_buffer_size = 256;
867 encode_buffer = xmalloc (encode_buffer_size);
868 }
869 else
870 *encode_buffer = 0;
871
872 for (bp = 0; *keyword != 0; ++bp, ++keyword)
873 {
874 char c = *keyword;
875
876 if (bp + 2 /* enough for URL encoding also.. */ >= encode_buffer_size)
877 {
878 encode_buffer = x2realloc (encode_buffer, &encode_buffer_size);
879 }
880
881 if (c == '%')
882 {
883 strcpy (encode_buffer + bp, "%25");
884 bp += 2;
885 }
886 else if (c == '=')
887 {
888 strcpy (encode_buffer + bp, "%3D");
889 bp += 2;
890 }
891 else
892 encode_buffer[bp] = c;
893 }
894
895 encode_buffer[bp] = 0;
896
897 return encode_buffer;
898 }
899
900 static void
901 xheader_print_n (struct xheader *xhdr, char const *keyword,
902 char const *value, size_t vsize)
903 {
904 size_t p;
905 size_t n = 0;
906 char nbuf[UINTMAX_STRSIZE_BOUND];
907 char const *np;
908 size_t len, klen;
909
910 keyword = xattr_encode_keyword (keyword);
911 klen = strlen (keyword);
912 len = klen + vsize + 3; /* ' ' + '=' + '\n' */
913
914 do
915 {
916 p = n;
917 np = umaxtostr (len + p, nbuf);
918 n = nbuf + sizeof nbuf - 1 - np;
919 }
920 while (n != p);
921
922 x_obstack_grow (xhdr, np, n);
923 x_obstack_1grow (xhdr, ' ');
924 x_obstack_grow (xhdr, keyword, klen);
925 x_obstack_1grow (xhdr, '=');
926 x_obstack_grow (xhdr, value, vsize);
927 x_obstack_1grow (xhdr, '\n');
928 }
929
930 static void
931 xheader_print (struct xheader *xhdr, char const *keyword, char const *value)
932 {
933 xheader_print_n (xhdr, keyword, value, strlen (value));
934 }
935
936 void
937 xheader_finish (struct xheader *xhdr)
938 {
939 struct keyword_list *kp;
940
941 for (kp = keyword_override_list; kp; kp = kp->next)
942 code_string (kp->value, kp->pattern, xhdr);
943
944 xhdr->buffer = obstack_finish (xhdr->stk);
945 }
946
947 void
948 xheader_destroy (struct xheader *xhdr)
949 {
950 if (xhdr->stk)
951 {
952 obstack_free (xhdr->stk, NULL);
953 free (xhdr->stk);
954 xhdr->stk = NULL;
955 }
956 else
957 free (xhdr->buffer);
958 xhdr->buffer = 0;
959 xhdr->size = 0;
960 }
961
962 \f
963 /* Buildable strings */
964
965 void
966 xheader_string_begin (struct xheader *xhdr)
967 {
968 xhdr->string_length = 0;
969 }
970
971 void
972 xheader_string_add (struct xheader *xhdr, char const *s)
973 {
974 if (xhdr->buffer)
975 return;
976 xheader_init (xhdr);
977 xhdr->string_length += strlen (s);
978 x_obstack_grow (xhdr, s, strlen (s));
979 }
980
981 bool
982 xheader_string_end (struct xheader *xhdr, char const *keyword)
983 {
984 uintmax_t len;
985 uintmax_t p;
986 uintmax_t n = 0;
987 size_t size;
988 char nbuf[UINTMAX_STRSIZE_BOUND];
989 char const *np;
990 char *cp;
991
992 if (xhdr->buffer)
993 return false;
994 xheader_init (xhdr);
995
996 len = strlen (keyword) + xhdr->string_length + 3; /* ' ' + '=' + '\n' */
997
998 do
999 {
1000 p = n;
1001 np = umaxtostr (len + p, nbuf);
1002 n = nbuf + sizeof nbuf - 1 - np;
1003 }
1004 while (n != p);
1005
1006 p = strlen (keyword) + n + 2;
1007 size = p;
1008 if (size != p)
1009 {
1010 ERROR ((0, 0,
1011 _("Generated keyword/value pair is too long (keyword=%s, length=%s)"),
1012 keyword, nbuf));
1013 obstack_free (xhdr->stk, obstack_finish (xhdr->stk));
1014 return false;
1015 }
1016 x_obstack_blank (xhdr, p);
1017 x_obstack_1grow (xhdr, '\n');
1018 cp = obstack_next_free (xhdr->stk) - xhdr->string_length - p - 1;
1019 memmove (cp + p, cp, xhdr->string_length);
1020 cp = stpcpy (cp, np);
1021 *cp++ = ' ';
1022 cp = stpcpy (cp, keyword);
1023 *cp++ = '=';
1024 return true;
1025 }
1026
1027 \f
1028 /* Implementations */
1029
1030 static void
1031 out_of_range_header (char const *keyword, char const *value,
1032 uintmax_t minus_minval, uintmax_t maxval)
1033 {
1034 char minval_buf[UINTMAX_STRSIZE_BOUND + 1];
1035 char maxval_buf[UINTMAX_STRSIZE_BOUND];
1036 char *minval_string = umaxtostr (minus_minval, minval_buf + 1);
1037 char *maxval_string = umaxtostr (maxval, maxval_buf);
1038 if (minus_minval)
1039 *--minval_string = '-';
1040
1041 /* TRANSLATORS: The first %s is the pax extended header keyword
1042 (atime, gid, etc.). */
1043 ERROR ((0, 0, _("Extended header %s=%s is out of range %s..%s"),
1044 keyword, value, minval_string, maxval_string));
1045 }
1046
1047 static void
1048 code_string (char const *string, char const *keyword, struct xheader *xhdr)
1049 {
1050 char *outstr;
1051 if (!utf8_convert (true, string, &outstr))
1052 {
1053 /* FIXME: report error */
1054 outstr = xstrdup (string);
1055 }
1056 xheader_print (xhdr, keyword, outstr);
1057 free (outstr);
1058 }
1059
1060 static void
1061 decode_string (char **string, char const *arg)
1062 {
1063 if (*string)
1064 {
1065 free (*string);
1066 *string = NULL;
1067 }
1068 if (!utf8_convert (false, arg, string))
1069 {
1070 /* FIXME: report error and act accordingly to --pax invalid=UTF-8 */
1071 assign_string (string, arg);
1072 }
1073 }
1074
1075 static void
1076 code_time (struct timespec t, char const *keyword, struct xheader *xhdr)
1077 {
1078 char buf[TIMESPEC_STRSIZE_BOUND];
1079 xheader_print (xhdr, keyword, code_timespec (t, buf));
1080 }
1081
1082 enum decode_time_status
1083 {
1084 decode_time_success,
1085 decode_time_range,
1086 decode_time_bad_header
1087 };
1088
1089 static enum decode_time_status
1090 _decode_time (struct timespec *ts, char const *arg, char const *keyword)
1091 {
1092 time_t s;
1093 unsigned long int ns = 0;
1094 char *p;
1095 char *arg_lim;
1096 bool negative = *arg == '-';
1097
1098 errno = 0;
1099
1100 if (ISDIGIT (arg[negative]))
1101 {
1102 if (negative)
1103 {
1104 intmax_t i = strtoimax (arg, &arg_lim, 10);
1105 if (TYPE_SIGNED (time_t) ? i < TYPE_MINIMUM (time_t) : i < 0)
1106 return decode_time_range;
1107 s = i;
1108 }
1109 else
1110 {
1111 uintmax_t i = strtoumax (arg, &arg_lim, 10);
1112 if (TYPE_MAXIMUM (time_t) < i)
1113 return decode_time_range;
1114 s = i;
1115 }
1116
1117 p = arg_lim;
1118
1119 if (errno == ERANGE)
1120 return decode_time_range;
1121
1122 if (*p == '.')
1123 {
1124 int digits = 0;
1125 bool trailing_nonzero = false;
1126
1127 while (ISDIGIT (*++p))
1128 if (digits < LOG10_BILLION)
1129 {
1130 ns = 10 * ns + (*p - '0');
1131 digits++;
1132 }
1133 else
1134 trailing_nonzero |= *p != '0';
1135
1136 while (digits++ < LOG10_BILLION)
1137 ns *= 10;
1138
1139 if (negative)
1140 {
1141 /* Convert "-1.10000000000001" to s == -2, ns == 89999999.
1142 I.e., truncate time stamps towards minus infinity while
1143 converting them to internal form. */
1144 ns += trailing_nonzero;
1145 if (ns != 0)
1146 {
1147 if (s == TYPE_MINIMUM (time_t))
1148 return decode_time_range;
1149 s--;
1150 ns = BILLION - ns;
1151 }
1152 }
1153 }
1154
1155 if (! *p)
1156 {
1157 ts->tv_sec = s;
1158 ts->tv_nsec = ns;
1159 return decode_time_success;
1160 }
1161 }
1162
1163 return decode_time_bad_header;
1164 }
1165
1166 static bool
1167 decode_time (struct timespec *ts, char const *arg, char const *keyword)
1168 {
1169 switch (_decode_time (ts, arg, keyword))
1170 {
1171 case decode_time_success:
1172 return true;
1173 case decode_time_bad_header:
1174 ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
1175 keyword, arg));
1176 return false;
1177 case decode_time_range:
1178 out_of_range_header (keyword, arg, - (uintmax_t) TYPE_MINIMUM (time_t),
1179 TYPE_MAXIMUM (time_t));
1180 return false;
1181 }
1182 return true;
1183 }
1184
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.110655 seconds and 5 git commands to generate.