verify: new macro 'assume'
[gnulib.git] / lib / tmpfile-safer.c
1 /* Invoke tmpfile, but avoid some glitches.
2    Copyright (C) 2006, 2009-2013 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8
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
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 /* Written by Eric Blake, based on ideas from Paul Eggert.  */
18
19 #include <config.h>
20
21 #include "stdio-safer.h"
22
23 #include <errno.h>
24 #include <unistd.h>
25 #include "unistd-safer.h"
26
27 #include "binary-io.h"
28
29 /* Like tmpfile, but do not return stdin, stdout, or stderr.
30
31    Remember that tmpfile can leave files behind if your program calls _exit,
32    so this function should not be mixed with the close_stdout module.  */
33
34 FILE *
35 tmpfile_safer (void)
36 {
37   FILE *fp = tmpfile ();
38
39   if (fp)
40     {
41       int fd = fileno (fp);
42
43       if (0 <= fd && fd <= STDERR_FILENO)
44         {
45           int f = dup_safer (fd);
46
47           if (f < 0)
48             {
49               int e = errno;
50               fclose (fp);
51               errno = e;
52               return NULL;
53             }
54
55           /* Keep the temporary file in binary mode, on platforms
56              where that matters.  */
57           if (fclose (fp) != 0
58               || ! (fp = fdopen (f, O_BINARY ? "wb+" : "w+")))
59             {
60               int e = errno;
61               close (f);
62               errno = e;
63               return NULL;
64             }
65         }
66     }
67
68   return fp;
69 }