This source file includes following definitions.
- gl_lock_define_initialized
- clean_temp_string_hash
- init_fatal_signal_set
- clean_temp_asyncsafe_close
- clean_temp_init_asyncsafe_close
- cleanup_action
- do_clean_temp_init
- gl_once_define
- clean_temp_unlink
- register_temporary_file
- unregister_temporary_file
- cleanup_temporary_file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <config.h>
19
20
21 #include "clean-temp-simple.h"
22 #include "clean-temp-private.h"
23
24 #include <errno.h>
25 #include <limits.h>
26 #include <signal.h>
27 #include <stdbool.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31
32 #include "error.h"
33 #include "fatal-signal.h"
34 #include "asyncsafe-spin.h"
35 #include "glthread/lock.h"
36 #include "thread-optim.h"
37 #include "gl_list.h"
38 #include "gl_linkedhash_list.h"
39 #include "gettext.h"
40
41 #define _(str) gettext (str)
42
43
44
45
46 gl_lock_define_initialized (static, file_cleanup_list_lock)
47
48
49 static gl_list_t volatile file_cleanup_list;
50
51
52
53 struct all_tempdirs dir_cleanup_list ;
54
55
56
57 gl_list_t volatile descriptors;
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 bool
112 clean_temp_string_equals (const void *x1, const void *x2)
113 {
114 const char *s1 = (const char *) x1;
115 const char *s2 = (const char *) x2;
116 return strcmp (s1, s2) == 0;
117 }
118
119 #define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
120
121
122
123
124 size_t
125 clean_temp_string_hash (const void *x)
126 {
127 const char *s = (const char *) x;
128 size_t h = 0;
129
130 for (; *s; s++)
131 h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
132
133 return h;
134 }
135
136
137
138
139
140 static const sigset_t *fatal_signal_set ;
141
142 static void
143 init_fatal_signal_set (void)
144 {
145 if (fatal_signal_set == NULL)
146 fatal_signal_set = get_fatal_signal_set ();
147 }
148
149
150
151
152
153 _GL_ASYNC_SAFE int
154 clean_temp_asyncsafe_close (struct closeable_fd *element)
155 {
156 sigset_t saved_mask;
157 int ret;
158 int saved_errno;
159
160 asyncsafe_spin_lock (&element->lock, fatal_signal_set, &saved_mask);
161 if (!element->closed)
162 {
163 ret = close (element->fd);
164 saved_errno = errno;
165 element->closed = true;
166 }
167 else
168 {
169 ret = 0;
170 saved_errno = 0;
171 }
172 asyncsafe_spin_unlock (&element->lock, &saved_mask);
173 element->done = true;
174
175 errno = saved_errno;
176 return ret;
177 }
178
179 void
180 clean_temp_init_asyncsafe_close (void)
181 {
182 init_fatal_signal_set ();
183 }
184
185
186 static _GL_ASYNC_SAFE void
187 cleanup_action (_GL_UNUSED int sig)
188 {
189 size_t i;
190
191
192 {
193 gl_list_t fds = descriptors;
194
195 if (fds != NULL)
196 {
197 gl_list_iterator_t iter;
198 const void *element;
199
200 iter = gl_list_iterator (fds);
201 while (gl_list_iterator_next (&iter, &element, NULL))
202 {
203 clean_temp_asyncsafe_close ((struct closeable_fd *) element);
204 }
205 gl_list_iterator_free (&iter);
206 }
207 }
208
209 {
210 gl_list_t files = file_cleanup_list;
211
212 if (files != NULL)
213 {
214 gl_list_iterator_t iter;
215 const void *element;
216
217 iter = gl_list_iterator (files);
218 while (gl_list_iterator_next (&iter, &element, NULL))
219 {
220 const char *file = (const char *) element;
221 unlink (file);
222 }
223 gl_list_iterator_free (&iter);
224 }
225 }
226
227 for (i = 0; i < dir_cleanup_list.tempdir_count; i++)
228 {
229 struct tempdir *dir = dir_cleanup_list.tempdir_list[i];
230
231 if (dir != NULL)
232 {
233 gl_list_iterator_t iter;
234 const void *element;
235
236
237 iter = gl_list_iterator (dir->files);
238 while (gl_list_iterator_next (&iter, &element, NULL))
239 {
240 const char *file = (const char *) element;
241 unlink (file);
242 }
243 gl_list_iterator_free (&iter);
244
245
246 iter = gl_list_iterator (dir->subdirs);
247 while (gl_list_iterator_next (&iter, &element, NULL))
248 {
249 const char *subdir = (const char *) element;
250 rmdir (subdir);
251 }
252 gl_list_iterator_free (&iter);
253
254
255 rmdir (dir->dirname);
256 }
257 }
258 }
259
260
261
262 static int volatile init_failed ;
263
264
265 static void
266 do_clean_temp_init (void)
267 {
268
269 init_fatal_signal_set ();
270
271 if (at_fatal_signal (&cleanup_action) < 0)
272 init_failed = -1;
273 }
274
275
276 gl_once_define(static, clean_temp_once)
277
278
279
280 int
281 clean_temp_init (void)
282 {
283 gl_once (clean_temp_once, do_clean_temp_init);
284 return init_failed;
285 }
286
287
288
289
290 int
291 clean_temp_unlink (const char *absolute_file_name, bool cleanup_verbose)
292 {
293 if (unlink (absolute_file_name) < 0 && cleanup_verbose
294 && errno != ENOENT)
295 {
296 error (0, errno,
297 _("cannot remove temporary file %s"), absolute_file_name);
298 return -1;
299 }
300 return 0;
301 }
302
303
304
305
306
307
308
309
310 int
311 register_temporary_file (const char *absolute_file_name)
312 {
313 bool mt = gl_multithreaded ();
314
315 if (mt) gl_lock_lock (file_cleanup_list_lock);
316
317 int ret = 0;
318
319
320 if (file_cleanup_list == NULL)
321 {
322 if (clean_temp_init () < 0)
323 {
324 ret = -1;
325 goto done;
326 }
327 file_cleanup_list =
328 gl_list_nx_create_empty (GL_LINKEDHASH_LIST,
329 clean_temp_string_equals,
330 clean_temp_string_hash,
331 NULL, false);
332 if (file_cleanup_list == NULL)
333 {
334 ret = -1;
335 goto done;
336 }
337 }
338
339
340 if (gl_list_search (file_cleanup_list, absolute_file_name) == NULL)
341 {
342 char *absolute_file_name_copy = strdup (absolute_file_name);
343 if (absolute_file_name_copy == NULL)
344 {
345 ret = -1;
346 goto done;
347 }
348 if (gl_list_nx_add_first (file_cleanup_list, absolute_file_name_copy)
349 == NULL)
350 {
351 free (absolute_file_name_copy);
352 ret = -1;
353 goto done;
354 }
355 }
356
357 done:
358 if (mt) gl_lock_unlock (file_cleanup_list_lock);
359
360 return ret;
361 }
362
363
364
365
366 void
367 unregister_temporary_file (const char *absolute_file_name)
368 {
369 bool mt = gl_multithreaded ();
370
371 if (mt) gl_lock_lock (file_cleanup_list_lock);
372
373 gl_list_t list = file_cleanup_list;
374 if (list != NULL)
375 {
376 gl_list_node_t node = gl_list_search (list, absolute_file_name);
377 if (node != NULL)
378 {
379 char *old_string = (char *) gl_list_node_value (list, node);
380
381 gl_list_remove_node (list, node);
382 free (old_string);
383 }
384 }
385
386 if (mt) gl_lock_unlock (file_cleanup_list_lock);
387 }
388
389
390
391
392 int
393 cleanup_temporary_file (const char *absolute_file_name, bool cleanup_verbose)
394 {
395 int err;
396
397 err = clean_temp_unlink (absolute_file_name, cleanup_verbose);
398 unregister_temporary_file (absolute_file_name);
399
400 return err;
401 }