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