]> Dogcows Code - chaz/tar/blob - src/list.c
(tartime): Now extern.
[chaz/tar] / src / list.c
1 /* List a tar archive, with support routines for reading a tar archive.
2 Copyright 1988,92,93,94,96,97,98,1999 Free Software Foundation, Inc.
3 Written by John Gilmore, on 1985-08-26.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any later
8 version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19 /* Define to non-zero for forcing old ctime format instead of ISO format. */
20 #undef USE_OLD_CTIME
21
22 #include "system.h"
23 #include <quotearg.h>
24
25 #include <time.h>
26 #ifndef time
27 time_t time ();
28 #endif
29
30 #include "common.h"
31
32 #define max(a, b) ((a) < (b) ? (b) : (a))
33
34 union block *current_header; /* points to current archive header */
35 struct stat current_stat; /* stat struct corresponding */
36 enum archive_format current_format; /* recognized format */
37
38 static uintmax_t from_header PARAMS ((const char *, size_t, const char *,
39 uintmax_t, uintmax_t));
40
41 /* Base 64 digits; see Internet RFC 2045 Table 1. */
42 static char const base_64_digits[64] =
43 {
44 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
45 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
46 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
47 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
48 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
49 };
50
51 /* Table of base-64 digit values indexed by unsigned chars.
52 The value is 64 for unsigned chars that are not base-64 digits. */
53 static char base64_map[UCHAR_MAX + 1];
54
55 static void
56 base64_init (void)
57 {
58 int i;
59 memset (base64_map, 64, sizeof base64_map);
60 for (i = 0; i < 64; i++)
61 base64_map[(int) base_64_digits[i]] = i;
62 }
63
64 /*-----------------------------------.
65 | Main loop for reading an archive. |
66 `-----------------------------------*/
67
68 void
69 read_and (void (*do_something) ())
70 {
71 enum read_header status = HEADER_STILL_UNREAD;
72 enum read_header prev_status;
73
74 base64_init ();
75 name_gather ();
76 open_archive (ACCESS_READ);
77
78 while (1)
79 {
80 prev_status = status;
81 status = read_header ();
82 switch (status)
83 {
84 case HEADER_STILL_UNREAD:
85 abort ();
86
87 case HEADER_SUCCESS:
88
89 /* Valid header. We should decode next field (mode) first.
90 Ensure incoming names are null terminated. */
91
92 if (!name_match (current_file_name)
93 || (newer_mtime_option != TYPE_MINIMUM (time_t)
94 /* FIXME: We get mtime now, and again later; this
95 causes duplicate diagnostics if header.mtime is
96 bogus. */
97 && ((current_stat.st_mtime
98 = TIME_FROM_HEADER (current_header->header.mtime))
99 < newer_mtime_option))
100 || excluded_name (current_file_name))
101 {
102 char save_typeflag;
103
104 if (current_header->header.typeflag == GNUTYPE_VOLHDR
105 || current_header->header.typeflag == GNUTYPE_MULTIVOL
106 || current_header->header.typeflag == GNUTYPE_NAMES)
107 {
108 (*do_something) ();
109 continue;
110 }
111 if (show_omitted_dirs_option
112 && current_header->header.typeflag == DIRTYPE)
113 WARN ((0, 0, _("Omitting %s"), current_file_name));
114
115 /* Skip past it in the archive. */
116
117 save_typeflag = current_header->header.typeflag;
118 set_next_block_after (current_header);
119 if (current_header->oldgnu_header.isextended)
120 skip_extended_headers ();
121
122 /* Skip to the next header on the archive. */
123
124 if (save_typeflag != DIRTYPE)
125 skip_file (current_stat.st_size);
126 continue;
127 }
128
129 (*do_something) ();
130 continue;
131
132 case HEADER_ZERO_BLOCK:
133 if (block_number_option)
134 {
135 char buf[UINTMAX_STRSIZE_BOUND];
136 fprintf (stdlis, _("block %s: ** Block of NULs **\n"),
137 STRINGIFY_BIGINT (current_block_ordinal (), buf));
138 }
139
140 set_next_block_after (current_header);
141 status = prev_status;
142 if (ignore_zeros_option)
143 continue;
144 break;
145
146 case HEADER_END_OF_FILE:
147 if (block_number_option)
148 {
149 char buf[UINTMAX_STRSIZE_BOUND];
150 fprintf (stdlis, _("block %s: ** End of File **\n"),
151 STRINGIFY_BIGINT (current_block_ordinal (), buf));
152 }
153 break;
154
155 case HEADER_FAILURE:
156 /* If the previous header was good, tell them that we are
157 skipping bad ones. */
158 set_next_block_after (current_header);
159 switch (prev_status)
160 {
161 case HEADER_STILL_UNREAD:
162 ERROR ((0, 0, _("This does not look like a tar archive")));
163 /* Fall through. */
164
165 case HEADER_ZERO_BLOCK:
166 case HEADER_SUCCESS:
167 ERROR ((0, 0, _("Skipping to next header")));
168 break;
169
170 case HEADER_END_OF_FILE:
171 case HEADER_FAILURE:
172 /* We are in the middle of a cascade of errors. */
173 break;
174 }
175 continue;
176 }
177 break;
178 }
179
180 apply_delayed_set_stat ();
181 close_archive ();
182 names_notfound (); /* print names not found */
183 }
184
185 /*---------------------------------------------.
186 | Print a header block, based on tar options. |
187 `---------------------------------------------*/
188
189 void
190 list_archive (void)
191 {
192 /* Print the header block. */
193
194 if (verbose_option)
195 {
196 if (verbose_option > 1)
197 decode_header (current_header, &current_stat, &current_format, 0);
198 print_header ();
199 }
200
201 if (incremental_option && current_header->header.typeflag == GNUTYPE_DUMPDIR)
202 {
203 off_t size;
204 size_t written, check;
205 union block *data_block;
206
207 set_next_block_after (current_header);
208 if (multi_volume_option)
209 {
210 assign_string (&save_name, current_file_name);
211 save_totsize = current_stat.st_size;
212 }
213 for (size = current_stat.st_size; size > 0; size -= written)
214 {
215 if (multi_volume_option)
216 save_sizeleft = size;
217 data_block = find_next_block ();
218 if (!data_block)
219 {
220 ERROR ((0, 0, _("EOF in archive file")));
221 break; /* FIXME: What happens, then? */
222 }
223 written = available_space_after (data_block);
224 if (written > size)
225 written = size;
226 errno = 0; /* FIXME: errno should be read-only */
227 check = fwrite (data_block->buffer, sizeof (char), written, stdlis);
228 set_next_block_after ((union block *)
229 (data_block->buffer + written - 1));
230 if (check != written)
231 {
232 ERROR ((0, errno, _("Only wrote %lu of %lu bytes to file %s"),
233 (unsigned long) check,
234 (unsigned long) written, current_file_name));
235 skip_file (size - written);
236 break;
237 }
238 }
239 if (multi_volume_option)
240 assign_string (&save_name, 0);
241 fputc ('\n', stdlis);
242 fflush (stdlis);
243 return;
244
245 }
246
247 /* Skip past the header in the archive, and past any extended headers. */
248
249 set_next_block_after (current_header);
250 if (current_header->oldgnu_header.isextended)
251 skip_extended_headers ();
252
253 if (multi_volume_option)
254 assign_string (&save_name, current_file_name);
255
256 /* Skip to the next header on the archive. */
257
258 skip_file (current_stat.st_size);
259
260 if (multi_volume_option)
261 assign_string (&save_name, 0);
262 }
263
264 /*-----------------------------------------------------------------------.
265 | Read a block that's supposed to be a header block. Return its address |
266 | in "current_header", and if it is good, the file's size in |
267 | current_stat.st_size. |
268 | |
269 | Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a |
270 | block full of zeros (EOF marker). |
271 | |
272 | You must always set_next_block_after(current_header) to skip past the |
273 | header which this routine reads. |
274 `-----------------------------------------------------------------------*/
275
276 /* The standard BSD tar sources create the checksum by adding up the
277 bytes in the header as type char. I think the type char was unsigned
278 on the PDP-11, but it's signed on the Next and Sun. It looks like the
279 sources to BSD tar were never changed to compute the checksum
280 correctly, so both the Sun and Next add the bytes of the header as
281 signed chars. This doesn't cause a problem until you get a file with
282 a name containing characters with the high bit set. So read_header
283 computes two checksums -- signed and unsigned. */
284
285 enum read_header
286 read_header (void)
287 {
288 size_t i;
289 int unsigned_sum; /* the POSIX one :-) */
290 int signed_sum; /* the Sun one :-( */
291 int recorded_sum;
292 uintmax_t parsed_sum;
293 char *p;
294 union block *header;
295 char **longp;
296 char *bp;
297 union block *data_block;
298 size_t size, written;
299 static char *next_long_name, *next_long_link;
300
301 while (1)
302 {
303 header = find_next_block ();
304 current_header = header;
305 if (!header)
306 return HEADER_END_OF_FILE;
307
308 unsigned_sum = 0;
309 signed_sum = 0;
310 p = header->buffer;
311 for (i = sizeof *header; i-- != 0;)
312 {
313 unsigned_sum += (unsigned char) *p;
314 signed_sum += signed_char (*p++);
315 }
316
317 if (unsigned_sum == 0)
318 return HEADER_ZERO_BLOCK;
319
320 /* Adjust checksum to count the "chksum" field as blanks. */
321
322 for (i = sizeof header->header.chksum; i-- != 0;)
323 {
324 unsigned_sum -= (unsigned char) header->header.chksum[i];
325 signed_sum -= signed_char (header->header.chksum[i]);
326 }
327 unsigned_sum += ' ' * sizeof header->header.chksum;
328 signed_sum += ' ' * sizeof header->header.chksum;
329
330 parsed_sum = from_header (header->header.chksum,
331 sizeof header->header.chksum, 0,
332 (uintmax_t) 0,
333 (uintmax_t) TYPE_MAXIMUM (int));
334 if (parsed_sum == (uintmax_t) -1)
335 return HEADER_FAILURE;
336
337 recorded_sum = parsed_sum;
338
339 if (unsigned_sum != recorded_sum && signed_sum != recorded_sum)
340 return HEADER_FAILURE;
341
342 /* Good block. Decode file size and return. */
343
344 if (header->header.typeflag == LNKTYPE)
345 current_stat.st_size = 0; /* links 0 size on tape */
346 else
347 current_stat.st_size = OFF_FROM_HEADER (header->header.size);
348
349 if (header->header.typeflag == GNUTYPE_LONGNAME
350 || header->header.typeflag == GNUTYPE_LONGLINK)
351 {
352 longp = ((header->header.typeflag == GNUTYPE_LONGNAME)
353 ? &next_long_name
354 : &next_long_link);
355
356 set_next_block_after (header);
357 if (*longp)
358 free (*longp);
359 size = current_stat.st_size;
360 if (size != current_stat.st_size)
361 FATAL_ERROR ((0, 0, _("Memory exhausted")));
362 bp = *longp = xmalloc (size);
363
364 for (; size > 0; size -= written)
365 {
366 data_block = find_next_block ();
367 if (! data_block)
368 {
369 ERROR ((0, 0, _("Unexpected EOF on archive file")));
370 break;
371 }
372 written = available_space_after (data_block);
373 if (written > size)
374 written = size;
375
376 memcpy (bp, data_block->buffer, written);
377 bp += written;
378 set_next_block_after ((union block *)
379 (data_block->buffer + written - 1));
380 }
381
382 /* Loop! */
383
384 }
385 else
386 {
387 char *name;
388 struct posix_header *h = &current_header->header;
389 char namebuf[sizeof h->prefix + 1 + NAME_FIELD_SIZE + 1];
390
391 name = next_long_name;
392 if (! name)
393 {
394 /* Accept file names as specified by POSIX.1-1996
395 section 10.1.1. */
396 int posix_header = strcmp (h->magic, TMAGIC) == 0;
397 char *np = namebuf;
398
399 if (posix_header && h->prefix[0])
400 {
401 memcpy (np, h->prefix, sizeof h->prefix);
402 np[sizeof h->prefix] = '\0';
403 np += strlen (np);
404 *np++ = '/';
405 }
406 memcpy (np, h->name, sizeof h->name);
407 np[sizeof h->name] = '\0';
408 name = namebuf;
409 }
410 assign_string (&current_file_name, name);
411 if (next_long_name)
412 {
413 free (next_long_name);
414 next_long_name = 0;
415 }
416
417 name = next_long_link;
418 if (! name)
419 {
420 memcpy (namebuf, h->linkname, sizeof h->linkname);
421 namebuf[sizeof h->linkname] = '\0';
422 name = namebuf;
423 }
424 assign_string (&current_link_name, name);
425 if (next_long_link)
426 {
427 free (next_long_link);
428 next_long_link = 0;
429 }
430
431 return HEADER_SUCCESS;
432 }
433 }
434 }
435
436 /*-------------------------------------------------------------------------.
437 | Decode things from a file HEADER block into STAT_INFO, also setting |
438 | *FORMAT_POINTER depending on the header block format. If DO_USER_GROUP, |
439 | decode the user/group information (this is useful for extraction, but |
440 | waste time when merely listing). |
441 | |
442 | read_header() has already decoded the checksum and length, so we don't. |
443 | |
444 | This routine should *not* be called twice for the same block, since the |
445 | two calls might use different DO_USER_GROUP values and thus might end up |
446 | with different uid/gid for the two calls. If anybody wants the uid/gid |
447 | they should decode it first, and other callers should decode it without |
448 | uid/gid before calling a routine, e.g. print_header, that assumes |
449 | decoded data. |
450 `-------------------------------------------------------------------------*/
451
452 void
453 decode_header (union block *header, struct stat *stat_info,
454 enum archive_format *format_pointer, int do_user_group)
455 {
456 enum archive_format format;
457
458 if (strcmp (header->header.magic, TMAGIC) == 0)
459 format = POSIX_FORMAT;
460 else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
461 format = OLDGNU_FORMAT;
462 else
463 format = V7_FORMAT;
464 *format_pointer = format;
465
466 stat_info->st_mode = MODE_FROM_HEADER (header->header.mode);
467 stat_info->st_mtime = TIME_FROM_HEADER (header->header.mtime);
468
469 if (format == OLDGNU_FORMAT && incremental_option)
470 {
471 stat_info->st_atime = TIME_FROM_HEADER (header->oldgnu_header.atime);
472 stat_info->st_ctime = TIME_FROM_HEADER (header->oldgnu_header.ctime);
473 }
474
475 if (format == V7_FORMAT)
476 {
477 stat_info->st_uid = UID_FROM_HEADER (header->header.uid);
478 stat_info->st_gid = GID_FROM_HEADER (header->header.gid);
479 stat_info->st_rdev = 0;
480 }
481 else
482 {
483 if (do_user_group)
484 {
485 /* FIXME: Decide if this should somewhat depend on -p. */
486
487 if (numeric_owner_option
488 || !*header->header.uname
489 || !uname_to_uid (header->header.uname, &stat_info->st_uid))
490 stat_info->st_uid = UID_FROM_HEADER (header->header.uid);
491
492 if (numeric_owner_option
493 || !*header->header.gname
494 || !gname_to_gid (header->header.gname, &stat_info->st_gid))
495 stat_info->st_gid = GID_FROM_HEADER (header->header.gid);
496 }
497 switch (header->header.typeflag)
498 {
499 case BLKTYPE:
500 stat_info->st_rdev
501 = makedev (MAJOR_FROM_HEADER (header->header.devmajor),
502 MINOR_FROM_HEADER (header->header.devminor));
503 break;
504
505 case CHRTYPE:
506 stat_info->st_rdev
507 = makedev (MAJOR_FROM_HEADER (header->header.devmajor),
508 MINOR_FROM_HEADER (header->header.devminor));
509 break;
510
511 default:
512 stat_info->st_rdev = 0;
513 }
514 }
515 }
516
517 /*------------------------------------------------------------------------.
518 | Convert buffer at WHERE0 of size DIGS from external format to uintmax_t.|
519 | The data is of type TYPE. The buffer must represent a value in the |
520 | range -MINUS_MINVAL through MAXVAL. DIGS must be positive. |
521 `------------------------------------------------------------------------*/
522
523 static uintmax_t
524 from_header (char const *where0, size_t digs, char const *type,
525 uintmax_t minus_minval, uintmax_t maxval)
526 {
527 uintmax_t value;
528 char const *where = where0;
529 char const *lim = where + digs;
530 int negative = 0;
531
532 /* Accommodate buggy tar of unknown vintage, which outputs leading
533 NUL if the previous field overflows. */
534 where += !*where;
535
536 /* Accommodate older tars, which output leading spaces. */
537 for (;;)
538 {
539 if (where == lim)
540 {
541 if (type)
542 ERROR ((0, 0,
543 _("Blanks in header where numeric %s value expected"),
544 type));
545 return -1;
546 }
547 if (!ISSPACE ((unsigned char) *where))
548 break;
549 where++;
550 }
551
552 value = 0;
553 if (ISODIGIT (*where))
554 {
555 char const *where1 = where;
556 uintmax_t overflow = 0;
557
558 for (;;)
559 {
560 value += *where++ - '0';
561 if (where == lim || ! ISODIGIT (*where))
562 break;
563 overflow |= value ^ (value << LG_8 >> LG_8);
564 value <<= LG_8;
565 }
566
567 /* Parse the output of older, unportable tars, which generate
568 negative values in two's complement octal. */
569 if ((overflow || maxval < value) && '4' <= *where1)
570 {
571 /* Compute the negative of the input value, assuming two's
572 complement. */
573 for (value = 0, where = where1, overflow = 0; ; )
574 {
575 value += 7 - (*where++ - '0');
576 if (where == lim || ! ISODIGIT (*where))
577 break;
578 overflow |= value ^ (value << LG_8 >> LG_8);
579 value <<= LG_8;
580 }
581 value++;
582 overflow |= !value;
583
584 if (!overflow && value <= minus_minval)
585 {
586 WARN ((0, 0,
587 _("Archive octal value %.*s is out of %s range; assuming two's complement"),
588 (int) (where - where1), where1, type));
589 negative = 1;
590 }
591 }
592
593 if (overflow)
594 {
595 ERROR ((0, 0,
596 _("Archive octal value %.*s is out of %s range"),
597 (int) (where - where1), where1, type));
598 return -1;
599 }
600 }
601 else if (type)
602 {
603 /* The following forms cannot appear as checksums, so we don't
604 check for them if TYPE is null. */
605
606 if (*where == '-' || *where == '+')
607 {
608 /* Parse base-64 output produced only by tar test versions
609 1.13.6 (1999-08-11) through 1.13.11 (1999-08-23).
610 Support for this will be withdrawn in future releases. */
611 int dig;
612 static int warned_once;
613 if (! warned_once)
614 {
615 warned_once = 1;
616 WARN ((0, 0,
617 _("Archive contains obsolescent base-64 headers")));
618 }
619 negative = *where++ == '-';
620 while (where != lim
621 && (dig = base64_map[(unsigned char) *where]) < 64)
622 {
623 if (value << LG_64 >> LG_64 != value)
624 {
625 ERROR ((0, 0,
626 _("Archive signed base-64 string `%.*s' is out of %s range"),
627 (int) digs, where0, type));
628 return -1;
629 }
630 value = (value << LG_64) | dig;
631 where++;
632 }
633 }
634 else if (*where == '\200' /* positive base-256 */
635 || *where == '\377' /* negative base-256 */)
636 {
637 /* Parse base-256 output. A nonnegative number N is
638 represented as (256**DIGS)/2 + N; a negative number -N is
639 represented as (256**DIGS) - N, i.e. as two's complement.
640 The representation guarantees that the leading bit is
641 always on, so that we don't confuse this format with the
642 others (assuming ASCII bytes of 8 bits or more). */
643 int signbit = *where & (1 << (LG_256 - 2));
644 uintmax_t topbits = (((uintmax_t) - signbit)
645 << (CHAR_BIT * sizeof (uintmax_t)
646 - LG_256 - (LG_256 - 2)));
647 value = (*where++ & ((1 << (LG_256 - 2)) - 1)) - signbit;
648 for (;;)
649 {
650 value = (value << LG_256) + (unsigned char) *where++;
651 if (where == lim)
652 break;
653 if (((value << LG_256 >> LG_256) | topbits) != value)
654 {
655 ERROR ((0, 0,
656 _("Archive base-256 value is out of %s range"),
657 type));
658 return -1;
659 }
660 }
661 negative = signbit;
662 if (negative)
663 value = -value;
664 }
665 }
666
667 if (where != lim && *where && !ISSPACE ((unsigned char) *where))
668 {
669 if (type)
670 {
671 char buf[1000]; /* Big enough to represent any header. */
672 static struct quoting_options *o;
673
674 if (!o)
675 {
676 o = clone_quoting_options (0);
677 set_quoting_style (o, c_quoting_style);
678 }
679
680 while (where0 != lim && ! lim[-1])
681 lim--;
682 quotearg_buffer (buf, sizeof buf, where0, lim - where, o);
683 ERROR ((0, 0,
684 _("Archive contains `%.*s' where numeric %s value expected"),
685 (int) sizeof buf, buf, type));
686 }
687
688 return -1;
689 }
690
691 if (value <= (negative ? minus_minval : maxval))
692 return negative ? -value : value;
693
694 if (type)
695 {
696 char minval_buf[UINTMAX_STRSIZE_BOUND + 1];
697 char maxval_buf[UINTMAX_STRSIZE_BOUND];
698 char value_buf[UINTMAX_STRSIZE_BOUND + 1];
699 char *minval_string = STRINGIFY_BIGINT (minus_minval, minval_buf + 1);
700 char *value_string = STRINGIFY_BIGINT (value, value_buf + 1);
701 if (negative)
702 *--value_string = '-';
703 if (minus_minval)
704 *--minval_string = '-';
705 ERROR ((0, 0, _("Archive value %s is out of %s range %s..%s"),
706 value_string, type,
707 minval_string, STRINGIFY_BIGINT (maxval, maxval_buf)));
708 }
709
710 return -1;
711 }
712
713 gid_t
714 gid_from_header (const char *p, size_t s)
715 {
716 return from_header (p, s, "gid_t",
717 - (uintmax_t) TYPE_MINIMUM (gid_t),
718 (uintmax_t) TYPE_MAXIMUM (gid_t));
719 }
720
721 major_t
722 major_from_header (const char *p, size_t s)
723 {
724 return from_header (p, s, "major_t",
725 - (uintmax_t) TYPE_MINIMUM (major_t),
726 (uintmax_t) TYPE_MAXIMUM (major_t));
727 }
728
729 minor_t
730 minor_from_header (const char *p, size_t s)
731 {
732 return from_header (p, s, "minor_t",
733 - (uintmax_t) TYPE_MINIMUM (minor_t),
734 (uintmax_t) TYPE_MAXIMUM (minor_t));
735 }
736
737 mode_t
738 mode_from_header (const char *p, size_t s)
739 {
740 /* Do not complain about unrecognized mode bits. */
741 unsigned u = from_header (p, s, "mode_t",
742 - (uintmax_t) TYPE_MINIMUM (mode_t),
743 TYPE_MAXIMUM (uintmax_t));
744 return ((u & TSUID ? S_ISUID : 0)
745 | (u & TSGID ? S_ISGID : 0)
746 | (u & TSVTX ? S_ISVTX : 0)
747 | (u & TUREAD ? S_IRUSR : 0)
748 | (u & TUWRITE ? S_IWUSR : 0)
749 | (u & TUEXEC ? S_IXUSR : 0)
750 | (u & TGREAD ? S_IRGRP : 0)
751 | (u & TGWRITE ? S_IWGRP : 0)
752 | (u & TGEXEC ? S_IXGRP : 0)
753 | (u & TOREAD ? S_IROTH : 0)
754 | (u & TOWRITE ? S_IWOTH : 0)
755 | (u & TOEXEC ? S_IXOTH : 0));
756 }
757
758 off_t
759 off_from_header (const char *p, size_t s)
760 {
761 /* Negative offsets are not allowed in tar files, so invoke
762 from_header with minimum value 0, not TYPE_MINIMUM (off_t). */
763 return from_header (p, s, "off_t", (uintmax_t) 0,
764 (uintmax_t) TYPE_MAXIMUM (off_t));
765 }
766
767 size_t
768 size_from_header (const char *p, size_t s)
769 {
770 return from_header (p, s, "size_t", (uintmax_t) 0,
771 (uintmax_t) TYPE_MAXIMUM (size_t));
772 }
773
774 time_t
775 time_from_header (const char *p, size_t s)
776 {
777 time_t t = from_header (p, s, "time_t",
778 - (uintmax_t) TYPE_MINIMUM (time_t),
779 (uintmax_t) TYPE_MAXIMUM (time_t));
780 if (start_time < t && time (0) < t)
781 WARN ((0, 0, _("Archive contains future timestamp %s"), tartime (t)));
782 return t;
783 }
784
785 uid_t
786 uid_from_header (const char *p, size_t s)
787 {
788 return from_header (p, s, "uid_t",
789 - (uintmax_t) TYPE_MINIMUM (uid_t),
790 (uintmax_t) TYPE_MAXIMUM (uid_t));
791 }
792
793 uintmax_t
794 uintmax_from_header (const char *p, size_t s)
795 {
796 return from_header (p, s, "uintmax_t", (uintmax_t) 0,
797 TYPE_MAXIMUM (uintmax_t));
798 }
799
800
801 /*----------------------------------------------------------------------.
802 | Format O as a null-terminated decimal string into BUF _backwards_; |
803 | return pointer to start of result. |
804 `----------------------------------------------------------------------*/
805 char *
806 stringify_uintmax_t_backwards (uintmax_t o, char *buf)
807 {
808 *--buf = '\0';
809 do
810 *--buf = '0' + (int) (o % 10);
811 while ((o /= 10) != 0);
812 return buf;
813 }
814
815 /* Return a printable representation of T. The result points to
816 static storage that can be reused in the next call to this
817 function, to ctime, or to asctime. */
818 char const *
819 tartime (time_t t)
820 {
821 static char buffer[max (UINTMAX_STRSIZE_BOUND + 1,
822 INT_STRLEN_BOUND (int) + 16)];
823 char *p;
824
825 #if USE_OLD_CTIME
826 p = ctime (&t);
827 if (p)
828 {
829 char const *time_stamp = p + 4;
830 for (p += 16; p[4] != '\n'; p++)
831 p[0] = p[4];
832 p[0] = '\0';
833 return time_stamp;
834 }
835 #else
836 /* Use ISO 8610 format. See:
837 http://www.cl.cam.ac.uk/~mgk25/iso-time.html */
838 struct tm *tm = localtime (&t);
839 if (tm)
840 {
841 sprintf (buffer, "%04d-%02d-%02d %02d:%02d:%02d",
842 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
843 tm->tm_hour, tm->tm_min, tm->tm_sec);
844 return buffer;
845 }
846 #endif
847
848 /* The time stamp cannot be broken down, most likely because it
849 is out of range. Convert it as an integer,
850 right-adjusted in a field with the same width as the usual
851 19-byte 4-year ISO time format. */
852 p = stringify_uintmax_t_backwards (t < 0 ? - (uintmax_t) t : (uintmax_t) t,
853 buffer + sizeof buffer);
854 if (t < 0)
855 *--p = '-';
856 while (buffer + sizeof buffer - 19 - 1 < p)
857 *--p = ' ';
858 return p;
859 }
860
861 /*-------------------------------------------------------------------------.
862 | Decode MODE from its binary form in a stat structure, and encode it into |
863 | a 9 characters string STRING, terminated with a NUL. |
864 `-------------------------------------------------------------------------*/
865
866 static void
867 decode_mode (mode_t mode, char *string)
868 {
869 *string++ = mode & S_IRUSR ? 'r' : '-';
870 *string++ = mode & S_IWUSR ? 'w' : '-';
871 *string++ = (mode & S_ISUID
872 ? (mode & S_IXUSR ? 's' : 'S')
873 : (mode & S_IXUSR ? 'x' : '-'));
874 *string++ = mode & S_IRGRP ? 'r' : '-';
875 *string++ = mode & S_IWGRP ? 'w' : '-';
876 *string++ = (mode & S_ISGID
877 ? (mode & S_IXGRP ? 's' : 'S')
878 : (mode & S_IXGRP ? 'x' : '-'));
879 *string++ = mode & S_IROTH ? 'r' : '-';
880 *string++ = mode & S_IWOTH ? 'w' : '-';
881 *string++ = (mode & S_ISVTX
882 ? (mode & S_IXOTH ? 't' : 'T')
883 : (mode & S_IXOTH ? 'x' : '-'));
884 *string = '\0';
885 }
886
887 /*-------------------------------------------------------------------------.
888 | Actually print it. |
889 | |
890 | Plain and fancy file header block logging. Non-verbose just prints the |
891 | name, e.g. for "tar t" or "tar x". This should just contain file names, |
892 | so it can be fed back into tar with xargs or the "-T" option. The |
893 | verbose option can give a bunch of info, one line per file. I doubt |
894 | anybody tries to parse its format, or if they do, they shouldn't. Unix |
895 | tar is pretty random here anyway. |
896 `-------------------------------------------------------------------------*/
897
898 /* FIXME: Note that print_header uses the globals HEAD, HSTAT, and
899 HEAD_STANDARD, which must be set up in advance. Not very clean... */
900
901 /* UGSWIDTH starts with 18, so with user and group names <= 8 chars, the
902 columns never shift during the listing. */
903 #define UGSWIDTH 18
904 static int ugswidth = UGSWIDTH; /* maximum width encountered so far */
905
906 /* DATEWIDTH is the number of columns taken by the date and time fields. */
907 #if USE_OLD_CDATE
908 # define DATEWIDTH 19
909 #else
910 # define DATEWIDTH 18
911 #endif
912
913 void
914 print_header (void)
915 {
916 char modes[11];
917 char const *time_stamp;
918 /* These hold formatted ints. */
919 char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND];
920 char *user, *group;
921 char size[2 * UINTMAX_STRSIZE_BOUND];
922 /* holds formatted size or major,minor */
923 char uintbuf[UINTMAX_STRSIZE_BOUND];
924 int pad;
925 char *name;
926
927 if (block_number_option)
928 {
929 char buf[UINTMAX_STRSIZE_BOUND];
930 fprintf (stdlis, _("block %s: "),
931 STRINGIFY_BIGINT (current_block_ordinal (), buf));
932 }
933
934 if (verbose_option <= 1)
935 {
936 /* Just the fax, mam. */
937
938 char *quoted_name = quote_copy_string (current_file_name);
939
940 if (quoted_name)
941 {
942 fprintf (stdlis, "%s\n", quoted_name);
943 free (quoted_name);
944 }
945 else
946 fprintf (stdlis, "%s\n", current_file_name);
947 }
948 else
949 {
950 /* File type and modes. */
951
952 modes[0] = '?';
953 switch (current_header->header.typeflag)
954 {
955 case GNUTYPE_VOLHDR:
956 modes[0] = 'V';
957 break;
958
959 case GNUTYPE_MULTIVOL:
960 modes[0] = 'M';
961 break;
962
963 case GNUTYPE_NAMES:
964 modes[0] = 'N';
965 break;
966
967 case GNUTYPE_LONGNAME:
968 case GNUTYPE_LONGLINK:
969 ERROR ((0, 0, _("Visible longname error")));
970 break;
971
972 case GNUTYPE_SPARSE:
973 case REGTYPE:
974 case AREGTYPE:
975 case LNKTYPE:
976 modes[0] = '-';
977 if (current_file_name[strlen (current_file_name) - 1] == '/')
978 modes[0] = 'd';
979 break;
980 case GNUTYPE_DUMPDIR:
981 modes[0] = 'd';
982 break;
983 case DIRTYPE:
984 modes[0] = 'd';
985 break;
986 case SYMTYPE:
987 modes[0] = 'l';
988 break;
989 case BLKTYPE:
990 modes[0] = 'b';
991 break;
992 case CHRTYPE:
993 modes[0] = 'c';
994 break;
995 case FIFOTYPE:
996 modes[0] = 'p';
997 break;
998 case CONTTYPE:
999 modes[0] = 'C';
1000 break;
1001 }
1002
1003 decode_mode (current_stat.st_mode, modes + 1);
1004
1005 /* Time stamp. */
1006
1007 time_stamp = tartime (current_stat.st_mtime);
1008
1009 /* User and group names. */
1010
1011 if (*current_header->header.uname && current_format != V7_FORMAT
1012 && !numeric_owner_option)
1013 user = current_header->header.uname;
1014 else
1015 user = STRINGIFY_BIGINT (UINTMAX_FROM_HEADER
1016 (current_header->header.uid),
1017 uform);
1018
1019 if (*current_header->header.gname && current_format != V7_FORMAT
1020 && !numeric_owner_option)
1021 group = current_header->header.gname;
1022 else
1023 group = STRINGIFY_BIGINT (UINTMAX_FROM_HEADER
1024 (current_header->header.gid),
1025 gform);
1026
1027 /* Format the file size or major/minor device numbers. */
1028
1029 switch (current_header->header.typeflag)
1030 {
1031 case CHRTYPE:
1032 case BLKTYPE:
1033 strcpy (size,
1034 STRINGIFY_BIGINT (major (current_stat.st_rdev), uintbuf));
1035 strcat (size, ",");
1036 strcat (size,
1037 STRINGIFY_BIGINT (minor (current_stat.st_rdev), uintbuf));
1038 break;
1039 case GNUTYPE_SPARSE:
1040 strcpy (size,
1041 STRINGIFY_BIGINT
1042 (UINTMAX_FROM_HEADER (current_header
1043 ->oldgnu_header.realsize),
1044 uintbuf));
1045 break;
1046 default:
1047 strcpy (size, STRINGIFY_BIGINT (current_stat.st_size, uintbuf));
1048 break;
1049 }
1050
1051 /* Figure out padding and print the whole line. */
1052
1053 pad = strlen (user) + strlen (group) + strlen (size) + 1;
1054 if (pad > ugswidth)
1055 ugswidth = pad;
1056
1057 fprintf (stdlis, "%s %s/%s %*s%s %s",
1058 modes, user, group, ugswidth - pad, "", size, time_stamp);
1059
1060 name = quote_copy_string (current_file_name);
1061 if (name)
1062 {
1063 fprintf (stdlis, " %s", name);
1064 free (name);
1065 }
1066 else
1067 fprintf (stdlis, " %s", current_file_name);
1068
1069 switch (current_header->header.typeflag)
1070 {
1071 case SYMTYPE:
1072 name = quote_copy_string (current_link_name);
1073 if (name)
1074 {
1075 fprintf (stdlis, " -> %s\n", name);
1076 free (name);
1077 }
1078 else
1079 fprintf (stdlis, " -> %s\n", current_link_name);
1080 break;
1081
1082 case LNKTYPE:
1083 name = quote_copy_string (current_link_name);
1084 if (name)
1085 {
1086 fprintf (stdlis, _(" link to %s\n"), name);
1087 free (name);
1088 }
1089 else
1090 fprintf (stdlis, _(" link to %s\n"), current_link_name);
1091 break;
1092
1093 default:
1094 fprintf (stdlis, _(" unknown file type `%c'\n"),
1095 current_header->header.typeflag);
1096 break;
1097
1098 case AREGTYPE:
1099 case REGTYPE:
1100 case GNUTYPE_SPARSE:
1101 case CHRTYPE:
1102 case BLKTYPE:
1103 case DIRTYPE:
1104 case FIFOTYPE:
1105 case CONTTYPE:
1106 case GNUTYPE_DUMPDIR:
1107 putc ('\n', stdlis);
1108 break;
1109
1110 case GNUTYPE_VOLHDR:
1111 fprintf (stdlis, _("--Volume Header--\n"));
1112 break;
1113
1114 case GNUTYPE_MULTIVOL:
1115 strcpy (size,
1116 STRINGIFY_BIGINT
1117 (UINTMAX_FROM_HEADER (current_header->oldgnu_header.offset),
1118 uintbuf));
1119 fprintf (stdlis, _("--Continued at byte %s--\n"), size);
1120 break;
1121
1122 case GNUTYPE_NAMES:
1123 fprintf (stdlis, _("--Mangled file names--\n"));
1124 break;
1125 }
1126 }
1127 fflush (stdlis);
1128 }
1129
1130 /*--------------------------------------------------------------.
1131 | Print a similar line when we make a directory automatically. |
1132 `--------------------------------------------------------------*/
1133
1134 void
1135 print_for_mkdir (char *pathname, int length, mode_t mode)
1136 {
1137 char modes[11];
1138 char *name;
1139
1140 if (verbose_option > 1)
1141 {
1142 /* File type and modes. */
1143
1144 modes[0] = 'd';
1145 decode_mode (mode, modes + 1);
1146
1147 if (block_number_option)
1148 {
1149 char buf[UINTMAX_STRSIZE_BOUND];
1150 fprintf (stdlis, _("block %s: "),
1151 STRINGIFY_BIGINT (current_block_ordinal (), buf));
1152 }
1153 name = quote_copy_string (pathname);
1154 if (name)
1155 {
1156 fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
1157 _("Creating directory:"), length, name);
1158 free (name);
1159 }
1160 else
1161 fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
1162 _("Creating directory:"), length, pathname);
1163 }
1164 }
1165
1166 /*--------------------------------------------------------.
1167 | Skip over SIZE bytes of data in blocks in the archive. |
1168 `--------------------------------------------------------*/
1169
1170 void
1171 skip_file (off_t size)
1172 {
1173 union block *x;
1174
1175 if (multi_volume_option)
1176 {
1177 save_totsize = size;
1178 save_sizeleft = size;
1179 }
1180
1181 while (size > 0)
1182 {
1183 x = find_next_block ();
1184 if (! x)
1185 FATAL_ERROR ((0, 0, _("Unexpected EOF on archive file")));
1186
1187 set_next_block_after (x);
1188 size -= BLOCKSIZE;
1189 if (multi_volume_option)
1190 save_sizeleft -= BLOCKSIZE;
1191 }
1192 }
1193
1194 /*---.
1195 | ? |
1196 `---*/
1197
1198 void
1199 skip_extended_headers (void)
1200 {
1201 union block *exhdr;
1202
1203 do
1204 {
1205 exhdr = find_next_block ();
1206 if (!exhdr)
1207 FATAL_ERROR ((0, 0, _("Unexpected EOF on archive file")));
1208 set_next_block_after (exhdr);
1209 }
1210 while (exhdr->sparse_header.isextended);
1211 }
This page took 0.089663 seconds and 5 git commands to generate.