]> Dogcows Code - chaz/tar/blobdiff - src/buffer.c
(read_header0): Use read_header_primitive to avoid clubbering current_tar_info. All...
[chaz/tar] / src / buffer.c
index 586b1f9536fc444605e9c8ac6897aa65a0b0cd1c..d788b167fed142a4b308413ab1a8b3fbadacf580 100644 (file)
@@ -1,7 +1,7 @@
 /* Buffer management for tar.
 
    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
-   2003, 2004, 2005 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
    Written by John Gilmore, on 1985-08-25.
 
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #include <system.h>
+#include <system-ioctl.h>
 
 #include <signal.h>
 
+#include <closeout.h>
 #include <fnmatch.h>
+#include <getline.h>
 #include <human.h>
 #include <quotearg.h>
 
@@ -41,6 +44,7 @@
 static tarlong prev_written;   /* bytes written on previous volumes */
 static tarlong bytes_written;  /* bytes written on this volume */
 static void *record_buffer[2]; /* allocated memory */
+union block *record_buffer_aligned[2];
 static int record_index;
 
 /* FIXME: The following variables should ideally be static to this
@@ -366,10 +370,11 @@ xclose (int fd)
 static void
 init_buffer ()
 {
-  if (!record_buffer[record_index])
-    page_aligned_alloc (&record_buffer[record_index], record_size);
-      
-  record_start = record_buffer[record_index];
+  if (! record_buffer_aligned[record_index])
+    record_buffer_aligned[record_index] =
+      page_aligned_alloc (&record_buffer[record_index], record_size);
+
+  record_start = record_buffer_aligned[record_index];
   current_block = record_start;
   record_end = record_start + blocking_factor;
 }
@@ -383,9 +388,10 @@ _open_archive (enum access_mode wanted_access)
 
   if (index_file_name)
     {
-      stdlis = fopen (index_file_name, "w");
+      stdlis = freopen (index_file_name, "w", stdout);
       if (! stdlis)
        open_error (index_file_name);
+      close_stdout_set_file_name (index_file_name);
     }
   else
     stdlis = to_stdout_option ? stderr : stdout;
@@ -402,7 +408,7 @@ _open_archive (enum access_mode wanted_access)
 
   record_index = 0;
   init_buffer ();
-  
+
   /* When updating the archive, we start with reading.  */
   access_mode = wanted_access == ACCESS_UPDATE ? ACCESS_READ : wanted_access;
 
@@ -447,7 +453,7 @@ _open_archive (enum access_mode wanted_access)
 
            archive = STDIN_FILENO;
 
-           type = check_compressed_archive (archive);
+           type = check_compressed_archive ();
            if (type != ct_none)
              FATAL_ERROR ((0, 0,
                            _("Archive is compressed. Use %s option"),
@@ -876,19 +882,19 @@ change_tape_menu (FILE *read_file)
               _("Prepare volume #%d for %s and hit return: "),
               global_volno + 1, quote (*archive_name_cursor));
       fflush (stderr);
-      
+
       if (getline (&input_buffer, &size, read_file) <= 0)
        {
          WARN ((0, 0, _("EOF where user reply was expected")));
-         
+
          if (subcommand_option != EXTRACT_SUBCOMMAND
              && subcommand_option != LIST_SUBCOMMAND
              && subcommand_option != DIFF_SUBCOMMAND)
            WARN ((0, 0, _("WARNING: Archive is incomplete")));
-         
+
          fatal_exit ();
        }
-      
+
       if (input_buffer[0] == '\n'
          || input_buffer[0] == 'y'
          || input_buffer[0] == 'Y')
@@ -910,37 +916,37 @@ change_tape_menu (FILE *read_file)
 
        case 'q':
          /* Quit.  */
-         
+
          WARN ((0, 0, _("No new volume; exiting.\n")));
-         
+
          if (subcommand_option != EXTRACT_SUBCOMMAND
              && subcommand_option != LIST_SUBCOMMAND
              && subcommand_option != DIFF_SUBCOMMAND)
            WARN ((0, 0, _("WARNING: Archive is incomplete")));
-         
+
          fatal_exit ();
-         
+
        case 'n':
          /* Get new file name.  */
-         
+
          {
            char *name;
            char *cursor;
-           
+
            for (name = input_buffer + 1;
                 *name == ' ' || *name == '\t';
                 name++)
              ;
-           
+
            for (cursor = name; *cursor && *cursor != '\n'; cursor++)
              ;
            *cursor = '\0';
-           
+
            /* FIXME: the following allocation is never reclaimed.  */
            *archive_name_cursor = xstrdup (name);
          }
          break;
-         
+
        case '!':
          if (!restrict_option)
            {
@@ -964,6 +970,7 @@ new_volume (enum access_mode mode)
 {
   static FILE *read_file;
   static int looped;
+  int prompt;
 
   if (!read_file && !info_script_option)
     /* FIXME: if fopen is used, it will never be closed.  */
@@ -977,7 +984,7 @@ new_volume (enum access_mode mode)
   assign_string (&volume_label, NULL);
   assign_string (&continued_file_name, NULL);
   continued_file_size = continued_file_offset = 0;
-  
+
   if (rmtclose (archive) != 0)
     close_warn (*archive_name_cursor);
 
@@ -987,9 +994,10 @@ new_volume (enum access_mode mode)
       archive_name_cursor = archive_name_array;
       looped = 1;
     }
+  prompt = looped;
 
  tryagain:
-  if (looped)
+  if (prompt)
     {
       /* We have to prompt from now on.  */
 
@@ -1039,6 +1047,7 @@ new_volume (enum access_mode mode)
       open_warn (*archive_name_cursor);
       if (!verify_option && mode == ACCESS_WRITE && backup_option)
        undo_last_backup ();
+      prompt = 1;
       goto tryagain;
     }
 
@@ -1048,10 +1057,12 @@ new_volume (enum access_mode mode)
 }
 
 static bool
-read_header0 ()
+read_header0 (struct tar_stat_info *info)
 {
-  enum read_header rc = read_header (false);
+  enum read_header rc;
 
+  tar_stat_init (info);
+  rc = read_header_primitive (false, info);
   if (rc == HEADER_SUCCESS)
     {
       set_next_block_after (current_header);
@@ -1066,7 +1077,8 @@ try_new_volume ()
 {
   size_t status;
   union block *header;
-
+  struct tar_stat_info dummy;
+       
   switch (subcommand_option)
     {
     case APPEND_SUBCOMMAND:
@@ -1092,14 +1104,13 @@ try_new_volume ()
   header = find_next_block ();
   if (!header)
     return false;
+
   switch (header->header.typeflag)
     {
     case XGLTYPE:
       {
-       struct tar_stat_info dummy;
-       if (!read_header0 ())
+       if (!read_header0 (&dummy))
          return false;
-       tar_stat_init (&dummy);
        xheader_decode (&dummy); /* decodes values from the global header */
        tar_stat_destroy (&dummy);
        if (!real_s_name)
@@ -1111,27 +1122,29 @@ try_new_volume ()
          }
        break;
       }
-      
+
     case GNUTYPE_VOLHDR:
-      if (!read_header0 ())
+      if (!read_header0 (&dummy))
        return false;
+      tar_stat_destroy (&dummy);
       assign_string (&volume_label, current_header->header.name);
       set_next_block_after (header);
       header = find_next_block ();
       if (header->header.typeflag != GNUTYPE_MULTIVOL)
        break;
       /* FALL THROUGH */
-      
+
     case GNUTYPE_MULTIVOL:
-      if (!read_header0 ())
+      if (!read_header0 (&dummy))
        return false;
+      tar_stat_destroy (&dummy);
       assign_string (&continued_file_name, current_header->header.name);
       continued_file_size =
        UINTMAX_FROM_HEADER (current_header->header.size);
       continued_file_offset =
        UINTMAX_FROM_HEADER (current_header->oldgnu_header.offset);
       break;
-      
+
     default:
       break;
     }
@@ -1139,12 +1152,22 @@ try_new_volume ()
   if (real_s_name)
     {
       uintmax_t s;
-      if (!continued_file_name 
+      if (!continued_file_name
          || strcmp (continued_file_name, real_s_name))
        {
-         WARN ((0, 0, _("%s is not continued on this volume"),
-                quote (real_s_name)));
-         return false;
+         if ((archive_format == GNU_FORMAT || archive_format == OLDGNU_FORMAT)
+             && strlen (real_s_name) >= NAME_FIELD_SIZE
+             && strncmp (continued_file_name, real_s_name,
+                         NAME_FIELD_SIZE) == 0)
+           WARN ((0, 0,
+ _("%s is possibly continued on this volume: header contains truncated name"),
+                  quote (real_s_name)));
+         else
+           {
+             WARN ((0, 0, _("%s is not continued on this volume"),
+                    quote (real_s_name)));
+             return false;
+           }
        }
 
       s = continued_file_size + continued_file_offset;
@@ -1162,7 +1185,7 @@ try_new_volume ()
                 STRINGIFY_BIGINT (continued_file_offset, s2buf)));
          return false;
        }
-      
+
       if (real_s_totsize - real_s_sizeleft != continued_file_offset)
        {
          WARN ((0, 0, _("This volume is out of sequence")));
@@ -1228,7 +1251,7 @@ _write_volume_label (const char *str)
   else
     {
       union block *label = find_next_block ();
-      
+
       memset (label, 0, BLOCKSIZE);
 
       strcpy (label->header.name, volume_label_option);
@@ -1280,13 +1303,13 @@ add_chunk_header ()
                                               real_s_part_no);
       st.file_name = st.orig_file_name;
       st.archive_file_size = st.stat.st_size = real_s_sizeleft;
-      
+
       block_ordinal = current_block_ordinal ();
       blk = start_header (&st);
-      free (st.orig_file_name);
       if (!blk)
        abort (); /* FIXME */
       finish_header (&st, blk, block_ordinal);
+      free (st.orig_file_name);
     }
 }
 
@@ -1307,25 +1330,25 @@ gnu_add_multi_volume_header (void)
 {
   int tmp;
   union block *block = find_next_block ();
-  
+
   if (strlen (real_s_name) > NAME_FIELD_SIZE)
     WARN ((0, 0,
           _("%s: file name too long to be stored in a GNU multivolume header, truncated"),
           quotearg_colon (real_s_name)));
-  
+
   memset (block, 0, BLOCKSIZE);
-  
+
   /* FIXME: Michael P Urban writes: [a long name file] is being written
      when a new volume rolls around [...]  Looks like the wrong value is
      being preserved in real_s_name, though.  */
-  
+
   strncpy (block->header.name, real_s_name, NAME_FIELD_SIZE);
   block->header.typeflag = GNUTYPE_MULTIVOL;
-  
+
   OFF_TO_CHARS (real_s_sizeleft, block->header.size);
   OFF_TO_CHARS (real_s_totsize - real_s_sizeleft,
                block->oldgnu_header.offset);
-  
+
   tmp = verbose_option;
   verbose_option = 0;
   finish_header (&current_stat_info, block, -1);
@@ -1401,7 +1424,7 @@ simple_flush_read (void)
       if (status != record_size)
        archive_write_error (status);
     }
-  
+
   for (;;)
     {
       status = rmtread (archive, record_start->buffer, record_size);
@@ -1493,7 +1516,7 @@ _gnu_flush_read (void)
       else if (status == SAFE_READ_ERROR)
        {
          archive_read_error ();
-         continue; 
+         continue;
        }
       break;
     }
@@ -1505,7 +1528,7 @@ gnu_flush_read (void)
 {
   flush_read_ptr = simple_flush_read; /* Avoid recursion */
   _gnu_flush_read ();
-  flush_read_ptr = gnu_flush_read; 
+  flush_read_ptr = gnu_flush_read;
 }
 
 static void
@@ -1516,7 +1539,7 @@ _gnu_flush_write (size_t buffer_level)
   char *copy_ptr;
   size_t copy_size;
   size_t bufsize;
-    
+
   status = _flush_write ();
   if (status != record_size && !multi_volume_option)
     archive_write_error (status);
@@ -1552,7 +1575,7 @@ _gnu_flush_write (size_t buffer_level)
   /* Switch to the next buffer */
   record_index = !record_index;
   init_buffer ();
-  
+
   if (volume_label_option)
     add_volume_label ();
 
@@ -1584,7 +1607,7 @@ gnu_flush_write (size_t buffer_level)
 {
   flush_write_ptr = simple_flush_write; /* Avoid recursion */
   _gnu_flush_write (buffer_level);
-  flush_write_ptr = gnu_flush_write; 
+  flush_write_ptr = gnu_flush_write;
 }
 
 void
@@ -1597,7 +1620,7 @@ void
 flush_write ()
 {
   flush_write_ptr (record_size);
-}    
+}
 
 void
 open_archive (enum access_mode wanted_access)
@@ -1618,6 +1641,8 @@ open_archive (enum access_mode wanted_access)
       if (volume_label_option)
        write_volume_label ();
       break;
+
+    default:
+      break;
     }
 }
-
This page took 0.030785 seconds and 4 git commands to generate.