intprops: Avoid bogus "warning: division by zero is undefined" on clang.
[gnulib.git] / lib / clean-temp.c
blob4a992c41ab60e589c45c8e9ac43a483d333560a1
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.
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.
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.
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/>. */
20 #include <config.h>
22 /* Specification. */
23 #include "clean-temp.h"
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>
34 #if defined _WIN32 && ! defined __CYGWIN__
35 # define WIN32_LEAN_AND_MEAN /* avoid including junk */
36 # include <windows.h>
37 #endif
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 "thread-optim.h"
48 #include "gl_xlist.h"
49 #include "gl_linkedhash_list.h"
50 #include "gl_linked_list.h"
51 #include "gettext.h"
52 #if GNULIB_TEMPNAME
53 # include "tempname.h"
54 #endif
55 #if GNULIB_FWRITEERROR
56 # include "fwriteerror.h"
57 #endif
58 #if GNULIB_CLOSE_STREAM
59 # include "close-stream.h"
60 #endif
61 #if GNULIB_FCNTL_SAFER
62 # include "fcntl--.h"
63 #endif
64 #if GNULIB_FOPEN_SAFER
65 # include "stdio--.h"
66 #endif
68 #define _(str) gettext (str)
70 /* GNU Hurd doesn't have PATH_MAX. Use a fallback.
71 Temporary directory names are usually not that long. */
72 #ifndef PATH_MAX
73 # define PATH_MAX 1024
74 #endif
76 #if defined _WIN32 && ! defined __CYGWIN__
77 /* Don't assume that UNICODE is not defined. */
78 # undef OSVERSIONINFO
79 # define OSVERSIONINFO OSVERSIONINFOA
80 # undef GetVersionEx
81 # define GetVersionEx GetVersionExA
82 #endif
85 /* The use of 'volatile' in the types below (and ISO C 99 section 5.1.2.3.(5))
86 ensure that while constructing or modifying the data structures, the field
87 values are written to memory in the order of the C statements. So the
88 signal handler can rely on these field values to be up to date. */
91 /* Lock that protects the file_cleanup_list from concurrent modification in
92 different threads. */
93 gl_lock_define_initialized (static, file_cleanup_list_lock)
95 /* List of all temporary files without temporary directories. */
96 static gl_list_t /* <char *> */ volatile file_cleanup_list;
99 /* Registry for a single temporary directory.
100 'struct temp_dir' from the public header file overlaps with this. */
101 struct tempdir
103 /* The absolute pathname of the directory. */
104 char * volatile dirname;
105 /* Whether errors during explicit cleanup are reported to standard error. */
106 bool cleanup_verbose;
107 /* Absolute pathnames of subdirectories. */
108 gl_list_t /* <char *> */ volatile subdirs;
109 /* Absolute pathnames of files. */
110 gl_list_t /* <char *> */ volatile files;
113 /* Lock that protects the dir_cleanup_list from concurrent modification in
114 different threads. */
115 gl_lock_define_initialized (static, dir_cleanup_list_lock)
117 /* List of all temporary directories. */
118 static struct
120 struct tempdir * volatile * volatile tempdir_list;
121 size_t volatile tempdir_count;
122 size_t tempdir_allocated;
123 } dir_cleanup_list /* = { NULL, 0, 0 } */;
126 /* A file descriptor to be closed.
127 In multithreaded programs, it is forbidden to close the same fd twice,
128 because you never know what unrelated open() calls are being executed in
129 other threads. So, the 'close (fd)' must be guarded by a once-only guard. */
130 struct closeable_fd
132 /* The file descriptor to close. */
133 int volatile fd;
134 /* Set to true when it has been closed. */
135 bool volatile closed;
136 /* Lock that protects the fd from being closed twice. */
137 asyncsafe_spinlock_t lock;
138 /* Tells whether this list element has been done and can be freed. */
139 bool volatile done;
142 /* Lock that protects the descriptors list from concurrent modification in
143 different threads. */
144 gl_lock_define_initialized (static, descriptors_lock)
146 /* List of all open file descriptors to temporary files. */
147 static gl_list_t /* <closeable_fd *> */ volatile descriptors;
150 /* For the subdirs and for the files, we use a gl_list_t of type LINKEDHASH.
151 Why? We need a data structure that
153 1) Can contain an arbitrary number of 'char *' values. The strings
154 are compared via strcmp, not pointer comparison.
155 2) Has insertion and deletion operations that are fast: ideally O(1),
156 or possibly O(log n). This is important for GNU sort, which may
157 create a large number of temporary files.
158 3) Allows iteration through all elements from within a signal handler.
159 4) May or may not allow duplicates. It doesn't matter here, since
160 any file or subdir can only be removed once.
162 Criterion 1) would allow any gl_list_t or gl_oset_t implementation.
164 Criterion 2) leaves only GL_LINKEDHASH_LIST, GL_TREEHASH_LIST, or
165 GL_TREE_OSET.
167 Criterion 3) puts at disadvantage GL_TREEHASH_LIST and GL_TREE_OSET.
168 Namely, iteration through the elements of a binary tree requires access
169 to many ->left, ->right, ->parent pointers. However, the rebalancing
170 code for insertion and deletion in an AVL or red-black tree is so
171 complicated that we cannot assume that >left, ->right, ->parent pointers
172 are in a consistent state throughout these operations. Therefore, to
173 avoid a crash in the signal handler, all destructive operations to the
174 lists would have to be protected by a
175 block_fatal_signals ();
177 unblock_fatal_signals ();
178 pair. Which causes extra system calls.
180 Criterion 3) would also discourage GL_ARRAY_LIST and GL_CARRAY_LIST,
181 if they were not already excluded. Namely, these implementations use
182 xrealloc(), leaving a time window in which in the list->elements pointer
183 points to already deallocated memory. To avoid a crash in the signal
184 handler at such a moment, all destructive operations would have to
185 protected by block/unblock_fatal_signals (), in this case too.
187 A list of type GL_LINKEDHASH_LIST without duplicates fulfills all
188 requirements:
189 2) Insertion and deletion are O(1) on average.
190 3) The gl_list_iterator, gl_list_iterator_next implementations do
191 not trigger memory allocations, nor other system calls, and are
192 therefore safe to be called from a signal handler.
193 Furthermore, since SIGNAL_SAFE_LIST is defined, the implementation
194 of the destructive functions ensures that the list structure is
195 safe to be traversed at any moment, even when interrupted by an
196 asynchronous signal.
199 /* String equality and hash code functions used by the lists. */
201 static bool
202 string_equals (const void *x1, const void *x2)
204 const char *s1 = (const char *) x1;
205 const char *s2 = (const char *) x2;
206 return strcmp (s1, s2) == 0;
209 #define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
211 /* A hash function for NUL-terminated char* strings using
212 the method described by Bruno Haible.
213 See https://www.haible.de/bruno/hashfunc.html. */
214 static size_t
215 string_hash (const void *x)
217 const char *s = (const char *) x;
218 size_t h = 0;
220 for (; *s; s++)
221 h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
223 return h;
227 /* The set of fatal signal handlers.
228 Cached here because we are not allowed to call get_fatal_signal_set ()
229 from a signal handler. */
230 static const sigset_t *fatal_signal_set /* = NULL */;
232 static void
233 init_fatal_signal_set (void)
235 if (fatal_signal_set == NULL)
236 fatal_signal_set = get_fatal_signal_set ();
240 /* Close a file descriptor.
241 Avoids race conditions with normal thread code or signal-handler code that
242 might want to close the same file descriptor. */
243 static _GL_ASYNC_SAFE int
244 asyncsafe_close (struct closeable_fd *element)
246 sigset_t saved_mask;
247 int ret;
248 int saved_errno;
250 asyncsafe_spin_lock (&element->lock, fatal_signal_set, &saved_mask);
251 if (!element->closed)
253 ret = close (element->fd);
254 saved_errno = errno;
255 element->closed = true;
257 else
259 ret = 0;
260 saved_errno = 0;
262 asyncsafe_spin_unlock (&element->lock, &saved_mask);
263 element->done = true;
265 errno = saved_errno;
266 return ret;
269 /* Close a file descriptor and the stream that contains it.
270 Avoids race conditions with signal-handler code that might want to close the
271 same file descriptor. */
272 static int
273 asyncsafe_fclose_variant (struct closeable_fd *element, FILE *fp,
274 int (*fclose_variant) (FILE *))
276 if (fileno (fp) != element->fd)
277 abort ();
279 /* Flush buffered data first, to minimize the duration of the spin lock. */
280 fflush (fp);
282 sigset_t saved_mask;
283 int ret;
284 int saved_errno;
286 asyncsafe_spin_lock (&element->lock, fatal_signal_set, &saved_mask);
287 if (!element->closed)
289 ret = fclose_variant (fp); /* invokes close (element->fd) */
290 saved_errno = errno;
291 element->closed = true;
293 else
295 ret = 0;
296 saved_errno = 0;
298 asyncsafe_spin_unlock (&element->lock, &saved_mask);
299 element->done = true;
301 errno = saved_errno;
302 return ret;
305 /* The signal handler. It gets called asynchronously. */
306 static _GL_ASYNC_SAFE void
307 cleanup_action (int sig _GL_UNUSED)
309 size_t i;
311 /* First close all file descriptors to temporary files. */
313 gl_list_t fds = descriptors;
315 if (fds != NULL)
317 gl_list_iterator_t iter;
318 const void *element;
320 iter = gl_list_iterator (fds);
321 while (gl_list_iterator_next (&iter, &element, NULL))
323 asyncsafe_close ((struct closeable_fd *) element);
325 gl_list_iterator_free (&iter);
330 gl_list_t files = file_cleanup_list;
332 if (files != NULL)
334 gl_list_iterator_t iter;
335 const void *element;
337 iter = gl_list_iterator (files);
338 while (gl_list_iterator_next (&iter, &element, NULL))
340 const char *file = (const char *) element;
341 unlink (file);
343 gl_list_iterator_free (&iter);
347 for (i = 0; i < dir_cleanup_list.tempdir_count; i++)
349 struct tempdir *dir = dir_cleanup_list.tempdir_list[i];
351 if (dir != NULL)
353 gl_list_iterator_t iter;
354 const void *element;
356 /* First cleanup the files in the subdirectories. */
357 iter = gl_list_iterator (dir->files);
358 while (gl_list_iterator_next (&iter, &element, NULL))
360 const char *file = (const char *) element;
361 unlink (file);
363 gl_list_iterator_free (&iter);
365 /* Then cleanup the subdirectories. */
366 iter = gl_list_iterator (dir->subdirs);
367 while (gl_list_iterator_next (&iter, &element, NULL))
369 const char *subdir = (const char *) element;
370 rmdir (subdir);
372 gl_list_iterator_free (&iter);
374 /* Then cleanup the temporary directory itself. */
375 rmdir (dir->dirname);
381 /* Initializes this facility. */
382 static void
383 do_init_clean_temp (void)
385 /* Initialize the data used by the cleanup handler. */
386 init_fatal_signal_set ();
387 /* Register the cleanup handler. */
388 at_fatal_signal (&cleanup_action);
391 /* Ensure that do_init_clean_temp is called once only. */
392 gl_once_define(static, clean_temp_once)
394 /* Initializes this facility upon first use. */
395 static void
396 init_clean_temp (void)
398 gl_once (clean_temp_once, do_init_clean_temp);
402 /* ============= Temporary files without temporary directories ============= */
404 /* Register the given ABSOLUTE_FILE_NAME as being a file that needs to be
405 removed.
406 Should be called before the file ABSOLUTE_FILE_NAME is created. */
407 void
408 register_temporary_file (const char *absolute_file_name)
410 bool mt = gl_multithreaded ();
412 if (mt) gl_lock_lock (file_cleanup_list_lock);
414 /* Make sure that this facility and the file_cleanup_list are initialized. */
415 if (file_cleanup_list == NULL)
417 init_clean_temp ();
418 file_cleanup_list =
419 gl_list_create_empty (GL_LINKEDHASH_LIST,
420 string_equals, string_hash, NULL, false);
423 /* Add absolute_file_name to file_cleanup_list, without duplicates. */
424 if (gl_list_search (file_cleanup_list, absolute_file_name) == NULL)
425 gl_list_add_first (file_cleanup_list, xstrdup (absolute_file_name));
427 if (mt) gl_lock_unlock (file_cleanup_list_lock);
430 /* Unregister the given ABSOLUTE_FILE_NAME as being a file that needs to be
431 removed.
432 Should be called when the file ABSOLUTE_FILE_NAME could not be created. */
433 void
434 unregister_temporary_file (const char *absolute_file_name)
436 bool mt = gl_multithreaded ();
438 if (mt) gl_lock_lock (file_cleanup_list_lock);
440 gl_list_t list = file_cleanup_list;
441 if (list != NULL)
443 gl_list_node_t node = gl_list_search (list, absolute_file_name);
444 if (node != NULL)
446 char *old_string = (char *) gl_list_node_value (list, node);
448 gl_list_remove_node (list, node);
449 free (old_string);
453 if (mt) gl_lock_unlock (file_cleanup_list_lock);
456 /* Remove a file, with optional error message.
457 Return 0 upon success, or -1 if there was some problem. */
458 static int
459 do_unlink (const char *absolute_file_name, bool cleanup_verbose)
461 if (unlink (absolute_file_name) < 0 && cleanup_verbose
462 && errno != ENOENT)
464 error (0, errno,
465 _("cannot remove temporary file %s"), absolute_file_name);
466 return -1;
468 return 0;
471 /* Remove the given ABSOLUTE_FILE_NAME and unregister it.
472 CLEANUP_VERBOSE determines whether errors are reported to standard error.
473 Return 0 upon success, or -1 if there was some problem. */
475 cleanup_temporary_file (const char *absolute_file_name, bool cleanup_verbose)
477 int err;
479 err = do_unlink (absolute_file_name, cleanup_verbose);
480 unregister_temporary_file (absolute_file_name);
482 return err;
486 /* ========= Temporary directories and temporary files inside them ========= */
488 /* Create a temporary directory.
489 PREFIX is used as a prefix for the name of the temporary directory. It
490 should be short and still give an indication about the program.
491 PARENTDIR can be used to specify the parent directory; if NULL, a default
492 parent directory is used (either $TMPDIR or /tmp or similar).
493 CLEANUP_VERBOSE determines whether errors during explicit cleanup are
494 reported to standard error.
495 Return a fresh 'struct temp_dir' on success. Upon error, an error message
496 is shown and NULL is returned. */
497 struct temp_dir *
498 create_temp_dir (const char *prefix, const char *parentdir,
499 bool cleanup_verbose)
501 bool mt = gl_multithreaded ();
503 if (mt) gl_lock_lock (dir_cleanup_list_lock);
505 struct tempdir * volatile *tmpdirp = NULL;
506 struct tempdir *tmpdir;
507 size_t i;
508 char *xtemplate;
509 char *tmpdirname;
511 /* See whether it can take the slot of an earlier temporary directory
512 already cleaned up. */
513 for (i = 0; i < dir_cleanup_list.tempdir_count; i++)
514 if (dir_cleanup_list.tempdir_list[i] == NULL)
516 tmpdirp = &dir_cleanup_list.tempdir_list[i];
517 break;
519 if (tmpdirp == NULL)
521 /* See whether the array needs to be extended. */
522 if (dir_cleanup_list.tempdir_count == dir_cleanup_list.tempdir_allocated)
524 /* Note that we cannot use xrealloc(), because then the cleanup()
525 function could access an already deallocated array. */
526 struct tempdir * volatile *old_array = dir_cleanup_list.tempdir_list;
527 size_t old_allocated = dir_cleanup_list.tempdir_allocated;
528 size_t new_allocated = 2 * dir_cleanup_list.tempdir_allocated + 1;
529 struct tempdir * volatile *new_array =
530 XNMALLOC (new_allocated, struct tempdir * volatile);
532 if (old_allocated == 0)
534 /* First use of this facility. */
535 init_clean_temp ();
537 else
539 /* Don't use memcpy() here, because memcpy takes non-volatile
540 arguments and is therefore not guaranteed to complete all
541 memory stores before the next statement. */
542 size_t k;
544 for (k = 0; k < old_allocated; k++)
545 new_array[k] = old_array[k];
548 dir_cleanup_list.tempdir_list = new_array;
549 dir_cleanup_list.tempdir_allocated = new_allocated;
551 /* Now we can free the old array. */
552 /* No, we can't do that. If cleanup_action is running in a different
553 thread and has already fetched the tempdir_list pointer (getting
554 old_array) but not yet accessed its i-th element, that thread may
555 crash when accessing an element of the already freed old_array
556 array. */
557 #if 0
558 if (old_array != NULL)
559 free ((struct tempdir **) old_array);
560 #endif
563 tmpdirp = &dir_cleanup_list.tempdir_list[dir_cleanup_list.tempdir_count];
564 /* Initialize *tmpdirp before incrementing tempdir_count, so that
565 cleanup() will skip this entry before it is fully initialized. */
566 *tmpdirp = NULL;
567 dir_cleanup_list.tempdir_count++;
570 /* Initialize a 'struct tempdir'. */
571 tmpdir = XMALLOC (struct tempdir);
572 tmpdir->dirname = NULL;
573 tmpdir->cleanup_verbose = cleanup_verbose;
574 tmpdir->subdirs = gl_list_create_empty (GL_LINKEDHASH_LIST,
575 string_equals, string_hash, NULL,
576 false);
577 tmpdir->files = gl_list_create_empty (GL_LINKEDHASH_LIST,
578 string_equals, string_hash, NULL,
579 false);
581 /* Create the temporary directory. */
582 xtemplate = (char *) xmalloca (PATH_MAX);
583 if (path_search (xtemplate, PATH_MAX, parentdir, prefix, parentdir == NULL))
585 error (0, errno,
586 _("cannot find a temporary directory, try setting $TMPDIR"));
587 goto quit;
589 block_fatal_signals ();
590 tmpdirname = mkdtemp (xtemplate);
591 int saved_errno = errno;
592 if (tmpdirname != NULL)
594 tmpdir->dirname = tmpdirname;
595 *tmpdirp = tmpdir;
597 unblock_fatal_signals ();
598 if (tmpdirname == NULL)
600 error (0, saved_errno,
601 _("cannot create a temporary directory using template \"%s\""),
602 xtemplate);
603 goto quit;
605 /* Replace tmpdir->dirname with a copy that has indefinite extent.
606 We cannot do this inside the block_fatal_signals/unblock_fatal_signals
607 block because then the cleanup handler would not remove the directory
608 if xstrdup fails. */
609 tmpdir->dirname = xstrdup (tmpdirname);
610 if (mt) gl_lock_unlock (dir_cleanup_list_lock);
611 freea (xtemplate);
612 return (struct temp_dir *) tmpdir;
614 quit:
615 if (mt) gl_lock_unlock (dir_cleanup_list_lock);
616 freea (xtemplate);
617 return NULL;
620 /* Register the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
621 needs to be removed before DIR can be removed.
622 Should be called before the file ABSOLUTE_FILE_NAME is created. */
623 void
624 register_temp_file (struct temp_dir *dir,
625 const char *absolute_file_name)
627 struct tempdir *tmpdir = (struct tempdir *)dir;
628 bool mt = gl_multithreaded ();
630 if (mt) gl_lock_lock (dir_cleanup_list_lock);
632 /* Add absolute_file_name to tmpdir->files, without duplicates. */
633 if (gl_list_search (tmpdir->files, absolute_file_name) == NULL)
634 gl_list_add_first (tmpdir->files, xstrdup (absolute_file_name));
636 if (mt) gl_lock_unlock (dir_cleanup_list_lock);
639 /* Unregister the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
640 needs to be removed before DIR can be removed.
641 Should be called when the file ABSOLUTE_FILE_NAME could not be created. */
642 void
643 unregister_temp_file (struct temp_dir *dir,
644 const char *absolute_file_name)
646 struct tempdir *tmpdir = (struct tempdir *)dir;
647 bool mt = gl_multithreaded ();
649 if (mt) gl_lock_lock (dir_cleanup_list_lock);
651 gl_list_t list = tmpdir->files;
652 gl_list_node_t node;
654 node = gl_list_search (list, absolute_file_name);
655 if (node != NULL)
657 char *old_string = (char *) gl_list_node_value (list, node);
659 gl_list_remove_node (list, node);
660 free (old_string);
663 if (mt) gl_lock_unlock (dir_cleanup_list_lock);
666 /* Register the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
667 that needs to be removed before DIR can be removed.
668 Should be called before the subdirectory ABSOLUTE_DIR_NAME is created. */
669 void
670 register_temp_subdir (struct temp_dir *dir,
671 const char *absolute_dir_name)
673 struct tempdir *tmpdir = (struct tempdir *)dir;
674 bool mt = gl_multithreaded ();
676 if (mt) gl_lock_lock (dir_cleanup_list_lock);
678 /* Add absolute_dir_name to tmpdir->subdirs, without duplicates. */
679 if (gl_list_search (tmpdir->subdirs, absolute_dir_name) == NULL)
680 gl_list_add_first (tmpdir->subdirs, xstrdup (absolute_dir_name));
682 if (mt) gl_lock_unlock (dir_cleanup_list_lock);
685 /* Unregister the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
686 that needs to be removed before DIR can be removed.
687 Should be called when the subdirectory ABSOLUTE_DIR_NAME could not be
688 created. */
689 void
690 unregister_temp_subdir (struct temp_dir *dir,
691 const char *absolute_dir_name)
693 struct tempdir *tmpdir = (struct tempdir *)dir;
694 bool mt = gl_multithreaded ();
696 if (mt) gl_lock_lock (dir_cleanup_list_lock);
698 gl_list_t list = tmpdir->subdirs;
699 gl_list_node_t node;
701 node = gl_list_search (list, absolute_dir_name);
702 if (node != NULL)
704 char *old_string = (char *) gl_list_node_value (list, node);
706 gl_list_remove_node (list, node);
707 free (old_string);
710 if (mt) gl_lock_unlock (dir_cleanup_list_lock);
713 /* Remove a directory, with optional error message.
714 Return 0 upon success, or -1 if there was some problem. */
715 static int
716 do_rmdir (const char *absolute_dir_name, bool cleanup_verbose)
718 if (rmdir (absolute_dir_name) < 0 && cleanup_verbose
719 && errno != ENOENT)
721 error (0, errno,
722 _("cannot remove temporary directory %s"), absolute_dir_name);
723 return -1;
725 return 0;
728 /* Remove the given ABSOLUTE_FILE_NAME and unregister it.
729 Return 0 upon success, or -1 if there was some problem. */
731 cleanup_temp_file (struct temp_dir *dir,
732 const char *absolute_file_name)
734 int err;
736 err = do_unlink (absolute_file_name, dir->cleanup_verbose);
737 unregister_temp_file (dir, absolute_file_name);
739 return err;
742 /* Remove the given ABSOLUTE_DIR_NAME and unregister it.
743 Return 0 upon success, or -1 if there was some problem. */
745 cleanup_temp_subdir (struct temp_dir *dir,
746 const char *absolute_dir_name)
748 int err;
750 err = do_rmdir (absolute_dir_name, dir->cleanup_verbose);
751 unregister_temp_subdir (dir, absolute_dir_name);
753 return err;
756 /* Remove all registered files and subdirectories inside DIR.
757 Only to be called with dir_cleanup_list_lock locked.
758 Return 0 upon success, or -1 if there was some problem. */
760 cleanup_temp_dir_contents (struct temp_dir *dir)
762 struct tempdir *tmpdir = (struct tempdir *)dir;
763 int err = 0;
764 gl_list_t list;
765 gl_list_iterator_t iter;
766 const void *element;
767 gl_list_node_t node;
769 /* First cleanup the files in the subdirectories. */
770 list = tmpdir->files;
771 iter = gl_list_iterator (list);
772 while (gl_list_iterator_next (&iter, &element, &node))
774 char *file = (char *) element;
776 err |= do_unlink (file, dir->cleanup_verbose);
777 gl_list_remove_node (list, node);
778 /* Now only we can free file. */
779 free (file);
781 gl_list_iterator_free (&iter);
783 /* Then cleanup the subdirectories. */
784 list = tmpdir->subdirs;
785 iter = gl_list_iterator (list);
786 while (gl_list_iterator_next (&iter, &element, &node))
788 char *subdir = (char *) element;
790 err |= do_rmdir (subdir, dir->cleanup_verbose);
791 gl_list_remove_node (list, node);
792 /* Now only we can free subdir. */
793 free (subdir);
795 gl_list_iterator_free (&iter);
797 return err;
800 /* Remove all registered files and subdirectories inside DIR and DIR itself.
801 DIR cannot be used any more after this call.
802 Return 0 upon success, or -1 if there was some problem. */
804 cleanup_temp_dir (struct temp_dir *dir)
806 bool mt = gl_multithreaded ();
808 if (mt) gl_lock_lock (dir_cleanup_list_lock);
810 struct tempdir *tmpdir = (struct tempdir *)dir;
811 int err = 0;
812 size_t i;
814 err |= cleanup_temp_dir_contents (dir);
815 err |= do_rmdir (tmpdir->dirname, dir->cleanup_verbose);
817 for (i = 0; i < dir_cleanup_list.tempdir_count; i++)
818 if (dir_cleanup_list.tempdir_list[i] == tmpdir)
820 /* Remove dir_cleanup_list.tempdir_list[i]. */
821 if (i + 1 == dir_cleanup_list.tempdir_count)
823 while (i > 0 && dir_cleanup_list.tempdir_list[i - 1] == NULL)
824 i--;
825 dir_cleanup_list.tempdir_count = i;
827 else
828 dir_cleanup_list.tempdir_list[i] = NULL;
829 /* Now only we can free the tmpdir->dirname, tmpdir->subdirs,
830 tmpdir->files, and tmpdir itself. */
831 gl_list_free (tmpdir->files);
832 gl_list_free (tmpdir->subdirs);
833 free (tmpdir->dirname);
834 free (tmpdir);
835 if (mt) gl_lock_unlock (dir_cleanup_list_lock);
836 return err;
839 /* The user passed an invalid DIR argument. */
840 abort ();
844 /* ================== Opening and closing temporary files ================== */
846 #if defined _WIN32 && ! defined __CYGWIN__
848 /* On Windows, opening a file with _O_TEMPORARY has the effect of passing
849 the FILE_FLAG_DELETE_ON_CLOSE flag to CreateFile(), which has the effect
850 of deleting the file when it is closed - even when the program crashes.
851 But (according to the Cygwin sources) it works only on Windows NT or newer.
852 So we cache the info whether we are running on Windows NT or newer. */
854 static bool
855 supports_delete_on_close ()
857 static int known; /* 1 = yes, -1 = no, 0 = unknown */
858 if (!known)
860 OSVERSIONINFO v;
862 /* According to
863 <https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getversionexa>
864 this structure must be initialized as follows: */
865 v.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
867 if (GetVersionEx (&v))
868 known = (v.dwPlatformId == VER_PLATFORM_WIN32_NT ? 1 : -1);
869 else
870 known = -1;
872 return (known > 0);
875 #endif
878 /* Register a file descriptor to be closed. */
879 static void
880 register_fd (int fd)
882 bool mt = gl_multithreaded ();
884 if (mt) gl_lock_lock (descriptors_lock);
886 if (descriptors == NULL)
887 descriptors = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL,
888 false);
890 struct closeable_fd *element = XMALLOC (struct closeable_fd);
891 element->fd = fd;
892 element->closed = false;
893 asyncsafe_spin_init (&element->lock);
894 element->done = false;
896 gl_list_add_first (descriptors, element);
898 if (mt) gl_lock_unlock (descriptors_lock);
901 /* Open a temporary file in a temporary directory.
902 FILE_NAME must already have been passed to register_temp_file.
903 Registers the resulting file descriptor to be closed.
904 DELETE_ON_CLOSE indicates whether the file can be deleted when the resulting
905 file descriptor or stream is closed. */
907 open_temp (const char *file_name, int flags, mode_t mode, bool delete_on_close)
909 int fd;
910 int saved_errno;
912 block_fatal_signals ();
913 /* Note: 'open' here is actually open() or open_safer(). */
914 #if defined _WIN32 && ! defined __CYGWIN__
915 /* Use _O_TEMPORARY when possible, to increase the chances that the
916 temporary file is removed when the process crashes. */
917 if (delete_on_close && supports_delete_on_close ())
918 fd = open (file_name, flags | _O_TEMPORARY, mode);
919 else
920 #endif
921 fd = open (file_name, flags, mode);
922 saved_errno = errno;
923 if (fd >= 0)
924 register_fd (fd);
925 unblock_fatal_signals ();
926 errno = saved_errno;
927 return fd;
930 /* Open a temporary file in a temporary directory.
931 FILE_NAME must already have been passed to register_temp_file.
932 Registers the resulting file descriptor to be closed.
933 DELETE_ON_CLOSE indicates whether the file can be deleted when the resulting
934 file descriptor or stream is closed. */
935 FILE *
936 fopen_temp (const char *file_name, const char *mode, bool delete_on_close)
938 FILE *fp;
939 int saved_errno;
941 block_fatal_signals ();
942 /* Note: 'fopen' here is actually fopen() or fopen_safer(). */
943 #if defined _WIN32 && ! defined __CYGWIN__
944 /* Use _O_TEMPORARY when possible, to increase the chances that the
945 temporary file is removed when the process crashes. */
946 if (delete_on_close && supports_delete_on_close ())
948 size_t mode_len = strlen (mode);
949 char *augmented_mode = (char *) xmalloca (mode_len + 2);
950 memcpy (augmented_mode, mode, mode_len);
951 memcpy (augmented_mode + mode_len, "D", 2);
953 fp = fopen (file_name, augmented_mode);
954 saved_errno = errno;
956 freea (augmented_mode);
958 else
959 #endif
961 fp = fopen (file_name, mode);
962 saved_errno = errno;
964 if (fp != NULL)
966 /* It is sufficient to register fileno (fp) instead of the entire fp,
967 because at cleanup time there is no need to do an fflush (fp); a
968 close (fileno (fp)) will be enough. */
969 int fd = fileno (fp);
970 if (!(fd >= 0))
971 abort ();
972 register_fd (fd);
974 unblock_fatal_signals ();
975 errno = saved_errno;
976 return fp;
979 #if GNULIB_TEMPNAME
981 struct try_create_file_params
983 int flags;
984 mode_t mode;
987 static int
988 try_create_file (char *file_name_tmpl, void *params_)
990 struct try_create_file_params *params = params_;
991 return open (file_name_tmpl,
992 (params->flags & ~O_ACCMODE) | O_RDWR | O_CREAT | O_EXCL,
993 params->mode);
996 /* Open a temporary file, generating its name based on FILE_NAME_TMPL.
997 FILE_NAME_TMPL must match the rules for mk[s]temp (i.e. end in "XXXXXX",
998 possibly with a suffix). The name constructed does not exist at the time
999 of the call. FILE_NAME_TMPL is overwritten with the result.
1000 A safe choice for MODE is S_IRUSR | S_IWUSR, a.k.a. 0600.
1001 Registers the file for deletion.
1002 Opens the file, with the given FLAGS and mode MODE.
1003 Registers the resulting file descriptor to be closed. */
1005 gen_register_open_temp (char *file_name_tmpl, int suffixlen,
1006 int flags, mode_t mode)
1008 block_fatal_signals ();
1010 struct try_create_file_params params;
1011 params.flags = flags;
1012 params.mode = mode;
1014 int fd = try_tempname (file_name_tmpl, suffixlen, &params, try_create_file);
1016 int saved_errno = errno;
1017 if (fd >= 0)
1019 init_clean_temp ();
1020 register_fd (fd);
1021 register_temporary_file (file_name_tmpl);
1023 unblock_fatal_signals ();
1024 errno = saved_errno;
1025 return fd;
1028 #endif
1030 /* Close a temporary file.
1031 FD must have been returned by open_temp or gen_register_open_temp.
1032 Unregisters the previously registered file descriptor. */
1034 close_temp (int fd)
1036 if (fd < 0)
1037 return close (fd);
1039 init_fatal_signal_set ();
1041 int result = 0;
1042 int saved_errno = 0;
1044 bool mt = gl_multithreaded ();
1046 if (mt) gl_lock_lock (descriptors_lock);
1048 gl_list_t list = descriptors;
1049 if (list == NULL)
1050 /* descriptors should already contain fd. */
1051 abort ();
1053 /* Search through the list, and clean it up on the fly. */
1054 bool found = false;
1055 gl_list_iterator_t iter = gl_list_iterator (list);
1056 const void *elt;
1057 gl_list_node_t node;
1058 if (gl_list_iterator_next (&iter, &elt, &node))
1059 for (;;)
1061 struct closeable_fd *element = (struct closeable_fd *) elt;
1063 /* Close the file descriptor, avoiding races with the signal
1064 handler. */
1065 if (element->fd == fd)
1067 found = true;
1068 result = asyncsafe_close (element);
1069 saved_errno = errno;
1072 bool free_this_node = element->done;
1073 struct closeable_fd *element_to_free = element;
1074 gl_list_node_t node_to_free = node;
1076 bool have_next = gl_list_iterator_next (&iter, &elt, &node);
1078 if (free_this_node)
1080 free (element_to_free);
1081 gl_list_remove_node (list, node_to_free);
1084 if (!have_next)
1085 break;
1087 gl_list_iterator_free (&iter);
1088 if (!found)
1089 /* descriptors should already contain fd. */
1090 abort ();
1092 if (mt) gl_lock_unlock (descriptors_lock);
1094 errno = saved_errno;
1095 return result;
1098 static int
1099 fclose_variant_temp (FILE *fp, int (*fclose_variant) (FILE *))
1101 int fd = fileno (fp);
1103 init_fatal_signal_set ();
1105 int result = 0;
1106 int saved_errno = 0;
1108 bool mt = gl_multithreaded ();
1110 if (mt) gl_lock_lock (descriptors_lock);
1112 gl_list_t list = descriptors;
1113 if (list == NULL)
1114 /* descriptors should already contain fd. */
1115 abort ();
1117 /* Search through the list, and clean it up on the fly. */
1118 bool found = false;
1119 gl_list_iterator_t iter = gl_list_iterator (list);
1120 const void *elt;
1121 gl_list_node_t node;
1122 if (gl_list_iterator_next (&iter, &elt, &node))
1123 for (;;)
1125 struct closeable_fd *element = (struct closeable_fd *) elt;
1127 /* Close the file descriptor and the stream, avoiding races with the
1128 signal handler. */
1129 if (element->fd == fd)
1131 found = true;
1132 result = asyncsafe_fclose_variant (element, fp, fclose_variant);
1133 saved_errno = errno;
1136 bool free_this_node = element->done;
1137 struct closeable_fd *element_to_free = element;
1138 gl_list_node_t node_to_free = node;
1140 bool have_next = gl_list_iterator_next (&iter, &elt, &node);
1142 if (free_this_node)
1144 free (element_to_free);
1145 gl_list_remove_node (list, node_to_free);
1148 if (!have_next)
1149 break;
1151 gl_list_iterator_free (&iter);
1152 if (!found)
1153 /* descriptors should have contained fd. */
1154 abort ();
1156 if (mt) gl_lock_unlock (descriptors_lock);
1158 errno = saved_errno;
1159 return result;
1162 /* Close a temporary file.
1163 FP must have been returned by fopen_temp, or by fdopen on a file descriptor
1164 returned by open_temp or gen_register_open_temp.
1165 Unregisters the previously registered file descriptor. */
1167 fclose_temp (FILE *fp)
1169 return fclose_variant_temp (fp, fclose);
1172 #if GNULIB_FWRITEERROR
1173 /* Like fwriteerror.
1174 FP must have been returned by fopen_temp, or by fdopen on a file descriptor
1175 returned by open_temp or gen_register_open_temp.
1176 Unregisters the previously registered file descriptor. */
1178 fwriteerror_temp (FILE *fp)
1180 return fclose_variant_temp (fp, fwriteerror);
1182 #endif
1184 #if GNULIB_CLOSE_STREAM
1185 /* Like close_stream.
1186 FP must have been returned by fopen_temp, or by fdopen on a file descriptor
1187 returned by open_temp or gen_register_open_temp.
1188 Unregisters the previously registered file descriptor. */
1190 close_stream_temp (FILE *fp)
1192 return fclose_variant_temp (fp, close_stream);
1194 #endif