]> Dogcows Code - chaz/tar/blobdiff - src/buffer.c
Bugfixes.
[chaz/tar] / src / buffer.c
index 77ebe272f14b827a26f6506b587787917ee45b11..4286f67ce09672a84aa0e9ae060c906cc91c0fee 100644 (file)
@@ -1,13 +1,13 @@
 /* Buffer management for tar.
 
    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
-   2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
    Written by John Gilmore, on 1985-08-25.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any later
+   Free Software Foundation; either version 3, or (at your option) any later
    version.
 
    This program is distributed in the hope that it will be useful, but
@@ -26,7 +26,6 @@
 
 #include <closeout.h>
 #include <fnmatch.h>
-#include <getline.h>
 #include <human.h>
 #include <quotearg.h>
 
@@ -75,9 +74,6 @@ static int read_error_count;
 /* Have we hit EOF yet?  */
 static bool hit_eof;
 
-/* Checkpointing counter */
-static unsigned checkpoint;
-
 static bool read_full_records = false;
 
 /* We're reading, but we just read the last block and it's time to update.
@@ -121,6 +117,15 @@ static off_t save_totsize; /* total size of file we are writing, only
 static off_t save_sizeleft;    /* where we are in the file we are writing,
                                   only valid if save_name is nonzero */
 
+\f
+static struct tar_stat_info dummy;
+
+void
+buffer_write_global_xheader ()
+{
+  xheader_write_global (&dummy.xhdr);
+}
+
 void
 mv_begin (struct tar_stat_info *st)
 {
@@ -196,7 +201,8 @@ enum compress_type {
   ct_none,
   ct_compress,
   ct_gzip,
-  ct_bzip2
+  ct_bzip2,
+  ct_lzma
 };
 
 struct zip_magic
@@ -213,6 +219,7 @@ static struct zip_magic const magic[] = {
   { ct_compress, 2, "\037\235", "compress", "-Z" },
   { ct_gzip,     2, "\037\213", "gzip", "-z"  },
   { ct_bzip2,    3, "BZh",      "bzip2", "-j" },
+  { ct_lzma,     6, "\xFFLZMA", "lzma", "--lzma" }, /* FIXME: ???? */
 };
 
 #define NMAGIC (sizeof(magic)/sizeof(magic[0]))
@@ -222,18 +229,22 @@ static struct zip_magic const magic[] = {
 
 /* Check if the file ARCHIVE is a compressed archive. */
 enum compress_type
-check_compressed_archive ()
+check_compressed_archive (bool *pshort)
 {
   struct zip_magic const *p;
   bool sfr;
+  bool temp;
 
+  if (!pshort)
+    pshort = &temp;
+  
   /* Prepare global data needed for find_next_block: */
   record_end = record_start; /* set up for 1st record = # 0 */
   sfr = read_full_records;
   read_full_records = true; /* Suppress fatal error on reading a partial
                               record */
-  find_next_block ();
-
+  *pshort = find_next_block () == 0;
+  
   /* Restore global values */
   read_full_records = sfr;
 
@@ -261,11 +272,16 @@ open_compressed_archive ()
 
   if (!multi_volume_option)
     {
-      enum compress_type type = check_compressed_archive ();
+      bool shortfile;
+      enum compress_type type = check_compressed_archive (&shortfile);
 
       if (type == ct_none)
-       return archive;
-
+       {
+         if (shortfile)
+           ERROR ((0, 0, _("This does not look like a tar archive")));
+         return archive;
+       }
+      
       /* FD is not needed any more */
       rmtclose (archive);
 
@@ -474,6 +490,11 @@ _open_archive (enum access_mode wanted_access)
          abort (); /* Should not happen */
          break;
        }
+
+      if (!index_file_name
+         && wanted_access == ACCESS_WRITE
+         && strcmp (archive_name_array[0], "-") == 0)
+       stdlis = stderr;
     }
   else if (strcmp (archive_name_array[0], "-") == 0)
     {
@@ -485,26 +506,33 @@ _open_archive (enum access_mode wanted_access)
        {
        case ACCESS_READ:
          {
+           bool shortfile;
            enum compress_type type;
 
            archive = STDIN_FILENO;
 
-           type = check_compressed_archive ();
+           type = check_compressed_archive (&shortfile);
            if (type != ct_none)
              FATAL_ERROR ((0, 0,
                            _("Archive is compressed. Use %s option"),
                            compress_option (type)));
+           if (shortfile)
+             ERROR ((0, 0, _("This does not look like a tar archive")));
          }
          break;
 
        case ACCESS_WRITE:
          archive = STDOUT_FILENO;
+         if (!index_file_name)
+           stdlis = stderr;
          break;
 
        case ACCESS_UPDATE:
          archive = STDIN_FILENO;
          write_archive_to_stdout = true;
          record_end = record_start; /* set up for 1st record = # 0 */
+         if (!index_file_name)
+           stdlis = stderr;
          break;
        }
     }
@@ -533,7 +561,7 @@ _open_archive (enum access_mode wanted_access)
                           O_RDWR | O_CREAT | O_BINARY,
                           MODE_RW, rsh_command_option);
 
-       if (check_compressed_archive () != ct_none)
+       if (check_compressed_archive (NULL) != ct_none)
          FATAL_ERROR ((0, 0,
                        _("Cannot update compressed archives")));
        break;
@@ -567,43 +595,13 @@ _open_archive (enum access_mode wanted_access)
     }
 }
 
-static void
-do_checkpoint (bool write)
-{
-  if (checkpoint_option && !(++checkpoint % checkpoint_option))
-    {
-      switch (checkpoint_style)
-       {
-       case checkpoint_dot:
-         fputc ('.', stdlis);
-         fflush (stdlis);
-         break;
-
-       case checkpoint_text:
-         if (write)
-           /* TRANSLATORS: This is a ``checkpoint of write operation'',
-            *not* ``Writing a checkpoint''.
-            E.g. in Spanish ``Punto de comprobaci@'on de escritura'',
-            *not* ``Escribiendo un punto de comprobaci@'on'' */
-           WARN ((0, 0, _("Write checkpoint %u"), checkpoint));
-         else
-           /* TRANSLATORS: This is a ``checkpoint of read operation'',
-              *not* ``Reading a checkpoint''.
-              E.g. in Spanish ``Punto de comprobaci@'on de lectura'',
-              *not* ``Leyendo un punto de comprobaci@'on'' */
-           WARN ((0, 0, _("Read checkpoint %u"), checkpoint));
-         break;
-       }
-    }
-}  
-
 /* Perform a write to flush the buffer.  */
 ssize_t
 _flush_write (void)
 {
   ssize_t status;
 
-  do_checkpoint (true);
+  checkpoint_run (true);
   if (tape_length_option && tape_length_option <= bytes_written)
     {
       errno = ENOSPC;
@@ -613,7 +611,7 @@ _flush_write (void)
     status = record_size;
   else
     status = sys_write_archive_buffer ();
-
+  
   return status;
 }
 
@@ -835,7 +833,7 @@ close_archive (void)
     verify_volume ();
 
   if (rmtclose (archive) != 0)
-    close_warn (*archive_name_cursor);
+    close_error (*archive_name_cursor);
 
   sys_wait_for_child (child_pid);
 
@@ -1020,9 +1018,10 @@ new_volume (enum access_mode mode)
   assign_string (&volume_label, NULL);
   assign_string (&continued_file_name, NULL);
   continued_file_size = continued_file_offset = 0;
-
+  current_block = record_start;
+  
   if (rmtclose (archive) != 0)
-    close_warn (*archive_name_cursor);
+    close_error (*archive_name_cursor);
 
   archive_name_cursor++;
   if (archive_name_cursor == archive_name_array + archive_names)
@@ -1113,23 +1112,24 @@ try_new_volume ()
 {
   size_t status;
   union block *header;
-  struct tar_stat_info dummy;
-       
+  enum access_mode acc;
+  
   switch (subcommand_option)
     {
     case APPEND_SUBCOMMAND:
     case CAT_SUBCOMMAND:
     case UPDATE_SUBCOMMAND:
-      if (!new_volume (ACCESS_UPDATE))
-       return true;
+      acc = ACCESS_UPDATE;
       break;
 
     default:
-      if (!new_volume (ACCESS_READ))
-       return true;
+      acc = ACCESS_READ;
       break;
     }
 
+  if (!new_volume (acc))
+    return true;
+  
   while ((status = rmtread (archive, record_start->buffer, record_size))
         == SAFE_READ_ERROR)
     archive_read_error ();
@@ -1224,7 +1224,15 @@ try_new_volume ()
 
       if (real_s_totsize - real_s_sizeleft != continued_file_offset)
        {
-         WARN ((0, 0, _("This volume is out of sequence")));
+         char totsizebuf[UINTMAX_STRSIZE_BOUND];
+         char s1buf[UINTMAX_STRSIZE_BOUND];
+         char s2buf[UINTMAX_STRSIZE_BOUND];
+
+         WARN ((0, 0, _("This volume is out of sequence (%s - %s != %s)"),
+                STRINGIFY_BIGINT (real_s_totsize, totsizebuf),
+                STRINGIFY_BIGINT (real_s_sizeleft, s1buf),
+                STRINGIFY_BIGINT (continued_file_offset, s2buf)));
+        
          return false;
        }
     }
@@ -1283,7 +1291,7 @@ static void
 _write_volume_label (const char *str)
 {
   if (archive_format == POSIX_FORMAT)
-    xheader_store ("GNU.volume.label", NULL, str);
+    xheader_store ("GNU.volume.label", &dummy, str);
   else
     {
       union block *label = find_next_block ();
@@ -1400,9 +1408,9 @@ add_multi_volume_header (void)
   if (archive_format == POSIX_FORMAT)
     {
       off_t d = real_s_totsize - real_s_sizeleft;
-      xheader_store ("GNU.volume.filename", NULL, real_s_name);
-      xheader_store ("GNU.volume.size", NULL, &real_s_sizeleft);
-      xheader_store ("GNU.volume.offset", NULL, &d);
+      xheader_store ("GNU.volume.filename", &dummy, real_s_name);
+      xheader_store ("GNU.volume.size", &dummy, &real_s_sizeleft);
+      xheader_store ("GNU.volume.offset", &dummy, &d);
     }
   else
     gnu_add_multi_volume_header ();
@@ -1440,7 +1448,7 @@ simple_flush_read (void)
 {
   size_t status;               /* result from system call */
 
-  do_checkpoint (false);
+  checkpoint_run (false);
   
   /* Clear the count of errors.  This only applies to a single call to
      flush_read.  */
@@ -1499,7 +1507,7 @@ _gnu_flush_read (void)
 {
   size_t status;               /* result from system call */
 
-  do_checkpoint (false);
+  checkpoint_run (false);
   
   /* Clear the count of errors.  This only applies to a single call to
      flush_read.  */
@@ -1581,15 +1589,22 @@ _gnu_flush_write (size_t buffer_level)
       return;
     }
 
+  if (status % BLOCKSIZE)
+    {
+      ERROR ((0, 0, _("write did not end on a block boundary")));
+      archive_write_error (status);
+    }
+  
   /* In multi-volume mode. */
   /* ENXIO is for the UNIX PC.  */
   if (status < 0 && errno != ENOSPC && errno != EIO && errno != ENXIO)
     archive_write_error (status);
 
+  real_s_sizeleft -= status;
   if (!new_volume (ACCESS_WRITE))
     return;
 
-  xheader_destroy (&extended_header);
+  tar_stat_destroy (&dummy);
 
   increase_volume_number ();
   prev_written += bytes_written;
@@ -1597,6 +1612,7 @@ _gnu_flush_write (size_t buffer_level)
 
   copy_ptr = record_start->buffer + status;
   copy_size = buffer_level - status;
+                  
   /* Switch to the next buffer */
   record_index = !record_index;
   init_buffer ();
@@ -1607,7 +1623,9 @@ _gnu_flush_write (size_t buffer_level)
   if (real_s_name)
     add_multi_volume_header ();
 
-  write_extended (true, NULL, find_next_block ());
+  write_extended (true, &dummy, find_next_block ());
+  tar_stat_destroy (&dummy);
+  
   if (real_s_name)
     add_chunk_header ();
   header = find_next_block ();
This page took 0.029304 seconds and 4 git commands to generate.