]> Dogcows Code - chaz/tar/blob - src/unlink.c
Remove some lint, found by gcc -W etc.
[chaz/tar] / src / unlink.c
1 /* This file is part of GNU tar.
2 Copyright (C) 2009 Free Software Foundation, Inc.
3
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
7 version.
8
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.
13
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. */
17
18 #include <system.h>
19 #include "common.h"
20 #include <quotearg.h>
21
22 struct deferred_unlink
23 {
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 */
29 };
30
31 /* The unlink queue */
32 static struct deferred_unlink *dunlink_head, *dunlink_tail;
33
34 /* Number of entries in the queue */
35 static size_t dunlink_count;
36
37 /* List of entries available for allocation */
38 static struct deferred_unlink *dunlink_avail;
39
40 /* Delay (number of records written) between adding entry to the
41 list and its actual removal. */
42 size_t deferred_unlink_delay = 0;
43
44 static struct deferred_unlink *
45 dunlink_alloc (void)
46 {
47 struct deferred_unlink *p;
48 if (dunlink_avail)
49 {
50 p = dunlink_avail;
51 dunlink_avail = p->next;
52 p->next = NULL;
53 }
54 else
55 p = xmalloc (sizeof (*p));
56 return p;
57 }
58
59 static void
60 dunlink_reclaim (struct deferred_unlink *p)
61 {
62 free (p->file_name);
63 p->next = dunlink_avail;
64 dunlink_avail = p;
65 }
66
67 static void
68 flush_deferred_unlinks (bool force)
69 {
70 struct deferred_unlink *p, *prev = NULL;
71
72 for (p = dunlink_head; p; )
73 {
74 struct deferred_unlink *next = p->next;
75 if (force
76 || records_written > p->records_written + deferred_unlink_delay)
77 {
78 if (p->is_dir)
79 {
80 if (rmdir (p->file_name) != 0)
81 {
82 switch (errno)
83 {
84 case ENOENT:
85 /* nothing to worry about */
86 break;
87 case ENOTEMPTY:
88 if (!force)
89 {
90 /* Keep the record in list, in the hope we'll
91 be able to remove it later */
92 prev = p;
93 p = next;
94 continue;
95 }
96 /* fall through */
97 default:
98 rmdir_error (p->file_name);
99 }
100 }
101 }
102 else
103 {
104 if (unlink (p->file_name) != 0 && errno != ENOENT)
105 unlink_error (p->file_name);
106 }
107 dunlink_reclaim (p);
108 dunlink_count--;
109 p = next;
110 if (prev)
111 prev->next = p;
112 else
113 dunlink_head = p;
114 }
115 else
116 {
117 prev = p;
118 p = next;
119 }
120 }
121 if (!dunlink_head)
122 dunlink_tail = NULL;
123 }
124
125 void
126 finish_deferred_unlinks ()
127 {
128 flush_deferred_unlinks (true);
129 while (dunlink_avail)
130 {
131 struct deferred_unlink *next = dunlink_avail->next;
132 free (dunlink_avail);
133 dunlink_avail = next;
134 }
135 }
136
137 void
138 queue_deferred_unlink (const char *name, bool is_dir)
139 {
140 struct deferred_unlink *p;
141
142 if (dunlink_head
143 && records_written > dunlink_head->records_written + deferred_unlink_delay)
144 flush_deferred_unlinks (false);
145
146 p = dunlink_alloc ();
147 p->next = NULL;
148 p->file_name = normalize_filename (name);
149 p->is_dir = is_dir;
150 p->records_written = records_written;
151
152 if (dunlink_tail)
153 dunlink_tail->next = p;
154 else
155 dunlink_head = p;
156 dunlink_tail = p;
157 dunlink_count++;
158 }
This page took 0.040985 seconds and 4 git commands to generate.