1 /* Temporary directories and temporary files with automatic cleanup.
2 Copyright (C) 2001, 2003, 2006-2007, 2009-2020 Free Software Foundation,
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/>. */
23 #include "clean-temp.h"
34 #if defined _WIN32 && ! defined __CYGWIN__
35 # define WIN32_LEAN_AND_MEAN /* avoid including junk */
40 #include "fatal-signal.h"
41 #include "asyncsafe-spin.h"
46 #include "glthread/lock.h"
47 #include "thread-optim.h"
49 #include "gl_linkedhash_list.h"
50 #include "gl_linked_list.h"
53 # include "tempname.h"
55 #if GNULIB_FWRITEERROR
56 # include "fwriteerror.h"
58 #if GNULIB_CLOSE_STREAM
59 # include "close-stream.h"
61 #if GNULIB_FCNTL_SAFER
64 #if GNULIB_FOPEN_SAFER
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. */
73 # define PATH_MAX 1024
76 #if defined _WIN32 && ! defined __CYGWIN__
77 /* Don't assume that UNICODE is not defined. */
79 # define OSVERSIONINFO OSVERSIONINFOA
81 # define GetVersionEx GetVersionExA
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
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. */
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. */
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. */
132 /* The file descriptor to close. */
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. */
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
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
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
199 /* String equality and hash code functions used by the lists. */
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. */
215 string_hash (const void *x
)
217 const char *s
= (const char *) x
;
221 h
= *s
+ ((h
<< 9) | (h
>> (SIZE_BITS
- 9)));
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 */;
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
)
250 asyncsafe_spin_lock (&element
->lock
, fatal_signal_set
, &saved_mask
);
251 if (!element
->closed
)
253 ret
= close (element
->fd
);
255 element
->closed
= true;
262 asyncsafe_spin_unlock (&element
->lock
, &saved_mask
);
263 element
->done
= true;
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. */
273 asyncsafe_fclose_variant (struct closeable_fd
*element
, FILE *fp
,
274 int (*fclose_variant
) (FILE *))
276 if (fileno (fp
) != element
->fd
)
279 /* Flush buffered data first, to minimize the duration of the spin lock. */
286 asyncsafe_spin_lock (&element
->lock
, fatal_signal_set
, &saved_mask
);
287 if (!element
->closed
)
289 ret
= fclose_variant (fp
); /* invokes close (element->fd) */
291 element
->closed
= true;
298 asyncsafe_spin_unlock (&element
->lock
, &saved_mask
);
299 element
->done
= true;
305 /* The signal handler. It gets called asynchronously. */
306 static _GL_ASYNC_SAFE
void
307 cleanup_action (int sig _GL_UNUSED
)
311 /* First close all file descriptors to temporary files. */
313 gl_list_t fds
= descriptors
;
317 gl_list_iterator_t iter
;
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
;
334 gl_list_iterator_t iter
;
337 iter
= gl_list_iterator (files
);
338 while (gl_list_iterator_next (&iter
, &element
, NULL
))
340 const char *file
= (const char *) element
;
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
];
353 gl_list_iterator_t iter
;
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
;
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
;
372 gl_list_iterator_free (&iter
);
374 /* Then cleanup the temporary directory itself. */
375 rmdir (dir
->dirname
);
381 /* Initializes this facility. */
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. */
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
406 Should be called before the file ABSOLUTE_FILE_NAME is created. */
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
)
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
432 Should be called when the file ABSOLUTE_FILE_NAME could not be created. */
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
;
443 gl_list_node_t node
= gl_list_search (list
, absolute_file_name
);
446 char *old_string
= (char *) gl_list_node_value (list
, node
);
448 gl_list_remove_node (list
, node
);
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. */
459 do_unlink (const char *absolute_file_name
, bool cleanup_verbose
)
461 if (unlink (absolute_file_name
) < 0 && cleanup_verbose
465 _("cannot remove temporary file %s"), absolute_file_name
);
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
)
479 err
= do_unlink (absolute_file_name
, cleanup_verbose
);
480 unregister_temporary_file (absolute_file_name
);
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. */
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
;
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
];
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. */
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. */
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
558 if (old_array
!= NULL
)
559 free ((struct tempdir
**) old_array
);
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. */
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
,
577 tmpdir
->files
= gl_list_create_empty (GL_LINKEDHASH_LIST
,
578 string_equals
, string_hash
, NULL
,
581 /* Create the temporary directory. */
582 xtemplate
= (char *) xmalloca (PATH_MAX
);
583 if (path_search (xtemplate
, PATH_MAX
, parentdir
, prefix
, parentdir
== NULL
))
586 _("cannot find a temporary directory, try setting $TMPDIR"));
589 block_fatal_signals ();
590 tmpdirname
= mkdtemp (xtemplate
);
591 int saved_errno
= errno
;
592 if (tmpdirname
!= NULL
)
594 tmpdir
->dirname
= tmpdirname
;
597 unblock_fatal_signals ();
598 if (tmpdirname
== NULL
)
600 error (0, saved_errno
,
601 _("cannot create a temporary directory using template \"%s\""),
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
609 tmpdir
->dirname
= xstrdup (tmpdirname
);
610 if (mt
) gl_lock_unlock (dir_cleanup_list_lock
);
612 return (struct temp_dir
*) tmpdir
;
615 if (mt
) gl_lock_unlock (dir_cleanup_list_lock
);
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. */
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. */
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
;
654 node
= gl_list_search (list
, absolute_file_name
);
657 char *old_string
= (char *) gl_list_node_value (list
, node
);
659 gl_list_remove_node (list
, node
);
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. */
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
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
;
701 node
= gl_list_search (list
, absolute_dir_name
);
704 char *old_string
= (char *) gl_list_node_value (list
, node
);
706 gl_list_remove_node (list
, node
);
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. */
716 do_rmdir (const char *absolute_dir_name
, bool cleanup_verbose
)
718 if (rmdir (absolute_dir_name
) < 0 && cleanup_verbose
722 _("cannot remove temporary directory %s"), absolute_dir_name
);
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
)
736 err
= do_unlink (absolute_file_name
, dir
->cleanup_verbose
);
737 unregister_temp_file (dir
, absolute_file_name
);
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
)
750 err
= do_rmdir (absolute_dir_name
, dir
->cleanup_verbose
);
751 unregister_temp_subdir (dir
, absolute_dir_name
);
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
;
765 gl_list_iterator_t iter
;
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. */
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. */
795 gl_list_iterator_free (&iter
);
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
;
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
)
825 dir_cleanup_list
.tempdir_count
= i
;
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
);
835 if (mt
) gl_lock_unlock (dir_cleanup_list_lock
);
839 /* The user passed an invalid DIR argument. */
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. */
855 supports_delete_on_close ()
857 static int known
; /* 1 = yes, -1 = no, 0 = unknown */
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);
878 /* Register a file descriptor to be closed. */
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
,
890 struct closeable_fd
*element
= XMALLOC (struct closeable_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
)
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
);
921 fd
= open (file_name
, flags
, mode
);
925 unblock_fatal_signals ();
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. */
936 fopen_temp (const char *file_name
, const char *mode
, bool delete_on_close
)
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
);
956 freea (augmented_mode
);
961 fp
= fopen (file_name
, mode
);
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
);
974 unblock_fatal_signals ();
981 struct try_create_file_params
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
,
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
;
1014 int fd
= try_tempname (file_name_tmpl
, suffixlen
, ¶ms
, try_create_file
);
1016 int saved_errno
= errno
;
1021 register_temporary_file (file_name_tmpl
);
1023 unblock_fatal_signals ();
1024 errno
= saved_errno
;
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. */
1039 init_fatal_signal_set ();
1042 int saved_errno
= 0;
1044 bool mt
= gl_multithreaded ();
1046 if (mt
) gl_lock_lock (descriptors_lock
);
1048 gl_list_t list
= descriptors
;
1050 /* descriptors should already contain fd. */
1053 /* Search through the list, and clean it up on the fly. */
1055 gl_list_iterator_t iter
= gl_list_iterator (list
);
1057 gl_list_node_t node
;
1058 if (gl_list_iterator_next (&iter
, &elt
, &node
))
1061 struct closeable_fd
*element
= (struct closeable_fd
*) elt
;
1063 /* Close the file descriptor, avoiding races with the signal
1065 if (element
->fd
== fd
)
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
);
1080 free (element_to_free
);
1081 gl_list_remove_node (list
, node_to_free
);
1087 gl_list_iterator_free (&iter
);
1089 /* descriptors should already contain fd. */
1092 if (mt
) gl_lock_unlock (descriptors_lock
);
1094 errno
= saved_errno
;
1099 fclose_variant_temp (FILE *fp
, int (*fclose_variant
) (FILE *))
1101 int fd
= fileno (fp
);
1103 init_fatal_signal_set ();
1106 int saved_errno
= 0;
1108 bool mt
= gl_multithreaded ();
1110 if (mt
) gl_lock_lock (descriptors_lock
);
1112 gl_list_t list
= descriptors
;
1114 /* descriptors should already contain fd. */
1117 /* Search through the list, and clean it up on the fly. */
1119 gl_list_iterator_t iter
= gl_list_iterator (list
);
1121 gl_list_node_t node
;
1122 if (gl_list_iterator_next (&iter
, &elt
, &node
))
1125 struct closeable_fd
*element
= (struct closeable_fd
*) elt
;
1127 /* Close the file descriptor and the stream, avoiding races with the
1129 if (element
->fd
== fd
)
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
);
1144 free (element_to_free
);
1145 gl_list_remove_node (list
, node_to_free
);
1151 gl_list_iterator_free (&iter
);
1153 /* descriptors should have contained fd. */
1156 if (mt
) gl_lock_unlock (descriptors_lock
);
1158 errno
= saved_errno
;
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
);
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
);