]> Dogcows Code - chaz/tar/blobdiff - src/list.c
Fix improper use of 'path' word
[chaz/tar] / src / list.c
index 850faeb1e2e584434616b7d04d6e5a9f7a25db95..cb207a982b9633eec275daf8ca8fa287139f3002 100644 (file)
@@ -1,7 +1,7 @@
 /* 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.
 
@@ -73,13 +73,17 @@ read_and (void (*do_something) (void))
   name_gather ();
   open_archive (ACCESS_READ);
 
-  while (1)
+  do
     {
       prev_status = status;
-      status = read_header (0);
+      tar_stat_destroy (&current_stat_info);
+      xheader_destroy (&extended_header);
+
+      status = read_header (false);
       switch (status)
        {
        case HEADER_STILL_UNREAD:
+       case HEADER_SUCCESS_EXTENDED:
          abort ();
 
        case HEADER_SUCCESS:
@@ -88,12 +92,17 @@ read_and (void (*do_something) (void))
             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)
@@ -112,7 +121,7 @@ read_and (void (*do_something) (void))
                  skip_member ();
                  continue;
                }
-             }
+           }
 
          (*do_something) ();
          continue;
@@ -126,10 +135,20 @@ read_and (void (*do_something) (void))
            }
 
          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)
@@ -152,6 +171,15 @@ read_and (void (*do_something) (void))
 
            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;
 
@@ -159,11 +187,15 @@ read_and (void (*do_something) (void))
            case HEADER_FAILURE:
              /* We are in the middle of a cascade of errors.  */
              break;
+
+           case HEADER_SUCCESS_EXTENDED:
+             abort ();
            }
          continue;
        }
       break;
     }
+  while (!all_names_found (&current_stat_info));
 
   close_archive ();
   names_notfound ();           /* print names not found */
@@ -175,12 +207,9 @@ list_archive (void)
 {
   /* Print the header block.  */
 
+  decode_header (current_header, &current_stat_info, &current_format, 0);
   if (verbose_option)
-    {
-      if (verbose_option > 1)
-       decode_header (current_header, &current_stat_info, &current_format, 0);
-      print_header (-1);
-    }
+    print_header (&current_stat_info, -1);
 
   if (incremental_option && current_header->header.typeflag == GNUTYPE_DUMPDIR)
     {
@@ -319,71 +348,75 @@ read_header (bool raw_extended_headers)
 
       /* Good block.  Decode file size and return.  */
 
-      if (header->header.typeflag == XHDTYPE
-         || header->header.typeflag == XGLTYPE)
-       {
-         xheader_read (header, OFF_FROM_HEADER (header->header.size));
-         continue;
-       }
-      
       if (header->header.typeflag == LNKTYPE)
        current_stat_info.stat.st_size = 0;     /* links 0 size on tape */
       else
        current_stat_info.stat.st_size = OFF_FROM_HEADER (header->header.size);
 
       if (header->header.typeflag == GNUTYPE_LONGNAME
-         || header->header.typeflag == GNUTYPE_LONGLINK)
+         || header->header.typeflag == GNUTYPE_LONGLINK
+         || header->header.typeflag == XHDTYPE
+         || header->header.typeflag == XGLTYPE)
        {
          if (raw_extended_headers)
            return HEADER_SUCCESS_EXTENDED;
-         else
+         else if (header->header.typeflag == GNUTYPE_LONGNAME
+                  || header->header.typeflag == GNUTYPE_LONGLINK)
            {
              size_t name_size = current_stat_info.stat.st_size;
              size = name_size - name_size % BLOCKSIZE + 2 * BLOCKSIZE;
-             if (name_size != current_stat_info.stat.st_size || size < name_size)
+             if (name_size != current_stat_info.stat.st_size
+                 || size < name_size)
                xalloc_die ();
-           }
 
-         header_copy = xmalloc (size + 1);
+             header_copy = xmalloc (size + 1);
 
-         if (header->header.typeflag == GNUTYPE_LONGNAME)
-           {
-             if (next_long_name)
-               free (next_long_name);
-             next_long_name = header_copy;
-             next_long_name_blocks = size / BLOCKSIZE;
-           }
-         else
-           {
-             if (next_long_link)
-               free (next_long_link);
-             next_long_link = header_copy;
-             next_long_link_blocks = size / BLOCKSIZE;
-           }
+             if (header->header.typeflag == GNUTYPE_LONGNAME)
+               {
+                 if (next_long_name)
+                   free (next_long_name);
+                 next_long_name = header_copy;
+                 next_long_name_blocks = size / BLOCKSIZE;
+               }
+             else
+               {
+                 if (next_long_link)
+                   free (next_long_link);
+                 next_long_link = header_copy;
+                 next_long_link_blocks = size / BLOCKSIZE;
+               }
 
-         set_next_block_after (header);
-         *header_copy = *header;
-         bp = header_copy->buffer + BLOCKSIZE;
+             set_next_block_after (header);
+             *header_copy = *header;
+             bp = header_copy->buffer + BLOCKSIZE;
 
-         for (size -= BLOCKSIZE; size > 0; size -= written)
-           {
-             data_block = find_next_block ();
-             if (! data_block)
+             for (size -= BLOCKSIZE; size > 0; size -= written)
                {
-                 ERROR ((0, 0, _("Unexpected EOF in archive")));
-                 break;
+                 data_block = find_next_block ();
+                 if (! data_block)
+                   {
+                     ERROR ((0, 0, _("Unexpected EOF in archive")));
+                     break;
+                   }
+                 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 *)
+                                       (data_block->buffer + written - 1));
                }
-             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 *)
-                                   (data_block->buffer + written - 1));
-           }
 
-         *bp = '\0';
+             *bp = '\0';
+           }
+         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!  */
 
@@ -484,8 +517,10 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
          && 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;
@@ -499,7 +534,10 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
   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);
@@ -535,12 +573,13 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
              || !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:
@@ -548,8 +587,14 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
        }
     }
 
-  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
@@ -876,7 +921,7 @@ tartime (time_t t)
 #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",
@@ -925,12 +970,12 @@ static int ugswidth = UGSWIDTH;   /* maximum width encountered so far */
 #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;
@@ -1013,17 +1058,17 @@ print_header (off_t block_ordinal)
          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
@@ -1043,9 +1088,9 @@ print_header (off_t block_ordinal)
            }
        }
 
-      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
@@ -1072,20 +1117,15 @@ print_header (off_t block_ordinal)
        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;
        }
 
@@ -1103,11 +1143,11 @@ print_header (off_t block_ordinal)
       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:
@@ -1162,7 +1202,7 @@ print_header (off_t block_ordinal)
 
 /* 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];
 
@@ -1181,7 +1221,7 @@ print_for_mkdir (char *pathname, int length, mode_t mode)
        }
 
       fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
-              _("Creating directory:"), length, quotearg (pathname));
+              _("Creating directory:"), length, quotearg (dirname));
     }
 }
 
@@ -1217,20 +1257,10 @@ skip_member (void)
   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 (&current_stat_info))
+    sparse_skip_file (&current_stat_info);
+  else if (save_typeflag != DIRTYPE)
     skip_file (current_stat_info.stat.st_size);
 }
This page took 0.032918 seconds and 4 git commands to generate.