]> Dogcows Code - chaz/tar/blob - src/list.c
(isotime): Report ??? if localtime returns null.
[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[INT_STRLEN_BOUND (int) + 16];
750 struct tm *tm = localtime (time);
751 if (tm)
752 sprintf (buffer, "%04d-%02d-%02d %02d:%02d:%02d",
753 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
754 tm->tm_hour, tm->tm_min, tm->tm_sec);
755 else
756 /* Interpose %s between ?? and - to avoid ANSI C trigraph brain damage. */
757 sprintf (buffer, "????%s-??%s-?? ??:??:??", "", "");
758
759 return buffer;
760 }
761
762 #endif /* not USE_OLD_CTIME */
763
764 /*-------------------------------------------------------------------------.
765 | Decode MODE from its binary form in a stat structure, and encode it into |
766 | a 9 characters string STRING, terminated with a NUL. |
767 `-------------------------------------------------------------------------*/
768
769 static void
770 decode_mode (mode_t mode, char *string)
771 {
772 *string++ = mode & S_IRUSR ? 'r' : '-';
773 *string++ = mode & S_IWUSR ? 'w' : '-';
774 *string++ = (mode & S_ISUID
775 ? (mode & S_IXUSR ? 's' : 'S')
776 : (mode & S_IXUSR ? 'x' : '-'));
777 *string++ = mode & S_IRGRP ? 'r' : '-';
778 *string++ = mode & S_IWGRP ? 'w' : '-';
779 *string++ = (mode & S_ISGID
780 ? (mode & S_IXGRP ? 's' : 'S')
781 : (mode & S_IXGRP ? 'x' : '-'));
782 *string++ = mode & S_IROTH ? 'r' : '-';
783 *string++ = mode & S_IWOTH ? 'w' : '-';
784 *string++ = (mode & S_ISVTX
785 ? (mode & S_IXOTH ? 't' : 'T')
786 : (mode & S_IXOTH ? 'x' : '-'));
787 *string = '\0';
788 }
789
790 /*-------------------------------------------------------------------------.
791 | Actually print it. |
792 | |
793 | Plain and fancy file header block logging. Non-verbose just prints the |
794 | name, e.g. for "tar t" or "tar x". This should just contain file names, |
795 | so it can be fed back into tar with xargs or the "-T" option. The |
796 | verbose option can give a bunch of info, one line per file. I doubt |
797 | anybody tries to parse its format, or if they do, they shouldn't. Unix |
798 | tar is pretty random here anyway. |
799 `-------------------------------------------------------------------------*/
800
801 /* FIXME: Note that print_header uses the globals HEAD, HSTAT, and
802 HEAD_STANDARD, which must be set up in advance. Not very clean... */
803
804 /* UGSWIDTH starts with 18, so with user and group names <= 8 chars, the
805 columns never shift during the listing. */
806 #define UGSWIDTH 18
807 static int ugswidth = UGSWIDTH; /* maximum width encountered so far */
808
809 /* DATEWIDTH is the number of columns taken by the date and time fields. */
810 #if USE_OLD_CDATE
811 # define DATEWIDTH 19
812 #else
813 # define DATEWIDTH 18
814 #endif
815
816 void
817 print_header (void)
818 {
819 char modes[11];
820 char const *timestamp;
821 /* These hold formatted ints. */
822 char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND];
823 char *user, *group;
824 char size[2 * UINTMAX_STRSIZE_BOUND];
825 /* holds formatted size or major,minor */
826 char uintbuf[UINTMAX_STRSIZE_BOUND];
827 time_t longie; /* to make ctime() call portable */
828 int pad;
829 char *name;
830
831 if (block_number_option)
832 {
833 char buf[UINTMAX_STRSIZE_BOUND];
834 fprintf (stdlis, _("block %s: "),
835 STRINGIFY_BIGINT (current_block_ordinal (), buf));
836 }
837
838 if (verbose_option <= 1)
839 {
840 /* Just the fax, mam. */
841
842 char *quoted_name = quote_copy_string (current_file_name);
843
844 if (quoted_name)
845 {
846 fprintf (stdlis, "%s\n", quoted_name);
847 free (quoted_name);
848 }
849 else
850 fprintf (stdlis, "%s\n", current_file_name);
851 }
852 else
853 {
854 /* File type and modes. */
855
856 modes[0] = '?';
857 switch (current_header->header.typeflag)
858 {
859 case GNUTYPE_VOLHDR:
860 modes[0] = 'V';
861 break;
862
863 case GNUTYPE_MULTIVOL:
864 modes[0] = 'M';
865 break;
866
867 case GNUTYPE_NAMES:
868 modes[0] = 'N';
869 break;
870
871 case GNUTYPE_LONGNAME:
872 case GNUTYPE_LONGLINK:
873 ERROR ((0, 0, _("Visible longname error")));
874 break;
875
876 case GNUTYPE_SPARSE:
877 case REGTYPE:
878 case AREGTYPE:
879 case LNKTYPE:
880 modes[0] = '-';
881 if (current_file_name[strlen (current_file_name) - 1] == '/')
882 modes[0] = 'd';
883 break;
884 case GNUTYPE_DUMPDIR:
885 modes[0] = 'd';
886 break;
887 case DIRTYPE:
888 modes[0] = 'd';
889 break;
890 case SYMTYPE:
891 modes[0] = 'l';
892 break;
893 case BLKTYPE:
894 modes[0] = 'b';
895 break;
896 case CHRTYPE:
897 modes[0] = 'c';
898 break;
899 case FIFOTYPE:
900 modes[0] = 'p';
901 break;
902 case CONTTYPE:
903 modes[0] = 'C';
904 break;
905 }
906
907 decode_mode (current_stat.st_mode, modes + 1);
908
909 /* Timestamp. */
910
911 longie = current_stat.st_mtime;
912 #if USE_OLD_CTIME
913 {
914 char *ct = ctime (&longie);
915 if (ct)
916 {
917 timestamp = ct + 4;
918 for (ct += 16; ct[4] != '\n'; ct++)
919 ct[0] = ct[4];
920 ct[0] = '\0';
921 }
922 else
923 timestamp = "??? ?? ??:?? ????";
924 }
925 #else
926 timestamp = isotime (&longie);
927 #endif
928
929 /* User and group names. */
930
931 if (*current_header->header.uname && current_format != V7_FORMAT
932 && !numeric_owner_option)
933 user = current_header->header.uname;
934 else
935 user = STRINGIFY_BIGINT (UINTMAX_FROM_CHARS
936 (current_header->header.uid),
937 uform);
938
939 if (*current_header->header.gname && current_format != V7_FORMAT
940 && !numeric_owner_option)
941 group = current_header->header.gname;
942 else
943 group = STRINGIFY_BIGINT (UINTMAX_FROM_CHARS
944 (current_header->header.gid),
945 gform);
946
947 /* Format the file size or major/minor device numbers. */
948
949 switch (current_header->header.typeflag)
950 {
951 case CHRTYPE:
952 case BLKTYPE:
953 sprintf (size, "%lu,%lu",
954 (unsigned long) major (current_stat.st_rdev),
955 (unsigned long) minor (current_stat.st_rdev));
956 break;
957 case GNUTYPE_SPARSE:
958 strcpy (size,
959 STRINGIFY_BIGINT
960 (UINTMAX_FROM_CHARS (current_header->oldgnu_header.realsize),
961 uintbuf));
962 break;
963 default:
964 strcpy (size, STRINGIFY_BIGINT (current_stat.st_size, uintbuf));
965 break;
966 }
967
968 /* Figure out padding and print the whole line. */
969
970 pad = strlen (user) + strlen (group) + strlen (size) + 1;
971 if (pad > ugswidth)
972 ugswidth = pad;
973
974 fprintf (stdlis, "%s %s/%s %*s%s %s",
975 modes, user, group, ugswidth - pad, "", size, timestamp);
976
977 name = quote_copy_string (current_file_name);
978 if (name)
979 {
980 fprintf (stdlis, " %s", name);
981 free (name);
982 }
983 else
984 fprintf (stdlis, " %s", current_file_name);
985
986 switch (current_header->header.typeflag)
987 {
988 case SYMTYPE:
989 name = quote_copy_string (current_link_name);
990 if (name)
991 {
992 fprintf (stdlis, " -> %s\n", name);
993 free (name);
994 }
995 else
996 fprintf (stdlis, " -> %s\n", current_link_name);
997 break;
998
999 case LNKTYPE:
1000 name = quote_copy_string (current_link_name);
1001 if (name)
1002 {
1003 fprintf (stdlis, _(" link to %s\n"), name);
1004 free (name);
1005 }
1006 else
1007 fprintf (stdlis, _(" link to %s\n"), current_link_name);
1008 break;
1009
1010 default:
1011 fprintf (stdlis, _(" unknown file type `%c'\n"),
1012 current_header->header.typeflag);
1013 break;
1014
1015 case AREGTYPE:
1016 case REGTYPE:
1017 case GNUTYPE_SPARSE:
1018 case CHRTYPE:
1019 case BLKTYPE:
1020 case DIRTYPE:
1021 case FIFOTYPE:
1022 case CONTTYPE:
1023 case GNUTYPE_DUMPDIR:
1024 putc ('\n', stdlis);
1025 break;
1026
1027 case GNUTYPE_VOLHDR:
1028 fprintf (stdlis, _("--Volume Header--\n"));
1029 break;
1030
1031 case GNUTYPE_MULTIVOL:
1032 strcpy (size,
1033 STRINGIFY_BIGINT
1034 (UINTMAX_FROM_CHARS (current_header->oldgnu_header.offset),
1035 uintbuf));
1036 fprintf (stdlis, _("--Continued at byte %s--\n"), size);
1037 break;
1038
1039 case GNUTYPE_NAMES:
1040 fprintf (stdlis, _("--Mangled file names--\n"));
1041 break;
1042 }
1043 }
1044 fflush (stdlis);
1045 }
1046
1047 /*--------------------------------------------------------------.
1048 | Print a similar line when we make a directory automatically. |
1049 `--------------------------------------------------------------*/
1050
1051 void
1052 print_for_mkdir (char *pathname, int length, mode_t mode)
1053 {
1054 char modes[11];
1055 char *name;
1056
1057 if (verbose_option > 1)
1058 {
1059 /* File type and modes. */
1060
1061 modes[0] = 'd';
1062 decode_mode (mode, modes + 1);
1063
1064 if (block_number_option)
1065 {
1066 char buf[UINTMAX_STRSIZE_BOUND];
1067 fprintf (stdlis, _("block %s: "),
1068 STRINGIFY_BIGINT (current_block_ordinal (), buf));
1069 }
1070 name = quote_copy_string (pathname);
1071 if (name)
1072 {
1073 fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
1074 _("Creating directory:"), length, name);
1075 free (name);
1076 }
1077 else
1078 fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
1079 _("Creating directory:"), length, pathname);
1080 }
1081 }
1082
1083 /*--------------------------------------------------------.
1084 | Skip over SIZE bytes of data in blocks in the archive. |
1085 `--------------------------------------------------------*/
1086
1087 void
1088 skip_file (off_t size)
1089 {
1090 union block *x;
1091
1092 if (multi_volume_option)
1093 {
1094 save_totsize = size;
1095 save_sizeleft = size;
1096 }
1097
1098 while (size > 0)
1099 {
1100 x = find_next_block ();
1101 if (x == NULL)
1102 FATAL_ERROR ((0, 0, _("Unexpected EOF on archive file")));
1103
1104 set_next_block_after (x);
1105 size -= BLOCKSIZE;
1106 if (multi_volume_option)
1107 save_sizeleft -= BLOCKSIZE;
1108 }
1109 }
1110
1111 /*---.
1112 | ? |
1113 `---*/
1114
1115 void
1116 skip_extended_headers (void)
1117 {
1118 union block *exhdr;
1119
1120 while (1)
1121 {
1122 exhdr = find_next_block ();
1123 if (!exhdr->sparse_header.isextended)
1124 {
1125 set_next_block_after (exhdr);
1126 break;
1127 }
1128 set_next_block_after (exhdr);
1129 }
1130 }
This page took 0.084225 seconds and 5 git commands to generate.