]> Dogcows Code - chaz/tar/blob - src/list.c
(gid_from_oct, major_from_oct, minor_from_oct, mode_from_oct,
[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 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 char *name = next_long_name;
419 struct posix_header *h = &current_header->header;
420 char namebuf[sizeof h->prefix + 1 + sizeof h->name + 1];
421
422 if (! name)
423 {
424 /* Accept file names as specified by POSIX.1-1996
425 section 10.1.1. */
426 char *np = namebuf;
427 if (h->prefix[0])
428 {
429 memcpy (np, h->prefix, sizeof h->prefix);
430 np[sizeof h->prefix] = '\0';
431 np += strlen (np);
432 *np++ = '/';
433 }
434 memcpy (np, h->name, sizeof h->name);
435 np[sizeof h->name] = '\0';
436 name = namebuf;
437 }
438
439 assign_string (&current_file_name, name);
440 assign_string (&current_link_name,
441 (next_long_link ? next_long_link
442 : current_header->header.linkname));
443 next_long_link = next_long_name = 0;
444 return HEADER_SUCCESS;
445 }
446 }
447 }
448
449 /*-------------------------------------------------------------------------.
450 | Decode things from a file HEADER block into STAT_INFO, also setting |
451 | *FORMAT_POINTER depending on the header block format. If DO_USER_GROUP, |
452 | decode the user/group information (this is useful for extraction, but |
453 | waste time when merely listing). |
454 | |
455 | read_header() has already decoded the checksum and length, so we don't. |
456 | |
457 | This routine should *not* be called twice for the same block, since the |
458 | two calls might use different DO_USER_GROUP values and thus might end up |
459 | with different uid/gid for the two calls. If anybody wants the uid/gid |
460 | they should decode it first, and other callers should decode it without |
461 | uid/gid before calling a routine, e.g. print_header, that assumes |
462 | decoded data. |
463 `-------------------------------------------------------------------------*/
464
465 void
466 decode_header (union block *header, struct stat *stat_info,
467 enum archive_format *format_pointer, int do_user_group)
468 {
469 enum archive_format format;
470
471 if (strcmp (header->header.magic, TMAGIC) == 0)
472 format = POSIX_FORMAT;
473 else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
474 format = OLDGNU_FORMAT;
475 else
476 format = V7_FORMAT;
477 *format_pointer = format;
478
479 stat_info->st_mode = MODE_FROM_OCT (header->header.mode);
480 stat_info->st_mode &= 07777;
481 stat_info->st_mtime = TIME_FROM_OCT (header->header.mtime);
482
483 if (format == OLDGNU_FORMAT && incremental_option)
484 {
485 stat_info->st_atime = TIME_FROM_OCT (header->oldgnu_header.atime);
486 stat_info->st_ctime = TIME_FROM_OCT (header->oldgnu_header.ctime);
487 }
488
489 if (format == V7_FORMAT)
490 {
491 stat_info->st_uid = UID_FROM_OCT (header->header.uid);
492 stat_info->st_gid = GID_FROM_OCT (header->header.gid);
493 stat_info->st_rdev = 0;
494 }
495 else
496 {
497 if (do_user_group)
498 {
499 /* FIXME: Decide if this should somewhat depend on -p. */
500
501 if (numeric_owner_option
502 || !*header->header.uname
503 || !uname_to_uid (header->header.uname, &stat_info->st_uid))
504 stat_info->st_uid = UID_FROM_OCT (header->header.uid);
505
506 if (numeric_owner_option
507 || !*header->header.gname
508 || !gname_to_gid (header->header.gname, &stat_info->st_gid))
509 stat_info->st_gid = GID_FROM_OCT (header->header.gid);
510 }
511 switch (header->header.typeflag)
512 {
513 #ifdef S_IFBLK
514 case BLKTYPE:
515 stat_info->st_rdev
516 = makedev (MAJOR_FROM_OCT (header->header.devmajor),
517 MINOR_FROM_OCT (header->header.devminor));
518 break;
519 #endif
520
521 #ifdef S_IFCHR
522 case CHRTYPE:
523 stat_info->st_rdev
524 = makedev (MAJOR_FROM_OCT (header->header.devmajor),
525 MINOR_FROM_OCT (header->header.devminor));
526 break;
527 #endif
528
529 default:
530 stat_info->st_rdev = 0;
531 }
532 }
533 }
534
535 /*------------------------------------------------------------------------.
536 | Quick and dirty octal conversion. Result is -1 if the field is invalid |
537 | (all blank, or nonoctal). |
538 `------------------------------------------------------------------------*/
539
540 static uintmax_t
541 from_oct (const char *where0, size_t digs0, const char *type, uintmax_t maxval)
542 {
543 uintmax_t value;
544 const char *where = where0;
545 size_t digs = digs0;
546
547 for (;;)
548 {
549 if (digs == 0)
550 {
551 ERROR ((0, 0, _("Blanks in header where octal %s value expected"),
552 type));
553 return -1;
554 }
555 if (!ISSPACE (*where))
556 break;
557 where++;
558 digs--;
559 }
560
561 value = 0;
562 while (digs != 0 && ISODIGIT (*where))
563 {
564 /* Scan til nonoctal. */
565
566 if (value << 3 >> 3 != value)
567 goto out_of_range;
568 value = (value << 3) | (*where++ - '0');
569 --digs;
570 }
571
572 if (digs != 0 && *where && !ISSPACE (*where))
573 {
574 ERROR ((0, 0, _("Header contains `%.*s' where octal %s value expected"),
575 (int) digs0, where0, type));
576 return -1;
577 }
578
579 if (value <= maxval)
580 return value;
581
582 out_of_range:
583 ERROR ((0, 0, _("Octal value `%.*s' is out of range for %s"),
584 (int) digs0, where0, type));
585 return -1;
586 }
587 gid_t
588 gid_from_oct (const char *p, size_t s)
589 {
590 return from_oct (p, s, "gid_t", (uintmax_t) GID_MAX);
591 }
592 major_t
593 major_from_oct (const char *p, size_t s)
594 {
595 return from_oct (p, s, "major_t", (uintmax_t) MAJOR_MAX);
596 }
597 minor_t
598 minor_from_oct (const char *p, size_t s)
599 {
600 return from_oct (p, s, "minor_t", (uintmax_t) MINOR_MAX);
601 }
602 mode_t
603 mode_from_oct (const char *p, size_t s)
604 {
605 return from_oct (p, s, "mode_t", (uintmax_t) MODE_MAX);
606 }
607 off_t
608 off_from_oct (const char *p, size_t s)
609 {
610 return from_oct (p, s, "off_t", (uintmax_t) OFF_MAX);
611 }
612 size_t
613 size_from_oct (const char *p, size_t s)
614 {
615 return from_oct (p, s, "size_t", (uintmax_t) SIZE_MAX);
616 }
617 time_t
618 time_from_oct (const char *p, size_t s)
619 {
620 return from_oct (p, s, "time_t", (uintmax_t) TIME_MAX);
621 }
622 uid_t
623 uid_from_oct (const char *p, size_t s)
624 {
625 return from_oct (p, s, "uid_t", (uintmax_t) UID_MAX);
626 }
627 uintmax_t
628 uintmax_from_oct (const char *p, size_t s)
629 {
630 return from_oct (p, s, "uintmax_t", UINTMAX_MAX);
631 }
632
633
634
635 /*----------------------------------------------------------------------.
636 | Format O as a null-terminated decimal string into BUF _backwards_; |
637 | return pointer to start of result. |
638 `----------------------------------------------------------------------*/
639 char *
640 stringify_uintmax_t_backwards (uintmax_t o, char *buf)
641 {
642 *--buf = '\0';
643 do
644 *--buf = '0' + (int) (o % 10);
645 while ((o /= 10) != 0);
646 return buf;
647 }
648
649 #if !USE_OLD_CTIME
650
651 /*-------------------------------------------.
652 | Return the time formatted along ISO 8601. |
653 `-------------------------------------------*/
654
655 /* Also, see http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html. */
656
657 static char *
658 isotime (const time_t *time)
659 {
660 static char buffer[21];
661 struct tm *tm;
662
663 tm = localtime (time);
664 sprintf (buffer, "%4d-%02d-%02d %02d:%02d:%02d\n",
665 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
666 tm->tm_hour, tm->tm_min, tm->tm_sec);
667 return buffer;
668 }
669
670 #endif /* not USE_OLD_CTIME */
671
672 /*-------------------------------------------------------------------------.
673 | Decode MODE from its binary form in a stat structure, and encode it into |
674 | a 9 characters string STRING, terminated with a NUL. |
675 `-------------------------------------------------------------------------*/
676
677 static void
678 decode_mode (mode_t mode, char *string)
679 {
680 mode_t mask;
681 const char *rwx = "rwxrwxrwx";
682
683 for (mask = 0400; mask != 0; mask >>= 1)
684 if (mode & mask)
685 *string++ = *rwx++;
686 else
687 {
688 *string++ = '-';
689 rwx++;
690 }
691
692 if (mode & S_ISUID)
693 string[-7] = string[-7] == 'x' ? 's' : 'S';
694 if (mode & S_ISGID)
695 string[-4] = string[-4] == 'x' ? 's' : 'S';
696 if (mode & S_ISVTX)
697 string[-1] = string[-1] == 'x' ? 't' : 'T';
698
699 *string = '\0';
700 }
701
702 /*-------------------------------------------------------------------------.
703 | Actually print it. |
704 | |
705 | Plain and fancy file header block logging. Non-verbose just prints the |
706 | name, e.g. for "tar t" or "tar x". This should just contain file names, |
707 | so it can be fed back into tar with xargs or the "-T" option. The |
708 | verbose option can give a bunch of info, one line per file. I doubt |
709 | anybody tries to parse its format, or if they do, they shouldn't. Unix |
710 | tar is pretty random here anyway. |
711 `-------------------------------------------------------------------------*/
712
713 /* FIXME: Note that print_header uses the globals HEAD, HSTAT, and
714 HEAD_STANDARD, which must be set up in advance. Not very clean... */
715
716 /* UGSWIDTH starts with 18, so with user and group names <= 8 chars, the
717 columns never shift during the listing. */
718 #define UGSWIDTH 18
719 static int ugswidth = UGSWIDTH; /* maximum width encountered so far */
720
721 /* DATEWIDTH is the number of columns taken by the date and time fields. */
722 #if USE_OLD_CDATE
723 # define DATEWIDTH 19
724 #else
725 # define DATEWIDTH 18
726 #endif
727
728 void
729 print_header (void)
730 {
731 char modes[11];
732 char *timestamp;
733 char uform[11], gform[11]; /* these hold formatted ints */
734 char *user, *group;
735 char size[2 * UINTMAX_STRSIZE_BOUND];
736 /* holds formatted size or major,minor */
737 char uintbuf[UINTMAX_STRSIZE_BOUND];
738 time_t longie; /* to make ctime() call portable */
739 int pad;
740 char *name;
741
742 if (block_number_option)
743 {
744 char buf[UINTMAX_STRSIZE_BOUND];
745 fprintf (stdlis, _("block %s: "),
746 STRINGIFY_BIGINT (current_block_ordinal (), buf));
747 }
748
749 if (verbose_option <= 1)
750 {
751 /* Just the fax, mam. */
752
753 char *quoted_name = quote_copy_string (current_file_name);
754
755 if (quoted_name)
756 {
757 fprintf (stdlis, "%s\n", quoted_name);
758 free (quoted_name);
759 }
760 else
761 fprintf (stdlis, "%s\n", current_file_name);
762 }
763 else
764 {
765 /* File type and modes. */
766
767 modes[0] = '?';
768 switch (current_header->header.typeflag)
769 {
770 case GNUTYPE_VOLHDR:
771 modes[0] = 'V';
772 break;
773
774 case GNUTYPE_MULTIVOL:
775 modes[0] = 'M';
776 break;
777
778 case GNUTYPE_NAMES:
779 modes[0] = 'N';
780 break;
781
782 case GNUTYPE_LONGNAME:
783 case GNUTYPE_LONGLINK:
784 ERROR ((0, 0, _("Visible longname error")));
785 break;
786
787 case GNUTYPE_SPARSE:
788 case REGTYPE:
789 case AREGTYPE:
790 case LNKTYPE:
791 modes[0] = '-';
792 if (current_file_name[strlen (current_file_name) - 1] == '/')
793 modes[0] = 'd';
794 break;
795 case GNUTYPE_DUMPDIR:
796 modes[0] = 'd';
797 break;
798 case DIRTYPE:
799 modes[0] = 'd';
800 break;
801 case SYMTYPE:
802 modes[0] = 'l';
803 break;
804 case BLKTYPE:
805 modes[0] = 'b';
806 break;
807 case CHRTYPE:
808 modes[0] = 'c';
809 break;
810 case FIFOTYPE:
811 modes[0] = 'p';
812 break;
813 case CONTTYPE:
814 modes[0] = 'C';
815 break;
816 }
817
818 decode_mode (current_stat.st_mode, modes + 1);
819
820 /* Timestamp. */
821
822 longie = current_stat.st_mtime;
823 #if USE_OLD_CTIME
824 timestamp = ctime (&longie);
825 timestamp[16] = '\0';
826 timestamp[24] = '\0';
827 #else
828 timestamp = isotime (&longie);
829 timestamp[16] = '\0';
830 #endif
831
832 /* User and group names. */
833
834 if (*current_header->header.uname && current_format != V7_FORMAT)
835 user = current_header->header.uname;
836 else
837 user = STRINGIFY_BIGINT (UINTMAX_FROM_OCT (current_header->header.uid),
838 uform);
839
840 if (*current_header->header.gname && current_format != V7_FORMAT)
841 group = current_header->header.gname;
842 else
843 group = STRINGIFY_BIGINT (UINTMAX_FROM_OCT
844 (current_header->header.gid),
845 gform);
846
847 /* Format the file size or major/minor device numbers. */
848
849 switch (current_header->header.typeflag)
850 {
851 #if defined(S_IFBLK) || defined(S_IFCHR)
852 case CHRTYPE:
853 case BLKTYPE:
854 sprintf (size, "%lu,%lu",
855 (unsigned long) major (current_stat.st_rdev),
856 (unsigned long) minor (current_stat.st_rdev));
857 break;
858 #endif
859 case GNUTYPE_SPARSE:
860 strcpy (size,
861 STRINGIFY_BIGINT
862 (UINTMAX_FROM_OCT (current_header->oldgnu_header.realsize),
863 uintbuf));
864 break;
865 default:
866 strcpy (size, STRINGIFY_BIGINT (current_stat.st_size, uintbuf));
867 break;
868 }
869
870 /* Figure out padding and print the whole line. */
871
872 pad = strlen (user) + strlen (group) + strlen (size) + 1;
873 if (pad > ugswidth)
874 ugswidth = pad;
875
876 #if USE_OLD_CTIME
877 fprintf (stdlis, "%s %s/%s %*s%s %s %s",
878 modes, user, group, ugswidth - pad, "",
879 size, timestamp + 4, timestamp + 20);
880 #else
881 fprintf (stdlis, "%s %s/%s %*s%s %s",
882 modes, user, group, ugswidth - pad, "", size, timestamp);
883 #endif
884
885 name = quote_copy_string (current_file_name);
886 if (name)
887 {
888 fprintf (stdlis, " %s", name);
889 free (name);
890 }
891 else
892 fprintf (stdlis, " %s", current_file_name);
893
894 switch (current_header->header.typeflag)
895 {
896 case SYMTYPE:
897 name = quote_copy_string (current_link_name);
898 if (name)
899 {
900 fprintf (stdlis, " -> %s\n", name);
901 free (name);
902 }
903 else
904 fprintf (stdlis, " -> %s\n", current_link_name);
905 break;
906
907 case LNKTYPE:
908 name = quote_copy_string (current_link_name);
909 if (name)
910 {
911 fprintf (stdlis, _(" link to %s\n"), name);
912 free (name);
913 }
914 else
915 fprintf (stdlis, _(" link to %s\n"), current_link_name);
916 break;
917
918 default:
919 fprintf (stdlis, _(" unknown file type `%c'\n"),
920 current_header->header.typeflag);
921 break;
922
923 case AREGTYPE:
924 case REGTYPE:
925 case GNUTYPE_SPARSE:
926 case CHRTYPE:
927 case BLKTYPE:
928 case DIRTYPE:
929 case FIFOTYPE:
930 case CONTTYPE:
931 case GNUTYPE_DUMPDIR:
932 putc ('\n', stdlis);
933 break;
934
935 case GNUTYPE_VOLHDR:
936 fprintf (stdlis, _("--Volume Header--\n"));
937 break;
938
939 case GNUTYPE_MULTIVOL:
940 strcpy (size,
941 STRINGIFY_BIGINT
942 (UINTMAX_FROM_OCT (current_header->oldgnu_header.offset),
943 uintbuf));
944 fprintf (stdlis, _("--Continued at byte %s--\n"), size);
945 break;
946
947 case GNUTYPE_NAMES:
948 fprintf (stdlis, _("--Mangled file names--\n"));
949 break;
950 }
951 }
952 fflush (stdlis);
953 }
954
955 /*--------------------------------------------------------------.
956 | Print a similar line when we make a directory automatically. |
957 `--------------------------------------------------------------*/
958
959 void
960 print_for_mkdir (char *pathname, int length, mode_t mode)
961 {
962 char modes[11];
963 char *name;
964
965 if (verbose_option > 1)
966 {
967 /* File type and modes. */
968
969 modes[0] = 'd';
970 decode_mode (mode, modes + 1);
971
972 if (block_number_option)
973 {
974 char buf[UINTMAX_STRSIZE_BOUND];
975 fprintf (stdlis, _("block %s: "),
976 STRINGIFY_BIGINT (current_block_ordinal (), buf));
977 }
978 name = quote_copy_string (pathname);
979 if (name)
980 {
981 fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
982 _("Creating directory:"), length, name);
983 free (name);
984 }
985 else
986 fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
987 _("Creating directory:"), length, pathname);
988 }
989 }
990
991 /*--------------------------------------------------------.
992 | Skip over SIZE bytes of data in blocks in the archive. |
993 `--------------------------------------------------------*/
994
995 void
996 skip_file (off_t size)
997 {
998 union block *x;
999
1000 if (multi_volume_option)
1001 {
1002 save_totsize = size;
1003 save_sizeleft = size;
1004 }
1005
1006 while (size > 0)
1007 {
1008 x = find_next_block ();
1009 if (x == NULL)
1010 FATAL_ERROR ((0, 0, _("Unexpected EOF on archive file")));
1011
1012 set_next_block_after (x);
1013 size -= BLOCKSIZE;
1014 if (multi_volume_option)
1015 save_sizeleft -= BLOCKSIZE;
1016 }
1017 }
1018
1019 /*---.
1020 | ? |
1021 `---*/
1022
1023 void
1024 skip_extended_headers (void)
1025 {
1026 union block *exhdr;
1027
1028 while (1)
1029 {
1030 exhdr = find_next_block ();
1031 if (!exhdr->sparse_header.isextended)
1032 {
1033 set_next_block_after (exhdr);
1034 break;
1035 }
1036 set_next_block_after (exhdr);
1037 }
1038 }
This page took 0.087547 seconds and 5 git commands to generate.