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