1 /* This file is part of GNU tar.
2 Copyright (C) 2009 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 3, or (at your option) any later
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12 Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
22 struct deferred_unlink
24 struct deferred_unlink *next; /* Next unlink in the queue */
25 char *file_name; /* Absolute name of the file to unlink */
26 bool is_dir; /* True if file_name is a directory */
27 off_t records_written; /* Number of records written when this
28 entry got added to the queue */
31 /* The unlink queue */
32 static struct deferred_unlink *dunlink_head, *dunlink_tail;
34 /* Number of entries in the queue */
35 static size_t dunlink_count;
37 /* List of entries available for allocation */
38 static struct deferred_unlink *dunlink_avail;
40 /* Delay (number of records written) between adding entry to the
41 list and its actual removal. */
42 size_t deferred_unlink_delay = 0;
44 static struct deferred_unlink *
47 struct deferred_unlink *p;
51 dunlink_avail = p->next;
55 p = xmalloc (sizeof (*p));
60 dunlink_reclaim (struct deferred_unlink *p)
63 p->next = dunlink_avail;
68 flush_deferred_unlinks (bool force)
70 struct deferred_unlink *p, *prev = NULL;
72 for (p = dunlink_head; p; )
74 struct deferred_unlink *next = p->next;
76 || records_written > p->records_written + deferred_unlink_delay)
80 if (unlinkat (chdir_fd, p->file_name, AT_REMOVEDIR) != 0)
85 /* nothing to worry about */
90 /* Keep the record in list, in the hope we'll
91 be able to remove it later */
98 rmdir_error (p->file_name);
104 if (unlinkat (chdir_fd, p->file_name, 0) != 0 && errno != ENOENT)
105 unlink_error (p->file_name);
126 finish_deferred_unlinks ()
128 flush_deferred_unlinks (true);
129 while (dunlink_avail)
131 struct deferred_unlink *next = dunlink_avail->next;
132 free (dunlink_avail);
133 dunlink_avail = next;
138 queue_deferred_unlink (const char *name, bool is_dir)
140 struct deferred_unlink *p;
143 && records_written > dunlink_head->records_written + deferred_unlink_delay)
144 flush_deferred_unlinks (false);
146 p = dunlink_alloc ();
148 p->file_name = normalize_filename (name);
150 p->records_written = records_written;
153 dunlink_tail->next = p;