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