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