Change copyright notice from GPLv2+ to GPLv3+.
[gnulib.git] / lib / tmpfile-safer.c
1 /* Invoke tmpfile, but avoid some glitches.
2    Copyright (C) 2006 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 #ifndef STDERR_FILENO
30 # define STDERR_FILENO 2
31 #endif
32
33 /* Like tmpfile, but do not return stdin, stdout, or stderr.
34
35    Remember that tmpfile can leave files behind if your program calls _exit,
36    so this function should not be mixed with the close_stdout module.  */
37
38 FILE *
39 tmpfile_safer (void)
40 {
41   FILE *fp = tmpfile ();
42
43   if (fp)
44     {
45       int fd = fileno (fp);
46
47       if (0 <= fd && fd <= STDERR_FILENO)
48         {
49           int f = dup_safer (fd);
50
51           if (f < 0)
52             {
53               int e = errno;
54               fclose (fp);
55               errno = e;
56               return NULL;
57             }
58
59           /* Keep the temporary file in binary mode, on platforms
60              where that matters.  */
61           if (fclose (fp) != 0
62               || ! (fp = fdopen (f, O_BINARY ? "wb+" : "w+")))
63             {
64               int e = errno;
65               close (f);
66               errno = e;
67               return NULL;
68             }
69         }
70     }
71
72   return fp;
73 }