]> Dogcows Code - chaz/tar/blobdiff - src/delete.c
Fix bugs in handling the --remove-files option.
[chaz/tar] / src / delete.c
index bb09af8154bac990a66c358786777e0bb19b2ad4..a67993cb9be91e92b2d5677622ddde372099cf41 100644 (file)
@@ -1,11 +1,11 @@
 /* Delete entries from a tar archive.
 
 /* Delete entries from a tar archive.
 
-   Copyright (C) 1988, 1992, 1994, 1996, 1997, 2000, 2001, 2003 Free
-   Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1994, 1996, 1997, 2000, 2001, 2003, 2004,
+   2005, 2006 Free Software Foundation, Inc.
 
    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
 
    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
    version.
 
    This program is distributed in the hope that it will be useful, but
 
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
 
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 
-#include "system.h"
+#include <system.h>
+#include <system-ioctl.h>
 
 #include "common.h"
 
 #include "common.h"
-#include "rmt.h"
+#include <rmt.h>
 
 static union block *new_record;
 static int new_blocks;
 
 static union block *new_record;
 static int new_blocks;
@@ -33,12 +34,11 @@ extern union block *record_end;
 extern union block *current_block;
 extern union block *recent_long_name;
 extern union block *recent_long_link;
 extern union block *current_block;
 extern union block *recent_long_name;
 extern union block *recent_long_link;
-extern off_t records_read; 
-extern off_t records_written;
+extern off_t records_read;
 
 /* The number of records skipped at the start of the archive, when
    passing over members that are not deleted.  */
 
 /* The number of records skipped at the start of the archive, when
    passing over members that are not deleted.  */
-static off_t records_skipped;
+off_t records_skipped;
 
 /* Move archive descriptor by COUNT records worth.  If COUNT is
    positive we move forward, else we move negative.  If it's a tape,
 
 /* Move archive descriptor by COUNT records worth.  If COUNT is
    positive we move forward, else we move negative.  If it's a tape,
@@ -132,6 +132,21 @@ write_recent_blocks (union block *h, size_t blocks)
     }
 }
 
     }
 }
 
+static void
+write_recent_bytes (char *data, size_t bytes)
+{
+  size_t blocks = bytes / BLOCKSIZE;
+  size_t rest = bytes - blocks * BLOCKSIZE;
+
+  write_recent_blocks ((union block *)data, blocks);
+  memcpy (new_record[new_blocks].buffer, data + blocks * BLOCKSIZE, rest);
+  if (rest < BLOCKSIZE)
+    memset (new_record[new_blocks].buffer + rest, 0, BLOCKSIZE - rest);
+  new_blocks++;
+  if (new_blocks == blocking_factor)
+    write_record (1);
+}
+
 void
 delete_archive_members (void)
 {
 void
 delete_archive_members (void)
 {
@@ -150,7 +165,7 @@ delete_archive_members (void)
 
   do
     {
 
   do
     {
-      enum read_header status = read_header (1);
+      enum read_header status = read_header (true);
 
       switch (status)
        {
 
       switch (status)
        {
@@ -158,12 +173,18 @@ delete_archive_members (void)
          abort ();
 
        case HEADER_SUCCESS:
          abort ();
 
        case HEADER_SUCCESS:
-         if (name = name_scan (current_stat_info.file_name), !name)
+         if ((name = name_scan (current_stat_info.file_name)) == NULL)
+           {
+             skip_member ();
+             break;
+           }
+         name->found_count++;
+         if (!ISFOUND(name))
            {
              skip_member ();
              break;
            }
            {
              skip_member ();
              break;
            }
-         name->found = 1;
+
          /* Fall through.  */
        case HEADER_SUCCESS_EXTENDED:
          logical_status = status;
          /* Fall through.  */
        case HEADER_SUCCESS_EXTENDED:
          logical_status = status;
@@ -189,6 +210,7 @@ delete_archive_members (void)
              /* Fall through.  */
 
            case HEADER_SUCCESS:
              /* Fall through.  */
 
            case HEADER_SUCCESS:
+           case HEADER_SUCCESS_EXTENDED:
            case HEADER_ZERO_BLOCK:
              ERROR ((0, 0, _("Skipping to next header")));
              /* Fall through.  */
            case HEADER_ZERO_BLOCK:
              ERROR ((0, 0, _("Skipping to next header")));
              /* Fall through.  */
@@ -212,7 +234,7 @@ delete_archive_members (void)
   if (logical_status == HEADER_SUCCESS
       || logical_status == HEADER_SUCCESS_EXTENDED)
     {
   if (logical_status == HEADER_SUCCESS
       || logical_status == HEADER_SUCCESS_EXTENDED)
     {
-      write_archive_to_stdout = 0;
+      write_archive_to_stdout = false;
 
       /* Save away blocks before this one in this record.  */
 
 
       /* Save away blocks before this one in this record.  */
 
@@ -238,7 +260,9 @@ delete_archive_members (void)
 
          if (current_block == record_end)
            flush_archive ();
 
          if (current_block == record_end)
            flush_archive ();
-         status = read_header (0);
+         status = read_header (false);
+
+         xheader_decode (&current_stat_info);
 
          if (status == HEADER_ZERO_BLOCK && ignore_zeros_option)
            {
 
          if (status == HEADER_ZERO_BLOCK && ignore_zeros_option)
            {
@@ -260,27 +284,38 @@ delete_archive_members (void)
 
          /* Found another header.  */
 
 
          /* Found another header.  */
 
-         if (name = name_scan (current_stat_info.file_name), name)
+         if ((name = name_scan (current_stat_info.file_name)) != NULL)
            {
            {
-             name->found = 1;
-           flush_file:
-             set_next_block_after (current_header);
-             blocks_to_skip = (current_stat_info.stat.st_size + BLOCKSIZE - 1) / BLOCKSIZE;
-
-             while (record_end - current_block <= blocks_to_skip)
+             name->found_count++;
+             if (ISFOUND(name))
                {
                {
-                 blocks_to_skip -= (record_end - current_block);
-                 flush_archive ();
+               flush_file:
+                 set_next_block_after (current_header);
+                 blocks_to_skip = (current_stat_info.stat.st_size
+                                   + BLOCKSIZE - 1) / BLOCKSIZE;
+                 
+                 while (record_end - current_block <= blocks_to_skip)
+                   {
+                     blocks_to_skip -= (record_end - current_block);
+                     flush_archive ();
+                   }
+                 current_block += blocks_to_skip;
+                 blocks_to_skip = 0;
+                 continue;
                }
                }
-             current_block += blocks_to_skip;
-             blocks_to_skip = 0;
-             continue;
            }
            }
-
          /* Copy header.  */
 
          /* Copy header.  */
 
-         write_recent_blocks (recent_long_name, recent_long_name_blocks);
-         write_recent_blocks (recent_long_link, recent_long_link_blocks);
+         if (current_stat_info.xhdr.size)
+           {
+             write_recent_bytes (current_stat_info.xhdr.buffer,
+                                 current_stat_info.xhdr.size);
+           }
+         else
+           {
+             write_recent_blocks (recent_long_name, recent_long_name_blocks);
+             write_recent_blocks (recent_long_link, recent_long_link_blocks);
+           }
          new_record[new_blocks] = *current_header;
          new_blocks++;
          blocks_to_keep
          new_record[new_blocks] = *current_header;
          new_blocks++;
          blocks_to_keep
@@ -324,39 +359,32 @@ delete_archive_members (void)
                write_record (1);
            }
        }
                write_record (1);
            }
        }
-    }
 
 
-  if (logical_status == HEADER_END_OF_FILE)
-    {
-      /* Write the end of tape.  FIXME: we can't use write_eot here,
-        as it gets confused when the input is at end of file.  */
+      if (logical_status == HEADER_END_OF_FILE)
+       {
+         /* Write the end of tape.  FIXME: we can't use write_eot here,
+            as it gets confused when the input is at end of file.  */
+
+         int total_zero_blocks = 0;
 
 
-      int total_zero_blocks = 0;
+         do
+           {
+             int zero_blocks = blocking_factor - new_blocks;
+             memset (new_record + new_blocks, 0, BLOCKSIZE * zero_blocks);
+             total_zero_blocks += zero_blocks;
+             write_record (total_zero_blocks < 2);
+           }
+         while (total_zero_blocks < 2);
+       }
 
 
-      do
+      if (! acting_as_filter && ! _isrmt (archive))
        {
        {
-         int zero_blocks = blocking_factor - new_blocks;
-         memset (new_record + new_blocks, 0, BLOCKSIZE * zero_blocks);
-         total_zero_blocks += zero_blocks;
-         write_record (total_zero_blocks < 2);
+         if (sys_truncate (archive))
+           truncate_warn (archive_name_array[0]);
        }
        }
-      while (total_zero_blocks < 2);
     }
     }
-
   free (new_record);
 
   free (new_record);
 
-  if (! acting_as_filter && ! _isrmt (archive))
-    {
-#if MSDOS
-      int status = write (archive, "", 0);
-#else
-      off_t pos = lseek (archive, (off_t) 0, SEEK_CUR);
-      int status = pos < 0 ? -1 : ftruncate (archive, pos);
-#endif
-      if (status != 0)
-       truncate_warn (archive_name_array[0]);
-    }
-
   close_archive ();
   names_notfound ();
 }
   close_archive ();
   names_notfound ();
 }
This page took 0.02729 seconds and 4 git commands to generate.