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