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, &params, 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