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