1 /* Temporary directories and temporary files with automatic cleanup.
2 Copyright (C) 2001, 2003, 2006 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2006.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
23 #include "clean-temp.h"
34 #include "fatal-signal.h"
40 #include "gl_linkedhash_list.h"
42 #if GNULIB_FWRITEERROR
43 # include "fwriteerror.h"
45 #if GNULIB_CLOSE_STREAM
46 # include "close-stream.h"
48 #if GNULIB_FCNTL_SAFER
51 #if GNULIB_FOPEN_SAFER
55 #define _(str) gettext (str)
57 /* GNU Hurd doesn't have PATH_MAX. */
60 # define PATH_MAX MAXPATHLEN
62 # define PATH_MAX 1024
67 # define uintptr_t unsigned long
71 /* The use of 'volatile' in the types below (and ISO C 99 section 5.1.2.3.(5))
72 ensure that while constructing or modifying the data structures, the field
73 values are written to memory in the order of the C statements. So the
74 signal handler can rely on these field values to be up to date. */
77 /* Registry for a single temporary directory.
78 'struct temp_dir' from the public header file overlaps with this. */
81 /* The absolute pathname of the directory. */
82 char * volatile dirname;
83 /* Whether errors during explicit cleanup are reported to standard error. */
85 /* Absolute pathnames of subdirectories. */
86 gl_list_t /* <char *> */ volatile subdirs;
87 /* Absolute pathnames of files. */
88 gl_list_t /* <char *> */ volatile files;
91 /* List of all temporary directories. */
94 struct tempdir * volatile * volatile tempdir_list;
95 size_t volatile tempdir_count;
96 size_t tempdir_allocated;
97 } cleanup_list /* = { NULL, 0, 0 } */;
99 /* List of all open file descriptors to temporary files. */
100 static gl_list_t /* <int> */ volatile descriptors;
103 /* For the subdirs and for the files, we use a gl_list_t of type LINKEDHASH.
104 Why? We need a data structure that
106 1) Can contain an arbitrary number of 'char *' values. The strings
107 are compared via strcmp, not pointer comparison.
108 2) Has insertion and deletion operations that are fast: ideally O(1),
109 or possibly O(log n). This is important for GNU sort, which may
110 create a large number of temporary files.
111 3) Allows iteration through all elements from within a signal handler.
112 4) May or may not allow duplicates. It doesn't matter here, since
113 any file or subdir can only be removed once.
115 Criterion 1) would allow any gl_list_t or gl_oset_t implementation.
117 Criterion 2) leaves only GL_LINKEDHASH_LIST, GL_TREEHASH_LIST, or
120 Criterion 3) puts at disadvantage GL_TREEHASH_LIST and GL_TREE_OSET.
121 Namely, iteration through the elements of a binary tree requires access
122 to many ->left, ->right, ->parent pointers. However, the rebalancing
123 code for insertion and deletion in an AVL or red-black tree is so
124 complicated that we cannot assume that >left, ->right, ->parent pointers
125 are in a consistent state throughout these operations. Therefore, to
126 avoid a crash in the signal handler, all destructive operations to the
127 lists would have to be protected by a
128 block_fatal_signals ();
130 unblock_fatal_signals ();
131 pair. Which causes extra system calls.
133 Criterion 3) would also discourage GL_ARRAY_LIST and GL_CARRAY_LIST,
134 if they were not already excluded. Namely, these implementations use
135 xrealloc(), leaving a time window in which in the list->elements pointer
136 points to already deallocated memory. To avoid a crash in the signal
137 handler at such a moment, all destructive operations would have to
138 protected by block/unblock_fatal_signals (), in this case too.
140 A list of type GL_LINKEDHASH_LIST without duplicates fulfills all
142 2) Insertion and deletion are O(1) on average.
143 3) The gl_list_iterator, gl_list_iterator_next implementations do
144 not trigger memory allocations, nor other system calls, and are
145 therefore safe to be called from a signal handler.
146 Furthermore, since SIGNAL_SAFE_LIST is defined, the implementation
147 of the destructive functions ensures that the list structure is
148 safe to be traversed at any moment, even when interrupted by an
152 /* String equality and hash code functions used by the lists. */
155 string_equals (const void *x1, const void *x2)
157 const char *s1 = (const char *) x1;
158 const char *s2 = (const char *) x2;
159 return strcmp (s1, s2) == 0;
162 #define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
164 /* A hash function for NUL-terminated char* strings using
165 the method described by Bruno Haible.
166 See http://www.haible.de/bruno/hashfunc.html. */
168 string_hash (const void *x)
170 const char *s = (const char *) x;
174 h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
180 /* The signal handler. It gets called asynchronously. */
186 /* First close all file descriptors to temporary files. */
188 gl_list_t fds = descriptors;
192 gl_list_iterator_t iter;
195 iter = gl_list_iterator (fds);
196 while (gl_list_iterator_next (&iter, &element, NULL))
198 int fd = (int) (uintptr_t) element;
201 gl_list_iterator_free (&iter);
205 for (i = 0; i < cleanup_list.tempdir_count; i++)
207 struct tempdir *dir = cleanup_list.tempdir_list[i];
211 gl_list_iterator_t iter;
214 /* First cleanup the files in the subdirectories. */
215 iter = gl_list_iterator (dir->files);
216 while (gl_list_iterator_next (&iter, &element, NULL))
218 const char *file = (const char *) element;
221 gl_list_iterator_free (&iter);
223 /* Then cleanup the subdirectories. */
224 iter = gl_list_iterator (dir->subdirs);
225 while (gl_list_iterator_next (&iter, &element, NULL))
227 const char *subdir = (const char *) element;
230 gl_list_iterator_free (&iter);
232 /* Then cleanup the temporary directory itself. */
233 rmdir (dir->dirname);
238 /* Create a temporary directory.
239 PREFIX is used as a prefix for the name of the temporary directory. It
240 should be short and still give an indication about the program.
241 PARENTDIR can be used to specify the parent directory; if NULL, a default
242 parent directory is used (either $TMPDIR or /tmp or similar).
243 CLEANUP_VERBOSE determines whether errors during explicit cleanup are
244 reported to standard error.
245 Return a fresh 'struct temp_dir' on success. Upon error, an error message
246 is shown and NULL is returned. */
248 create_temp_dir (const char *prefix, const char *parentdir,
249 bool cleanup_verbose)
251 struct tempdir * volatile *tmpdirp = NULL;
252 struct tempdir *tmpdir;
257 /* See whether it can take the slot of an earlier temporary directory
258 already cleaned up. */
259 for (i = 0; i < cleanup_list.tempdir_count; i++)
260 if (cleanup_list.tempdir_list[i] == NULL)
262 tmpdirp = &cleanup_list.tempdir_list[i];
267 /* See whether the array needs to be extended. */
268 if (cleanup_list.tempdir_count == cleanup_list.tempdir_allocated)
270 /* Note that we cannot use xrealloc(), because then the cleanup()
271 function could access an already deallocated array. */
272 struct tempdir * volatile *old_array = cleanup_list.tempdir_list;
273 size_t old_allocated = cleanup_list.tempdir_allocated;
274 size_t new_allocated = 2 * cleanup_list.tempdir_allocated + 1;
275 struct tempdir * volatile *new_array =
276 (struct tempdir * volatile *)
277 xmalloc (new_allocated * sizeof (struct tempdir * volatile));
279 if (old_allocated == 0)
280 /* First use of this facility. Register the cleanup handler. */
281 at_fatal_signal (&cleanup);
284 /* Don't use memcpy() here, because memcpy takes non-volatile
285 arguments and is therefore not guaranteed to complete all
286 memory stores before the next statement. */
289 for (k = 0; k < old_allocated; k++)
290 new_array[k] = old_array[k];
293 cleanup_list.tempdir_list = new_array;
294 cleanup_list.tempdir_allocated = new_allocated;
296 /* Now we can free the old array. */
297 if (old_array != NULL)
298 free ((struct tempdir **) old_array);
301 tmpdirp = &cleanup_list.tempdir_list[cleanup_list.tempdir_count];
302 /* Initialize *tmpdirp before incrementing tempdir_count, so that
303 cleanup() will skip this entry before it is fully initialized. */
305 cleanup_list.tempdir_count++;
308 /* Initialize a 'struct tempdir'. */
309 tmpdir = (struct tempdir *) xmalloc (sizeof (struct tempdir));
310 tmpdir->dirname = NULL;
311 tmpdir->cleanup_verbose = cleanup_verbose;
312 tmpdir->subdirs = gl_list_create_empty (GL_LINKEDHASH_LIST,
313 string_equals, string_hash, false);
314 tmpdir->files = gl_list_create_empty (GL_LINKEDHASH_LIST,
315 string_equals, string_hash, false);
317 /* Create the temporary directory. */
318 xtemplate = (char *) xallocsa (PATH_MAX);
319 if (path_search (xtemplate, PATH_MAX, parentdir, prefix, parentdir == NULL))
322 _("cannot find a temporary directory, try setting $TMPDIR"));
325 block_fatal_signals ();
326 tmpdirname = mkdtemp (xtemplate);
327 if (tmpdirname != NULL)
329 tmpdir->dirname = tmpdirname;
332 unblock_fatal_signals ();
333 if (tmpdirname == NULL)
336 _("cannot create a temporary directory using template \"%s\""),
340 /* Replace tmpdir->dirname with a copy that has indefinite extent.
341 We cannot do this inside the block_fatal_signals/unblock_fatal_signals
342 block because then the cleanup handler would not remove the directory
344 tmpdir->dirname = xstrdup (tmpdirname);
346 return (struct temp_dir *) tmpdir;
353 /* Register the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
354 needs to be removed before DIR can be removed.
355 Should be called before the file ABSOLUTE_FILE_NAME is created. */
357 register_temp_file (struct temp_dir *dir,
358 const char *absolute_file_name)
360 struct tempdir *tmpdir = (struct tempdir *)dir;
362 /* Add absolute_file_name to tmpdir->files, without duplicates. */
363 if (gl_list_search (tmpdir->files, absolute_file_name) == NULL)
364 gl_list_add_first (tmpdir->files, xstrdup (absolute_file_name));
367 /* Unregister the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
368 needs to be removed before DIR can be removed.
369 Should be called when the file ABSOLUTE_FILE_NAME could not be created. */
371 unregister_temp_file (struct temp_dir *dir,
372 const char *absolute_file_name)
374 struct tempdir *tmpdir = (struct tempdir *)dir;
375 gl_list_t list = tmpdir->files;
378 node = gl_list_search (list, absolute_file_name);
381 char *old_string = (char *) gl_list_node_value (list, node);
383 gl_list_remove_node (list, node);
388 /* Register the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
389 that needs to be removed before DIR can be removed.
390 Should be called before the subdirectory ABSOLUTE_DIR_NAME is created. */
392 register_temp_subdir (struct temp_dir *dir,
393 const char *absolute_dir_name)
395 struct tempdir *tmpdir = (struct tempdir *)dir;
397 /* Add absolute_dir_name to tmpdir->subdirs, without duplicates. */
398 if (gl_list_search (tmpdir->subdirs, absolute_dir_name) == NULL)
399 gl_list_add_first (tmpdir->subdirs, xstrdup (absolute_dir_name));
402 /* Unregister the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
403 that needs to be removed before DIR can be removed.
404 Should be called when the subdirectory ABSOLUTE_DIR_NAME could not be
407 unregister_temp_subdir (struct temp_dir *dir,
408 const char *absolute_dir_name)
410 struct tempdir *tmpdir = (struct tempdir *)dir;
411 gl_list_t list = tmpdir->subdirs;
414 node = gl_list_search (list, absolute_dir_name);
417 char *old_string = (char *) gl_list_node_value (list, node);
419 gl_list_remove_node (list, node);
424 /* Remove a file, with optional error message.
425 Return 0 upon success, or -1 if there was some problem. */
427 do_unlink (struct temp_dir *dir, const char *absolute_file_name)
429 if (unlink (absolute_file_name) < 0 && dir->cleanup_verbose
432 error (0, errno, _("cannot remove temporary file %s"), absolute_file_name);
438 /* Remove a directory, with optional error message.
439 Return 0 upon success, or -1 if there was some problem. */
441 do_rmdir (struct temp_dir *dir, const char *absolute_dir_name)
443 if (rmdir (absolute_dir_name) < 0 && dir->cleanup_verbose
447 _("cannot remove temporary directory %s"), absolute_dir_name);
453 /* Remove the given ABSOLUTE_FILE_NAME and unregister it.
454 Return 0 upon success, or -1 if there was some problem. */
456 cleanup_temp_file (struct temp_dir *dir,
457 const char *absolute_file_name)
461 err = do_unlink (dir, absolute_file_name);
462 unregister_temp_file (dir, absolute_file_name);
467 /* Remove the given ABSOLUTE_DIR_NAME and unregister it.
468 Return 0 upon success, or -1 if there was some problem. */
470 cleanup_temp_subdir (struct temp_dir *dir,
471 const char *absolute_dir_name)
475 err = do_rmdir (dir, absolute_dir_name);
476 unregister_temp_subdir (dir, absolute_dir_name);
481 /* Remove all registered files and subdirectories inside DIR.
482 Return 0 upon success, or -1 if there was some problem. */
484 cleanup_temp_dir_contents (struct temp_dir *dir)
486 struct tempdir *tmpdir = (struct tempdir *)dir;
489 gl_list_iterator_t iter;
493 /* First cleanup the files in the subdirectories. */
494 list = tmpdir->files;
495 iter = gl_list_iterator (list);
496 while (gl_list_iterator_next (&iter, &element, &node))
498 char *file = (char *) element;
500 err |= do_unlink (dir, file);
501 gl_list_remove_node (list, node);
502 /* Now only we can free file. */
505 gl_list_iterator_free (&iter);
507 /* Then cleanup the subdirectories. */
508 list = tmpdir->subdirs;
509 iter = gl_list_iterator (list);
510 while (gl_list_iterator_next (&iter, &element, &node))
512 char *subdir = (char *) element;
514 err |= do_rmdir (dir, subdir);
515 gl_list_remove_node (list, node);
516 /* Now only we can free subdir. */
519 gl_list_iterator_free (&iter);
524 /* Remove all registered files and subdirectories inside DIR and DIR itself.
525 DIR cannot be used any more after this call.
526 Return 0 upon success, or -1 if there was some problem. */
528 cleanup_temp_dir (struct temp_dir *dir)
530 struct tempdir *tmpdir = (struct tempdir *)dir;
534 err |= cleanup_temp_dir_contents (dir);
535 err |= do_rmdir (dir, tmpdir->dirname);
537 for (i = 0; i < cleanup_list.tempdir_count; i++)
538 if (cleanup_list.tempdir_list[i] == tmpdir)
540 /* Remove cleanup_list.tempdir_list[i]. */
541 if (i + 1 == cleanup_list.tempdir_count)
543 while (i > 0 && cleanup_list.tempdir_list[i - 1] == NULL)
545 cleanup_list.tempdir_count = i;
548 cleanup_list.tempdir_list[i] = NULL;
549 /* Now only we can free the tmpdir->dirname and tmpdir itself. */
550 free (tmpdir->dirname);
555 /* The user passed an invalid DIR argument. */
560 /* Register a file descriptor to be closed. */
564 if (descriptors == NULL)
565 descriptors = gl_list_create_empty (GL_LINKEDHASH_LIST, NULL, NULL, false);
566 gl_list_add_first (descriptors, (void *) (uintptr_t) fd);
569 /* Unregister a file descriptor to be closed. */
571 unregister_fd (int fd)
573 gl_list_t fds = descriptors;
577 /* descriptors should already contain fd. */
579 node = gl_list_search (fds, (void *) (uintptr_t) fd);
581 /* descriptors should already contain fd. */
583 gl_list_remove_node (fds, node);
586 /* Open a temporary file in a temporary directory.
587 Registers the resulting file descriptor to be closed. */
589 open_temp (const char *file_name, int flags, mode_t mode)
594 block_fatal_signals ();
595 fd = open (file_name, flags, mode); /* actually open or open_safer */
599 unblock_fatal_signals ();
604 /* Open a temporary file in a temporary directory.
605 Registers the resulting file descriptor to be closed. */
607 fopen_temp (const char *file_name, const char *mode)
612 block_fatal_signals ();
613 fp = fopen (file_name, mode); /* actually fopen or fopen_safer */
617 /* It is sufficient to register fileno (fp) instead of the entire fp,
618 because at cleanup time there is no need to do an fflush (fp); a
619 close (fileno (fp)) will be enough. */
620 int fd = fileno (fp);
625 unblock_fatal_signals ();
630 /* Close a temporary file in a temporary directory.
631 Unregisters the previously registered file descriptor. */
637 /* No blocking of signals is needed here, since a double close of a
638 file descriptor is harmless. */
639 int result = close (fd);
640 int saved_errno = errno;
642 /* No race condition here: we assume a single-threaded program, hence
643 fd cannot be re-opened here. */
654 /* Close a temporary file in a temporary directory.
655 Unregisters the previously registered file descriptor. */
657 fclose_temp (FILE *fp)
659 int fd = fileno (fp);
660 /* No blocking of signals is needed here, since a double close of a
661 file descriptor is harmless. */
662 int result = fclose (fp);
663 int saved_errno = errno;
665 /* No race condition here: we assume a single-threaded program, hence
666 fd cannot be re-opened here. */
674 #if GNULIB_FWRITEERROR
676 Unregisters the previously registered file descriptor. */
678 fwriteerror_temp (FILE *fp)
680 int fd = fileno (fp);
681 /* No blocking of signals is needed here, since a double close of a
682 file descriptor is harmless. */
683 int result = fwriteerror (fp);
684 int saved_errno = errno;
686 /* No race condition here: we assume a single-threaded program, hence
687 fd cannot be re-opened here. */
696 #if GNULIB_CLOSE_STREAM
697 /* Like close_stream.
698 Unregisters the previously registered file descriptor. */
700 close_stream_temp (FILE *fp)
702 int fd = fileno (fp);
703 /* No blocking of signals is needed here, since a double close of a
704 file descriptor is harmless. */
705 int result = close_stream (fp);
706 int saved_errno = errno;
708 /* No race condition here: we assume a single-threaded program, hence
709 fd cannot be re-opened here. */