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