Have clean-temp register file open descriptors to temporary files.
[pspp] / 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 #ifndef uintptr_t
45 # define uintptr_t unsigned long
46 #endif
47
48
49 /* The use of 'volatile' in the types below (and ISO C 99 section 5.1.2.3.(5))
50    ensure that while constructing or modifying the data structures, the field
51    values are written to memory in the order of the C statements.  So the
52    signal handler can rely on these field values to be up to date.  */
53
54
55 /* Registry for a single temporary directory.
56    'struct temp_dir' from the public header file overlaps with this.  */
57 struct tempdir
58 {
59   /* The absolute pathname of the directory.  */
60   char * volatile dirname;
61   /* Whether errors during explicit cleanup are reported to standard error.  */
62   bool cleanup_verbose;
63   /* Absolute pathnames of subdirectories.  */
64   gl_list_t /* <char *> */ volatile subdirs;
65   /* Absolute pathnames of files.  */
66   gl_list_t /* <char *> */ volatile files;
67 };
68
69 /* List of all temporary directories.  */
70 static struct
71 {
72   struct tempdir * volatile * volatile tempdir_list;
73   size_t volatile tempdir_count;
74   size_t tempdir_allocated;
75 } cleanup_list /* = { NULL, 0, 0 } */;
76
77 /* List of all open file descriptors to temporary files.  */
78 static gl_list_t /* <int> */ volatile descriptors;
79
80
81 /* For the subdirs and for the files, we use a gl_list_t of type LINKEDHASH.
82    Why?  We need a data structure that
83
84      1) Can contain an arbitrary number of 'char *' values.  The strings
85         are compared via strcmp, not pointer comparison.
86      2) Has insertion and deletion operations that are fast: ideally O(1),
87         or possibly O(log n).  This is important for GNU sort, which may
88         create a large number of temporary files.
89      3) Allows iteration through all elements from within a signal handler.
90      4) May or may not allow duplicates.  It doesn't matter here, since
91         any file or subdir can only be removed once.
92
93    Criterion 1) would allow any gl_list_t or gl_oset_t implementation.
94
95    Criterion 2) leaves only GL_LINKEDHASH_LIST, GL_TREEHASH_LIST, or
96    GL_TREE_OSET.
97
98    Criterion 3) puts at disadvantage GL_TREEHASH_LIST and GL_TREE_OSET.
99    Namely, iteration through the elements of a binary tree requires access
100    to many ->left, ->right, ->parent pointers. However, the rebalancing
101    code for insertion and deletion in an AVL or red-black tree is so
102    complicated that we cannot assume that >left, ->right, ->parent pointers
103    are in a consistent state throughout these operations.  Therefore, to
104    avoid a crash in the signal handler, all destructive operations to the
105    lists would have to be protected by a
106        block_fatal_signals ();
107        ...
108        unblock_fatal_signals ();
109    pair.  Which causes extra system calls.
110
111    Criterion 3) would also discourage GL_ARRAY_LIST and GL_CARRAY_LIST,
112    if they were not already excluded.  Namely, these implementations use
113    xrealloc(), leaving a time window in which in the list->elements pointer
114    points to already deallocated memory.  To avoid a crash in the signal
115    handler at such a moment, all destructive operations would have to
116    protected by block/unblock_fatal_signals (), in this case too.
117
118    A list of type GL_LINKEDHASH_LIST without duplicates fulfills all
119    requirements:
120      2) Insertion and deletion are O(1) on average.
121      3) The gl_list_iterator, gl_list_iterator_next implementations do
122         not trigger memory allocations, nor other system calls, and are
123         therefore safe to be called from a signal handler.
124         Furthermore, since SIGNAL_SAFE_LIST is defined, the implementation
125         of the destructive functions ensures that the list structure is
126         safe to be traversed at any moment, even when interrupted by an
127         asynchronous signal.
128  */
129
130 /* String equality and hash code functions used by the lists.  */
131
132 static bool
133 string_equals (const void *x1, const void *x2)
134 {
135   const char *s1 = x1;
136   const char *s2 = x2;
137   return strcmp (s1, s2) == 0;
138 }
139
140 #define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
141
142 /* A hash function for NUL-terminated char* strings using
143    the method described by Bruno Haible.
144    See http://www.haible.de/bruno/hashfunc.html.  */
145 static size_t
146 string_hash (const void *x)
147 {
148   const char *s = x;
149   size_t h = 0;
150
151   for (; *s; s++)
152     h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
153
154   return h;
155 }
156
157
158 /* The signal handler.  It gets called asynchronously.  */
159 static void
160 cleanup ()
161 {
162   size_t i;
163
164   /* First close all file descriptors to temporary files.  */
165   {
166     gl_list_t fds = descriptors;
167
168     if (fds != NULL)
169       {
170         gl_list_iterator_t iter;
171         const void *element;
172
173         iter = gl_list_iterator (fds);
174         while (gl_list_iterator_next (&iter, &element, NULL))
175           {
176             int fd = (int) (uintptr_t) element;
177             close (fd);
178           }
179         gl_list_iterator_free (&iter);
180       }
181   }
182
183   for (i = 0; i < cleanup_list.tempdir_count; i++)
184     {
185       struct tempdir *dir = cleanup_list.tempdir_list[i];
186
187       if (dir != NULL)
188         {
189           gl_list_iterator_t iter;
190           const void *element;
191
192           /* First cleanup the files in the subdirectories.  */
193           iter = gl_list_iterator (dir->files);
194           while (gl_list_iterator_next (&iter, &element, NULL))
195             {
196               const char *file = (const char *) element;
197               unlink (file);
198             }
199           gl_list_iterator_free (&iter);
200
201           /* Then cleanup the subdirectories.  */
202           iter = gl_list_iterator (dir->subdirs);
203           while (gl_list_iterator_next (&iter, &element, NULL))
204             {
205               const char *subdir = (const char *) element;
206               rmdir (subdir);
207             }
208           gl_list_iterator_free (&iter);
209
210           /* Then cleanup the temporary directory itself.  */
211           rmdir (dir->dirname);
212         }
213     }
214 }
215
216 /* Create a temporary directory.
217    PREFIX is used as a prefix for the name of the temporary directory. It
218    should be short and still give an indication about the program.
219    PARENTDIR can be used to specify the parent directory; if NULL, a default
220    parent directory is used (either $TMPDIR or /tmp or similar).
221    CLEANUP_VERBOSE determines whether errors during explicit cleanup are
222    reported to standard error.
223    Return a fresh 'struct temp_dir' on success.  Upon error, an error message
224    is shown and NULL is returned.  */
225 struct temp_dir *
226 create_temp_dir (const char *prefix, const char *parentdir,
227                  bool cleanup_verbose)
228 {
229   struct tempdir * volatile *tmpdirp = NULL;
230   struct tempdir *tmpdir;
231   size_t i;
232   char *template;
233   char *tmpdirname;
234
235   /* See whether it can take the slot of an earlier temporary directory
236      already cleaned up.  */
237   for (i = 0; i < cleanup_list.tempdir_count; i++)
238     if (cleanup_list.tempdir_list[i] == NULL)
239       {
240         tmpdirp = &cleanup_list.tempdir_list[i];
241         break;
242       }
243   if (tmpdirp == NULL)
244     {
245       /* See whether the array needs to be extended.  */
246       if (cleanup_list.tempdir_count == cleanup_list.tempdir_allocated)
247         {
248           /* Note that we cannot use xrealloc(), because then the cleanup()
249              function could access an already deallocated array.  */
250           struct tempdir * volatile *old_array = cleanup_list.tempdir_list;
251           size_t old_allocated = cleanup_list.tempdir_allocated;
252           size_t new_allocated = 2 * cleanup_list.tempdir_allocated + 1;
253           struct tempdir * volatile *new_array =
254             (struct tempdir * volatile *)
255             xmalloc (new_allocated * sizeof (struct tempdir * volatile));
256
257           if (old_allocated == 0)
258             /* First use of this facility.  Register the cleanup handler.  */
259             at_fatal_signal (&cleanup);
260           else
261             {
262               /* Don't use memcpy() here, because memcpy takes non-volatile
263                  arguments and is therefore not guaranteed to complete all
264                  memory stores before the next statement.  */
265               size_t k;
266
267               for (k = 0; k < old_allocated; k++)
268                 new_array[k] = old_array[k];
269             }
270
271           cleanup_list.tempdir_list = new_array;
272           cleanup_list.tempdir_allocated = new_allocated;
273
274           /* Now we can free the old array.  */
275           if (old_array != NULL)
276             free ((struct tempdir **) old_array);
277         }
278
279       tmpdirp = &cleanup_list.tempdir_list[cleanup_list.tempdir_count];
280       /* Initialize *tmpdirp before incrementing tempdir_count, so that
281          cleanup() will skip this entry before it is fully initialized.  */
282       *tmpdirp = NULL;
283       cleanup_list.tempdir_count++;
284     }
285
286   /* Initialize a 'struct tempdir'.  */
287   tmpdir = (struct tempdir *) xmalloc (sizeof (struct tempdir));
288   tmpdir->dirname = NULL;
289   tmpdir->cleanup_verbose = cleanup_verbose;
290   tmpdir->subdirs = gl_list_create_empty (GL_LINKEDHASH_LIST,
291                                           string_equals, string_hash, false);
292   tmpdir->files = gl_list_create_empty (GL_LINKEDHASH_LIST,
293                                         string_equals, string_hash, false);
294
295   /* Create the temporary directory.  */
296   template = (char *) xallocsa (PATH_MAX);
297   if (path_search (template, PATH_MAX, parentdir, prefix, parentdir == NULL))
298     {
299       error (0, errno,
300              _("cannot find a temporary directory, try setting $TMPDIR"));
301       goto quit;
302     }
303   block_fatal_signals ();
304   tmpdirname = mkdtemp (template);
305   if (tmpdirname != NULL)
306     {
307       tmpdir->dirname = tmpdirname;
308       *tmpdirp = tmpdir;
309     }
310   unblock_fatal_signals ();
311   if (tmpdirname == NULL)
312     {
313       error (0, errno,
314              _("cannot create a temporary directory using template \"%s\""),
315              template);
316       goto quit;
317     }
318   /* Replace tmpdir->dirname with a copy that has indefinite extent.
319      We cannot do this inside the block_fatal_signals/unblock_fatal_signals
320      block because then the cleanup handler would not remove the directory
321      if xstrdup fails.  */
322   tmpdir->dirname = xstrdup (tmpdirname);
323   freesa (template);
324   return (struct temp_dir *) tmpdir;
325
326  quit:
327   freesa (template);
328   return NULL;
329 }
330
331 /* Register the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
332    needs to be removed before DIR can be removed.
333    Should be called before the file ABSOLUTE_FILE_NAME is created.  */
334 void
335 register_temp_file (struct temp_dir *dir,
336                     const char *absolute_file_name)
337 {
338   struct tempdir *tmpdir = (struct tempdir *)dir;
339
340   /* Add absolute_file_name to tmpdir->files, without duplicates.  */
341   if (gl_list_search (tmpdir->files, absolute_file_name) == NULL)
342     gl_list_add_first (tmpdir->files, xstrdup (absolute_file_name));
343 }
344
345 /* Unregister the given ABSOLUTE_FILE_NAME as being a file inside DIR, that
346    needs to be removed before DIR can be removed.
347    Should be called when the file ABSOLUTE_FILE_NAME could not be created.  */
348 void
349 unregister_temp_file (struct temp_dir *dir,
350                       const char *absolute_file_name)
351 {
352   struct tempdir *tmpdir = (struct tempdir *)dir;
353   gl_list_t list = tmpdir->files;
354   gl_list_node_t node;
355
356   node = gl_list_search (list, absolute_file_name);
357   if (node != NULL)
358     {
359       char *old_string = (char *) gl_list_node_value (list, node);
360
361       gl_list_remove_node (list, node);
362       free (old_string);
363     }
364 }
365
366 /* Register the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
367    that needs to be removed before DIR can be removed.
368    Should be called before the subdirectory ABSOLUTE_DIR_NAME is created.  */
369 void
370 register_temp_subdir (struct temp_dir *dir,
371                       const char *absolute_dir_name)
372 {
373   struct tempdir *tmpdir = (struct tempdir *)dir;
374
375   /* Add absolute_dir_name to tmpdir->subdirs, without duplicates.  */
376   if (gl_list_search (tmpdir->subdirs, absolute_dir_name) == NULL)
377     gl_list_add_first (tmpdir->subdirs, xstrdup (absolute_dir_name));
378 }
379
380 /* Unregister the given ABSOLUTE_DIR_NAME as being a subdirectory inside DIR,
381    that needs to be removed before DIR can be removed.
382    Should be called when the subdirectory ABSOLUTE_DIR_NAME could not be
383    created.  */
384 void
385 unregister_temp_subdir (struct temp_dir *dir,
386                         const char *absolute_dir_name)
387 {
388   struct tempdir *tmpdir = (struct tempdir *)dir;
389   gl_list_t list = tmpdir->subdirs;
390   gl_list_node_t node;
391
392   node = gl_list_search (list, absolute_dir_name);
393   if (node != NULL)
394     {
395       char *old_string = (char *) gl_list_node_value (list, node);
396
397       gl_list_remove_node (list, node);
398       free (old_string);
399     }
400 }
401
402 /* Remove a file, with optional error message.  */
403 static void
404 do_unlink (struct temp_dir *dir, const char *absolute_file_name)
405 {
406   if (unlink (absolute_file_name) < 0 && dir->cleanup_verbose
407       && errno != ENOENT)
408     error (0, errno, _("cannot remove temporary file %s"), absolute_file_name);
409 }
410
411 /* Remove a directory, with optional error message.  */
412 static void
413 do_rmdir (struct temp_dir *dir, const char *absolute_dir_name)
414 {
415   if (rmdir (absolute_dir_name) < 0 && dir->cleanup_verbose
416       && errno != ENOENT)
417     error (0, errno,
418            _("cannot remove temporary directory %s"), absolute_dir_name);
419 }
420
421 /* Remove the given ABSOLUTE_FILE_NAME and unregister it.  */
422 void
423 cleanup_temp_file (struct temp_dir *dir,
424                    const char *absolute_file_name)
425 {
426   do_unlink (dir, absolute_file_name);
427   unregister_temp_file (dir, absolute_file_name);
428 }
429
430 /* Remove the given ABSOLUTE_DIR_NAME and unregister it.  */
431 void
432 cleanup_temp_subdir (struct temp_dir *dir,
433                      const char *absolute_dir_name)
434 {
435   do_rmdir (dir, absolute_dir_name);
436   unregister_temp_subdir (dir, absolute_dir_name);
437 }
438
439 /* Remove all registered files and subdirectories inside DIR.  */
440 void
441 cleanup_temp_dir_contents (struct temp_dir *dir)
442 {
443   struct tempdir *tmpdir = (struct tempdir *)dir;
444   gl_list_t list;
445   gl_list_iterator_t iter;
446   const void *element;
447   gl_list_node_t node;
448
449   /* First cleanup the files in the subdirectories.  */
450   list = tmpdir->files;
451   iter = gl_list_iterator (list);
452   while (gl_list_iterator_next (&iter, &element, &node))
453     {
454       char *file = (char *) element;
455
456       do_unlink (dir, file);
457       gl_list_remove_node (list, node);
458       /* Now only we can free file.  */
459       free (file);
460     }
461   gl_list_iterator_free (&iter);
462
463   /* Then cleanup the subdirectories.  */
464   list = tmpdir->subdirs;
465   iter = gl_list_iterator (list);
466   while (gl_list_iterator_next (&iter, &element, &node))
467     {
468       char *subdir = (char *) element;
469
470       do_rmdir (dir, subdir);
471       gl_list_remove_node (list, node);
472       /* Now only we can free subdir.  */
473       free (subdir);
474     }
475   gl_list_iterator_free (&iter);
476 }
477
478 /* Remove all registered files and subdirectories inside DIR and DIR itself.
479    DIR cannot be used any more after this call.  */
480 void
481 cleanup_temp_dir (struct temp_dir *dir)
482 {
483   struct tempdir *tmpdir = (struct tempdir *)dir;
484   size_t i;
485
486   cleanup_temp_dir_contents (dir);
487   do_rmdir (dir, tmpdir->dirname);
488
489   for (i = 0; i < cleanup_list.tempdir_count; i++)
490     if (cleanup_list.tempdir_list[i] == tmpdir)
491       {
492         /* Remove cleanup_list.tempdir_list[i].  */
493         if (i + 1 == cleanup_list.tempdir_count)
494           {
495             while (i > 0 && cleanup_list.tempdir_list[i - 1] == NULL)
496               i--;
497             cleanup_list.tempdir_count = i;
498           }
499         else
500           cleanup_list.tempdir_list[i] = NULL;
501         /* Now only we can free the tmpdir->dirname and tmpdir itself.  */
502         free (tmpdir->dirname);
503         free (tmpdir);
504         return;
505       }
506
507   /* The user passed an invalid DIR argument.  */
508   abort ();
509 }
510
511
512 /* Register a file descriptor to be closed.  */
513 static void
514 register_fd (int fd)
515 {
516   if (descriptors == NULL)
517     descriptors = gl_list_create_empty (GL_LINKEDHASH_LIST, NULL, NULL, false);
518   gl_list_add_first (descriptors, (void *) (uintptr_t) fd);
519 }
520
521 /* Unregister a file descriptor to be closed.  */
522 static void
523 unregister_fd (int fd)
524 {
525   gl_list_t fds = descriptors;
526   gl_list_node_t node;
527
528   if (fds == NULL)
529     /* descriptors should already contain fd.  */
530     abort ();
531   node = gl_list_search (fds, (void *) (uintptr_t) fd);
532   if (node == NULL)
533     /* descriptors should already contain fd.  */
534     abort ();
535   gl_list_remove_node (fds, node);
536 }
537
538 /* Open a temporary file in a temporary directory.
539    Registers the resulting file descriptor to be closed.  */
540 int
541 open_temp (const char *file_name, int flags, mode_t mode)
542 {
543   int fd;
544   int saved_errno;
545
546   block_fatal_signals ();
547   fd = open (file_name, flags, mode);
548   saved_errno = errno;
549   if (fd >= 0)
550     register_fd (fd);
551   unblock_fatal_signals ();
552   errno = saved_errno;
553   return fd;
554 }
555
556 /* Open a temporary file in a temporary directory.
557    Registers the resulting file descriptor to be closed.  */
558 FILE *
559 fopen_temp (const char *file_name, const char *mode)
560 {
561   FILE *fp;
562   int saved_errno;
563
564   block_fatal_signals ();
565   fp = fopen (file_name, mode);
566   saved_errno = errno;
567   if (fp != NULL)
568     {
569       /* It is sufficient to register fileno (fp) instead of the entire fp,
570          because at cleanup time there is no need to do an fflush (fp); a
571          close (fileno (fp)) will be enough.  */
572       int fd = fileno (fp);
573       if (!(fd >= 0))
574         abort ();
575       register_fd (fd);
576     }
577   unblock_fatal_signals ();
578   errno = saved_errno;
579   return fp;
580 }
581
582 /* Close a temporary file in a temporary directory.
583    Unregisters the previously registered file descriptor.  */
584 int
585 close_temp (int fd)
586 {
587   if (fd >= 0)
588     {
589       /* No blocking of signals is needed here, since a double close of a
590          file descriptor is harmless.  */
591       int result = close (fd);
592       int saved_errno = errno;
593
594       /* No race condition here: we assume a single-threaded program, hence
595          fd cannot be re-opened here.  */
596
597       unregister_fd (fd);
598
599       errno = saved_errno;
600       return result;
601     }
602   else
603     return close (fd);
604 }
605
606 /* Close a temporary file in a temporary directory.
607    Unregisters the previously registered file descriptor.  */
608 int
609 fclose_temp (FILE *fp)
610 {
611   int fd = fileno (fp);
612   /* No blocking of signals is needed here, since a double close of a
613      file descriptor is harmless.  */
614   int result = fclose (fp);
615   int saved_errno = errno;
616
617   /* No race condition here: we assume a single-threaded program, hence
618      fd cannot be re-opened here.  */
619
620   unregister_fd (fd);
621
622   errno = saved_errno;
623   return result;
624 }
625
626 #if GNULIB_FWRITEERROR
627 /* Like fwriteerror.
628    Unregisters the previously registered file descriptor.  */
629 int
630 fwriteerror_temp (FILE *fp)
631 {
632   int fd = fileno (fp);
633   /* No blocking of signals is needed here, since a double close of a
634      file descriptor is harmless.  */
635   int result = fwriteerror (fp);
636   int saved_errno = errno;
637
638   /* No race condition here: we assume a single-threaded program, hence
639      fd cannot be re-opened here.  */
640
641   unregister_fd (fd);
642
643   errno = saved_errno;
644   return result;
645 }
646 #endif