/* List a tar archive, with support routines for reading a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
- 2001, 2003 Free Software Foundation, Inc.
+ 2001, 2003, 2004 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-26.
name_gather ();
open_archive (ACCESS_READ);
- while (!all_names_found ())
+ do
{
prev_status = status;
+ tar_stat_destroy (¤t_stat_info);
+ xheader_destroy (&extended_header);
+
status = read_header (false);
switch (status)
{
Ensure incoming names are null terminated. */
if (! name_match (current_stat_info.file_name)
- || (newer_mtime_option != TYPE_MINIMUM (time_t)
+ || (NEWER_OPTION_INITIALIZED (newer_mtime_option)
/* FIXME: We get mtime now, and again later; this causes
duplicate diagnostics if header.mtime is bogus. */
&& ((current_stat_info.stat.st_mtime
- = TIME_FROM_HEADER (current_header->header.mtime))
- < newer_mtime_option))
+ = TIME_FROM_HEADER (current_header->header.mtime)),
+#ifdef ST_MTIM_NSEC
+ /* FIXME: Grab fractional time stamps from
+ extended header. */
+ current_stat_info.stat.st_mtim.ST_MTIM_NSEC = 0,
+#endif
+ OLDER_STAT_TIME (current_stat_info.stat, m)))
|| excluded_name (current_stat_info.file_name))
{
switch (current_header->header.typeflag)
skip_member ();
continue;
}
- }
+ }
(*do_something) ();
continue;
}
set_next_block_after (current_header);
+
+ if (!ignore_zeros_option)
+ {
+ char buf[UINTMAX_STRSIZE_BOUND];
+
+ status = read_header (false);
+ if (status == HEADER_ZERO_BLOCK)
+ break;
+ WARN ((0, 0, _("A lone zero block at %s"),
+ STRINGIFY_BIGINT (current_block_ordinal (), buf)));
+ break;
+ }
status = prev_status;
- if (ignore_zeros_option)
- continue;
- break;
+ continue;
case HEADER_END_OF_FILE:
if (block_number_option)
case HEADER_ZERO_BLOCK:
case HEADER_SUCCESS:
+ if (block_number_option)
+ {
+ char buf[UINTMAX_STRSIZE_BOUND];
+ off_t block_ordinal = current_block_ordinal ();
+ block_ordinal -= recent_long_name_blocks;
+ block_ordinal -= recent_long_link_blocks;
+ fprintf (stdlis, _("block %s: "),
+ STRINGIFY_BIGINT (block_ordinal, buf));
+ }
ERROR ((0, 0, _("Skipping to next header")));
break;
}
break;
}
+ while (!all_names_found (¤t_stat_info));
close_archive ();
names_notfound (); /* print names not found */
decode_header (current_header, ¤t_stat_info, ¤t_format, 0);
if (verbose_option)
- print_header (-1);
+ print_header (¤t_stat_info, -1);
if (incremental_option && current_header->header.typeflag == GNUTYPE_DUMPDIR)
{
xalloc_die ();
header_copy = xmalloc (size + 1);
-
+
if (header->header.typeflag == GNUTYPE_LONGNAME)
{
if (next_long_name)
next_long_link = header_copy;
next_long_link_blocks = size / BLOCKSIZE;
}
-
+
set_next_block_after (header);
*header_copy = *header;
bp = header_copy->buffer + BLOCKSIZE;
written = available_space_after (data_block);
if (written > size)
written = size;
-
+
memcpy (bp, data_block->buffer, written);
bp += written;
set_next_block_after ((union block *)
*bp = '\0';
}
- else if (header->header.typeflag == XHDTYPE
- || header->header.typeflag == XGLTYPE)
+ else if (header->header.typeflag == XHDTYPE)
xheader_read (header, OFF_FROM_HEADER (header->header.size));
-
+ else if (header->header.typeflag == XGLTYPE)
+ {
+ xheader_read (header, OFF_FROM_HEADER (header->header.size));
+ xheader_decode_global ();
+ }
+
/* Loop! */
}
&& ISOCTAL (header->star_header.ctime[0])
&& header->star_header.ctime[11] == ' ')
format = STAR_FORMAT;
- else
+ else if (extended_header.size)
format = POSIX_FORMAT;
+ else
+ format = USTAR_FORMAT;
}
else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
format = OLDGNU_FORMAT;
assign_string (&stat_info->gname, header->header.gname);
stat_info->devmajor = MAJOR_FROM_HEADER (header->header.devmajor);
stat_info->devminor = MINOR_FROM_HEADER (header->header.devminor);
-
+
+ stat_info->stat.st_atime = start_time;
+ stat_info->stat.st_ctime = start_time;
+
if (format == OLDGNU_FORMAT && incremental_option)
{
stat_info->stat.st_atime = TIME_FROM_HEADER (header->oldgnu_header.atime);
|| !gname_to_gid (header->header.gname, &stat_info->stat.st_gid))
stat_info->stat.st_gid = GID_FROM_HEADER (header->header.gid);
}
-
+
switch (header->header.typeflag)
{
case BLKTYPE:
case CHRTYPE:
- stat_info->stat.st_rdev = makedev (stat_info->devmajor, stat_info->devminor);
+ stat_info->stat.st_rdev = makedev (stat_info->devmajor,
+ stat_info->devminor);
break;
default:
}
}
- if (extended_header.size)
- xheader_decode (stat_info);
+ stat_info->archive_file_size = stat_info->stat.st_size;
+ xheader_decode (stat_info);
+
+ if (sparse_member_p (stat_info))
+ {
+ sparse_fixup_header (stat_info);
+ stat_info->is_sparse = true;
+ }
}
/* Convert buffer at WHERE0 of size DIGS from external format to
#else
/* Use ISO 8610 format. See:
http://www.cl.cam.ac.uk/~mgk25/iso-time.html */
- struct tm *tm = localtime (&t);
+ struct tm *tm = utc_option ? gmtime (&t) : localtime (&t);
if (tm)
{
sprintf (buffer, "%04ld-%02d-%02d %02d:%02d:%02d",
#endif
void
-print_header (off_t block_ordinal)
+print_header (struct tar_stat_info *st, off_t block_ordinal)
{
char modes[11];
char const *time_stamp;
- char *temp_name = current_stat_info.orig_file_name ? current_stat_info.orig_file_name : current_stat_info.file_name;
-
+ char *temp_name = st->orig_file_name ? st->orig_file_name : st->file_name;
+
/* These hold formatted ints. */
char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND];
char *user, *group;
break;
}
- decode_mode (current_stat_info.stat.st_mode, modes + 1);
+ decode_mode (st->stat.st_mode, modes + 1);
/* Time stamp. */
- time_stamp = tartime (current_stat_info.stat.st_mtime);
+ time_stamp = tartime (st->stat.st_mtime);
/* User and group names. */
- if (current_stat_info.uname && current_format != V7_FORMAT
+ if (st->uname && current_format != V7_FORMAT
&& !numeric_owner_option)
- user = current_stat_info.uname;
+ user = st->uname;
else
{
/* Try parsing it as an unsigned integer first, and as a
}
}
- if (current_stat_info.gname && current_format != V7_FORMAT
+ if (st->gname && current_format != V7_FORMAT
&& !numeric_owner_option)
- group = current_stat_info.gname;
+ group = st->gname;
else
{
/* Try parsing it as an unsigned integer first, and as a
case CHRTYPE:
case BLKTYPE:
strcpy (size,
- STRINGIFY_BIGINT (major (current_stat_info.stat.st_rdev), uintbuf));
+ STRINGIFY_BIGINT (major (st->stat.st_rdev), uintbuf));
strcat (size, ",");
strcat (size,
- STRINGIFY_BIGINT (minor (current_stat_info.stat.st_rdev), uintbuf));
- break;
- case GNUTYPE_SPARSE:
- strcpy (size,
- STRINGIFY_BIGINT
- (UINTMAX_FROM_HEADER (current_header
- ->oldgnu_header.realsize),
- uintbuf));
+ STRINGIFY_BIGINT (minor (st->stat.st_rdev), uintbuf));
break;
+
default:
- strcpy (size, STRINGIFY_BIGINT (current_stat_info.stat.st_size, uintbuf));
+ /* st->stat.st_size keeps stored file size */
+ strcpy (size, STRINGIFY_BIGINT (st->stat.st_size, uintbuf));
break;
}
switch (current_header->header.typeflag)
{
case SYMTYPE:
- fprintf (stdlis, " -> %s\n", quotearg (current_stat_info.link_name));
+ fprintf (stdlis, " -> %s\n", quotearg (st->link_name));
break;
case LNKTYPE:
- fprintf (stdlis, _(" link to %s\n"), quotearg (current_stat_info.link_name));
+ fprintf (stdlis, _(" link to %s\n"), quotearg (st->link_name));
break;
default:
/* Print a similar line when we make a directory automatically. */
void
-print_for_mkdir (char *pathname, int length, mode_t mode)
+print_for_mkdir (char *dirname, int length, mode_t mode)
{
char modes[11];
}
fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
- _("Creating directory:"), length, quotearg (pathname));
+ _("Creating directory:"), length, quotearg (dirname));
}
}
save_sizeleft = size;
}
+ if (seekable_archive)
+ {
+ off_t nblk = seek_archive (size);
+ if (nblk >= 0)
+ {
+ size -= nblk * BLOCKSIZE;
+ if (multi_volume_option) /* Argh.. */
+ save_sizeleft -= nblk * BLOCKSIZE;
+ }
+ else
+ seekable_archive = false;
+ }
+
while (size > 0)
{
x = find_next_block ();
char save_typeflag = current_header->header.typeflag;
set_next_block_after (current_header);
- if (current_format == OLDGNU_FORMAT
- && current_header->oldgnu_header.isextended)
- {
- union block *exhdr;
- do
- {
- exhdr = find_next_block ();
- if (!exhdr)
- FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
- set_next_block_after (exhdr);
- }
- while (exhdr->sparse_header.isextended);
- }
+ assign_string (&save_name, current_stat_info.file_name);
- if (save_typeflag != DIRTYPE)
+ if (sparse_member_p (¤t_stat_info))
+ sparse_skip_file (¤t_stat_info);
+ else if (save_typeflag != DIRTYPE)
skip_file (current_stat_info.stat.st_size);
}