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