3 Copyright 2009, 2013 Free Software Foundation, Inc.
5 This file is part of GNU tar.
7 GNU tar is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 GNU tar is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 struct deferred_unlink
26 struct deferred_unlink *next; /* Next unlink in the queue */
27 int dir_idx; /* Directory index in wd */
28 char *file_name; /* Name of the file to unlink, relative
30 bool is_dir; /* True if file_name is a directory */
31 off_t records_written; /* Number of records written when this
32 entry got added to the queue */
35 /* The unlink queue */
36 static struct deferred_unlink *dunlink_head, *dunlink_tail;
38 /* Number of entries in the queue */
39 static size_t dunlink_count;
41 /* List of entries available for allocation */
42 static struct deferred_unlink *dunlink_avail;
44 /* Delay (number of records written) between adding entry to the
45 list and its actual removal. */
46 static size_t deferred_unlink_delay = 0;
48 static struct deferred_unlink *
51 struct deferred_unlink *p;
55 dunlink_avail = p->next;
59 p = xmalloc (sizeof (*p));
64 dunlink_reclaim (struct deferred_unlink *p)
67 p->next = dunlink_avail;
72 flush_deferred_unlinks (bool force)
74 struct deferred_unlink *p, *prev = NULL;
75 int saved_chdir = chdir_current;
77 for (p = dunlink_head; p; )
79 struct deferred_unlink *next = p->next;
82 || records_written > p->records_written + deferred_unlink_delay)
84 chdir_do (p->dir_idx);
89 if (p->file_name[0] == 0 ||
90 strcmp (p->file_name, ".") == 0)
92 fname = tar_dirname ();
93 chdir_do (p->dir_idx - 1);
98 if (unlinkat (chdir_fd, fname, AT_REMOVEDIR) != 0)
103 /* nothing to worry about */
108 /* Keep the record in list, in the hope we'll
109 be able to remove it later */
122 if (unlinkat (chdir_fd, p->file_name, 0) != 0 && errno != ENOENT)
123 unlink_error (p->file_name);
141 chdir_do (saved_chdir);
145 finish_deferred_unlinks (void)
147 flush_deferred_unlinks (true);
148 while (dunlink_avail)
150 struct deferred_unlink *next = dunlink_avail->next;
151 free (dunlink_avail);
152 dunlink_avail = next;
157 queue_deferred_unlink (const char *name, bool is_dir)
159 struct deferred_unlink *p;
162 && records_written > dunlink_head->records_written + deferred_unlink_delay)
163 flush_deferred_unlinks (false);
165 p = dunlink_alloc ();
167 p->dir_idx = chdir_current;
168 p->file_name = xstrdup (name);
169 normalize_filename_x (p->file_name);
171 p->records_written = records_written;
174 dunlink_tail->next = p;