]> Dogcows Code - chaz/tar/blob - src/list.c
Make sure transformed file names retain trailing slash in listing.
[chaz/tar] / src / list.c
1 /* List a tar archive, with support routines for reading a tar archive.
2
3 Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2013
4 Free Software Foundation, Inc.
5
6 This file is part of GNU tar.
7
8 GNU tar is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU tar is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20
21 Written by John Gilmore, on 1985-08-26. */
22
23 #include <system.h>
24 #include <inttostr.h>
25 #include <quotearg.h>
26
27 #include "common.h"
28
29 union block *current_header; /* points to current archive header */
30 enum archive_format current_format; /* recognized format */
31 union block *recent_long_name; /* recent long name header and contents */
32 union block *recent_long_link; /* likewise, for long link */
33 size_t recent_long_name_blocks; /* number of blocks in recent_long_name */
34 size_t recent_long_link_blocks; /* likewise, for long link */
35 static union block *recent_global_header; /* Recent global header block */
36
37 #define GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
38 #define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
39 #define MINOR_FROM_HEADER(where) minor_from_header (where, sizeof (where))
40 #define MODE_FROM_HEADER(where, hbits) \
41 mode_from_header (where, sizeof (where), hbits)
42 #define TIME_FROM_HEADER(where) time_from_header (where, sizeof (where))
43 #define UID_FROM_HEADER(where) uid_from_header (where, sizeof (where))
44
45 static gid_t gid_from_header (const char *buf, size_t size);
46 static major_t major_from_header (const char *buf, size_t size);
47 static minor_t minor_from_header (const char *buf, size_t size);
48 static mode_t mode_from_header (const char *buf, size_t size, bool *hbits);
49 static time_t time_from_header (const char *buf, size_t size);
50 static uid_t uid_from_header (const char *buf, size_t size);
51 static intmax_t from_header (const char *, size_t, const char *,
52 intmax_t, uintmax_t, bool, bool);
53
54 /* Base 64 digits; see Internet RFC 2045 Table 1. */
55 static char const base_64_digits[64] =
56 {
57 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
58 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
59 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
60 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
61 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
62 };
63
64 /* Table of base-64 digit values indexed by unsigned chars.
65 The value is 64 for unsigned chars that are not base-64 digits. */
66 static char base64_map[UCHAR_MAX + 1];
67
68 static void
69 base64_init (void)
70 {
71 int i;
72 memset (base64_map, 64, sizeof base64_map);
73 for (i = 0; i < 64; i++)
74 base64_map[(int) base_64_digits[i]] = i;
75 }
76
77 static char *
78 decode_xform (char *file_name, void *data)
79 {
80 int type = *(int*)data;
81
82 switch (type)
83 {
84 case XFORM_SYMLINK:
85 /* FIXME: It is not quite clear how and to which extent are the symbolic
86 links subject to filename transformation. In the absence of another
87 solution, symbolic links are exempt from component stripping and
88 name suffix normalization, but subject to filename transformation
89 proper. */
90 return file_name;
91
92 case XFORM_LINK:
93 file_name = safer_name_suffix (file_name, true, absolute_names_option);
94 break;
95
96 case XFORM_REGFILE:
97 file_name = safer_name_suffix (file_name, false, absolute_names_option);
98 break;
99 }
100
101 if (strip_name_components)
102 {
103 size_t prefix_len = stripped_prefix_len (file_name,
104 strip_name_components);
105 if (prefix_len == (size_t) -1)
106 prefix_len = strlen (file_name);
107 file_name += prefix_len;
108 }
109 return file_name;
110 }
111
112 static bool
113 transform_member_name (char **pinput, int type)
114 {
115 return transform_name_fp (pinput, type, decode_xform, &type);
116 }
117
118 void
119 transform_stat_info (int typeflag, struct tar_stat_info *stat_info)
120 {
121 if (typeflag == GNUTYPE_VOLHDR)
122 /* Name transformations don't apply to volume headers. */
123 return;
124
125 transform_member_name (&stat_info->file_name, XFORM_REGFILE);
126 switch (typeflag)
127 {
128 case SYMTYPE:
129 transform_member_name (&stat_info->link_name, XFORM_SYMLINK);
130 break;
131
132 case LNKTYPE:
133 transform_member_name (&stat_info->link_name, XFORM_LINK);
134 }
135 }
136
137 /* Main loop for reading an archive. */
138 void
139 read_and (void (*do_something) (void))
140 {
141 enum read_header status = HEADER_STILL_UNREAD;
142 enum read_header prev_status;
143 struct timespec mtime;
144
145 base64_init ();
146 name_gather ();
147
148 open_archive (ACCESS_READ);
149 do
150 {
151 prev_status = status;
152 tar_stat_destroy (&current_stat_info);
153
154 status = read_header (&current_header, &current_stat_info,
155 read_header_auto);
156 switch (status)
157 {
158 case HEADER_STILL_UNREAD:
159 case HEADER_SUCCESS_EXTENDED:
160 abort ();
161
162 case HEADER_SUCCESS:
163
164 /* Valid header. We should decode next field (mode) first.
165 Ensure incoming names are null terminated. */
166 decode_header (current_header, &current_stat_info,
167 &current_format, 1);
168 if (! name_match (current_stat_info.file_name)
169 || (NEWER_OPTION_INITIALIZED (newer_mtime_option)
170 /* FIXME: We get mtime now, and again later; this causes
171 duplicate diagnostics if header.mtime is bogus. */
172 && ((mtime.tv_sec
173 = TIME_FROM_HEADER (current_header->header.mtime)),
174 /* FIXME: Grab fractional time stamps from
175 extended header. */
176 mtime.tv_nsec = 0,
177 current_stat_info.mtime = mtime,
178 OLDER_TAR_STAT_TIME (current_stat_info, m)))
179 || excluded_name (current_stat_info.file_name))
180 {
181 switch (current_header->header.typeflag)
182 {
183 case GNUTYPE_VOLHDR:
184 case GNUTYPE_MULTIVOL:
185 break;
186
187 case DIRTYPE:
188 if (show_omitted_dirs_option)
189 WARN ((0, 0, _("%s: Omitting"),
190 quotearg_colon (current_stat_info.file_name)));
191 /* Fall through. */
192 default:
193 skip_member ();
194 continue;
195 }
196 }
197 transform_stat_info (current_header->header.typeflag,
198 &current_stat_info);
199 (*do_something) ();
200 continue;
201
202 case HEADER_ZERO_BLOCK:
203 if (block_number_option)
204 {
205 char buf[UINTMAX_STRSIZE_BOUND];
206 fprintf (stdlis, _("block %s: ** Block of NULs **\n"),
207 STRINGIFY_BIGINT (current_block_ordinal (), buf));
208 }
209
210 set_next_block_after (current_header);
211
212 if (!ignore_zeros_option)
213 {
214 char buf[UINTMAX_STRSIZE_BOUND];
215
216 status = read_header (&current_header, &current_stat_info,
217 read_header_auto);
218 if (status == HEADER_ZERO_BLOCK)
219 break;
220 WARNOPT (WARN_ALONE_ZERO_BLOCK,
221 (0, 0, _("A lone zero block at %s"),
222 STRINGIFY_BIGINT (current_block_ordinal (), buf)));
223 break;
224 }
225 status = prev_status;
226 continue;
227
228 case HEADER_END_OF_FILE:
229 if (block_number_option)
230 {
231 char buf[UINTMAX_STRSIZE_BOUND];
232 fprintf (stdlis, _("block %s: ** End of File **\n"),
233 STRINGIFY_BIGINT (current_block_ordinal (), buf));
234 }
235 break;
236
237 case HEADER_FAILURE:
238 /* If the previous header was good, tell them that we are
239 skipping bad ones. */
240 set_next_block_after (current_header);
241 switch (prev_status)
242 {
243 case HEADER_STILL_UNREAD:
244 ERROR ((0, 0, _("This does not look like a tar archive")));
245 /* Fall through. */
246
247 case HEADER_ZERO_BLOCK:
248 case HEADER_SUCCESS:
249 if (block_number_option)
250 {
251 char buf[UINTMAX_STRSIZE_BOUND];
252 off_t block_ordinal = current_block_ordinal ();
253 block_ordinal -= recent_long_name_blocks;
254 block_ordinal -= recent_long_link_blocks;
255 fprintf (stdlis, _("block %s: "),
256 STRINGIFY_BIGINT (block_ordinal, buf));
257 }
258 ERROR ((0, 0, _("Skipping to next header")));
259 break;
260
261 case HEADER_END_OF_FILE:
262 case HEADER_FAILURE:
263 /* We are in the middle of a cascade of errors. */
264 break;
265
266 case HEADER_SUCCESS_EXTENDED:
267 abort ();
268 }
269 continue;
270 }
271 break;
272 }
273 while (!all_names_found (&current_stat_info));
274
275 close_archive ();
276 names_notfound (); /* print names not found */
277 }
278
279 /* Print a header block, based on tar options. */
280 void
281 list_archive (void)
282 {
283 off_t block_ordinal = current_block_ordinal ();
284
285 /* Print the header block. */
286 if (verbose_option)
287 print_header (&current_stat_info, current_header, block_ordinal);
288
289 if (incremental_option)
290 {
291 if (verbose_option > 2)
292 {
293 if (is_dumpdir (&current_stat_info))
294 list_dumpdir (current_stat_info.dumpdir,
295 dumpdir_size (current_stat_info.dumpdir));
296 }
297 }
298
299 skip_member ();
300 }
301
302 /* Check header checksum */
303 /* The standard BSD tar sources create the checksum by adding up the
304 bytes in the header as type char. I think the type char was unsigned
305 on the PDP-11, but it's signed on the Next and Sun. It looks like the
306 sources to BSD tar were never changed to compute the checksum
307 correctly, so both the Sun and Next add the bytes of the header as
308 signed chars. This doesn't cause a problem until you get a file with
309 a name containing characters with the high bit set. So tar_checksum
310 computes two checksums -- signed and unsigned. */
311
312 enum read_header
313 tar_checksum (union block *header, bool silent)
314 {
315 size_t i;
316 int unsigned_sum = 0; /* the POSIX one :-) */
317 int signed_sum = 0; /* the Sun one :-( */
318 int recorded_sum;
319 int parsed_sum;
320 char *p;
321
322 p = header->buffer;
323 for (i = sizeof *header; i-- != 0;)
324 {
325 unsigned_sum += (unsigned char) *p;
326 signed_sum += (signed char) (*p++);
327 }
328
329 if (unsigned_sum == 0)
330 return HEADER_ZERO_BLOCK;
331
332 /* Adjust checksum to count the "chksum" field as blanks. */
333
334 for (i = sizeof header->header.chksum; i-- != 0;)
335 {
336 unsigned_sum -= (unsigned char) header->header.chksum[i];
337 signed_sum -= (signed char) (header->header.chksum[i]);
338 }
339 unsigned_sum += ' ' * sizeof header->header.chksum;
340 signed_sum += ' ' * sizeof header->header.chksum;
341
342 parsed_sum = from_header (header->header.chksum,
343 sizeof header->header.chksum, 0,
344 0, INT_MAX, true, silent);
345 if (parsed_sum < 0)
346 return HEADER_FAILURE;
347
348 recorded_sum = parsed_sum;
349
350 if (unsigned_sum != recorded_sum && signed_sum != recorded_sum)
351 return HEADER_FAILURE;
352
353 return HEADER_SUCCESS;
354 }
355
356 /* Read a block that's supposed to be a header block. Return its
357 address in *RETURN_BLOCK, and if it is good, the file's size
358 and names (file name, link name) in *INFO.
359
360 Return one of enum read_header describing the status of the
361 operation.
362
363 The MODE parameter instructs read_header what to do with special
364 header blocks, i.e.: extended POSIX, GNU long name or long link,
365 etc.:
366
367 read_header_auto process them automatically,
368 read_header_x_raw when a special header is read, return
369 HEADER_SUCCESS_EXTENDED without actually
370 processing the header,
371 read_header_x_global when a POSIX global header is read,
372 decode it and return HEADER_SUCCESS_EXTENDED.
373
374 You must always set_next_block_after(*return_block) to skip past
375 the header which this routine reads. */
376
377 enum read_header
378 read_header (union block **return_block, struct tar_stat_info *info,
379 enum read_header_mode mode)
380 {
381 union block *header;
382 union block *header_copy;
383 char *bp;
384 union block *data_block;
385 size_t size, written;
386 union block *next_long_name = 0;
387 union block *next_long_link = 0;
388 size_t next_long_name_blocks = 0;
389 size_t next_long_link_blocks = 0;
390
391 while (1)
392 {
393 enum read_header status;
394
395 header = find_next_block ();
396 *return_block = header;
397 if (!header)
398 return HEADER_END_OF_FILE;
399
400 if ((status = tar_checksum (header, false)) != HEADER_SUCCESS)
401 return status;
402
403 /* Good block. Decode file size and return. */
404
405 if (header->header.typeflag == LNKTYPE)
406 info->stat.st_size = 0; /* links 0 size on tape */
407 else
408 {
409 info->stat.st_size = OFF_FROM_HEADER (header->header.size);
410 if (info->stat.st_size < 0)
411 return HEADER_FAILURE;
412 }
413
414 if (header->header.typeflag == GNUTYPE_LONGNAME
415 || header->header.typeflag == GNUTYPE_LONGLINK
416 || header->header.typeflag == XHDTYPE
417 || header->header.typeflag == XGLTYPE
418 || header->header.typeflag == SOLARIS_XHDTYPE)
419 {
420 if (mode == read_header_x_raw)
421 return HEADER_SUCCESS_EXTENDED;
422 else if (header->header.typeflag == GNUTYPE_LONGNAME
423 || header->header.typeflag == GNUTYPE_LONGLINK)
424 {
425 size_t name_size = info->stat.st_size;
426 size_t n = name_size % BLOCKSIZE;
427 size = name_size + BLOCKSIZE;
428 if (n)
429 size += BLOCKSIZE - n;
430
431 if (name_size != info->stat.st_size || size < name_size)
432 xalloc_die ();
433
434 header_copy = xmalloc (size + 1);
435
436 if (header->header.typeflag == GNUTYPE_LONGNAME)
437 {
438 free (next_long_name);
439 next_long_name = header_copy;
440 next_long_name_blocks = size / BLOCKSIZE;
441 }
442 else
443 {
444 free (next_long_link);
445 next_long_link = header_copy;
446 next_long_link_blocks = size / BLOCKSIZE;
447 }
448
449 set_next_block_after (header);
450 *header_copy = *header;
451 bp = header_copy->buffer + BLOCKSIZE;
452
453 for (size -= BLOCKSIZE; size > 0; size -= written)
454 {
455 data_block = find_next_block ();
456 if (! data_block)
457 {
458 ERROR ((0, 0, _("Unexpected EOF in archive")));
459 break;
460 }
461 written = available_space_after (data_block);
462 if (written > size)
463 written = size;
464
465 memcpy (bp, data_block->buffer, written);
466 bp += written;
467 set_next_block_after ((union block *)
468 (data_block->buffer + written - 1));
469 }
470
471 *bp = '\0';
472 }
473 else if (header->header.typeflag == XHDTYPE
474 || header->header.typeflag == SOLARIS_XHDTYPE)
475 xheader_read (&info->xhdr, header,
476 OFF_FROM_HEADER (header->header.size));
477 else if (header->header.typeflag == XGLTYPE)
478 {
479 struct xheader xhdr;
480
481 if (!recent_global_header)
482 recent_global_header = xmalloc (sizeof *recent_global_header);
483 memcpy (recent_global_header, header,
484 sizeof *recent_global_header);
485 memset (&xhdr, 0, sizeof xhdr);
486 xheader_read (&xhdr, header,
487 OFF_FROM_HEADER (header->header.size));
488 xheader_decode_global (&xhdr);
489 xheader_destroy (&xhdr);
490 if (mode == read_header_x_global)
491 return HEADER_SUCCESS_EXTENDED;
492 }
493
494 /* Loop! */
495
496 }
497 else
498 {
499 char const *name;
500 struct posix_header const *h = &header->header;
501 char namebuf[sizeof h->prefix + 1 + NAME_FIELD_SIZE + 1];
502
503 free (recent_long_name);
504
505 if (next_long_name)
506 {
507 name = next_long_name->buffer + BLOCKSIZE;
508 recent_long_name = next_long_name;
509 recent_long_name_blocks = next_long_name_blocks;
510 }
511 else
512 {
513 /* Accept file names as specified by POSIX.1-1996
514 section 10.1.1. */
515 char *np = namebuf;
516
517 if (h->prefix[0] && strcmp (h->magic, TMAGIC) == 0)
518 {
519 memcpy (np, h->prefix, sizeof h->prefix);
520 np[sizeof h->prefix] = '\0';
521 np += strlen (np);
522 *np++ = '/';
523 }
524 memcpy (np, h->name, sizeof h->name);
525 np[sizeof h->name] = '\0';
526 name = namebuf;
527 recent_long_name = 0;
528 recent_long_name_blocks = 0;
529 }
530 assign_string (&info->orig_file_name, name);
531 assign_string (&info->file_name, name);
532 info->had_trailing_slash = strip_trailing_slashes (info->file_name);
533
534 free (recent_long_link);
535
536 if (next_long_link)
537 {
538 name = next_long_link->buffer + BLOCKSIZE;
539 recent_long_link = next_long_link;
540 recent_long_link_blocks = next_long_link_blocks;
541 }
542 else
543 {
544 memcpy (namebuf, h->linkname, sizeof h->linkname);
545 namebuf[sizeof h->linkname] = '\0';
546 name = namebuf;
547 recent_long_link = 0;
548 recent_long_link_blocks = 0;
549 }
550 assign_string (&info->link_name, name);
551
552 return HEADER_SUCCESS;
553 }
554 }
555 }
556
557 #define ISOCTAL(c) ((c)>='0'&&(c)<='7')
558
559 /* Decode things from a file HEADER block into STAT_INFO, also setting
560 *FORMAT_POINTER depending on the header block format. If
561 DO_USER_GROUP, decode the user/group information (this is useful
562 for extraction, but waste time when merely listing).
563
564 read_header() has already decoded the checksum and length, so we don't.
565
566 This routine should *not* be called twice for the same block, since
567 the two calls might use different DO_USER_GROUP values and thus
568 might end up with different uid/gid for the two calls. If anybody
569 wants the uid/gid they should decode it first, and other callers
570 should decode it without uid/gid before calling a routine,
571 e.g. print_header, that assumes decoded data. */
572 void
573 decode_header (union block *header, struct tar_stat_info *stat_info,
574 enum archive_format *format_pointer, int do_user_group)
575 {
576 enum archive_format format;
577 bool hbits;
578 mode_t mode = MODE_FROM_HEADER (header->header.mode, &hbits);
579
580 if (strcmp (header->header.magic, TMAGIC) == 0)
581 {
582 if (header->star_header.prefix[130] == 0
583 && ISOCTAL (header->star_header.atime[0])
584 && header->star_header.atime[11] == ' '
585 && ISOCTAL (header->star_header.ctime[0])
586 && header->star_header.ctime[11] == ' ')
587 format = STAR_FORMAT;
588 else if (stat_info->xhdr.size)
589 format = POSIX_FORMAT;
590 else
591 format = USTAR_FORMAT;
592 }
593 else if (strcmp (header->buffer + offsetof (struct posix_header, magic),
594 OLDGNU_MAGIC)
595 == 0)
596 format = hbits ? OLDGNU_FORMAT : GNU_FORMAT;
597 else
598 format = V7_FORMAT;
599 *format_pointer = format;
600
601 stat_info->stat.st_mode = mode;
602 stat_info->mtime.tv_sec = TIME_FROM_HEADER (header->header.mtime);
603 stat_info->mtime.tv_nsec = 0;
604 assign_string (&stat_info->uname,
605 header->header.uname[0] ? header->header.uname : NULL);
606 assign_string (&stat_info->gname,
607 header->header.gname[0] ? header->header.gname : NULL);
608
609 xheader_xattr_init (stat_info);
610
611 if (format == OLDGNU_FORMAT && incremental_option)
612 {
613 stat_info->atime.tv_sec = TIME_FROM_HEADER (header->oldgnu_header.atime);
614 stat_info->ctime.tv_sec = TIME_FROM_HEADER (header->oldgnu_header.ctime);
615 stat_info->atime.tv_nsec = stat_info->ctime.tv_nsec = 0;
616 }
617 else if (format == STAR_FORMAT)
618 {
619 stat_info->atime.tv_sec = TIME_FROM_HEADER (header->star_header.atime);
620 stat_info->ctime.tv_sec = TIME_FROM_HEADER (header->star_header.ctime);
621 stat_info->atime.tv_nsec = stat_info->ctime.tv_nsec = 0;
622 }
623 else
624 stat_info->atime = stat_info->ctime = start_time;
625
626 if (format == V7_FORMAT)
627 {
628 stat_info->stat.st_uid = UID_FROM_HEADER (header->header.uid);
629 stat_info->stat.st_gid = GID_FROM_HEADER (header->header.gid);
630 stat_info->stat.st_rdev = 0;
631 }
632 else
633 {
634 if (do_user_group)
635 {
636 /* FIXME: Decide if this should somewhat depend on -p. */
637
638 if (numeric_owner_option
639 || !*header->header.uname
640 || !uname_to_uid (header->header.uname, &stat_info->stat.st_uid))
641 stat_info->stat.st_uid = UID_FROM_HEADER (header->header.uid);
642
643 if (numeric_owner_option
644 || !*header->header.gname
645 || !gname_to_gid (header->header.gname, &stat_info->stat.st_gid))
646 stat_info->stat.st_gid = GID_FROM_HEADER (header->header.gid);
647 }
648
649 switch (header->header.typeflag)
650 {
651 case BLKTYPE:
652 case CHRTYPE:
653 stat_info->stat.st_rdev =
654 makedev (MAJOR_FROM_HEADER (header->header.devmajor),
655 MINOR_FROM_HEADER (header->header.devminor));
656 break;
657
658 default:
659 stat_info->stat.st_rdev = 0;
660 }
661 }
662
663 stat_info->archive_file_size = stat_info->stat.st_size;
664 xheader_decode (stat_info);
665
666 if (sparse_member_p (stat_info))
667 {
668 sparse_fixup_header (stat_info);
669 stat_info->is_sparse = true;
670 }
671 else
672 {
673 stat_info->is_sparse = false;
674 if (((current_format == GNU_FORMAT
675 || current_format == OLDGNU_FORMAT)
676 && current_header->header.typeflag == GNUTYPE_DUMPDIR)
677 || stat_info->dumpdir)
678 stat_info->is_dumpdir = true;
679 }
680 }
681
682
683 /* Convert buffer at WHERE0 of size DIGS from external format to
684 intmax_t. DIGS must be positive. If TYPE is nonnull, the data are
685 of type TYPE. The buffer must represent a value in the range
686 MINVAL through MAXVAL; if the mathematically correct result V would
687 be greater than INTMAX_MAX, return a negative integer V such that
688 (uintmax_t) V yields the correct result. If OCTAL_ONLY, allow only octal
689 numbers instead of the other GNU extensions. Return -1 on error,
690 diagnosing the error if TYPE is nonnull and if !SILENT. */
691 #if ! (INTMAX_MAX <= UINTMAX_MAX && - (INTMAX_MIN + 1) <= UINTMAX_MAX)
692 # error "from_header internally represents intmax_t as uintmax_t + sign"
693 #endif
694 #if ! (UINTMAX_MAX / 2 <= INTMAX_MAX)
695 # error "from_header returns intmax_t to represent uintmax_t"
696 #endif
697 static intmax_t
698 from_header (char const *where0, size_t digs, char const *type,
699 intmax_t minval, uintmax_t maxval,
700 bool octal_only, bool silent)
701 {
702 uintmax_t value;
703 uintmax_t uminval = minval;
704 uintmax_t minus_minval = - uminval;
705 char const *where = where0;
706 char const *lim = where + digs;
707 bool negative = false;
708
709 /* Accommodate buggy tar of unknown vintage, which outputs leading
710 NUL if the previous field overflows. */
711 where += !*where;
712
713 /* Accommodate older tars, which output leading spaces. */
714 for (;;)
715 {
716 if (where == lim)
717 {
718 if (type && !silent)
719 ERROR ((0, 0,
720 /* TRANSLATORS: %s is type of the value (gid_t, uid_t,
721 etc.) */
722 _("Blanks in header where numeric %s value expected"),
723 type));
724 return -1;
725 }
726 if (!isspace ((unsigned char) *where))
727 break;
728 where++;
729 }
730
731 value = 0;
732 if (ISODIGIT (*where))
733 {
734 char const *where1 = where;
735 bool overflow = false;
736
737 for (;;)
738 {
739 value += *where++ - '0';
740 if (where == lim || ! ISODIGIT (*where))
741 break;
742 overflow |= value != (value << LG_8 >> LG_8);
743 value <<= LG_8;
744 }
745
746 /* Parse the output of older, unportable tars, which generate
747 negative values in two's complement octal. If the leading
748 nonzero digit is 1, we can't recover the original value
749 reliably; so do this only if the digit is 2 or more. This
750 catches the common case of 32-bit negative time stamps. */
751 if ((overflow || maxval < value) && '2' <= *where1 && type)
752 {
753 /* Compute the negative of the input value, assuming two's
754 complement. */
755 int digit = (*where1 - '0') | 4;
756 overflow = 0;
757 value = 0;
758 where = where1;
759 for (;;)
760 {
761 value += 7 - digit;
762 where++;
763 if (where == lim || ! ISODIGIT (*where))
764 break;
765 digit = *where - '0';
766 overflow |= value != (value << LG_8 >> LG_8);
767 value <<= LG_8;
768 }
769 value++;
770 overflow |= !value;
771
772 if (!overflow && value <= minus_minval)
773 {
774 if (!silent)
775 WARN ((0, 0,
776 /* TRANSLATORS: Second %s is a type name (gid_t,uid_t,etc.) */
777 _("Archive octal value %.*s is out of %s range; assuming two's complement"),
778 (int) (where - where1), where1, type));
779 negative = true;
780 }
781 }
782
783 if (overflow)
784 {
785 if (type && !silent)
786 ERROR ((0, 0,
787 /* TRANSLATORS: Second %s is a type name (gid_t,uid_t,etc.) */
788 _("Archive octal value %.*s is out of %s range"),
789 (int) (where - where1), where1, type));
790 return -1;
791 }
792 }
793 else if (octal_only)
794 {
795 /* Suppress the following extensions. */
796 }
797 else if (*where == '-' || *where == '+')
798 {
799 /* Parse base-64 output produced only by tar test versions
800 1.13.6 (1999-08-11) through 1.13.11 (1999-08-23).
801 Support for this will be withdrawn in future releases. */
802 int dig;
803 if (!silent)
804 {
805 static bool warned_once;
806 if (! warned_once)
807 {
808 warned_once = true;
809 WARN ((0, 0, _("Archive contains obsolescent base-64 headers")));
810 }
811 }
812 negative = *where++ == '-';
813 while (where != lim
814 && (dig = base64_map[(unsigned char) *where]) < 64)
815 {
816 if (value << LG_64 >> LG_64 != value)
817 {
818 char *string = alloca (digs + 1);
819 memcpy (string, where0, digs);
820 string[digs] = '\0';
821 if (type && !silent)
822 ERROR ((0, 0,
823 _("Archive signed base-64 string %s is out of %s range"),
824 quote (string), type));
825 return -1;
826 }
827 value = (value << LG_64) | dig;
828 where++;
829 }
830 }
831 else if (*where == '\200' /* positive base-256 */
832 || *where == '\377' /* negative base-256 */)
833 {
834 /* Parse base-256 output. A nonnegative number N is
835 represented as (256**DIGS)/2 + N; a negative number -N is
836 represented as (256**DIGS) - N, i.e. as two's complement.
837 The representation guarantees that the leading bit is
838 always on, so that we don't confuse this format with the
839 others (assuming ASCII bytes of 8 bits or more). */
840 int signbit = *where & (1 << (LG_256 - 2));
841 uintmax_t topbits = (((uintmax_t) - signbit)
842 << (CHAR_BIT * sizeof (uintmax_t)
843 - LG_256 - (LG_256 - 2)));
844 value = (*where++ & ((1 << (LG_256 - 2)) - 1)) - signbit;
845 for (;;)
846 {
847 value = (value << LG_256) + (unsigned char) *where++;
848 if (where == lim)
849 break;
850 if (((value << LG_256 >> LG_256) | topbits) != value)
851 {
852 if (type && !silent)
853 ERROR ((0, 0,
854 _("Archive base-256 value is out of %s range"),
855 type));
856 return -1;
857 }
858 }
859 negative = signbit != 0;
860 if (negative)
861 value = -value;
862 }
863
864 if (where != lim && *where && !isspace ((unsigned char) *where))
865 {
866 if (type)
867 {
868 char buf[1000]; /* Big enough to represent any header. */
869 static struct quoting_options *o;
870
871 if (!o)
872 {
873 o = clone_quoting_options (0);
874 set_quoting_style (o, locale_quoting_style);
875 }
876
877 while (where0 != lim && ! lim[-1])
878 lim--;
879 quotearg_buffer (buf, sizeof buf, where0, lim - where0, o);
880 if (!silent)
881 ERROR ((0, 0,
882 /* TRANSLATORS: Second %s is a type name (gid_t,uid_t,etc.) */
883 _("Archive contains %.*s where numeric %s value expected"),
884 (int) sizeof buf, buf, type));
885 }
886
887 return -1;
888 }
889
890 if (value <= (negative ? minus_minval : maxval))
891 return represent_uintmax (negative ? -value : value);
892
893 if (type && !silent)
894 {
895 char minval_buf[UINTMAX_STRSIZE_BOUND + 1];
896 char maxval_buf[UINTMAX_STRSIZE_BOUND];
897 char value_buf[UINTMAX_STRSIZE_BOUND + 1];
898 char *minval_string = STRINGIFY_BIGINT (minus_minval, minval_buf + 1);
899 char *value_string = STRINGIFY_BIGINT (value, value_buf + 1);
900 if (negative)
901 *--value_string = '-';
902 if (minus_minval)
903 *--minval_string = '-';
904 /* TRANSLATORS: Second %s is type name (gid_t,uid_t,etc.) */
905 ERROR ((0, 0, _("Archive value %s is out of %s range %s..%s"),
906 value_string, type,
907 minval_string, STRINGIFY_BIGINT (maxval, maxval_buf)));
908 }
909
910 return -1;
911 }
912
913 static gid_t
914 gid_from_header (const char *p, size_t s)
915 {
916 return from_header (p, s, "gid_t",
917 TYPE_MINIMUM (gid_t), TYPE_MAXIMUM (gid_t),
918 false, false);
919 }
920
921 static major_t
922 major_from_header (const char *p, size_t s)
923 {
924 return from_header (p, s, "major_t",
925 TYPE_MINIMUM (major_t), TYPE_MAXIMUM (major_t),
926 false, false);
927 }
928
929 static minor_t
930 minor_from_header (const char *p, size_t s)
931 {
932 return from_header (p, s, "minor_t",
933 TYPE_MINIMUM (minor_t), TYPE_MAXIMUM (minor_t),
934 false, false);
935 }
936
937 /* Convert P to the file mode, as understood by tar.
938 Set *HBITS if there are any unrecognized bits. */
939 static mode_t
940 mode_from_header (const char *p, size_t s, bool *hbits)
941 {
942 intmax_t u = from_header (p, s, "mode_t",
943 INTMAX_MIN, UINTMAX_MAX,
944 false, false);
945 mode_t mode = ((u & TSUID ? S_ISUID : 0)
946 | (u & TSGID ? S_ISGID : 0)
947 | (u & TSVTX ? S_ISVTX : 0)
948 | (u & TUREAD ? S_IRUSR : 0)
949 | (u & TUWRITE ? S_IWUSR : 0)
950 | (u & TUEXEC ? S_IXUSR : 0)
951 | (u & TGREAD ? S_IRGRP : 0)
952 | (u & TGWRITE ? S_IWGRP : 0)
953 | (u & TGEXEC ? S_IXGRP : 0)
954 | (u & TOREAD ? S_IROTH : 0)
955 | (u & TOWRITE ? S_IWOTH : 0)
956 | (u & TOEXEC ? S_IXOTH : 0));
957 *hbits = (u & ~07777) != 0;
958 return mode;
959 }
960
961 off_t
962 off_from_header (const char *p, size_t s)
963 {
964 /* Negative offsets are not allowed in tar files, so invoke
965 from_header with minimum value 0, not TYPE_MINIMUM (off_t). */
966 return from_header (p, s, "off_t",
967 0, TYPE_MAXIMUM (off_t),
968 false, false);
969 }
970
971 static time_t
972 time_from_header (const char *p, size_t s)
973 {
974 return from_header (p, s, "time_t",
975 TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t),
976 false, false);
977 }
978
979 static uid_t
980 uid_from_header (const char *p, size_t s)
981 {
982 return from_header (p, s, "uid_t",
983 TYPE_MINIMUM (uid_t), TYPE_MAXIMUM (uid_t),
984 false, false);
985 }
986
987 uintmax_t
988 uintmax_from_header (const char *p, size_t s)
989 {
990 return from_header (p, s, "uintmax_t", 0, UINTMAX_MAX, false, false);
991 }
992
993
994 /* Return a printable representation of T. The result points to
995 static storage that can be reused in the next call to this
996 function, to ctime, or to asctime. If FULL_TIME, then output the
997 time stamp to its full resolution; otherwise, just output it to
998 1-minute resolution. */
999 char const *
1000 tartime (struct timespec t, bool full_time)
1001 {
1002 enum { fraclen = sizeof ".FFFFFFFFF" - 1 };
1003 static char buffer[max (UINTMAX_STRSIZE_BOUND + 1,
1004 INT_STRLEN_BOUND (int) + 16)
1005 + fraclen];
1006 struct tm *tm;
1007 time_t s = t.tv_sec;
1008 int ns = t.tv_nsec;
1009 bool negative = s < 0;
1010 char *p;
1011
1012 if (negative && ns != 0)
1013 {
1014 s++;
1015 ns = 1000000000 - ns;
1016 }
1017
1018 tm = utc_option ? gmtime (&s) : localtime (&s);
1019 if (tm)
1020 {
1021 if (full_time)
1022 {
1023 sprintf (buffer, "%04ld-%02d-%02d %02d:%02d:%02d",
1024 tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
1025 tm->tm_hour, tm->tm_min, tm->tm_sec);
1026 code_ns_fraction (ns, buffer + strlen (buffer));
1027 }
1028 else
1029 sprintf (buffer, "%04ld-%02d-%02d %02d:%02d",
1030 tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
1031 tm->tm_hour, tm->tm_min);
1032 return buffer;
1033 }
1034
1035 /* The time stamp cannot be broken down, most likely because it
1036 is out of range. Convert it as an integer,
1037 right-adjusted in a field with the same width as the usual
1038 4-year ISO time format. */
1039 p = umaxtostr (negative ? - (uintmax_t) s : s,
1040 buffer + sizeof buffer - UINTMAX_STRSIZE_BOUND - fraclen);
1041 if (negative)
1042 *--p = '-';
1043 while ((buffer + sizeof buffer - sizeof "YYYY-MM-DD HH:MM"
1044 + (full_time ? sizeof ":SS.FFFFFFFFF" - 1 : 0))
1045 < p)
1046 *--p = ' ';
1047 if (full_time)
1048 code_ns_fraction (ns, buffer + sizeof buffer - 1 - fraclen);
1049 return p;
1050 }
1051
1052 /* Actually print it.
1053
1054 Plain and fancy file header block logging. Non-verbose just prints
1055 the name, e.g. for "tar t" or "tar x". This should just contain
1056 file names, so it can be fed back into tar with xargs or the "-T"
1057 option. The verbose option can give a bunch of info, one line per
1058 file. I doubt anybody tries to parse its format, or if they do,
1059 they shouldn't. Unix tar is pretty random here anyway. */
1060
1061
1062 /* Width of "user/group size", with initial value chosen
1063 heuristically. This grows as needed, though this may cause some
1064 stairstepping in the output. Make it too small and the output will
1065 almost always look ragged. Make it too large and the output will
1066 be spaced out too far. */
1067 static int ugswidth = 19;
1068
1069 /* Width of printed time stamps. It grows if longer time stamps are
1070 found (typically, those with nanosecond resolution). Like
1071 USGWIDTH, some stairstepping may occur. */
1072 static int datewidth = sizeof "YYYY-MM-DD HH:MM" - 1;
1073
1074 static bool volume_label_printed = false;
1075
1076 static void
1077 simple_print_header (struct tar_stat_info *st, union block *blk,
1078 off_t block_ordinal)
1079 {
1080 char modes[12];
1081 char const *time_stamp;
1082 int time_stamp_len;
1083 char *temp_name;
1084
1085 /* These hold formatted ints. */
1086 char uform[max (INT_BUFSIZE_BOUND (intmax_t), UINTMAX_STRSIZE_BOUND)];
1087 char gform[sizeof uform];
1088 char *user, *group;
1089 char size[2 * UINTMAX_STRSIZE_BOUND];
1090 /* holds formatted size or major,minor */
1091 char uintbuf[UINTMAX_STRSIZE_BOUND];
1092 int pad;
1093 int sizelen;
1094
1095 if (show_transformed_names_option)
1096 temp_name = st->file_name ? st->file_name : st->orig_file_name;
1097 else
1098 temp_name = st->orig_file_name ? st->orig_file_name : st->file_name;
1099
1100 if (block_number_option)
1101 {
1102 char buf[UINTMAX_STRSIZE_BOUND];
1103 if (block_ordinal < 0)
1104 block_ordinal = current_block_ordinal ();
1105 block_ordinal -= recent_long_name_blocks;
1106 block_ordinal -= recent_long_link_blocks;
1107 fprintf (stdlis, _("block %s: "),
1108 STRINGIFY_BIGINT (block_ordinal, buf));
1109 }
1110
1111 if (verbose_option <= 1)
1112 {
1113 /* Just the fax, mam. */
1114 fputs (quotearg (temp_name), stdlis);
1115 if (show_transformed_names_option && st->had_trailing_slash)
1116 fputc ('/', stdlis);
1117 fputc ('\n', stdlis);
1118 }
1119 else
1120 {
1121 /* File type and modes. */
1122
1123 modes[0] = '?';
1124 switch (blk->header.typeflag)
1125 {
1126 case GNUTYPE_VOLHDR:
1127 volume_label_printed = true;
1128 modes[0] = 'V';
1129 break;
1130
1131 case GNUTYPE_MULTIVOL:
1132 modes[0] = 'M';
1133 break;
1134
1135 case GNUTYPE_LONGNAME:
1136 case GNUTYPE_LONGLINK:
1137 modes[0] = 'L';
1138 ERROR ((0, 0, _("Unexpected long name header")));
1139 break;
1140
1141 case GNUTYPE_SPARSE:
1142 case REGTYPE:
1143 case AREGTYPE:
1144 modes[0] = st->had_trailing_slash ? 'd' : '-';
1145 break;
1146 case LNKTYPE:
1147 modes[0] = 'h';
1148 break;
1149 case GNUTYPE_DUMPDIR:
1150 modes[0] = 'd';
1151 break;
1152 case DIRTYPE:
1153 modes[0] = 'd';
1154 break;
1155 case SYMTYPE:
1156 modes[0] = 'l';
1157 break;
1158 case BLKTYPE:
1159 modes[0] = 'b';
1160 break;
1161 case CHRTYPE:
1162 modes[0] = 'c';
1163 break;
1164 case FIFOTYPE:
1165 modes[0] = 'p';
1166 break;
1167 case CONTTYPE:
1168 modes[0] = 'C';
1169 break;
1170 }
1171
1172 pax_decode_mode (st->stat.st_mode, modes + 1);
1173
1174 /* extended attributes: GNU `ls -l'-like preview */
1175 xattrs_print_char (st, modes + 10);
1176
1177 /* Time stamp. */
1178
1179 time_stamp = tartime (st->mtime, full_time_option);
1180 time_stamp_len = strlen (time_stamp);
1181 if (datewidth < time_stamp_len)
1182 datewidth = time_stamp_len;
1183
1184 /* User and group names. */
1185
1186 if (st->uname
1187 && st->uname[0]
1188 && current_format != V7_FORMAT
1189 && !numeric_owner_option)
1190 user = st->uname;
1191 else
1192 {
1193 /* Try parsing it as an unsigned integer first, and as a
1194 uid_t if that fails. This method can list positive user
1195 ids that are too large to fit in a uid_t. */
1196 uintmax_t u = from_header (blk->header.uid,
1197 sizeof blk->header.uid, 0,
1198 0, UINTMAX_MAX,
1199 false, false);
1200 user = (u != -1
1201 ? STRINGIFY_BIGINT (u, uform)
1202 : imaxtostr (UID_FROM_HEADER (blk->header.uid), uform));
1203 }
1204
1205 if (st->gname
1206 && st->gname[0]
1207 && current_format != V7_FORMAT
1208 && !numeric_owner_option)
1209 group = st->gname;
1210 else
1211 {
1212 /* Try parsing it as an unsigned integer first, and as a
1213 gid_t if that fails. This method can list positive group
1214 ids that are too large to fit in a gid_t. */
1215 uintmax_t g = from_header (blk->header.gid,
1216 sizeof blk->header.gid, 0,
1217 0, UINTMAX_MAX,
1218 false, false);
1219 group = (g != -1
1220 ? STRINGIFY_BIGINT (g, gform)
1221 : imaxtostr (GID_FROM_HEADER (blk->header.gid), gform));
1222 }
1223
1224 /* Format the file size or major/minor device numbers. */
1225
1226 switch (blk->header.typeflag)
1227 {
1228 case CHRTYPE:
1229 case BLKTYPE:
1230 strcpy (size,
1231 STRINGIFY_BIGINT (major (st->stat.st_rdev), uintbuf));
1232 strcat (size, ",");
1233 strcat (size,
1234 STRINGIFY_BIGINT (minor (st->stat.st_rdev), uintbuf));
1235 break;
1236
1237 default:
1238 /* st->stat.st_size keeps stored file size */
1239 strcpy (size, STRINGIFY_BIGINT (st->stat.st_size, uintbuf));
1240 break;
1241 }
1242
1243 /* Figure out padding and print the whole line. */
1244
1245 sizelen = strlen (size);
1246 pad = strlen (user) + 1 + strlen (group) + 1 + sizelen;
1247 if (pad > ugswidth)
1248 ugswidth = pad;
1249
1250 fprintf (stdlis, "%s %s/%s %*s %-*s",
1251 modes, user, group, ugswidth - pad + sizelen, size,
1252 datewidth, time_stamp);
1253
1254 fprintf (stdlis, " %s", quotearg (temp_name));
1255 if (show_transformed_names_option && st->had_trailing_slash)
1256 fputc ('/', stdlis);
1257
1258 switch (blk->header.typeflag)
1259 {
1260 case SYMTYPE:
1261 fprintf (stdlis, " -> %s\n", quotearg (st->link_name));
1262 break;
1263
1264 case LNKTYPE:
1265 fprintf (stdlis, _(" link to %s\n"), quotearg (st->link_name));
1266 break;
1267
1268 default:
1269 {
1270 char type_string[2];
1271 type_string[0] = blk->header.typeflag;
1272 type_string[1] = '\0';
1273 fprintf (stdlis, _(" unknown file type %s\n"),
1274 quote (type_string));
1275 }
1276 break;
1277
1278 case AREGTYPE:
1279 case REGTYPE:
1280 case GNUTYPE_SPARSE:
1281 case CHRTYPE:
1282 case BLKTYPE:
1283 case DIRTYPE:
1284 case FIFOTYPE:
1285 case CONTTYPE:
1286 case GNUTYPE_DUMPDIR:
1287 putc ('\n', stdlis);
1288 break;
1289
1290 case GNUTYPE_LONGLINK:
1291 fprintf (stdlis, _("--Long Link--\n"));
1292 break;
1293
1294 case GNUTYPE_LONGNAME:
1295 fprintf (stdlis, _("--Long Name--\n"));
1296 break;
1297
1298 case GNUTYPE_VOLHDR:
1299 fprintf (stdlis, _("--Volume Header--\n"));
1300 break;
1301
1302 case GNUTYPE_MULTIVOL:
1303 strcpy (size,
1304 STRINGIFY_BIGINT
1305 (UINTMAX_FROM_HEADER (blk->oldgnu_header.offset),
1306 uintbuf));
1307 fprintf (stdlis, _("--Continued at byte %s--\n"), size);
1308 break;
1309 }
1310 }
1311 fflush (stdlis);
1312 xattrs_print (st);
1313 }
1314
1315
1316 static void
1317 print_volume_label (void)
1318 {
1319 struct tar_stat_info vstat;
1320 union block vblk;
1321 enum archive_format dummy;
1322
1323 memset (&vblk, 0, sizeof (vblk));
1324 vblk.header.typeflag = GNUTYPE_VOLHDR;
1325 if (recent_global_header)
1326 memcpy (vblk.header.mtime, recent_global_header->header.mtime,
1327 sizeof vblk.header.mtime);
1328 tar_stat_init (&vstat);
1329 assign_string (&vstat.file_name, ".");
1330 decode_header (&vblk, &vstat, &dummy, 0);
1331 assign_string (&vstat.file_name, volume_label);
1332 simple_print_header (&vstat, &vblk, 0);
1333 tar_stat_destroy (&vstat);
1334 }
1335
1336 void
1337 print_header (struct tar_stat_info *st, union block *blk,
1338 off_t block_ordinal)
1339 {
1340 if (current_format == POSIX_FORMAT && !volume_label_printed && volume_label)
1341 {
1342 print_volume_label ();
1343 volume_label_printed = true;
1344 }
1345
1346 simple_print_header (st, blk, block_ordinal);
1347 }
1348
1349 /* Print a similar line when we make a directory automatically. */
1350 void
1351 print_for_mkdir (char *dirname, int length, mode_t mode)
1352 {
1353 char modes[11];
1354
1355 if (verbose_option > 1)
1356 {
1357 /* File type and modes. */
1358
1359 modes[0] = 'd';
1360 pax_decode_mode (mode, modes + 1);
1361
1362 if (block_number_option)
1363 {
1364 char buf[UINTMAX_STRSIZE_BOUND];
1365 fprintf (stdlis, _("block %s: "),
1366 STRINGIFY_BIGINT (current_block_ordinal (), buf));
1367 }
1368
1369 fprintf (stdlis, "%s %*s %s\n", modes, ugswidth + 1 + datewidth,
1370 _("Creating directory:"), quotearg (dirname));
1371 }
1372 }
1373
1374 /* Skip over SIZE bytes of data in blocks in the archive. */
1375 void
1376 skip_file (off_t size)
1377 {
1378 union block *x;
1379
1380 /* FIXME: Make sure mv_begin_read is always called before it */
1381
1382 if (seekable_archive)
1383 {
1384 off_t nblk = seek_archive (size);
1385 if (nblk >= 0)
1386 size -= nblk * BLOCKSIZE;
1387 else
1388 seekable_archive = false;
1389 }
1390
1391 mv_size_left (size);
1392
1393 while (size > 0)
1394 {
1395 x = find_next_block ();
1396 if (! x)
1397 FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
1398
1399 set_next_block_after (x);
1400 size -= BLOCKSIZE;
1401 mv_size_left (size);
1402 }
1403 }
1404
1405 /* Skip the current member in the archive.
1406 NOTE: Current header must be decoded before calling this function. */
1407 void
1408 skip_member (void)
1409 {
1410 if (!current_stat_info.skipped)
1411 {
1412 char save_typeflag = current_header->header.typeflag;
1413 set_next_block_after (current_header);
1414
1415 mv_begin_read (&current_stat_info);
1416
1417 if (current_stat_info.is_sparse)
1418 sparse_skip_file (&current_stat_info);
1419 else if (save_typeflag != DIRTYPE)
1420 skip_file (current_stat_info.stat.st_size);
1421
1422 mv_end ();
1423 }
1424 }
1425
1426 void
1427 test_archive_label (void)
1428 {
1429 base64_init ();
1430 name_gather ();
1431
1432 open_archive (ACCESS_READ);
1433 if (read_header (&current_header, &current_stat_info, read_header_auto)
1434 == HEADER_SUCCESS)
1435 {
1436 decode_header (current_header,
1437 &current_stat_info, &current_format, 0);
1438 if (current_header->header.typeflag == GNUTYPE_VOLHDR)
1439 assign_string (&volume_label, current_header->header.name);
1440
1441 if (volume_label)
1442 {
1443 if (verbose_option)
1444 print_volume_label ();
1445 if (!name_match (volume_label) && multi_volume_option)
1446 {
1447 char *s = drop_volume_label_suffix (volume_label);
1448 name_match (s);
1449 free (s);
1450 }
1451 }
1452 }
1453 close_archive ();
1454 label_notfound ();
1455 }
This page took 0.092292 seconds and 4 git commands to generate.