]> Dogcows Code - chaz/tar/blobdiff - src/list.c
(read_and): Invoke apply_nonancestor_delayed_set_stat on file names
[chaz/tar] / src / list.c
index 396d83aaf1fcb2f1e3520bbf636aa24886de96d9..cb3862bc1def4fba9600ccbf66c5b26811d8ebdf 100644 (file)
@@ -35,7 +35,6 @@ union block *current_header;  /* points to current archive header */
 struct stat current_stat;      /* stat struct corresponding */
 enum archive_format current_format; /* recognized format */
 
-static char const *tartime PARAMS ((time_t));
 static uintmax_t from_header PARAMS ((const char *, size_t, const char *,
                                      uintmax_t, uintmax_t));
 
@@ -90,43 +89,45 @@ read_and (void (*do_something) ())
          /* Valid header.  We should decode next field (mode) first.
             Ensure incoming names are null terminated.  */
 
-         if (!name_match (current_file_name)
+         if (! name_match (current_file_name)
              || (newer_mtime_option != TYPE_MINIMUM (time_t)
-                 /* FIXME: We get mtime now, and again later; this
-                    causes duplicate diagnostics if header.mtime is
-                    bogus.  */
+                 /* FIXME: We get mtime now, and again later; this causes
+                    duplicate diagnostics if header.mtime is bogus.  */
                  && ((current_stat.st_mtime
                       = TIME_FROM_HEADER (current_header->header.mtime))
                      < newer_mtime_option))
              || excluded_name (current_file_name))
            {
-             char save_typeflag;
-
-             if (current_header->header.typeflag == GNUTYPE_VOLHDR
-                 || current_header->header.typeflag == GNUTYPE_MULTIVOL
-                 || current_header->header.typeflag == GNUTYPE_NAMES)
+             char save_typeflag = current_header->header.typeflag;
+             switch (save_typeflag)
                {
-                 (*do_something) ();
-                 continue;
-               }
-             if (show_omitted_dirs_option
-                 && current_header->header.typeflag == DIRTYPE)
-               WARN ((0, 0, _("Omitting %s"), current_file_name));
+               case GNUTYPE_VOLHDR:
+               case GNUTYPE_MULTIVOL:
+               case GNUTYPE_NAMES:
+                 break;
+               
+               case DIRTYPE:
+                 if (show_omitted_dirs_option)
+                   WARN ((0, 0, _("%s: Omitting"),
+                          quotearg_colon (current_file_name)));
+                 /* Fall through.  */
+               default:
 
-             /* Skip past it in the archive.  */
+                 /* Skip past it in the archive.  */
 
-             save_typeflag = current_header->header.typeflag;
-             set_next_block_after (current_header);
-             if (current_header->oldgnu_header.isextended)
-               skip_extended_headers ();
+                 set_next_block_after (current_header);
+                 if (current_header->oldgnu_header.isextended)
+                   skip_extended_headers ();
 
-             /* Skip to the next header on the archive.  */
+                 /* Skip to the next header on the archive.  */
 
-             if (save_typeflag != DIRTYPE)
-               skip_file (current_stat.st_size);
-             continue;
-           }
+                 if (save_typeflag != DIRTYPE)
+                   skip_file (current_stat.st_size);
+                 continue;
+               }
+             }
 
+         apply_nonancestor_delayed_set_stat (current_file_name);
          (*do_something) ();
          continue;
 
@@ -160,12 +161,12 @@ read_and (void (*do_something) ())
          switch (prev_status)
            {
            case HEADER_STILL_UNREAD:
-             WARN ((0, 0, _("This does not look like a tar archive")));
+             ERROR ((0, 0, _("This does not look like a tar archive")));
              /* Fall through.  */
 
            case HEADER_ZERO_BLOCK:
            case HEADER_SUCCESS:
-             WARN ((0, 0, _("Skipping to next header")));
+             ERROR ((0, 0, _("Skipping to next header")));
              break;
 
            case HEADER_END_OF_FILE:
@@ -218,21 +219,19 @@ list_archive (void)
          data_block = find_next_block ();
          if (!data_block)
            {
-             ERROR ((0, 0, _("EOF in archive file")));
+             ERROR ((0, 0, _("Unexpected EOF in archive")));
              break;            /* FIXME: What happens, then?  */
            }
          written = available_space_after (data_block);
          if (written > size)
            written = size;
-         errno = 0;            /* FIXME: errno should be read-only */
+         errno = 0;
          check = fwrite (data_block->buffer, sizeof (char), written, stdlis);
          set_next_block_after ((union block *)
                                (data_block->buffer + written - 1));
          if (check != written)
            {
-             ERROR ((0, errno, _("Only wrote %lu of %lu bytes to file %s"),
-                     (unsigned long) check,
-                     (unsigned long) written, current_file_name));
+             write_error_details (current_file_name, check, written);
              skip_file (size - written);
              break;
            }
@@ -359,7 +358,7 @@ read_header (void)
            free (*longp);
          size = current_stat.st_size;
          if (size != current_stat.st_size)
-           FATAL_ERROR ((0, 0, _("Memory exhausted")));
+           xalloc_die ();
          bp = *longp = xmalloc (size);
 
          for (; size > 0; size -= written)
@@ -367,7 +366,7 @@ read_header (void)
              data_block = find_next_block ();
              if (! data_block)
                {
-                 ERROR ((0, 0, _("Unexpected EOF on archive file")));
+                 ERROR ((0, 0, _("Unexpected EOF in archive")));
                  break;
                }
              written = available_space_after (data_block);
@@ -566,16 +565,25 @@ from_header (char const *where0, size_t digs, char const *type,
        }
 
       /* Parse the output of older, unportable tars, which generate
-        negative values in two's complement octal.  */
-      if ((overflow || maxval < value) && '4' <= *where1)
+         negative values in two's complement octal.  If the leading
+         nonzero digit is 1, we can't recover the original value
+         reliably; so do this only if the digit is 2 or more.  This
+         catches the common case of 32-bit negative time stamps.  */
+      if ((overflow || maxval < value) && '2' <= *where1)
        {
          /* Compute the negative of the input value, assuming two's
             complement.  */
-         for (value = 0, where = where1, overflow = 0; ; )
+         int digit = (*where1 - '0') | 4;
+         overflow = 0;
+         value = 0;
+         where = where1;
+         for (;;)
            {
-             value += 7 - (*where++ - '0');
+             value += 7 - digit;
+             where++;
              if (where == lim || ! ISODIGIT (*where))
                break;
+             digit = *where - '0';
              overflow |= value ^ (value << LG_8 >> LG_8);
              value <<= LG_8;
            }
@@ -675,14 +683,14 @@ from_header (char const *where0, size_t digs, char const *type,
          if (!o)
            {
              o = clone_quoting_options (0);
-             set_quoting_style (o, c_quoting_style);
+             set_quoting_style (o, locale_quoting_style);
            }
 
          while (where0 != lim && ! lim[-1])
            lim--;
          quotearg_buffer (buf, sizeof buf, where0, lim - where, o);
          ERROR ((0, 0,
-                 _("Archive contains `%.*s' where numeric %s value expected"),
+                 _("Archive contains %.*s where numeric %s value expected"),
                  (int) sizeof buf, buf, type));
        }
 
@@ -816,7 +824,7 @@ stringify_uintmax_t_backwards (uintmax_t o, char *buf)
 /* Return a printable representation of T.  The result points to
    static storage that can be reused in the next call to this
    function, to ctime, or to asctime.  */
-static char const *
+char const *
 tartime (time_t t)
 {
   static char buffer[max (UINTMAX_STRSIZE_BOUND + 1,
@@ -859,32 +867,6 @@ tartime (time_t t)
   return p;
 }
 
-/*-------------------------------------------------------------------------.
-| Decode MODE from its binary form in a stat structure, and encode it into |
-| a 9 characters string STRING, terminated with a NUL.                     |
-`-------------------------------------------------------------------------*/
-
-static void
-decode_mode (mode_t mode, char *string)
-{
-  *string++ = mode & S_IRUSR ? 'r' : '-';
-  *string++ = mode & S_IWUSR ? 'w' : '-';
-  *string++ = (mode & S_ISUID
-              ? (mode & S_IXUSR ? 's' : 'S')
-              : (mode & S_IXUSR ? 'x' : '-'));
-  *string++ = mode & S_IRGRP ? 'r' : '-';
-  *string++ = mode & S_IWGRP ? 'w' : '-';
-  *string++ = (mode & S_ISGID
-              ? (mode & S_IXGRP ? 's' : 'S')
-              : (mode & S_IXGRP ? 'x' : '-'));
-  *string++ = mode & S_IROTH ? 'r' : '-';
-  *string++ = mode & S_IWOTH ? 'w' : '-';
-  *string++ = (mode & S_ISVTX
-              ? (mode & S_IXOTH ? 't' : 'T')
-              : (mode & S_IXOTH ? 'x' : '-'));
-  *string = '\0';
-}
-
 /*-------------------------------------------------------------------------.
 | Actually print it.                                                      |
 |                                                                         |
@@ -923,7 +905,6 @@ print_header (void)
                                /* holds formatted size or major,minor */
   char uintbuf[UINTMAX_STRSIZE_BOUND];
   int pad;
-  char *name;
 
   if (block_number_option)
     {
@@ -935,16 +916,7 @@ print_header (void)
   if (verbose_option <= 1)
     {
       /* Just the fax, mam.  */
-
-      char *quoted_name = quote_copy_string (current_file_name);
-
-      if (quoted_name)
-       {
-         fprintf (stdlis, "%s\n", quoted_name);
-         free (quoted_name);
-       }
-      else
-       fprintf (stdlis, "%s\n", current_file_name);
+      fprintf (stdlis, "%s\n", quotearg (current_file_name));
     }
   else
     {
@@ -1058,37 +1030,16 @@ print_header (void)
       fprintf (stdlis, "%s %s/%s %*s%s %s",
               modes, user, group, ugswidth - pad, "", size, time_stamp);
 
-      name = quote_copy_string (current_file_name);
-      if (name)
-       {
-         fprintf (stdlis, " %s", name);
-         free (name);
-       }
-      else
-       fprintf (stdlis, " %s", current_file_name);
+      fprintf (stdlis, " %s", quotearg (current_file_name));
 
       switch (current_header->header.typeflag)
        {
        case SYMTYPE:
-         name = quote_copy_string (current_link_name);
-         if (name)
-           {
-             fprintf (stdlis, " -> %s\n", name);
-             free (name);
-           }
-         else
-           fprintf (stdlis, " -> %s\n", current_link_name);
+         fprintf (stdlis, " -> %s\n", quotearg (current_link_name));
          break;
 
        case LNKTYPE:
-         name = quote_copy_string (current_link_name);
-         if (name)
-           {
-             fprintf (stdlis, _(" link to %s\n"), name);
-             free (name);
-           }
-         else
-           fprintf (stdlis, _(" link to %s\n"), current_link_name);
+         fprintf (stdlis, _(" link to %s\n"), quotearg (current_link_name));
          break;
 
        default:
@@ -1136,7 +1087,6 @@ void
 print_for_mkdir (char *pathname, int length, mode_t mode)
 {
   char modes[11];
-  char *name;
 
   if (verbose_option > 1)
     {
@@ -1151,16 +1101,9 @@ print_for_mkdir (char *pathname, int length, mode_t mode)
          fprintf (stdlis, _("block %s: "),
                   STRINGIFY_BIGINT (current_block_ordinal (), buf));
        }
-      name = quote_copy_string (pathname);
-      if (name)
-       {
-         fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
-                  _("Creating directory:"), length, name);
-         free (name);
-       }
-      else
-       fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
-                _("Creating directory:"), length, pathname);
+
+      fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
+              _("Creating directory:"), length, quotearg (pathname));
     }
 }
 
@@ -1183,7 +1126,7 @@ skip_file (off_t size)
     {
       x = find_next_block ();
       if (! x)
-       FATAL_ERROR ((0, 0, _("Unexpected EOF on archive file")));
+       FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
 
       set_next_block_after (x);
       size -= BLOCKSIZE;
@@ -1205,7 +1148,7 @@ skip_extended_headers (void)
     {
       exhdr = find_next_block ();
       if (!exhdr)
-       FATAL_ERROR ((0, 0, _("Unexpected EOF on archive file")));
+       FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
       set_next_block_after (exhdr);
     }
   while (exhdr->sparse_header.isextended);
This page took 0.034154 seconds and 4 git commands to generate.