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