Import upstream version 1.29
[debian/tar] / src / buffer.c
index a7d89712fc0d931dddd948403f95249a1c7f0c6e..dcbfd028f42ae68afc21b2bb14c02c7d2acb9218 100644 (file)
@@ -1,6 +1,6 @@
 /* Buffer management for tar.
 
-   Copyright 1988, 1992-1994, 1996-1997, 1999-2010, 2013-2014 Free
+   Copyright 1988, 1992-1994, 1996-1997, 1999-2010, 2013-2014, 2016 Free
    Software Foundation, Inc.
 
    This file is part of GNU tar.
@@ -391,7 +391,10 @@ check_compressed_archive (bool *pshort)
   /* Restore global values */
   read_full_records = sfr;
 
-  if (tar_checksum (record_start, true) == HEADER_SUCCESS)
+  if ((strcmp (record_start->header.magic, TMAGIC) == 0 ||
+       strcmp (record_start->buffer + offsetof (struct posix_header, magic),
+              OLDGNU_MAGIC) == 0) &&
+      tar_checksum (record_start, true) == HEADER_SUCCESS)
     /* Probably a valid header */
     return ct_tar;
 
@@ -495,7 +498,7 @@ print_stats (FILE *fp, const char *text, tarlong numbytes)
   char abbr[LONGEST_HUMAN_READABLE + 1];
   char rate[LONGEST_HUMAN_READABLE + 1];
   int n = 0;
-  
+
   int human_opts = human_autoscale | human_base_1024 | human_SI | human_B;
 
   if (text && text[0])
@@ -512,12 +515,12 @@ print_stats (FILE *fp, const char *text, tarlong numbytes)
    before each data item (bytes read, written, deleted, in that order).
    EOR is a delimiter to output after each item (used only if deleting
    from the archive), EOL is a delimiter to add at the end of the output
-   line. */ 
+   line. */
 int
-format_total_stats (FILE *fp, const char **formats, int eor, int eol)
+format_total_stats (FILE *fp, char const *const *formats, int eor, int eol)
 {
   int n;
-  
+
   switch (subcommand_option)
     {
     case CREATE_SUBCOMMAND:
@@ -536,7 +539,7 @@ format_total_stats (FILE *fp, const char **formats, int eor, int eol)
 
        fputc (eor, fp);
        n++;
-       
+
         n += print_stats (fp, formats[TF_WRITE],
                          prev_written + bytes_written);
 
@@ -570,7 +573,7 @@ format_total_stats (FILE *fp, const char **formats, int eor, int eol)
   return n;
 }
 
-const char *default_total_format[] = {
+static char const *const default_total_format[] = {
   N_("Total bytes read"),
   /* Amanda 2.4.1p1 looks for "Total bytes written: [0-9][0-9]*".  */
   N_("Total bytes written"),
@@ -980,18 +983,28 @@ short_read (size_t status)
 void
 flush_archive (void)
 {
-  size_t buffer_level = current_block->buffer - record_start->buffer;
-  record_start_block += record_end - record_start;
-  current_block = record_start;
-  record_end = record_start + blocking_factor;
-
+  size_t buffer_level;
+  
   if (access_mode == ACCESS_READ && time_to_start_writing)
     {
       access_mode = ACCESS_WRITE;
       time_to_start_writing = false;
       backspace_output ();
+      if (record_end - record_start < blocking_factor)
+       {
+         memset (record_end, 0,
+                 (blocking_factor - (record_end - record_start))
+                 * BLOCKSIZE);
+         record_end = record_start + blocking_factor;
+         return;
+       }
     }
 
+  buffer_level = current_block->buffer - record_start->buffer;
+  record_start_block += record_end - record_start;
+  current_block = record_start;
+  record_end = record_start + blocking_factor;
+
   switch (access_mode)
     {
     case ACCESS_READ:
@@ -1031,7 +1044,7 @@ backspace_output (void)
 
     /* Seek back to the beginning of this record and start writing there.  */
 
-    position -= record_size;
+    position -= record_end->buffer - record_start->buffer;
     if (position < 0)
       position = 0;
     if (rmtlseek (archive, position, SEEK_SET) != position)
@@ -1112,6 +1125,16 @@ close_archive (void)
   bufmap_free (NULL);
 }
 
+void
+write_fatal_details (char const *name, ssize_t status, size_t size)
+{
+  write_error_details (name, status, size);
+  if (rmtclose (archive) != 0)
+    close_error (*archive_name_cursor);
+  sys_wait_for_child (child_pid, false);
+  fatal_exit ();
+}
+
 /* Called to initialize the global volume number.  */
 void
 init_volume_number (void)
@@ -1406,7 +1429,10 @@ try_new_volume (void)
 
   header = find_next_block ();
   if (!header)
-    return false;
+    {
+      WARN ((0, 0, _("This does not look like a tar archive")));
+      return false;
+    }
 
   switch (header->header.typeflag)
     {
@@ -1416,7 +1442,7 @@ try_new_volume (void)
        if (read_header (&header, &dummy, read_header_x_global)
            != HEADER_SUCCESS_EXTENDED)
          {
-           ERROR ((0, 0, _("This does not look like a tar archive")));
+           WARN ((0, 0, _("This does not look like a tar archive")));
            return false;
          }
 
@@ -1445,7 +1471,7 @@ try_new_volume (void)
            break;
 
          default:
-           ERROR ((0, 0, _("This does not look like a tar archive")));
+           WARN ((0, 0, _("This does not look like a tar archive")));
            return false;
          }
         break;
@@ -1480,8 +1506,14 @@ try_new_volume (void)
   if (bufmap_head)
     {
       uintmax_t s;
-      if (!continued_file_name
-          || strcmp (continued_file_name, bufmap_head->file_name))
+      if (!continued_file_name)
+       {
+         WARN ((0, 0, _("%s is not continued on this volume"),
+                quote (bufmap_head->file_name)));
+         return false;
+       }
+      
+      if (strcmp (continued_file_name, bufmap_head->file_name))
         {
           if ((archive_format == GNU_FORMAT || archive_format == OLDGNU_FORMAT)
               && strlen (bufmap_head->file_name) >= NAME_FIELD_SIZE