clean-temp.c 24 KB

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