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