Include <config.h> unconditionally.
[gnulib.git] / lib / clean-temp.c
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.
4
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)
8    any later version.
9
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.
14
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.  */
18
19
20 #include <config.h>
21
22 /* Specification.  */
23 #include "clean-temp.h"
24
25 #include <errno.h>
26 #include <limits.h>
27 #include <stdbool.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31
32 #include "error.h"
33 #include "fatal-signal.h"
34 #include "pathmax.h"
35 #include "tmpdir.h"
36 #include "mkdtemp.h"
37 #include "xalloc.h"
38 #include "xallocsa.h"
39 #include "gl_linkedhash_list.h"
40 #include "gettext.h"
41
42 #define _(str) gettext (str)
43
44
45 /* The use of 'volatile' in the types below (and ISO C 99 section 5.1.2.3.(5))
46    ensure that while constructing or modifying the data structures, the field
47    values are written to memory in the order of the C statements.  So the
48    signal handler can rely on these field values to be up to date.  */
49
50
51 /* Registry for a single temporary directory.
52    'struct temp_dir' from the public header file overlaps with this.  */
53 struct tempdir
54 {
55   /* The absolute pathname of the directory.  */
56   char * volatile dirname;
57   /* Whether errors during explicit cleanup are reported to standard error.  */
58   bool cleanup_verbose;
59   /* Absolute pathnames of subdirectories.  */
60   gl_list_t /* <char *> */ volatile subdirs;
61   /* Absolute pathnames of files.  */
62   gl_list_t /* <char *> */ volatile files;
63 };
64
65 /* List of all temporary directories.  */
66 static struct
67 {
68   struct tempdir * volatile * volatile tempdir_list;
69   size_t volatile tempdir_count;
70   size_t tempdir_allocated;
71 } cleanup_list /* = { NULL, 0, 0 } */;
72
73
74 /* For the subdirs and for the files, we use a gl_list_t of type LINKEDHASH.
75    Why?  We need a data structure that
76
77      1) Can contain an arbitrary number of 'char *' values.  The strings
78         are compared via strcmp, not pointer comparison.
79      2) Has insertion and deletion operations that are fast: ideally O(1),
80         or possibly O(log n).  This is important for GNU sort, which may
81         create a large number of temporary files.
82      3) Allows iteration through all elements from within a signal handler.
83      4) May or may not allow duplicates.  It doesn't matter here, since
84         any file or subdir can only be removed once.
85
86    Criterion 1) would allow any gl_list_t or gl_oset_t implementation.
87
88    Criterion 2) leaves only GL_LINKEDHASH_LIST, GL_TREEHASH_LIST, or
89    GL_TREE_OSET.
90
91    Criterion 3) puts at disadvantage GL_TREEHASH_LIST and GL_TREE_OSET.
92    Namely, iteration through the elements of a binary tree requires access
93    to many ->left, ->right, ->parent pointers. However, the rebalancing
94    code for insertion and deletion in an AVL or red-black tree is so
95    complicated that we cannot assume that >left, ->right, ->parent pointers
96    are in a consistent state throughout these operations.  Therefore, to
97    avoid a crash in the signal handler, all destructive operations to the
98    lists would have to be protected by a
99        block_fatal_signals ();
100        ...
101        unblock_fatal_signals ();
102    pair.  Which causes extra system calls.
103
104    Criterion 3) would also discourage GL_ARRAY_LIST and GL_CARRAY_LIST,
105    if they were not already excluded.  Namely, these implementations use
106    xrealloc(), leaving a time window in which in the list->elements pointer
107    points to already deallocated memory.  To avoid a crash in the signal
108    handler at such a moment, all destructive operations would have to
109    protected by block/unblock_fatal_signals (), in this case too.
110
111    A list of type GL_LINKEDHASH_LIST without duplicates fulfills all
112    requirements:
113      2) Insertion and deletion are O(1) on average.
114      3) The gl_list_iterator, gl_list_iterator_next implementations do
115         not trigger memory allocations, nor other system calls, and are
116         therefore safe to be called from a signal handler.
117         Furthermore, since SIGNAL_SAFE_LIST is defined, the implementation
118         of the destructive functions ensures that the list structure is
119         safe to be traversed at any moment, even when interrupted by an
120         asynchronous signal.
121  */
122
123 /* String equality and hash code functions used by the lists.  */
124
125 static bool
126 string_equals (const void *x1, const void *x2)
127 {
128   const char *s1 = x1;
129   const char *s2 = x2;
130   return strcmp (s1, s2) == 0;
131 }
132
133 #define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
134
135 /* A hash function for NUL-terminated char* strings using
136    the method described by Bruno Haible.
137    See http://www.haible.de/bruno/hashfunc.html.  */
138 static size_t
139 string_hash (const void *x)
140 {
141   const char *s = x;
142   size_t h = 0;
143
144   for (; *s; s++)
145     h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
146
147   return h;
148 }
149
150
151 /* The signal handler.  It gets called asynchronously.  */
152 static void
153 cleanup ()
154 {
155   size_t i;
156
157   for (i = 0; i < cleanup_list.tempdir_count; i++)
158     {
159       struct tempdir *dir = cleanup_list.tempdir_list[i];
160
161       if (dir != NULL)
162         {
163           gl_list_iterator_t iter;
164           const void *element;
165
166           /* First cleanup the files in the subdirectories.  */
167           iter = gl_list_iterator (dir->files);
168           while (gl_list_iterator_next (&iter, &element, NULL))
169             {
170               const char *file = (const char *) element;
171               unlink (file);
172             }
173           gl_list_iterator_free (&iter);
174
175           /* Then cleanup the subdirectories.  */
176           iter = gl_list_iterator (dir->subdirs);
177           while (gl_list_iterator_next (&iter, &element, NULL))
178             {
179               const char *subdir = (const char *) element;
180               rmdir (subdir);
181             }
182           gl_list_iterator_free (&iter);
183
184           /* Then cleanup the temporary directory itself.  */
185           rmdir (dir->dirname);
186         }
187     }
188 }
189
190 /* Create a temporary directory.
191    PREFIX is used as a prefix for the name of the temporary directory. It
192    should be short and still give an indication about the program.
193    PARENTDIR can be used to specify the parent directory; if NULL, a default
194    parent directory is used (either $TMPDIR or /tmp or similar).
195    CLEANUP_VERBOSE determines whether errors during explicit cleanup are
196    reported to standard error.
197    Return a fresh 'struct temp_dir' on success.  Upon error, an error message
198    is shown and NULL is returned.  */
199 struct temp_dir *
200 create_temp_dir (const char *prefix, const char *parentdir,
201                  bool cleanup_verbose)
202 {
203   struct tempdir * volatile *tmpdirp = NULL;
204   struct tempdir *tmpdir;
205   size_t i;
206   char *template;
207   char *tmpdirname;
208
209   /* See whether it can take the slot of an earlier temporary directory
210      already cleaned up.  */
211   for (i = 0; i < cleanup_list.tempdir_count; i++)
212     if (cleanup_list.tempdir_list[i] == NULL)
213       {
214         tmpdirp = &cleanup_list.tempdir_list[i];
215         break;
216       }
217   if (tmpdirp == NULL)
218     {
219       /* See whether the array needs to be extended.  */
220       if (cleanup_list.tempdir_count == cleanup_list.tempdir_allocated)
221         {
222           /* Note that we cannot use xrealloc(), because then the cleanup()
223              function could access an already deallocated array.  */
224           struct tempdir * volatile *old_array = cleanup_list.tempdir_list;
225           size_t old_allocated = cleanup_list.tempdir_allocated;
226           size_t new_allocated = 2 * cleanup_list.tempdir_allocated + 1;
227           struct tempdir * volatile *new_array =
228             (struct tempdir * volatile *)
229             xmalloc (new_allocated * sizeof (struct tempdir * volatile));
230
231           if (old_allocated == 0)
232             /* First use of this facility.  Register the cleanup handler.  */
233             at_fatal_signal (&cleanup);
234           else
235             {
236               /* Don't use memcpy() here, because memcpy takes non-volatile
237                  arguments and is therefore not guaranteed to complete all
238                  memory stores before the next statement.  */
239               size_t k;
240
241               for (k = 0; k < old_allocated; k++)
242                 new_array[k] = old_array[k];
243             }
244
245           cleanup_list.tempdir_list = new_array;
246           cleanup_list.tempdir_allocated = new_allocated;
247
248           /* Now we can free the old array.  */
249           if (old_array != NULL)
250             free ((struct tempdir **) old_array);
251         }
252
253       tmpdirp = &cleanup_list.tempdir_list[cleanup_list.tempdir_count];
254       /* Initialize *tmpdirp before incrementing tempdir_count, so that
255          cleanup() will skip this entry before it is fully initialized.  */
256       *tmpdirp = NULL;
257       cleanup_list.tempdir_count++;
258     }
259
260   /* Initialize a 'struct tempdir'.  */
261   tmpdir = (struct tempdir *) xmalloc (sizeof (struct tempdir));
262   tmpdir->dirname = NULL;
263   tmpdir->cleanup_verbose = cleanup_verbose;
264   tmpdir->subdirs = gl_list_create_empty (GL_LINKEDHASH_LIST,
265                                           string_equals, string_hash, false);
266   tmpdir->files = gl_list_create_empty (GL_LINKEDHASH_LIST,
267                                         string_equals, string_hash, false);
268
269   /* Create the temporary directory.  */
270   template = (char *) xallocsa (PATH_MAX);
271   if (path_search (template, PATH_MAX, parentdir, prefix, parentdir == NULL))
272     {
273       error (0, errno,
274              _("cannot find a temporary directory, try setting $TMPDIR"));
275       goto quit;
276     }
277   block_fatal_signals ();
278   tmpdirname = mkdtemp (template);
279   if (tmpdirname != NULL)
280     {
281       tmpdir->dirname = tmpdirname;
282       *tmpdirp = tmpdir;
283     }
284   unblock_fatal_signals ();
285   if (tmpdirname == NULL)
286     {
287       error (0, errno,
288              _("cannot create a temporary directory using template \"%s\""),
289              template);
290       goto quit;
291     }
292   /* Replace tmpdir->dirname with a copy that has indefinite extent.
293      We cannot do this inside the block_fatal_signals/unblock_fatal_signals
294      block because then the cleanup handler would not remove the directory
295      if xstrdup fails.  */
296   tmpdir->dirname = xstrdup (tmpdirname);
297   freesa (template);
298   return (struct temp_dir *) tmpdir;
299
300  quit:
301   freesa (template);
302   return NULL;
303 }
304
305 /* Register the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
306    needs to be removed before DIR can be removed.
307    Should be called before the file ABSOLUTE_FILE_NAME is created.  */
308 void
309 register_temp_file (struct temp_dir *dir,
310                     const char *absolute_file_name)
311 {
312   struct tempdir *tmpdir = (struct tempdir *)dir;
313
314   /* Add absolute_file_name to tmpdir->files, without duplicates.  */
315   if (gl_list_search (tmpdir->files, absolute_file_name) == NULL)
316     gl_list_add_first (tmpdir->files, xstrdup (absolute_file_name));
317 }
318
319 /* Unregister the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
320    needs to be removed before DIR can be removed.
321    Should be called when the file ABSOLUTE_FILE_NAME could not be created.  */
322 void
323 unregister_temp_file (struct temp_dir *dir,
324                       const char *absolute_file_name)
325 {
326   struct tempdir *tmpdir = (struct tempdir *)dir;
327   gl_list_t list = tmpdir->files;
328   gl_list_node_t node;
329
330   node = gl_list_search (list, absolute_file_name);
331   if (node != NULL)
332     {
333       char *old_string = (char *) gl_list_node_value (list, node);
334
335       gl_list_remove_node (list, node);
336       free (old_string);
337     }
338 }
339
340 /* Register the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
341    that needs to be removed before DIR can be removed.
342    Should be called before the subdirectory ABSOLUTE_DIR_NAME is created.  */
343 void
344 register_temp_subdir (struct temp_dir *dir,
345                       const char *absolute_dir_name)
346 {
347   struct tempdir *tmpdir = (struct tempdir *)dir;
348
349   /* Add absolute_dir_name to tmpdir->subdirs, without duplicates.  */
350   if (gl_list_search (tmpdir->subdirs, absolute_dir_name) == NULL)
351     gl_list_add_first (tmpdir->subdirs, xstrdup (absolute_dir_name));
352 }
353
354 /* Unregister the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
355    that needs to be removed before DIR can be removed.
356    Should be called when the subdirectory ABSOLUTE_DIR_NAME could not be
357    created.  */
358 void
359 unregister_temp_subdir (struct temp_dir *dir,
360                         const char *absolute_dir_name)
361 {
362   struct tempdir *tmpdir = (struct tempdir *)dir;
363   gl_list_t list = tmpdir->subdirs;
364   gl_list_node_t node;
365
366   node = gl_list_search (list, absolute_dir_name);
367   if (node != NULL)
368     {
369       char *old_string = (char *) gl_list_node_value (list, node);
370
371       gl_list_remove_node (list, node);
372       free (old_string);
373     }
374 }
375
376 /* Remove a file, with optional error message.  */
377 static void
378 do_unlink (struct temp_dir *dir, const char *absolute_file_name)
379 {
380   if (unlink (absolute_file_name) < 0 && dir->cleanup_verbose
381       && errno != ENOENT)
382     error (0, errno, _("cannot remove temporary file %s"), absolute_file_name);
383 }
384
385 /* Remove a directory, with optional error message.  */
386 static void
387 do_rmdir (struct temp_dir *dir, const char *absolute_dir_name)
388 {
389   if (rmdir (absolute_dir_name) < 0 && dir->cleanup_verbose
390       && errno != ENOENT)
391     error (0, errno,
392            _("cannot remove temporary directory %s"), absolute_dir_name);
393 }
394
395 /* Remove the given ABSOLUTE_FILE_NAME and unregister it.  */
396 void
397 cleanup_temp_file (struct temp_dir *dir,
398                    const char *absolute_file_name)
399 {
400   do_unlink (dir, absolute_file_name);
401   unregister_temp_file (dir, absolute_file_name);
402 }
403
404 /* Remove the given ABSOLUTE_DIR_NAME and unregister it.  */
405 void
406 cleanup_temp_subdir (struct temp_dir *dir,
407                      const char *absolute_dir_name)
408 {
409   do_rmdir (dir, absolute_dir_name);
410   unregister_temp_subdir (dir, absolute_dir_name);
411 }
412
413 /* Remove all registered files and subdirectories inside DIR.  */
414 void
415 cleanup_temp_dir_contents (struct temp_dir *dir)
416 {
417   struct tempdir *tmpdir = (struct tempdir *)dir;
418   gl_list_t list;
419   gl_list_iterator_t iter;
420   const void *element;
421   gl_list_node_t node;
422
423   /* First cleanup the files in the subdirectories.  */
424   list = tmpdir->files;
425   iter = gl_list_iterator (list);
426   while (gl_list_iterator_next (&iter, &element, &node))
427     {
428       char *file = (char *) element;
429
430       do_unlink (dir, file);
431       gl_list_remove_node (list, node);
432       /* Now only we can free file.  */
433       free (file);
434     }
435   gl_list_iterator_free (&iter);
436
437   /* Then cleanup the subdirectories.  */
438   list = tmpdir->subdirs;
439   iter = gl_list_iterator (list);
440   while (gl_list_iterator_next (&iter, &element, &node))
441     {
442       char *subdir = (char *) element;
443
444       do_rmdir (dir, subdir);
445       gl_list_remove_node (list, node);
446       /* Now only we can free subdir.  */
447       free (subdir);
448     }
449   gl_list_iterator_free (&iter);
450 }
451
452 /* Remove all registered files and subdirectories inside DIR and DIR itself.
453    DIR cannot be used any more after this call.  */
454 void
455 cleanup_temp_dir (struct temp_dir *dir)
456 {
457   struct tempdir *tmpdir = (struct tempdir *)dir;
458   size_t i;
459
460   cleanup_temp_dir_contents (dir);
461   do_rmdir (dir, tmpdir->dirname);
462
463   for (i = 0; i < cleanup_list.tempdir_count; i++)
464     if (cleanup_list.tempdir_list[i] == tmpdir)
465       {
466         /* Remove cleanup_list.tempdir_list[i].  */
467         if (i + 1 == cleanup_list.tempdir_count)
468           {
469             while (i > 0 && cleanup_list.tempdir_list[i - 1] == NULL)
470               i--;
471             cleanup_list.tempdir_count = i;
472           }
473         else
474           cleanup_list.tempdir_list[i] = NULL;
475         /* Now only we can free the tmpdir->dirname and tmpdir itself.  */
476         free (tmpdir->dirname);
477         free (tmpdir);
478         return;
479       }
480
481   /* The user passed an invalid DIR argument.  */
482   abort ();
483 }