]> git.cworth.org Git - tar/blobdiff - src/create.c
Merge branch 'dfsg-orig' into dfsg-debian
[tar] / src / create.c
index ff0e9d572c5e8606d0bf6a15c6c387bd4201ccd2..5a2e0b588226e5e8a3d80e49e75bd4bd9e66c59b 100644 (file)
@@ -1,7 +1,7 @@
 /* Create a tar archive.
 
    Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
-   2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
 
    Written by John Gilmore, on 1985-08-25.
 
@@ -63,22 +63,23 @@ exclusion_tag_warning (const char *dirname, const char *tagname,
                       const char *message)
 {
   if (verbose_option)
-    WARN ((0, 0,
-          _("%s: contains a cache directory tag %s; %s"),
-          quotearg_colon (dirname),
-          quotearg_n (1, tagname),
-          message));
+    WARNOPT (WARN_CACHEDIR,
+            (0, 0,
+             _("%s: contains a cache directory tag %s; %s"),
+             quotearg_colon (dirname),
+             quotearg_n (1, tagname),
+             message));
 }
 
 enum exclusion_tag_type 
-check_exclusion_tags (char *dirname, const char **tag_file_name)
+check_exclusion_tags (const char *dirname, const char **tag_file_name)
 {
   static char *tagname;
   static size_t tagsize;
   struct exclusion_tag *tag;
   size_t dlen = strlen (dirname);
-  int addslash = dirname[dlen-1] != '/';
-  char *nptr = NULL;
+  int addslash = !ISSLASH (dirname[dlen-1]);
+  size_t noff = 0;
   
   for (tag = exclusion_tags; tag; tag = tag->next)
     {
@@ -89,14 +90,14 @@ check_exclusion_tags (char *dirname, const char **tag_file_name)
          tagname = xrealloc (tagname, tagsize);
        }
 
-      if (!nptr)
+      if (noff == 0)
        {
          strcpy (tagname, dirname);
-         nptr = tagname + dlen;
+         noff = dlen;
          if (addslash)
-           *nptr++ = '/';
+           tagname[noff++] = '/';
        }
-      strcpy (nptr, tag->name);
+      strcpy (tagname + noff, tag->name);
       if (access (tagname, F_OK) == 0
          && (!tag->predicate || tag->predicate (tagname)))
        {
@@ -401,8 +402,7 @@ mode_to_chars (mode_t v, char *p, size_t s)
       && S_IROTH == TOREAD && S_IWOTH == TOWRITE && S_IXOTH == TOEXEC
       && archive_format != POSIX_FORMAT
       && archive_format != USTAR_FORMAT
-      && archive_format != GNU_FORMAT
-      && archive_format != OLDGNU_FORMAT)
+      && archive_format != GNU_FORMAT)
     {
       negative = v < 0;
       u = v;
@@ -515,9 +515,8 @@ write_eot (void)
 
 /* Write a "private" header */
 union block *
-start_private_header (const char *name, size_t size)
+start_private_header (const char *name, size_t size, time_t t)
 {
-  time_t t;
   union block *header = find_next_block ();
 
   memset (header->buffer, 0, sizeof (union block));
@@ -525,7 +524,6 @@ start_private_header (const char *name, size_t size)
   tar_name_copy_str (header->header.name, name, NAME_FIELD_SIZE);
   OFF_TO_CHARS (size, header->header.size);
 
-  time (&t);
   TIME_TO_CHARS (t, header->header.mtime);
   MODE_TO_CHARS (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, header->header.mode);
   UID_TO_CHARS (getuid (), header->header.uid);
@@ -563,13 +561,13 @@ write_gnu_long_link (struct tar_stat_info *st, const char *p, char type)
   union block *header;
   char *tmpname;
 
-  header = start_private_header ("././@LongLink", size);
-  FILL(header->header.mtime, '0');
-  FILL(header->header.mode, '0');
-  FILL(header->header.uid, '0');
-  FILL(header->header.gid, '0');
-  FILL(header->header.devmajor, 0);
-  FILL(header->header.devminor, 0);
+  header = start_private_header ("././@LongLink", size, time (NULL));
+  FILL (header->header.mtime, '0');
+  FILL (header->header.mode, '0');
+  FILL (header->header.uid, '0');
+  FILL (header->header.gid, '0');
+  FILL (header->header.devmajor, 0);
+  FILL (header->header.devminor, 0);
   uid_to_uname (0, &tmpname);
   UNAME_TO_CHARS (tmpname, header->header.uname);
   free (tmpname);
@@ -604,8 +602,10 @@ split_long_name (const char *name, size_t length)
 {
   size_t i;
 
-  if (length > PREFIX_FIELD_SIZE)
+  if (length > PREFIX_FIELD_SIZE + 1)
     length = PREFIX_FIELD_SIZE + 1;
+  else if (ISSLASH (name[length - 1]))
+    length--;
   for (i = length - 1; i > 0; i--)
     if (ISSLASH (name[i]))
       break;
@@ -616,9 +616,9 @@ static union block *
 write_ustar_long_name (const char *name)
 {
   size_t length = strlen (name);
-  size_t i;
+  size_t i, nlen;
   union block *header;
-
+  
   if (length > PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1)
     {
       ERROR ((0, 0, _("%s: file name is too long (max %d); not dumped"),
@@ -628,7 +628,7 @@ write_ustar_long_name (const char *name)
     }
 
   i = split_long_name (name, length);
-  if (i == 0 || length - i - 1 > NAME_FIELD_SIZE)
+  if (i == 0 || (nlen = length - i - 1) > NAME_FIELD_SIZE || nlen == 0)
     {
       ERROR ((0, 0,
              _("%s: file name is too long (cannot be split); not dumped"),
@@ -712,7 +712,8 @@ write_extended (bool global, struct tar_stat_info *st, union block *old_header)
   union block *header, hp;
   char *p;
   int type;
-
+  time_t t;
+  
   if (st->xhdr.buffer || st->xhdr.stk == NULL)
     return old_header;
 
@@ -722,13 +723,15 @@ write_extended (bool global, struct tar_stat_info *st, union block *old_header)
     {
       type = XGLTYPE;
       p = xheader_ghdr_name ();
+      time (&t);
     }
   else
     {
       type = XHDTYPE;
       p = xheader_xhdr_name (st);
+      t = st->stat.st_mtime;
     }
-  xheader_write (type, p, &st->xhdr);
+  xheader_write (type, p, t, &st->xhdr);
   free (p);
   header = find_next_block ();
   memcpy (header, &hp.buffer, sizeof (hp.buffer));
@@ -993,11 +996,9 @@ finish_header (struct tar_stat_info *st,
       && header->header.typeflag != XHDTYPE
       && header->header.typeflag != XGLTYPE)
     {
-      /* These globals are parameters to print_header, sigh.  */
-
-      current_header = header;
+      /* FIXME: This global is used in print_header, sigh.  */
       current_format = archive_format;
-      print_header (st, block_ordinal);
+      print_header (st, header, block_ordinal);
     }
 
   header = write_extended (false, st, header);
@@ -1072,14 +1073,15 @@ dump_regular_file (int fd, struct tar_stat_info *st)
        {
          char buf[UINTMAX_STRSIZE_BOUND];
          memset (blk->buffer + count, 0, bufsize - count);
-         WARN ((0, 0,
-                ngettext ("%s: File shrank by %s byte; padding with zeros",
-                          "%s: File shrank by %s bytes; padding with zeros",
-                          size_left),
-                quotearg_colon (st->orig_file_name),
-                STRINGIFY_BIGINT (size_left, buf)));
+         WARNOPT (WARN_FILE_SHRANK,
+                  (0, 0,
+                   ngettext ("%s: File shrank by %s byte; padding with zeros",
+                             "%s: File shrank by %s bytes; padding with zeros",
+                             size_left),
+                   quotearg_colon (st->orig_file_name),
+                   STRINGIFY_BIGINT (size_left, buf)));
          if (! ignore_failed_read_option) 
-           exit_status = TAREXIT_DIFFERS;
+           set_exit_status (TAREXIT_DIFFERS);
          pad_archive (size_left - (bufsize - count));
          return dump_status_short;
        }
@@ -1090,79 +1092,74 @@ dump_regular_file (int fd, struct tar_stat_info *st)
 \f
 static void
 dump_dir0 (char *directory,
-          struct tar_stat_info *st, int top_level, dev_t parent_device)
+          struct tar_stat_info *st, bool top_level, dev_t parent_device)
 {
   dev_t our_device = st->stat.st_dev;
   const char *tag_file_name;
-  
-  if (!is_avoided_name (st->orig_file_name))
-    {
-      union block *blk = NULL;
-      off_t block_ordinal = current_block_ordinal ();
-      st->stat.st_size = 0;    /* force 0 size on dir */
+  union block *blk = NULL;
+  off_t block_ordinal = current_block_ordinal ();
 
-      blk = start_header (st);
-      if (!blk)
-       return;
+  st->stat.st_size = 0;        /* force 0 size on dir */
+
+  blk = start_header (st);
+  if (!blk)
+    return;
 
-      if (incremental_option && archive_format != POSIX_FORMAT)
-       blk->header.typeflag = GNUTYPE_DUMPDIR;
-      else /* if (standard_option) */
-       blk->header.typeflag = DIRTYPE;
+  if (incremental_option && archive_format != POSIX_FORMAT)
+    blk->header.typeflag = GNUTYPE_DUMPDIR;
+  else /* if (standard_option) */
+    blk->header.typeflag = DIRTYPE;
 
-      /* If we're gnudumping, we aren't done yet so don't close it.  */
+  /* If we're gnudumping, we aren't done yet so don't close it.  */
 
-      if (!incremental_option)
-       finish_header (st, blk, block_ordinal);
-      else if (gnu_list_name->dir_contents)
+  if (!incremental_option)
+    finish_header (st, blk, block_ordinal);
+  else if (gnu_list_name->directory)
+    {
+      if (archive_format == POSIX_FORMAT)
        {
-         if (archive_format == POSIX_FORMAT)
-           {
-             xheader_store ("GNU.dumpdir", st, gnu_list_name->dir_contents);
-             finish_header (st, blk, block_ordinal);
-           }
-         else
+         xheader_store ("GNU.dumpdir", st,
+                        safe_directory_contents (gnu_list_name->directory));
+         finish_header (st, blk, block_ordinal);
+       }
+      else
+       {
+         off_t size_left;
+         off_t totsize;
+         size_t bufsize;
+         ssize_t count;
+         const char *buffer, *p_buffer;
+         
+         block_ordinal = current_block_ordinal ();
+         buffer = safe_directory_contents (gnu_list_name->directory);
+         totsize = dumpdir_size (buffer);
+         OFF_TO_CHARS (totsize, blk->header.size);
+         finish_header (st, blk, block_ordinal);
+         p_buffer = buffer;
+         size_left = totsize;
+         
+         mv_begin (st);
+         mv_total_size (totsize);
+         while (size_left > 0)
            {
-             off_t size_left;
-             off_t totsize;
-             size_t bufsize;
-             ssize_t count;
-             const char *buffer, *p_buffer;
-
-             block_ordinal = current_block_ordinal ();
-             buffer = gnu_list_name->dir_contents;
-             if (buffer)
-               totsize = dumpdir_size (buffer);
-             else
-               totsize = 0;
-             OFF_TO_CHARS (totsize, blk->header.size);
-             finish_header (st, blk, block_ordinal);
-             p_buffer = buffer;
-             size_left = totsize;
-
-             mv_begin (st);
-             mv_total_size (totsize);
-             while (size_left > 0)
+             mv_size_left (size_left);
+             blk = find_next_block ();
+             bufsize = available_space_after (blk);
+             if (size_left < bufsize)
                {
-                 mv_size_left (size_left);
-                 blk = find_next_block ();
-                 bufsize = available_space_after (blk);
-                 if (size_left < bufsize)
-                   {
-                     bufsize = size_left;
-                     count = bufsize % BLOCKSIZE;
-                     if (count)
-                       memset (blk->buffer + size_left, 0, BLOCKSIZE - count);
-                   }
-                 memcpy (blk->buffer, p_buffer, bufsize);
-                 size_left -= bufsize;
-                 p_buffer += bufsize;
-                 set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
+                 bufsize = size_left;
+                 count = bufsize % BLOCKSIZE;
+                 if (count)
+                   memset (blk->buffer + size_left, 0, BLOCKSIZE - count);
                }
-             mv_end ();
+             memcpy (blk->buffer, p_buffer, bufsize);
+             size_left -= bufsize;
+             p_buffer += bufsize;
+             set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
            }
-         return;
+         mv_end ();
        }
+      return;
     }
 
   if (!recursion_option)
@@ -1173,9 +1170,10 @@ dump_dir0 (char *directory,
       && parent_device != st->stat.st_dev)
     {
       if (verbose_option)
-       WARN ((0, 0,
-              _("%s: file is on a different filesystem; not dumped"),
-              quotearg_colon (st->orig_file_name)));
+       WARNOPT (WARN_XDEV,
+                (0, 0,
+                 _("%s: file is on a different filesystem; not dumped"),
+                 quotearg_colon (st->orig_file_name)));
     }
   else
     {
@@ -1209,7 +1207,7 @@ dump_dir0 (char *directory,
                  }
                strcpy (name_buf + name_len, entry);
                if (!excluded_name (name_buf))
-                 dump_file (name_buf, 0, our_device);
+                 dump_file (name_buf, false, our_device);
              }
            
            free (name_buf);
@@ -1223,7 +1221,7 @@ dump_dir0 (char *directory,
          name_buf = xmalloc (name_size);
          strcpy (name_buf, st->orig_file_name);
          strcat (name_buf, tag_file_name);
-         dump_file (name_buf, 0, our_device);
+         dump_file (name_buf, false, our_device);
          free (name_buf);
          break;
       
@@ -1249,7 +1247,8 @@ ensure_slash (char **pstr)
 }
 
 static bool
-dump_dir (int fd, struct tar_stat_info *st, int top_level, dev_t parent_device)
+dump_dir (int fd, struct tar_stat_info *st, bool top_level,
+         dev_t parent_device)
 {
   char *directory = fdsavedir (fd);
   if (!directory)
@@ -1270,7 +1269,7 @@ dump_dir (int fd, struct tar_stat_info *st, int top_level, dev_t parent_device)
 void
 create_archive (void)
 {
-  const char *p;
+  struct name const *p;
 
   open_archive (ACCESS_WRITE);
   buffer_write_global_xheader ();
@@ -1284,24 +1283,24 @@ create_archive (void)
       collect_and_sort_names ();
 
       while ((p = name_from_list ()) != NULL)
-       if (!excluded_name (p))
-         dump_file (p, -1, (dev_t) 0);
+       if (!excluded_name (p->name))
+         dump_file (p->name, p->cmdline, (dev_t) 0);
 
       blank_name_list ();
       while ((p = name_from_list ()) != NULL)
-       if (!excluded_name (p))
+       if (!excluded_name (p->name))
          {
-           size_t plen = strlen (p);
+           size_t plen = strlen (p->name);
            if (buffer_size <= plen)
              {
                while ((buffer_size *= 2) <= plen)
                  continue;
                buffer = xrealloc (buffer, buffer_size);
              }
-           memcpy (buffer, p, plen);
+           memcpy (buffer, p->name, plen);
            if (! ISSLASH (buffer[plen - 1]))
-             buffer[plen++] = '/';
-           q = gnu_list_name->dir_contents;
+             buffer[plen++] = DIRECTORY_SEPARATOR;
+           q = directory_contents (gnu_list_name->directory);
            if (q)
              while (*q)
                {
@@ -1315,7 +1314,7 @@ create_archive (void)
                          buffer = xrealloc (buffer, buffer_size);
                        }
                      strcpy (buffer + plen, q + 1);
-                     dump_file (buffer, -1, (dev_t) 0);
+                     dump_file (buffer, false, (dev_t) 0);
                    }
                  q += qlen + 1;
                }
@@ -1324,14 +1323,15 @@ create_archive (void)
     }
   else
     {
-      while ((p = name_next (1)) != NULL)
-       if (!excluded_name (p))
-         dump_file (p, 1, (dev_t) 0);
+      const char *name;
+      while ((name = name_next (1)) != NULL)
+       if (!excluded_name (name))
+         dump_file (name, true, (dev_t) 0);
     }
 
   write_eot ();
   close_archive ();
-
+  finish_deferred_unlinks ();
   if (listed_incremental_option)
     write_directory_file ();
 }
@@ -1358,10 +1358,11 @@ compare_links (void const *entry1, void const *entry2)
 static void
 unknown_file_error (char const *p)
 {
-  WARN ((0, 0, _("%s: Unknown file type; file ignored"),
-        quotearg_colon (p)));
+  WARNOPT (WARN_FILE_IGNORED,
+          (0, 0, _("%s: Unknown file type; file ignored"),
+           quotearg_colon (p)));
   if (!ignore_failed_read_option)
-    exit_status = TAREXIT_FAILURE;
+    set_exit_status (TAREXIT_FAILURE);
 }
 
 \f
@@ -1410,8 +1411,8 @@ dump_hard_link (struct tar_stat_info *st)
          blk->header.typeflag = LNKTYPE;
          finish_header (st, blk, block_ordinal);
 
-         if (remove_files_option && unlink (st->orig_file_name) != 0)
-           unlink_error (st->orig_file_name);
+         if (remove_files_option)
+           queue_deferred_unlink (st->orig_file_name, false);
 
          return true;
        }
@@ -1427,19 +1428,26 @@ file_count_links (struct tar_stat_info *st)
   if (st->stat.st_nlink > 1)
     {
       struct link *duplicate;
-      struct link *lp = xmalloc (offsetof (struct link, name)
-                                + strlen (st->orig_file_name) + 1);
+      char *linkname = NULL;
+      struct link *lp;
+
+      assign_string (&linkname, st->orig_file_name);
+      transform_name (&linkname, XFORM_LINK);
+      
+      lp = xmalloc (offsetof (struct link, name)
+                                + strlen (linkname) + 1);
       lp->ino = st->stat.st_ino;
       lp->dev = st->stat.st_dev;
       lp->nlink = st->stat.st_nlink;
-      strcpy (lp->name, st->orig_file_name);
-
+      strcpy (lp->name, linkname);
+      free (linkname);
+      
       if (! ((link_table
              || (link_table = hash_initialize (0, 0, hash_link,
                                                compare_links, 0)))
             && (duplicate = hash_insert (link_table, lp))))
        xalloc_die ();
-
+      
       if (duplicate != lp)
        abort ();
       lp->nlink--;
@@ -1466,7 +1474,6 @@ check_links (void)
     }
 }
 
-
 /* Dump a single file, recursing on directories.  P is the file name
    to dump.  TOP_LEVEL tells whether this is a top-level call; zero
    means no, positive means yes, and negative means the top level
@@ -1478,7 +1485,7 @@ check_links (void)
 
 static void
 dump_file0 (struct tar_stat_info *st, const char *p,
-           int top_level, dev_t parent_device)
+           bool top_level, dev_t parent_device)
 {
   union block *header;
   char type;
@@ -1499,7 +1506,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
 
   if (deref_stat (dereference_option, p, &st->stat) != 0)
     {
-      stat_diag (p);
+      file_removed_diag (p, top_level, stat_diag);
       return;
     }
   st->archive_file_size = original_size = st->stat.st_size;
@@ -1522,32 +1529,31 @@ dump_file0 (struct tar_stat_info *st, const char *p,
 
   /* See if we want only new files, and check if this one is too old to
      put in the archive.
-
+     
      This check is omitted if incremental_option is set *and* the
      requested file is not explicitely listed in the command line. */
-
+  
   if (!(incremental_option && !is_individual_file (p))
       && !S_ISDIR (st->stat.st_mode)
       && OLDER_TAR_STAT_TIME (*st, m)
       && (!after_date_option || OLDER_TAR_STAT_TIME (*st, c)))
     {
       if (!incremental_option && verbose_option)
-       WARN ((0, 0, _("%s: file is unchanged; not dumped"),
-              quotearg_colon (p)));
+       WARNOPT (WARN_FILE_UNCHANGED,
+                (0, 0, _("%s: file is unchanged; not dumped"),
+                 quotearg_colon (p)));
       return;
     }
 
   /* See if we are trying to dump the archive.  */
   if (sys_file_is_archive (st))
     {
-      WARN ((0, 0, _("%s: file is the archive; not dumped"),
-            quotearg_colon (p)));
+      WARNOPT (WARN_IGNORE_ARCHIVE,
+              (0, 0, _("%s: file is the archive; not dumped"),
+               quotearg_colon (p)));
       return;
     }
 
-  if (is_avoided_name (p))
-    return;
-
   is_dir = S_ISDIR (st->stat.st_mode) != 0;
 
   if (!is_dir && dump_hard_link (st))
@@ -1569,11 +1575,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
                         : 0)));
          if (fd < 0)
            {
-             if (!top_level && errno == ENOENT)
-               WARN ((0, 0, _("%s: File removed before we read it"),
-                      quotearg_colon (p)));
-             else
-               open_diag (p);
+             file_removed_diag (p, top_level, open_diag);
              return;
            }
        }
@@ -1589,6 +1591,8 @@ dump_file0 (struct tar_stat_info *st, const char *p,
            {
              exclusion_tag_warning (st->orig_file_name, tag_file_name,
                                     _("directory not dumped"));
+             if (fd >= 0)
+               close (fd);
              return;
            }
          
@@ -1643,7 +1647,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
               : fstat (fd, &final_stat))
              != 0)
            {
-             stat_diag (p);
+             file_removed_diag (p, top_level, stat_diag);
              ok = false;
            }
        }
@@ -1656,10 +1660,10 @@ dump_file0 (struct tar_stat_info *st, const char *p,
               && !(remove_files_option && is_dir))
              || original_size < final_stat.st_size)
            {
-             WARN ((0, 0, _("%s: file changed as we read it"),
-                    quotearg_colon (p)));
-             if (exit_status == TAREXIT_SUCCESS)
-               exit_status = TAREXIT_DIFFERS;
+             WARNOPT (WARN_FILE_CHANGED,
+                      (0, 0, _("%s: file changed as we read it"),
+                       quotearg_colon (p)));
+             set_exit_status (TAREXIT_DIFFERS);
            }
          else if (atime_preserve_option == replace_atime_preserve
                   && set_file_atime (fd, p, restore_times) != 0)
@@ -1673,18 +1677,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
        }
 
       if (ok && remove_files_option)
-       {
-         if (is_dir)
-           {
-             if (rmdir (p) != 0 && errno != ENOTEMPTY)
-               rmdir_error (p);
-           }
-         else
-           {
-             if (unlink (p) != 0)
-               unlink_error (p);
-           }
-       }
+       queue_deferred_unlink (p, is_dir);
 
       return;
     }
@@ -1700,7 +1693,7 @@ dump_file0 (struct tar_stat_info *st, const char *p,
       size = readlink (p, buffer, linklen + 1);
       if (size < 0)
        {
-         readlink_diag (p);
+         file_removed_diag (p, top_level, readlink_diag);
          return;
        }
       buffer[size] = '\0';
@@ -1720,10 +1713,8 @@ dump_file0 (struct tar_stat_info *st, const char *p,
       /* nothing more to do to it */
 
       if (remove_files_option)
-       {
-         if (unlink (p) == -1)
-           unlink_error (p);
-       }
+       queue_deferred_unlink (p, false);
+
       file_count_links (st);
       return;
     }
@@ -1736,12 +1727,14 @@ dump_file0 (struct tar_stat_info *st, const char *p,
     type = FIFOTYPE;
   else if (S_ISSOCK (st->stat.st_mode))
     {
-      WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p)));
+      WARNOPT (WARN_FILE_IGNORED,
+              (0, 0, _("%s: socket ignored"), quotearg_colon (p)));
       return;
     }
   else if (S_ISDOOR (st->stat.st_mode))
     {
-      WARN ((0, 0, _("%s: door ignored"), quotearg_colon (p)));
+      WARNOPT (WARN_FILE_IGNORED,
+              (0, 0, _("%s: door ignored"), quotearg_colon (p)));
       return;
     }
   else
@@ -1773,14 +1766,11 @@ dump_file0 (struct tar_stat_info *st, const char *p,
 
   finish_header (st, header, block_ordinal);
   if (remove_files_option)
-    {
-      if (unlink (p) == -1)
-       unlink_error (p);
-    }
+    queue_deferred_unlink (p, false);
 }
 
 void
-dump_file (const char *p, int top_level, dev_t parent_device)
+dump_file (const char *p, bool top_level, dev_t parent_device)
 {
   struct tar_stat_info st;
   tar_stat_init (&st);