1 /* Temporary directories and temporary files with automatic cleanup.
2 Copyright (C) 2001, 2003, 2006-2007, 2009-2020 Free Software Foundation,
3 Inc.
4 Written by Bruno Haible <bruno@clisp.org>, 2006.
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18
19
20 #include <config.h>
21
22 /* Specification. */
23 #include "clean-temp.h"
24
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <limits.h>
28 #include <stdbool.h>
29 #include <stdint.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 #if defined _WIN32 && ! defined __CYGWIN__
35 # define WIN32_LEAN_AND_MEAN /* avoid including junk */
36 # include <windows.h>
37 #endif
38
39 #include "error.h"
40 #include "fatal-signal.h"
41 #include "asyncsafe-spin.h"
42 #include "pathmax.h"
43 #include "tmpdir.h"
44 #include "xalloc.h"
45 #include "xmalloca.h"
46 #include "glthread/lock.h"
47 #include "gl_xlist.h"
48 #include "gl_linkedhash_list.h"
49 #include "gl_linked_list.h"
50 #include "gettext.h"
51 #if GNULIB_TEMPNAME
52 # include "tempname.h"
53 #endif
54 #if GNULIB_FWRITEERROR
55 # include "fwriteerror.h"
56 #endif
57 #if GNULIB_CLOSE_STREAM
58 # include "close-stream.h"
59 #endif
60 #if GNULIB_FCNTL_SAFER
61 # include "fcntl--.h"
62 #endif
63 #if GNULIB_FOPEN_SAFER
64 # include "stdio--.h"
65 #endif
66
67 #define _(str) gettext (str)
68
69 /* GNU Hurd doesn't have PATH_MAX. Use a fallback.
70 Temporary directory names are usually not that long. */
71 #ifndef PATH_MAX
72 # define PATH_MAX 1024
73 #endif
74
75 #if defined _WIN32 && ! defined __CYGWIN__
76 /* Don't assume that UNICODE is not defined. */
77 # undef OSVERSIONINFO
78 # define OSVERSIONINFO OSVERSIONINFOA
79 # undef GetVersionEx
80 # define GetVersionEx GetVersionExA
81 #endif
82
83
84 /* The use of 'volatile' in the types below (and ISO C 99 section 5.1.2.3.(5))
85 ensure that while constructing or modifying the data structures, the field
86 values are written to memory in the order of the C statements. So the
87 signal handler can rely on these field values to be up to date. */
88
89
90 /* Lock that protects the file_cleanup_list from concurrent modification in
91 different threads. */
92 gl_lock_define_initialized (static, file_cleanup_list_lock)
93
94 /* List of all temporary files without temporary directories. */
95 static gl_list_t /* <char *> */ volatile file_cleanup_list;
96
97
98 /* Registry for a single temporary directory.
99 'struct temp_dir' from the public header file overlaps with this. */
100 struct tempdir
101 {
102 /* The absolute pathname of the directory. */
103 char * volatile dirname;
104 /* Whether errors during explicit cleanup are reported to standard error. */
105 bool cleanup_verbose;
106 /* Absolute pathnames of subdirectories. */
107 gl_list_t /* <char *> */ volatile subdirs;
108 /* Absolute pathnames of files. */
109 gl_list_t /* <char *> */ volatile files;
110 };
111
112 /* Lock that protects the dir_cleanup_list from concurrent modification in
113 different threads. */
114 gl_lock_define_initialized (static, dir_cleanup_list_lock)
115
116 /* List of all temporary directories. */
117 static struct
118 {
119 struct tempdir * volatile * volatile tempdir_list;
120 size_t volatile tempdir_count;
121 size_t tempdir_allocated;
122 } dir_cleanup_list /* = { NULL, 0, 0 } */;
123
124
125 /* A file descriptor to be closed.
126 In multithreaded programs, it is forbidden to close the same fd twice,
127 because you never know what unrelated open() calls are being executed in
128 other threads. So, the 'close (fd)' must be guarded by a once-only guard. */
129 struct closeable_fd
130 {
131 /* The file descriptor to close. */
132 int volatile fd;
133 /* Set to true when it has been closed. */
134 bool volatile closed;
135 /* Lock that protects the fd from being closed twice. */
136 asyncsafe_spinlock_t lock;
137 /* Tells whether this list element has been done and can be freed. */
138 bool volatile done;
139 };
140
141 /* Lock that protects the descriptors list from concurrent modification in
142 different threads. */
143 gl_lock_define_initialized (static, descriptors_lock)
144
145 /* List of all open file descriptors to temporary files. */
146 static gl_list_t /* <closeable_fd *> */ volatile descriptors;
147
148
149 /* For the subdirs and for the files, we use a gl_list_t of type LINKEDHASH.
150 Why? We need a data structure that
151
152 1) Can contain an arbitrary number of 'char *' values. The strings
153 are compared via strcmp, not pointer comparison.
154 2) Has insertion and deletion operations that are fast: ideally O(1),
155 or possibly O(log n). This is important for GNU sort, which may
156 create a large number of temporary files.
157 3) Allows iteration through all elements from within a signal handler.
158 4) May or may not allow duplicates. It doesn't matter here, since
159 any file or subdir can only be removed once.
160
161 Criterion 1) would allow any gl_list_t or gl_oset_t implementation.
162
163 Criterion 2) leaves only GL_LINKEDHASH_LIST, GL_TREEHASH_LIST, or
164 GL_TREE_OSET.
165
166 Criterion 3) puts at disadvantage GL_TREEHASH_LIST and GL_TREE_OSET.
167 Namely, iteration through the elements of a binary tree requires access
168 to many ->left, ->right, ->parent pointers. However, the rebalancing
169 code for insertion and deletion in an AVL or red-black tree is so
170 complicated that we cannot assume that >left, ->right, ->parent pointers
171 are in a consistent state throughout these operations. Therefore, to
172 avoid a crash in the signal handler, all destructive operations to the
173 lists would have to be protected by a
174 block_fatal_signals ();
175 ...
176 unblock_fatal_signals ();
177 pair. Which causes extra system calls.
178
179 Criterion 3) would also discourage GL_ARRAY_LIST and GL_CARRAY_LIST,
180 if they were not already excluded. Namely, these implementations use
181 xrealloc(), leaving a time window in which in the list->elements pointer
182 points to already deallocated memory. To avoid a crash in the signal
183 handler at such a moment, all destructive operations would have to
184 protected by block/unblock_fatal_signals (), in this case too.
185
186 A list of type GL_LINKEDHASH_LIST without duplicates fulfills all
187 requirements:
188 2) Insertion and deletion are O(1) on average.
189 3) The gl_list_iterator, gl_list_iterator_next implementations do
190 not trigger memory allocations, nor other system calls, and are
191 therefore safe to be called from a signal handler.
192 Furthermore, since SIGNAL_SAFE_LIST is defined, the implementation
193 of the destructive functions ensures that the list structure is
194 safe to be traversed at any moment, even when interrupted by an
195 asynchronous signal.
196 */
197
198 /* String equality and hash code functions used by the lists. */
199
200 static bool
string_equals(const void * x1,const void * x2)201 string_equals (const void *x1, const void *x2)
202 {
203 const char *s1 = (const char *) x1;
204 const char *s2 = (const char *) x2;
205 return strcmp (s1, s2) == 0;
206 }
207
208 #define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
209
210 /* A hash function for NUL-terminated char* strings using
211 the method described by Bruno Haible.
212 See https://www.haible.de/bruno/hashfunc.html. */
213 static size_t
string_hash(const void * x)214 string_hash (const void *x)
215 {
216 const char *s = (const char *) x;
217 size_t h = 0;
218
219 for (; *s; s++)
220 h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
221
222 return h;
223 }
224
225
226 /* The set of fatal signal handlers.
227 Cached here because we are not allowed to call get_fatal_signal_set ()
228 from a signal handler. */
229 static const sigset_t *fatal_signal_set /* = NULL */;
230
231 static void
init_fatal_signal_set(void)232 init_fatal_signal_set (void)
233 {
234 if (fatal_signal_set == NULL)
235 fatal_signal_set = get_fatal_signal_set ();
236 }
237
238
239 /* Close a file descriptor.
240 Avoids race conditions with normal thread code or signal-handler code that
241 might want to close the same file descriptor. */
242 static _GL_ASYNC_SAFE int
asyncsafe_close(struct closeable_fd * element)243 asyncsafe_close (struct closeable_fd *element)
244 {
245 sigset_t saved_mask;
246 int ret;
247 int saved_errno;
248
249 asyncsafe_spin_lock (&element->lock, fatal_signal_set, &saved_mask);
250 if (!element->closed)
251 {
252 ret = close (element->fd);
253 saved_errno = errno;
254 element->closed = true;
255 }
256 else
257 {
258 ret = 0;
259 saved_errno = 0;
260 }
261 asyncsafe_spin_unlock (&element->lock, &saved_mask);
262 element->done = true;
263
264 errno = saved_errno;
265 return ret;
266 }
267
268 /* Close a file descriptor and the stream that contains it.
269 Avoids race conditions with signal-handler code that might want to close the
270 same file descriptor. */
271 static int
asyncsafe_fclose_variant(struct closeable_fd * element,FILE * fp,int (* fclose_variant)(FILE *))272 asyncsafe_fclose_variant (struct closeable_fd *element, FILE *fp,
273 int (*fclose_variant) (FILE *))
274 {
275 if (fileno (fp) != element->fd)
276 abort ();
277
278 /* Flush buffered data first, to minimize the duration of the spin lock. */
279 fflush (fp);
280
281 sigset_t saved_mask;
282 int ret;
283 int saved_errno;
284
285 asyncsafe_spin_lock (&element->lock, fatal_signal_set, &saved_mask);
286 if (!element->closed)
287 {
288 ret = fclose_variant (fp); /* invokes close (element->fd) */
289 saved_errno = errno;
290 element->closed = true;
291 }
292 else
293 {
294 ret = 0;
295 saved_errno = 0;
296 }
297 asyncsafe_spin_unlock (&element->lock, &saved_mask);
298 element->done = true;
299
300 errno = saved_errno;
301 return ret;
302 }
303
304 /* The signal handler. It gets called asynchronously. */
305 static _GL_ASYNC_SAFE void
cleanup_action(int sig _GL_UNUSED)306 cleanup_action (int sig _GL_UNUSED)
307 {
308 size_t i;
309
310 /* First close all file descriptors to temporary files. */
311 {
312 gl_list_t fds = descriptors;
313
314 if (fds != NULL)
315 {
316 gl_list_iterator_t iter;
317 const void *element;
318
319 iter = gl_list_iterator (fds);
320 while (gl_list_iterator_next (&iter, &element, NULL))
321 {
322 asyncsafe_close ((struct closeable_fd *) element);
323 }
324 gl_list_iterator_free (&iter);
325 }
326 }
327
328 {
329 gl_list_t files = file_cleanup_list;
330
331 if (files != NULL)
332 {
333 gl_list_iterator_t iter;
334 const void *element;
335
336 iter = gl_list_iterator (files);
337 while (gl_list_iterator_next (&iter, &element, NULL))
338 {
339 const char *file = (const char *) element;
340 unlink (file);
341 }
342 gl_list_iterator_free (&iter);
343 }
344 }
345
346 for (i = 0; i < dir_cleanup_list.tempdir_count; i++)
347 {
348 struct tempdir *dir = dir_cleanup_list.tempdir_list[i];
349
350 if (dir != NULL)
351 {
352 gl_list_iterator_t iter;
353 const void *element;
354
355 /* First cleanup the files in the subdirectories. */
356 iter = gl_list_iterator (dir->files);
357 while (gl_list_iterator_next (&iter, &element, NULL))
358 {
359 const char *file = (const char *) element;
360 unlink (file);
361 }
362 gl_list_iterator_free (&iter);
363
364 /* Then cleanup the subdirectories. */
365 iter = gl_list_iterator (dir->subdirs);
366 while (gl_list_iterator_next (&iter, &element, NULL))
367 {
368 const char *subdir = (const char *) element;
369 rmdir (subdir);
370 }
371 gl_list_iterator_free (&iter);
372
373 /* Then cleanup the temporary directory itself. */
374 rmdir (dir->dirname);
375 }
376 }
377 }
378
379
380 /* Initializes this facility. */
381 static void
do_init_clean_temp(void)382 do_init_clean_temp (void)
383 {
384 /* Initialize the data used by the cleanup handler. */
385 init_fatal_signal_set ();
386 /* Register the cleanup handler. */
387 at_fatal_signal (&cleanup_action);
388 }
389
390 /* Ensure that do_init_clean_temp is called once only. */
gl_once_define(static,clean_temp_once)391 gl_once_define(static, clean_temp_once)
392
393 /* Initializes this facility upon first use. */
394 static void
395 init_clean_temp (void)
396 {
397 gl_once (clean_temp_once, do_init_clean_temp);
398 }
399
400
401 /* ============= Temporary files without temporary directories ============= */
402
403 /* Register the given ABSOLUTE_FILE_NAME as being a file that needs to be
404 removed.
405 Should be called before the file ABSOLUTE_FILE_NAME is created. */
406 void
register_temporary_file(const char * absolute_file_name)407 register_temporary_file (const char *absolute_file_name)
408 {
409 gl_lock_lock (file_cleanup_list_lock);
410
411 /* Make sure that this facility and the file_cleanup_list are initialized. */
412 if (file_cleanup_list == NULL)
413 {
414 init_clean_temp ();
415 file_cleanup_list =
416 gl_list_create_empty (GL_LINKEDHASH_LIST,
417 string_equals, string_hash, NULL, false);
418 }
419
420 /* Add absolute_file_name to file_cleanup_list, without duplicates. */
421 if (gl_list_search (file_cleanup_list, absolute_file_name) == NULL)
422 gl_list_add_first (file_cleanup_list, xstrdup (absolute_file_name));
423
424 gl_lock_unlock (file_cleanup_list_lock);
425 }
426
427 /* Unregister the given ABSOLUTE_FILE_NAME as being a file that needs to be
428 removed.
429 Should be called when the file ABSOLUTE_FILE_NAME could not be created. */
430 void
unregister_temporary_file(const char * absolute_file_name)431 unregister_temporary_file (const char *absolute_file_name)
432 {
433 gl_lock_lock (file_cleanup_list_lock);
434
435 gl_list_t list = file_cleanup_list;
436 if (list != NULL)
437 {
438 gl_list_node_t node = gl_list_search (list, absolute_file_name);
439 if (node != NULL)
440 {
441 char *old_string = (char *) gl_list_node_value (list, node);
442
443 gl_list_remove_node (list, node);
444 free (old_string);
445 }
446 }
447
448 gl_lock_unlock (file_cleanup_list_lock);
449 }
450
451 /* Remove a file, with optional error message.
452 Return 0 upon success, or -1 if there was some problem. */
453 static int
do_unlink(const char * absolute_file_name,bool cleanup_verbose)454 do_unlink (const char *absolute_file_name, bool cleanup_verbose)
455 {
456 if (unlink (absolute_file_name) < 0 && cleanup_verbose
457 && errno != ENOENT)
458 {
459 error (0, errno,
460 _("cannot remove temporary file %s"), absolute_file_name);
461 return -1;
462 }
463 return 0;
464 }
465
466 /* Remove the given ABSOLUTE_FILE_NAME and unregister it.
467 CLEANUP_VERBOSE determines whether errors are reported to standard error.
468 Return 0 upon success, or -1 if there was some problem. */
469 int
cleanup_temporary_file(const char * absolute_file_name,bool cleanup_verbose)470 cleanup_temporary_file (const char *absolute_file_name, bool cleanup_verbose)
471 {
472 int err;
473
474 err = do_unlink (absolute_file_name, cleanup_verbose);
475 unregister_temporary_file (absolute_file_name);
476
477 return err;
478 }
479
480
481 /* ========= Temporary directories and temporary files inside them ========= */
482
483 /* Create a temporary directory.
484 PREFIX is used as a prefix for the name of the temporary directory. It
485 should be short and still give an indication about the program.
486 PARENTDIR can be used to specify the parent directory; if NULL, a default
487 parent directory is used (either $TMPDIR or /tmp or similar).
488 CLEANUP_VERBOSE determines whether errors during explicit cleanup are
489 reported to standard error.
490 Return a fresh 'struct temp_dir' on success. Upon error, an error message
491 is shown and NULL is returned. */
492 struct temp_dir *
create_temp_dir(const char * prefix,const char * parentdir,bool cleanup_verbose)493 create_temp_dir (const char *prefix, const char *parentdir,
494 bool cleanup_verbose)
495 {
496 gl_lock_lock (dir_cleanup_list_lock);
497
498 struct tempdir * volatile *tmpdirp = NULL;
499 struct tempdir *tmpdir;
500 size_t i;
501 char *xtemplate;
502 char *tmpdirname;
503
504 /* See whether it can take the slot of an earlier temporary directory
505 already cleaned up. */
506 for (i = 0; i < dir_cleanup_list.tempdir_count; i++)
507 if (dir_cleanup_list.tempdir_list[i] == NULL)
508 {
509 tmpdirp = &dir_cleanup_list.tempdir_list[i];
510 break;
511 }
512 if (tmpdirp == NULL)
513 {
514 /* See whether the array needs to be extended. */
515 if (dir_cleanup_list.tempdir_count == dir_cleanup_list.tempdir_allocated)
516 {
517 /* Note that we cannot use xrealloc(), because then the cleanup()
518 function could access an already deallocated array. */
519 struct tempdir * volatile *old_array = dir_cleanup_list.tempdir_list;
520 size_t old_allocated = dir_cleanup_list.tempdir_allocated;
521 size_t new_allocated = 2 * dir_cleanup_list.tempdir_allocated + 1;
522 struct tempdir * volatile *new_array =
523 XNMALLOC (new_allocated, struct tempdir * volatile);
524
525 if (old_allocated == 0)
526 {
527 /* First use of this facility. */
528 init_clean_temp ();
529 }
530 else
531 {
532 /* Don't use memcpy() here, because memcpy takes non-volatile
533 arguments and is therefore not guaranteed to complete all
534 memory stores before the next statement. */
535 size_t k;
536
537 for (k = 0; k < old_allocated; k++)
538 new_array[k] = old_array[k];
539 }
540
541 dir_cleanup_list.tempdir_list = new_array;
542 dir_cleanup_list.tempdir_allocated = new_allocated;
543
544 /* Now we can free the old array. */
545 /* No, we can't do that. If cleanup_action is running in a different
546 thread and has already fetched the tempdir_list pointer (getting
547 old_array) but not yet accessed its i-th element, that thread may
548 crash when accessing an element of the already freed old_array
549 array. */
550 #if 0
551 if (old_array != NULL)
552 free ((struct tempdir **) old_array);
553 #endif
554 }
555
556 tmpdirp = &dir_cleanup_list.tempdir_list[dir_cleanup_list.tempdir_count];
557 /* Initialize *tmpdirp before incrementing tempdir_count, so that
558 cleanup() will skip this entry before it is fully initialized. */
559 *tmpdirp = NULL;
560 dir_cleanup_list.tempdir_count++;
561 }
562
563 /* Initialize a 'struct tempdir'. */
564 tmpdir = XMALLOC (struct tempdir);
565 tmpdir->dirname = NULL;
566 tmpdir->cleanup_verbose = cleanup_verbose;
567 tmpdir->subdirs = gl_list_create_empty (GL_LINKEDHASH_LIST,
568 string_equals, string_hash, NULL,
569 false);
570 tmpdir->files = gl_list_create_empty (GL_LINKEDHASH_LIST,
571 string_equals, string_hash, NULL,
572 false);
573
574 /* Create the temporary directory. */
575 xtemplate = (char *) xmalloca (PATH_MAX);
576 if (path_search (xtemplate, PATH_MAX, parentdir, prefix, parentdir == NULL))
577 {
578 error (0, errno,
579 _("cannot find a temporary directory, try setting $TMPDIR"));
580 goto quit;
581 }
582 block_fatal_signals ();
583 tmpdirname = mkdtemp (xtemplate);
584 int saved_errno = errno;
585 if (tmpdirname != NULL)
586 {
587 tmpdir->dirname = tmpdirname;
588 *tmpdirp = tmpdir;
589 }
590 unblock_fatal_signals ();
591 if (tmpdirname == NULL)
592 {
593 error (0, saved_errno,
594 _("cannot create a temporary directory using template \"%s\""),
595 xtemplate);
596 goto quit;
597 }
598 /* Replace tmpdir->dirname with a copy that has indefinite extent.
599 We cannot do this inside the block_fatal_signals/unblock_fatal_signals
600 block because then the cleanup handler would not remove the directory
601 if xstrdup fails. */
602 tmpdir->dirname = xstrdup (tmpdirname);
603 gl_lock_unlock (dir_cleanup_list_lock);
604 freea (xtemplate);
605 return (struct temp_dir *) tmpdir;
606
607 quit:
608 gl_lock_unlock (dir_cleanup_list_lock);
609 freea (xtemplate);
610 return NULL;
611 }
612
613 /* Register the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
614 needs to be removed before DIR can be removed.
615 Should be called before the file ABSOLUTE_FILE_NAME is created. */
616 void
register_temp_file(struct temp_dir * dir,const char * absolute_file_name)617 register_temp_file (struct temp_dir *dir,
618 const char *absolute_file_name)
619 {
620 struct tempdir *tmpdir = (struct tempdir *)dir;
621
622 gl_lock_lock (dir_cleanup_list_lock);
623
624 /* Add absolute_file_name to tmpdir->files, without duplicates. */
625 if (gl_list_search (tmpdir->files, absolute_file_name) == NULL)
626 gl_list_add_first (tmpdir->files, xstrdup (absolute_file_name));
627
628 gl_lock_unlock (dir_cleanup_list_lock);
629 }
630
631 /* Unregister the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
632 needs to be removed before DIR can be removed.
633 Should be called when the file ABSOLUTE_FILE_NAME could not be created. */
634 void
unregister_temp_file(struct temp_dir * dir,const char * absolute_file_name)635 unregister_temp_file (struct temp_dir *dir,
636 const char *absolute_file_name)
637 {
638 struct tempdir *tmpdir = (struct tempdir *)dir;
639
640 gl_lock_lock (dir_cleanup_list_lock);
641
642 gl_list_t list = tmpdir->files;
643 gl_list_node_t node;
644
645 node = gl_list_search (list, absolute_file_name);
646 if (node != NULL)
647 {
648 char *old_string = (char *) gl_list_node_value (list, node);
649
650 gl_list_remove_node (list, node);
651 free (old_string);
652 }
653
654 gl_lock_unlock (dir_cleanup_list_lock);
655 }
656
657 /* Register the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
658 that needs to be removed before DIR can be removed.
659 Should be called before the subdirectory ABSOLUTE_DIR_NAME is created. */
660 void
register_temp_subdir(struct temp_dir * dir,const char * absolute_dir_name)661 register_temp_subdir (struct temp_dir *dir,
662 const char *absolute_dir_name)
663 {
664 struct tempdir *tmpdir = (struct tempdir *)dir;
665
666 gl_lock_lock (dir_cleanup_list_lock);
667
668 /* Add absolute_dir_name to tmpdir->subdirs, without duplicates. */
669 if (gl_list_search (tmpdir->subdirs, absolute_dir_name) == NULL)
670 gl_list_add_first (tmpdir->subdirs, xstrdup (absolute_dir_name));
671
672 gl_lock_unlock (dir_cleanup_list_lock);
673 }
674
675 /* Unregister the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
676 that needs to be removed before DIR can be removed.
677 Should be called when the subdirectory ABSOLUTE_DIR_NAME could not be
678 created. */
679 void
unregister_temp_subdir(struct temp_dir * dir,const char * absolute_dir_name)680 unregister_temp_subdir (struct temp_dir *dir,
681 const char *absolute_dir_name)
682 {
683 struct tempdir *tmpdir = (struct tempdir *)dir;
684
685 gl_lock_lock (dir_cleanup_list_lock);
686
687 gl_list_t list = tmpdir->subdirs;
688 gl_list_node_t node;
689
690 node = gl_list_search (list, absolute_dir_name);
691 if (node != NULL)
692 {
693 char *old_string = (char *) gl_list_node_value (list, node);
694
695 gl_list_remove_node (list, node);
696 free (old_string);
697 }
698
699 gl_lock_unlock (dir_cleanup_list_lock);
700 }
701
702 /* Remove a directory, with optional error message.
703 Return 0 upon success, or -1 if there was some problem. */
704 static int
do_rmdir(const char * absolute_dir_name,bool cleanup_verbose)705 do_rmdir (const char *absolute_dir_name, bool cleanup_verbose)
706 {
707 if (rmdir (absolute_dir_name) < 0 && cleanup_verbose
708 && errno != ENOENT)
709 {
710 error (0, errno,
711 _("cannot remove temporary directory %s"), absolute_dir_name);
712 return -1;
713 }
714 return 0;
715 }
716
717 /* Remove the given ABSOLUTE_FILE_NAME and unregister it.
718 Return 0 upon success, or -1 if there was some problem. */
719 int
cleanup_temp_file(struct temp_dir * dir,const char * absolute_file_name)720 cleanup_temp_file (struct temp_dir *dir,
721 const char *absolute_file_name)
722 {
723 int err;
724
725 err = do_unlink (absolute_file_name, dir->cleanup_verbose);
726 unregister_temp_file (dir, absolute_file_name);
727
728 return err;
729 }
730
731 /* Remove the given ABSOLUTE_DIR_NAME and unregister it.
732 Return 0 upon success, or -1 if there was some problem. */
733 int
cleanup_temp_subdir(struct temp_dir * dir,const char * absolute_dir_name)734 cleanup_temp_subdir (struct temp_dir *dir,
735 const char *absolute_dir_name)
736 {
737 int err;
738
739 err = do_rmdir (absolute_dir_name, dir->cleanup_verbose);
740 unregister_temp_subdir (dir, absolute_dir_name);
741
742 return err;
743 }
744
745 /* Remove all registered files and subdirectories inside DIR.
746 Only to be called with dir_cleanup_list_lock locked.
747 Return 0 upon success, or -1 if there was some problem. */
748 int
cleanup_temp_dir_contents(struct temp_dir * dir)749 cleanup_temp_dir_contents (struct temp_dir *dir)
750 {
751 struct tempdir *tmpdir = (struct tempdir *)dir;
752 int err = 0;
753 gl_list_t list;
754 gl_list_iterator_t iter;
755 const void *element;
756 gl_list_node_t node;
757
758 /* First cleanup the files in the subdirectories. */
759 list = tmpdir->files;
760 iter = gl_list_iterator (list);
761 while (gl_list_iterator_next (&iter, &element, &node))
762 {
763 char *file = (char *) element;
764
765 err |= do_unlink (file, dir->cleanup_verbose);
766 gl_list_remove_node (list, node);
767 /* Now only we can free file. */
768 free (file);
769 }
770 gl_list_iterator_free (&iter);
771
772 /* Then cleanup the subdirectories. */
773 list = tmpdir->subdirs;
774 iter = gl_list_iterator (list);
775 while (gl_list_iterator_next (&iter, &element, &node))
776 {
777 char *subdir = (char *) element;
778
779 err |= do_rmdir (subdir, dir->cleanup_verbose);
780 gl_list_remove_node (list, node);
781 /* Now only we can free subdir. */
782 free (subdir);
783 }
784 gl_list_iterator_free (&iter);
785
786 return err;
787 }
788
789 /* Remove all registered files and subdirectories inside DIR and DIR itself.
790 DIR cannot be used any more after this call.
791 Return 0 upon success, or -1 if there was some problem. */
792 int
cleanup_temp_dir(struct temp_dir * dir)793 cleanup_temp_dir (struct temp_dir *dir)
794 {
795 gl_lock_lock (dir_cleanup_list_lock);
796
797 struct tempdir *tmpdir = (struct tempdir *)dir;
798 int err = 0;
799 size_t i;
800
801 err |= cleanup_temp_dir_contents (dir);
802 err |= do_rmdir (tmpdir->dirname, dir->cleanup_verbose);
803
804 for (i = 0; i < dir_cleanup_list.tempdir_count; i++)
805 if (dir_cleanup_list.tempdir_list[i] == tmpdir)
806 {
807 /* Remove dir_cleanup_list.tempdir_list[i]. */
808 if (i + 1 == dir_cleanup_list.tempdir_count)
809 {
810 while (i > 0 && dir_cleanup_list.tempdir_list[i - 1] == NULL)
811 i--;
812 dir_cleanup_list.tempdir_count = i;
813 }
814 else
815 dir_cleanup_list.tempdir_list[i] = NULL;
816 /* Now only we can free the tmpdir->dirname, tmpdir->subdirs,
817 tmpdir->files, and tmpdir itself. */
818 gl_list_free (tmpdir->files);
819 gl_list_free (tmpdir->subdirs);
820 free (tmpdir->dirname);
821 free (tmpdir);
822 gl_lock_unlock (dir_cleanup_list_lock);
823 return err;
824 }
825
826 /* The user passed an invalid DIR argument. */
827 abort ();
828 }
829
830
831 /* ================== Opening and closing temporary files ================== */
832
833 #if defined _WIN32 && ! defined __CYGWIN__
834
835 /* On Windows, opening a file with _O_TEMPORARY has the effect of passing
836 the FILE_FLAG_DELETE_ON_CLOSE flag to CreateFile(), which has the effect
837 of deleting the file when it is closed - even when the program crashes.
838 But (according to the Cygwin sources) it works only on Windows NT or newer.
839 So we cache the info whether we are running on Windows NT or newer. */
840
841 static bool
supports_delete_on_close()842 supports_delete_on_close ()
843 {
844 static int known; /* 1 = yes, -1 = no, 0 = unknown */
845 if (!known)
846 {
847 OSVERSIONINFO v;
848
849 /* According to
850 <https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getversionexa>
851 this structure must be initialized as follows: */
852 v.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
853
854 if (GetVersionEx (&v))
855 known = (v.dwPlatformId == VER_PLATFORM_WIN32_NT ? 1 : -1);
856 else
857 known = -1;
858 }
859 return (known > 0);
860 }
861
862 #endif
863
864
865 /* Register a file descriptor to be closed. */
866 static void
register_fd(int fd)867 register_fd (int fd)
868 {
869 gl_lock_lock (descriptors_lock);
870
871 if (descriptors == NULL)
872 descriptors = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL,
873 false);
874
875 struct closeable_fd *element = XMALLOC (struct closeable_fd);
876 element->fd = fd;
877 element->closed = false;
878 asyncsafe_spin_init (&element->lock);
879 element->done = false;
880
881 gl_list_add_first (descriptors, element);
882
883 gl_lock_unlock (descriptors_lock);
884 }
885
886 /* Open a temporary file in a temporary directory.
887 FILE_NAME must already have been passed to register_temp_file.
888 Registers the resulting file descriptor to be closed.
889 DELETE_ON_CLOSE indicates whether the file can be deleted when the resulting
890 file descriptor or stream is closed. */
891 int
open_temp(const char * file_name,int flags,mode_t mode,bool delete_on_close)892 open_temp (const char *file_name, int flags, mode_t mode, bool delete_on_close)
893 {
894 int fd;
895 int saved_errno;
896
897 block_fatal_signals ();
898 /* Note: 'open' here is actually open() or open_safer(). */
899 #if defined _WIN32 && ! defined __CYGWIN__
900 /* Use _O_TEMPORARY when possible, to increase the chances that the
901 temporary file is removed when the process crashes. */
902 if (delete_on_close && supports_delete_on_close ())
903 fd = open (file_name, flags | _O_TEMPORARY, mode);
904 else
905 #endif
906 fd = open (file_name, flags, mode);
907 saved_errno = errno;
908 if (fd >= 0)
909 register_fd (fd);
910 unblock_fatal_signals ();
911 errno = saved_errno;
912 return fd;
913 }
914
915 /* Open a temporary file in a temporary directory.
916 FILE_NAME must already have been passed to register_temp_file.
917 Registers the resulting file descriptor to be closed.
918 DELETE_ON_CLOSE indicates whether the file can be deleted when the resulting
919 file descriptor or stream is closed. */
920 FILE *
fopen_temp(const char * file_name,const char * mode,bool delete_on_close)921 fopen_temp (const char *file_name, const char *mode, bool delete_on_close)
922 {
923 FILE *fp;
924 int saved_errno;
925
926 block_fatal_signals ();
927 /* Note: 'fopen' here is actually fopen() or fopen_safer(). */
928 #if defined _WIN32 && ! defined __CYGWIN__
929 /* Use _O_TEMPORARY when possible, to increase the chances that the
930 temporary file is removed when the process crashes. */
931 if (delete_on_close && supports_delete_on_close ())
932 {
933 size_t mode_len = strlen (mode);
934 char *augmented_mode = (char *) xmalloca (mode_len + 2);
935 memcpy (augmented_mode, mode, mode_len);
936 memcpy (augmented_mode + mode_len, "D", 2);
937
938 fp = fopen (file_name, augmented_mode);
939 saved_errno = errno;
940
941 freea (augmented_mode);
942 }
943 else
944 #endif
945 {
946 fp = fopen (file_name, mode);
947 saved_errno = errno;
948 }
949 if (fp != NULL)
950 {
951 /* It is sufficient to register fileno (fp) instead of the entire fp,
952 because at cleanup time there is no need to do an fflush (fp); a
953 close (fileno (fp)) will be enough. */
954 int fd = fileno (fp);
955 if (!(fd >= 0))
956 abort ();
957 register_fd (fd);
958 }
959 unblock_fatal_signals ();
960 errno = saved_errno;
961 return fp;
962 }
963
964 #if GNULIB_TEMPNAME
965
966 struct try_create_file_params
967 {
968 int flags;
969 mode_t mode;
970 };
971
972 static int
try_create_file(char * file_name_tmpl,void * params_)973 try_create_file (char *file_name_tmpl, void *params_)
974 {
975 struct try_create_file_params *params = params_;
976 return open (file_name_tmpl,
977 (params->flags & ~O_ACCMODE) | O_RDWR | O_CREAT | O_EXCL,
978 params->mode);
979 }
980
981 /* Open a temporary file, generating its name based on FILE_NAME_TMPL.
982 FILE_NAME_TMPL must match the rules for mk[s]temp (i.e. end in "XXXXXX",
983 possibly with a suffix). The name constructed does not exist at the time
984 of the call. FILE_NAME_TMPL is overwritten with the result.
985 A safe choice for MODE is S_IRUSR | S_IWUSR, a.k.a. 0600.
986 Registers the file for deletion.
987 Opens the file, with the given FLAGS and mode MODE.
988 Registers the resulting file descriptor to be closed. */
989 int
gen_register_open_temp(char * file_name_tmpl,int suffixlen,int flags,mode_t mode)990 gen_register_open_temp (char *file_name_tmpl, int suffixlen,
991 int flags, mode_t mode)
992 {
993 block_fatal_signals ();
994
995 struct try_create_file_params params;
996 params.flags = flags;
997 params.mode = mode;
998
999 int fd = try_tempname (file_name_tmpl, suffixlen, ¶ms, try_create_file);
1000
1001 int saved_errno = errno;
1002 if (fd >= 0)
1003 {
1004 init_clean_temp ();
1005 register_fd (fd);
1006 register_temporary_file (file_name_tmpl);
1007 }
1008 unblock_fatal_signals ();
1009 errno = saved_errno;
1010 return fd;
1011 }
1012
1013 #endif
1014
1015 /* Close a temporary file.
1016 FD must have been returned by open_temp or gen_register_open_temp.
1017 Unregisters the previously registered file descriptor. */
1018 int
close_temp(int fd)1019 close_temp (int fd)
1020 {
1021 if (fd < 0)
1022 return close (fd);
1023
1024 init_fatal_signal_set ();
1025
1026 int result = 0;
1027 int saved_errno = 0;
1028
1029 gl_lock_lock (descriptors_lock);
1030
1031 gl_list_t list = descriptors;
1032 if (list == NULL)
1033 /* descriptors should already contain fd. */
1034 abort ();
1035
1036 /* Search through the list, and clean it up on the fly. */
1037 bool found = false;
1038 gl_list_iterator_t iter = gl_list_iterator (list);
1039 const void *elt;
1040 gl_list_node_t node;
1041 if (gl_list_iterator_next (&iter, &elt, &node))
1042 for (;;)
1043 {
1044 struct closeable_fd *element = (struct closeable_fd *) elt;
1045
1046 /* Close the file descriptor, avoiding races with the signal
1047 handler. */
1048 if (element->fd == fd)
1049 {
1050 found = true;
1051 result = asyncsafe_close (element);
1052 saved_errno = errno;
1053 }
1054
1055 bool free_this_node = element->done;
1056 struct closeable_fd *element_to_free = element;
1057 gl_list_node_t node_to_free = node;
1058
1059 bool have_next = gl_list_iterator_next (&iter, &elt, &node);
1060
1061 if (free_this_node)
1062 {
1063 free (element_to_free);
1064 gl_list_remove_node (list, node_to_free);
1065 }
1066
1067 if (!have_next)
1068 break;
1069 }
1070 gl_list_iterator_free (&iter);
1071 if (!found)
1072 /* descriptors should already contain fd. */
1073 abort ();
1074
1075 gl_lock_unlock (descriptors_lock);
1076
1077 errno = saved_errno;
1078 return result;
1079 }
1080
1081 static int
fclose_variant_temp(FILE * fp,int (* fclose_variant)(FILE *))1082 fclose_variant_temp (FILE *fp, int (*fclose_variant) (FILE *))
1083 {
1084 int fd = fileno (fp);
1085
1086 init_fatal_signal_set ();
1087
1088 int result = 0;
1089 int saved_errno = 0;
1090
1091 gl_lock_lock (descriptors_lock);
1092
1093 gl_list_t list = descriptors;
1094 if (list == NULL)
1095 /* descriptors should already contain fd. */
1096 abort ();
1097
1098 /* Search through the list, and clean it up on the fly. */
1099 bool found = false;
1100 gl_list_iterator_t iter = gl_list_iterator (list);
1101 const void *elt;
1102 gl_list_node_t node;
1103 if (gl_list_iterator_next (&iter, &elt, &node))
1104 for (;;)
1105 {
1106 struct closeable_fd *element = (struct closeable_fd *) elt;
1107
1108 /* Close the file descriptor and the stream, avoiding races with the
1109 signal handler. */
1110 if (element->fd == fd)
1111 {
1112 found = true;
1113 result = asyncsafe_fclose_variant (element, fp, fclose_variant);
1114 saved_errno = errno;
1115 }
1116
1117 bool free_this_node = element->done;
1118 struct closeable_fd *element_to_free = element;
1119 gl_list_node_t node_to_free = node;
1120
1121 bool have_next = gl_list_iterator_next (&iter, &elt, &node);
1122
1123 if (free_this_node)
1124 {
1125 free (element_to_free);
1126 gl_list_remove_node (list, node_to_free);
1127 }
1128
1129 if (!have_next)
1130 break;
1131 }
1132 gl_list_iterator_free (&iter);
1133 if (!found)
1134 /* descriptors should have contained fd. */
1135 abort ();
1136
1137 gl_lock_unlock (descriptors_lock);
1138
1139 errno = saved_errno;
1140 return result;
1141 }
1142
1143 /* Close a temporary file.
1144 FP must have been returned by fopen_temp, or by fdopen on a file descriptor
1145 returned by open_temp or gen_register_open_temp.
1146 Unregisters the previously registered file descriptor. */
1147 int
fclose_temp(FILE * fp)1148 fclose_temp (FILE *fp)
1149 {
1150 return fclose_variant_temp (fp, fclose);
1151 }
1152
1153 #if GNULIB_FWRITEERROR
1154 /* Like fwriteerror.
1155 FP must have been returned by fopen_temp, or by fdopen on a file descriptor
1156 returned by open_temp or gen_register_open_temp.
1157 Unregisters the previously registered file descriptor. */
1158 int
fwriteerror_temp(FILE * fp)1159 fwriteerror_temp (FILE *fp)
1160 {
1161 return fclose_variant_temp (fp, fwriteerror);
1162 }
1163 #endif
1164
1165 #if GNULIB_CLOSE_STREAM
1166 /* Like close_stream.
1167 FP must have been returned by fopen_temp, or by fdopen on a file descriptor
1168 returned by open_temp or gen_register_open_temp.
1169 Unregisters the previously registered file descriptor. */
1170 int
close_stream_temp(FILE * fp)1171 close_stream_temp (FILE *fp)
1172 {
1173 return fclose_variant_temp (fp, close_stream);
1174 }
1175 #endif
1176