]> Dogcows Code - chaz/tar/blob - src/list.c
(read_and, list_archive): Simplify code.
[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 older tars, which output leading spaces, and at least one
516 buggy tar, which outputs leading NUL if the previous field overflows. */
517 for (;;)
518 {
519 if (where == lim)
520 {
521 if (type)
522 ERROR ((0, 0,
523 _("Empty header where numeric %s value expected"),
524 type));
525 return -1;
526 }
527 if (!ISSPACE ((unsigned char) *where) && *where)
528 break;
529 where++;
530 }
531
532 value = 0;
533 if (ISODIGIT (*where))
534 {
535 do
536 {
537 if (value << LG_8 >> LG_8 != value)
538 goto out_of_range;
539 value = (value << LG_8) | (*where++ - '0');
540 }
541 while (where != lim && ISODIGIT (*where));
542
543 /* Parse the output of older tars, which output negative values
544 in two's complement octal. This method works only if the
545 type has the same number of bits as it did on the host that
546 created the tar file, but that's the best we can do. */
547 if (maxval < value && value - maxval <= minus_minval)
548 {
549 value = minus_minval - (value - maxval);
550 negative = 1;
551 }
552 }
553 else if (*where == '-' || *where == '+')
554 {
555 int dig;
556 negative = *where++ == '-';
557 while (where != lim
558 && (dig = base64_map[(unsigned char) *where]) < 64)
559 {
560 if (value << LG_64 >> LG_64 != value)
561 goto out_of_range;
562 value = (value << LG_64) | dig;
563 where++;
564 }
565 }
566
567 if (where != lim && *where && !ISSPACE ((unsigned char) *where))
568 {
569 if (type)
570 {
571 char buf[1000]; /* Big enough to represent any header. */
572 static struct quoting_options *o;
573
574 if (!o)
575 {
576 o = clone_quoting_options ((struct quoting_options *) 0);
577 set_quoting_style (o, c_quoting_style);
578 }
579
580 while (where0 != lim && ! lim[-1])
581 lim--;
582 quotearg_buffer (buf, sizeof buf, where0, lim - where, o);
583 ERROR ((0, 0,
584 _("Header contains `%.*s' where numeric %s value expected"),
585 (int) sizeof buf, buf, type));
586 }
587
588 return -1;
589 }
590
591 if (value <= (negative ? minus_minval : maxval))
592 return negative ? -value : value;
593
594 out_of_range:
595 if (type)
596 ERROR ((0, 0, _("Numeric value `%.*s' is out of range for %s"),
597 (int) digs, where0, type));
598 return -1;
599 }
600
601 gid_t
602 gid_from_chars (const char *p, size_t s)
603 {
604 return from_chars (p, s, "gid_t",
605 - (uintmax_t) TYPE_MINIMUM (gid_t),
606 (uintmax_t) TYPE_MAXIMUM (gid_t));
607 }
608
609 major_t
610 major_from_chars (const char *p, size_t s)
611 {
612 return from_chars (p, s, "major_t",
613 - (uintmax_t) TYPE_MINIMUM (major_t),
614 (uintmax_t) TYPE_MAXIMUM (major_t));
615 }
616
617 minor_t
618 minor_from_chars (const char *p, size_t s)
619 {
620 return from_chars (p, s, "minor_t",
621 - (uintmax_t) TYPE_MINIMUM (minor_t),
622 (uintmax_t) TYPE_MAXIMUM (minor_t));
623 }
624
625 mode_t
626 mode_from_chars (const char *p, size_t s)
627 {
628 /* Do not complain about unrecognized mode bits. */
629 unsigned u = from_chars (p, s, "mode_t",
630 - (uintmax_t) TYPE_MINIMUM (mode_t),
631 TYPE_MAXIMUM (uintmax_t));
632 return ((u & TSUID ? S_ISUID : 0)
633 | (u & TSGID ? S_ISGID : 0)
634 | (u & TSVTX ? S_ISVTX : 0)
635 | (u & TUREAD ? S_IRUSR : 0)
636 | (u & TUWRITE ? S_IWUSR : 0)
637 | (u & TUEXEC ? S_IXUSR : 0)
638 | (u & TGREAD ? S_IRGRP : 0)
639 | (u & TGWRITE ? S_IWGRP : 0)
640 | (u & TGEXEC ? S_IXGRP : 0)
641 | (u & TOREAD ? S_IROTH : 0)
642 | (u & TOWRITE ? S_IWOTH : 0)
643 | (u & TOEXEC ? S_IXOTH : 0));
644 }
645
646 off_t
647 off_from_chars (const char *p, size_t s)
648 {
649 return from_chars (p, s, "off_t",
650 - (uintmax_t) TYPE_MINIMUM (off_t),
651 (uintmax_t) TYPE_MAXIMUM (off_t));
652 }
653
654 size_t
655 size_from_chars (const char *p, size_t s)
656 {
657 return from_chars (p, s, "size_t", (uintmax_t) 0,
658 (uintmax_t) TYPE_MAXIMUM (size_t));
659 }
660
661 time_t
662 time_from_chars (const char *p, size_t s)
663 {
664 return from_chars (p, s, "time_t",
665 - (uintmax_t) TYPE_MINIMUM (time_t),
666 (uintmax_t) TYPE_MAXIMUM (time_t));
667 }
668
669 uid_t
670 uid_from_chars (const char *p, size_t s)
671 {
672 return from_chars (p, s, "uid_t", (uintmax_t) 0,
673 (uintmax_t) TYPE_MAXIMUM (uid_t));
674 }
675
676 uintmax_t
677 uintmax_from_chars (const char *p, size_t s)
678 {
679 return from_chars (p, s, "uintmax_t", (uintmax_t) 0,
680 TYPE_MAXIMUM (uintmax_t));
681 }
682
683
684 /*----------------------------------------------------------------------.
685 | Format O as a null-terminated decimal string into BUF _backwards_; |
686 | return pointer to start of result. |
687 `----------------------------------------------------------------------*/
688 char *
689 stringify_uintmax_t_backwards (uintmax_t o, char *buf)
690 {
691 *--buf = '\0';
692 do
693 *--buf = '0' + (int) (o % 10);
694 while ((o /= 10) != 0);
695 return buf;
696 }
697
698 #if !USE_OLD_CTIME
699
700 /*-------------------------------------------.
701 | Return the time formatted along ISO 8601. |
702 `-------------------------------------------*/
703
704 /* Also, see http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html. */
705
706 static char *
707 isotime (const time_t *time)
708 {
709 static char buffer[INT_STRLEN_BOUND (int) + 16];
710 struct tm *tm = localtime (time);
711 if (tm)
712 sprintf (buffer, "%04d-%02d-%02d %02d:%02d:%02d",
713 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
714 tm->tm_hour, tm->tm_min, tm->tm_sec);
715 else
716 /* Interpose %s between ?? and - to avoid ANSI C trigraph brain damage. */
717 sprintf (buffer, "????%s-??%s-?? ??:??:??", "", "");
718
719 return buffer;
720 }
721
722 #endif /* not USE_OLD_CTIME */
723
724 /*-------------------------------------------------------------------------.
725 | Decode MODE from its binary form in a stat structure, and encode it into |
726 | a 9 characters string STRING, terminated with a NUL. |
727 `-------------------------------------------------------------------------*/
728
729 static void
730 decode_mode (mode_t mode, char *string)
731 {
732 *string++ = mode & S_IRUSR ? 'r' : '-';
733 *string++ = mode & S_IWUSR ? 'w' : '-';
734 *string++ = (mode & S_ISUID
735 ? (mode & S_IXUSR ? 's' : 'S')
736 : (mode & S_IXUSR ? 'x' : '-'));
737 *string++ = mode & S_IRGRP ? 'r' : '-';
738 *string++ = mode & S_IWGRP ? 'w' : '-';
739 *string++ = (mode & S_ISGID
740 ? (mode & S_IXGRP ? 's' : 'S')
741 : (mode & S_IXGRP ? 'x' : '-'));
742 *string++ = mode & S_IROTH ? 'r' : '-';
743 *string++ = mode & S_IWOTH ? 'w' : '-';
744 *string++ = (mode & S_ISVTX
745 ? (mode & S_IXOTH ? 't' : 'T')
746 : (mode & S_IXOTH ? 'x' : '-'));
747 *string = '\0';
748 }
749
750 /*-------------------------------------------------------------------------.
751 | Actually print it. |
752 | |
753 | Plain and fancy file header block logging. Non-verbose just prints the |
754 | name, e.g. for "tar t" or "tar x". This should just contain file names, |
755 | so it can be fed back into tar with xargs or the "-T" option. The |
756 | verbose option can give a bunch of info, one line per file. I doubt |
757 | anybody tries to parse its format, or if they do, they shouldn't. Unix |
758 | tar is pretty random here anyway. |
759 `-------------------------------------------------------------------------*/
760
761 /* FIXME: Note that print_header uses the globals HEAD, HSTAT, and
762 HEAD_STANDARD, which must be set up in advance. Not very clean... */
763
764 /* UGSWIDTH starts with 18, so with user and group names <= 8 chars, the
765 columns never shift during the listing. */
766 #define UGSWIDTH 18
767 static int ugswidth = UGSWIDTH; /* maximum width encountered so far */
768
769 /* DATEWIDTH is the number of columns taken by the date and time fields. */
770 #if USE_OLD_CDATE
771 # define DATEWIDTH 19
772 #else
773 # define DATEWIDTH 18
774 #endif
775
776 void
777 print_header (void)
778 {
779 char modes[11];
780 char const *timestamp;
781 /* These hold formatted ints. */
782 char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND];
783 char *user, *group;
784 char size[2 * UINTMAX_STRSIZE_BOUND];
785 /* holds formatted size or major,minor */
786 char uintbuf[UINTMAX_STRSIZE_BOUND];
787 time_t longie; /* to make ctime() call portable */
788 int pad;
789 char *name;
790
791 if (block_number_option)
792 {
793 char buf[UINTMAX_STRSIZE_BOUND];
794 fprintf (stdlis, _("block %s: "),
795 STRINGIFY_BIGINT (current_block_ordinal (), buf));
796 }
797
798 if (verbose_option <= 1)
799 {
800 /* Just the fax, mam. */
801
802 char *quoted_name = quote_copy_string (current_file_name);
803
804 if (quoted_name)
805 {
806 fprintf (stdlis, "%s\n", quoted_name);
807 free (quoted_name);
808 }
809 else
810 fprintf (stdlis, "%s\n", current_file_name);
811 }
812 else
813 {
814 /* File type and modes. */
815
816 modes[0] = '?';
817 switch (current_header->header.typeflag)
818 {
819 case GNUTYPE_VOLHDR:
820 modes[0] = 'V';
821 break;
822
823 case GNUTYPE_MULTIVOL:
824 modes[0] = 'M';
825 break;
826
827 case GNUTYPE_NAMES:
828 modes[0] = 'N';
829 break;
830
831 case GNUTYPE_LONGNAME:
832 case GNUTYPE_LONGLINK:
833 ERROR ((0, 0, _("Visible longname error")));
834 break;
835
836 case GNUTYPE_SPARSE:
837 case REGTYPE:
838 case AREGTYPE:
839 case LNKTYPE:
840 modes[0] = '-';
841 if (current_file_name[strlen (current_file_name) - 1] == '/')
842 modes[0] = 'd';
843 break;
844 case GNUTYPE_DUMPDIR:
845 modes[0] = 'd';
846 break;
847 case DIRTYPE:
848 modes[0] = 'd';
849 break;
850 case SYMTYPE:
851 modes[0] = 'l';
852 break;
853 case BLKTYPE:
854 modes[0] = 'b';
855 break;
856 case CHRTYPE:
857 modes[0] = 'c';
858 break;
859 case FIFOTYPE:
860 modes[0] = 'p';
861 break;
862 case CONTTYPE:
863 modes[0] = 'C';
864 break;
865 }
866
867 decode_mode (current_stat.st_mode, modes + 1);
868
869 /* Timestamp. */
870
871 longie = current_stat.st_mtime;
872 #if USE_OLD_CTIME
873 {
874 char *ct = ctime (&longie);
875 if (ct)
876 {
877 timestamp = ct + 4;
878 for (ct += 16; ct[4] != '\n'; ct++)
879 ct[0] = ct[4];
880 ct[0] = '\0';
881 }
882 else
883 timestamp = "??? ?? ??:?? ????";
884 }
885 #else
886 timestamp = isotime (&longie);
887 #endif
888
889 /* User and group names. */
890
891 if (*current_header->header.uname && current_format != V7_FORMAT
892 && !numeric_owner_option)
893 user = current_header->header.uname;
894 else
895 user = STRINGIFY_BIGINT (UINTMAX_FROM_CHARS
896 (current_header->header.uid),
897 uform);
898
899 if (*current_header->header.gname && current_format != V7_FORMAT
900 && !numeric_owner_option)
901 group = current_header->header.gname;
902 else
903 group = STRINGIFY_BIGINT (UINTMAX_FROM_CHARS
904 (current_header->header.gid),
905 gform);
906
907 /* Format the file size or major/minor device numbers. */
908
909 switch (current_header->header.typeflag)
910 {
911 case CHRTYPE:
912 case BLKTYPE:
913 sprintf (size, "%lu,%lu",
914 (unsigned long) major (current_stat.st_rdev),
915 (unsigned long) minor (current_stat.st_rdev));
916 break;
917 case GNUTYPE_SPARSE:
918 strcpy (size,
919 STRINGIFY_BIGINT
920 (UINTMAX_FROM_CHARS (current_header->oldgnu_header.realsize),
921 uintbuf));
922 break;
923 default:
924 strcpy (size, STRINGIFY_BIGINT (current_stat.st_size, uintbuf));
925 break;
926 }
927
928 /* Figure out padding and print the whole line. */
929
930 pad = strlen (user) + strlen (group) + strlen (size) + 1;
931 if (pad > ugswidth)
932 ugswidth = pad;
933
934 fprintf (stdlis, "%s %s/%s %*s%s %s",
935 modes, user, group, ugswidth - pad, "", size, timestamp);
936
937 name = quote_copy_string (current_file_name);
938 if (name)
939 {
940 fprintf (stdlis, " %s", name);
941 free (name);
942 }
943 else
944 fprintf (stdlis, " %s", current_file_name);
945
946 switch (current_header->header.typeflag)
947 {
948 case SYMTYPE:
949 name = quote_copy_string (current_link_name);
950 if (name)
951 {
952 fprintf (stdlis, " -> %s\n", name);
953 free (name);
954 }
955 else
956 fprintf (stdlis, " -> %s\n", current_link_name);
957 break;
958
959 case LNKTYPE:
960 name = quote_copy_string (current_link_name);
961 if (name)
962 {
963 fprintf (stdlis, _(" link to %s\n"), name);
964 free (name);
965 }
966 else
967 fprintf (stdlis, _(" link to %s\n"), current_link_name);
968 break;
969
970 default:
971 fprintf (stdlis, _(" unknown file type `%c'\n"),
972 current_header->header.typeflag);
973 break;
974
975 case AREGTYPE:
976 case REGTYPE:
977 case GNUTYPE_SPARSE:
978 case CHRTYPE:
979 case BLKTYPE:
980 case DIRTYPE:
981 case FIFOTYPE:
982 case CONTTYPE:
983 case GNUTYPE_DUMPDIR:
984 putc ('\n', stdlis);
985 break;
986
987 case GNUTYPE_VOLHDR:
988 fprintf (stdlis, _("--Volume Header--\n"));
989 break;
990
991 case GNUTYPE_MULTIVOL:
992 strcpy (size,
993 STRINGIFY_BIGINT
994 (UINTMAX_FROM_CHARS (current_header->oldgnu_header.offset),
995 uintbuf));
996 fprintf (stdlis, _("--Continued at byte %s--\n"), size);
997 break;
998
999 case GNUTYPE_NAMES:
1000 fprintf (stdlis, _("--Mangled file names--\n"));
1001 break;
1002 }
1003 }
1004 fflush (stdlis);
1005 }
1006
1007 /*--------------------------------------------------------------.
1008 | Print a similar line when we make a directory automatically. |
1009 `--------------------------------------------------------------*/
1010
1011 void
1012 print_for_mkdir (char *pathname, int length, mode_t mode)
1013 {
1014 char modes[11];
1015 char *name;
1016
1017 if (verbose_option > 1)
1018 {
1019 /* File type and modes. */
1020
1021 modes[0] = 'd';
1022 decode_mode (mode, modes + 1);
1023
1024 if (block_number_option)
1025 {
1026 char buf[UINTMAX_STRSIZE_BOUND];
1027 fprintf (stdlis, _("block %s: "),
1028 STRINGIFY_BIGINT (current_block_ordinal (), buf));
1029 }
1030 name = quote_copy_string (pathname);
1031 if (name)
1032 {
1033 fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
1034 _("Creating directory:"), length, name);
1035 free (name);
1036 }
1037 else
1038 fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
1039 _("Creating directory:"), length, pathname);
1040 }
1041 }
1042
1043 /*--------------------------------------------------------.
1044 | Skip over SIZE bytes of data in blocks in the archive. |
1045 `--------------------------------------------------------*/
1046
1047 void
1048 skip_file (off_t size)
1049 {
1050 union block *x;
1051
1052 if (multi_volume_option)
1053 {
1054 save_totsize = size;
1055 save_sizeleft = size;
1056 }
1057
1058 while (size > 0)
1059 {
1060 x = find_next_block ();
1061 if (x == NULL)
1062 FATAL_ERROR ((0, 0, _("Unexpected EOF on archive file")));
1063
1064 set_next_block_after (x);
1065 size -= BLOCKSIZE;
1066 if (multi_volume_option)
1067 save_sizeleft -= BLOCKSIZE;
1068 }
1069 }
1070
1071 /*---.
1072 | ? |
1073 `---*/
1074
1075 void
1076 skip_extended_headers (void)
1077 {
1078 union block *exhdr;
1079
1080 do
1081 {
1082 exhdr = find_next_block ();
1083 if (!exhdr)
1084 FATAL_ERROR ((0, 0, _("Unexpected EOF on archive file")));
1085 set_next_block_after (exhdr);
1086 }
1087 while (exhdr->sparse_header.isextended);
1088 }
This page took 0.083621 seconds and 5 git commands to generate.