1
1
/* Temporary directories and temporary files with automatic cleanup.
2
Copyright (C) 2001, 2003, 2006-2007 Free Software Foundation, Inc.
2
Copyright (C) 2001, 2003, 2006-2007, 2009-2010 Free Software Foundation,
3
4
Written by Bruno Haible <bruno@clisp.org>, 2006.
5
6
This program is free software: you can redistribute it and/or modify
202
gl_list_iterator_t iter;
204
gl_list_iterator_t iter;
205
iter = gl_list_iterator (fds);
206
while (gl_list_iterator_next (&iter, &element, NULL))
208
int fd = (int) (uintptr_t) element;
211
gl_list_iterator_free (&iter);
207
iter = gl_list_iterator (fds);
208
while (gl_list_iterator_next (&iter, &element, NULL))
210
int fd = (int) (uintptr_t) element;
213
gl_list_iterator_free (&iter);
217
219
struct tempdir *dir = cleanup_list.tempdir_list[i];
221
gl_list_iterator_t iter;
224
/* First cleanup the files in the subdirectories. */
225
iter = gl_list_iterator (dir->files);
226
while (gl_list_iterator_next (&iter, &element, NULL))
228
const char *file = (const char *) element;
231
gl_list_iterator_free (&iter);
233
/* Then cleanup the subdirectories. */
234
iter = gl_list_iterator (dir->subdirs);
235
while (gl_list_iterator_next (&iter, &element, NULL))
237
const char *subdir = (const char *) element;
240
gl_list_iterator_free (&iter);
242
/* Then cleanup the temporary directory itself. */
243
rmdir (dir->dirname);
223
gl_list_iterator_t iter;
226
/* First cleanup the files in the subdirectories. */
227
iter = gl_list_iterator (dir->files);
228
while (gl_list_iterator_next (&iter, &element, NULL))
230
const char *file = (const char *) element;
233
gl_list_iterator_free (&iter);
235
/* Then cleanup the subdirectories. */
236
iter = gl_list_iterator (dir->subdirs);
237
while (gl_list_iterator_next (&iter, &element, NULL))
239
const char *subdir = (const char *) element;
242
gl_list_iterator_free (&iter);
244
/* Then cleanup the temporary directory itself. */
245
rmdir (dir->dirname);
269
271
for (i = 0; i < cleanup_list.tempdir_count; i++)
270
272
if (cleanup_list.tempdir_list[i] == NULL)
272
tmpdirp = &cleanup_list.tempdir_list[i];
274
tmpdirp = &cleanup_list.tempdir_list[i];
275
277
if (tmpdirp == NULL)
277
279
/* See whether the array needs to be extended. */
278
280
if (cleanup_list.tempdir_count == cleanup_list.tempdir_allocated)
280
/* Note that we cannot use xrealloc(), because then the cleanup()
281
function could access an already deallocated array. */
282
struct tempdir * volatile *old_array = cleanup_list.tempdir_list;
283
size_t old_allocated = cleanup_list.tempdir_allocated;
284
size_t new_allocated = 2 * cleanup_list.tempdir_allocated + 1;
285
struct tempdir * volatile *new_array =
286
XNMALLOC (new_allocated, struct tempdir * volatile);
288
if (old_allocated == 0)
289
/* First use of this facility. Register the cleanup handler. */
290
at_fatal_signal (&cleanup);
293
/* Don't use memcpy() here, because memcpy takes non-volatile
294
arguments and is therefore not guaranteed to complete all
295
memory stores before the next statement. */
298
for (k = 0; k < old_allocated; k++)
299
new_array[k] = old_array[k];
302
cleanup_list.tempdir_list = new_array;
303
cleanup_list.tempdir_allocated = new_allocated;
305
/* Now we can free the old array. */
306
if (old_array != NULL)
307
free ((struct tempdir **) old_array);
282
/* Note that we cannot use xrealloc(), because then the cleanup()
283
function could access an already deallocated array. */
284
struct tempdir * volatile *old_array = cleanup_list.tempdir_list;
285
size_t old_allocated = cleanup_list.tempdir_allocated;
286
size_t new_allocated = 2 * cleanup_list.tempdir_allocated + 1;
287
struct tempdir * volatile *new_array =
288
XNMALLOC (new_allocated, struct tempdir * volatile);
290
if (old_allocated == 0)
291
/* First use of this facility. Register the cleanup handler. */
292
at_fatal_signal (&cleanup);
295
/* Don't use memcpy() here, because memcpy takes non-volatile
296
arguments and is therefore not guaranteed to complete all
297
memory stores before the next statement. */
300
for (k = 0; k < old_allocated; k++)
301
new_array[k] = old_array[k];
304
cleanup_list.tempdir_list = new_array;
305
cleanup_list.tempdir_allocated = new_allocated;
307
/* Now we can free the old array. */
308
if (old_array != NULL)
309
free ((struct tempdir **) old_array);
310
312
tmpdirp = &cleanup_list.tempdir_list[cleanup_list.tempdir_count];
311
313
/* Initialize *tmpdirp before incrementing tempdir_count, so that
312
cleanup() will skip this entry before it is fully initialized. */
314
cleanup() will skip this entry before it is fully initialized. */
314
316
cleanup_list.tempdir_count++;
319
321
tmpdir->dirname = NULL;
320
322
tmpdir->cleanup_verbose = cleanup_verbose;
321
323
tmpdir->subdirs = gl_list_create_empty (GL_LINKEDHASH_LIST,
322
string_equals, string_hash, NULL,
324
string_equals, string_hash, NULL,
324
326
tmpdir->files = gl_list_create_empty (GL_LINKEDHASH_LIST,
325
string_equals, string_hash, NULL,
327
string_equals, string_hash, NULL,
328
330
/* Create the temporary directory. */
329
331
xtemplate = (char *) xmalloca (PATH_MAX);
330
332
if (path_search (xtemplate, PATH_MAX, parentdir, prefix, parentdir == NULL))
333
_("cannot find a temporary directory, try setting $TMPDIR"));
335
_("cannot find a temporary directory, try setting $TMPDIR"));
336
338
block_fatal_signals ();
548
550
for (i = 0; i < cleanup_list.tempdir_count; i++)
549
551
if (cleanup_list.tempdir_list[i] == tmpdir)
551
/* Remove cleanup_list.tempdir_list[i]. */
552
if (i + 1 == cleanup_list.tempdir_count)
554
while (i > 0 && cleanup_list.tempdir_list[i - 1] == NULL)
556
cleanup_list.tempdir_count = i;
559
cleanup_list.tempdir_list[i] = NULL;
560
/* Now only we can free the tmpdir->dirname and tmpdir itself. */
561
free (tmpdir->dirname);
553
/* Remove cleanup_list.tempdir_list[i]. */
554
if (i + 1 == cleanup_list.tempdir_count)
556
while (i > 0 && cleanup_list.tempdir_list[i - 1] == NULL)
558
cleanup_list.tempdir_count = i;
561
cleanup_list.tempdir_list[i] = NULL;
562
/* Now only we can free the tmpdir->dirname and tmpdir itself. */
563
free (tmpdir->dirname);
566
568
/* The user passed an invalid DIR argument. */