Move create_tempfile() to tempfile.c out of util.c. This means dumpcap
[obnox/wireshark/wip.git] / tempfile.c
1 /* tempfile.c
2  * Routines to create temporary files
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <glib.h>
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <errno.h>
35
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39
40 #include "file_util.h"
41
42 #if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6)
43 #include <glib/gstdio.h>        /* available since GLib 2.6 only! */
44
45 /* GLib2.6 or above, using new wrapper functions */
46 #define eth_mkstemp g_mkstemp
47 #else
48 #define eth_mkstemp mkstemp
49 #endif
50
51 /*
52  * This has to come after the include of <pcap.h>, as the include of
53  * <pcap.h> might cause <winsock2.h> to be included, and if we've
54  * already included <winsock.h> as a result of including <windows.h>,
55  * we get a bunch of redefinitions.
56  */
57 #ifdef HAVE_WINDOWS_H
58 #include <windows.h>
59 #endif
60
61 #include "tempfile.h"
62
63 static const char *
64 setup_tmpdir(const char *dir)
65 {
66         size_t len = strlen(dir);
67         char *newdir;
68
69         /* Append path separator if necessary */
70         if (len != 0 && dir[len - 1] == G_DIR_SEPARATOR) {
71                 return dir;
72         }
73         else {
74                 newdir = g_malloc(len + 2);
75                 strcpy(newdir, dir);
76                 strcat(newdir, G_DIR_SEPARATOR_S);
77                 return newdir;
78         }
79 }
80
81 static int
82 try_tempfile(char *namebuf, int namebuflen, const char *dir, const char *pfx)
83 {
84         static const char suffix[] = "XXXXXXXXXX";
85         int namelen = strlen(dir) + strlen(pfx) + sizeof suffix;
86         int old_umask;
87         int tmp_fd;
88
89         if (namebuflen < namelen) {
90                 /* Stick in a truncated name, so that if this error is
91                    reported with the file name, you at least get
92                    something. */
93                 g_snprintf(namebuf, namebuflen, "%s%s%s", dir, pfx, suffix);
94                 errno = ENAMETOOLONG;
95                 return -1;
96         }
97         strcpy(namebuf, dir);
98         strcat(namebuf, pfx);
99         strcat(namebuf, suffix);
100
101         /* The Single UNIX Specification doesn't say that "mkstemp()"
102            creates the temporary file with mode rw-------, so we
103            won't assume that all UNIXes will do so; instead, we set
104            the umask to 0077 to take away all group and other
105            permissions, attempt to create the file, and then put
106            the umask back. */
107         old_umask = umask(0077);
108         tmp_fd = eth_mkstemp(namebuf);
109         umask(old_umask);
110         return tmp_fd;
111 }
112
113 static const char *tmpdir = NULL;
114 #ifdef _WIN32
115 static const char *temp = NULL;
116 #endif
117 static const char *E_tmpdir;
118
119 #ifndef P_tmpdir
120 #define P_tmpdir "/var/tmp"
121 #endif
122
123 int
124 create_tempfile(char *namebuf, int namebuflen, const char *pfx)
125 {
126         char *dir;
127         int fd;
128         static gboolean initialized;
129
130         if (!initialized) {
131                 if ((dir = getenv("TMPDIR")) != NULL)
132                         tmpdir = setup_tmpdir(dir);
133 #ifdef _WIN32
134                 if ((dir = getenv("TEMP")) != NULL)
135                         temp = setup_tmpdir(dir);
136 #endif
137
138                 E_tmpdir = setup_tmpdir(P_tmpdir);
139                 initialized = TRUE;
140         }
141
142         if (tmpdir != NULL) {
143                 fd = try_tempfile(namebuf, namebuflen, tmpdir, pfx);
144                 if (fd != -1)
145                         return fd;
146         }
147
148 #ifdef _WIN32
149         if (temp != NULL) {
150                 fd = try_tempfile(namebuf, namebuflen, temp, pfx);
151                 if (fd != -1)
152                         return fd;
153         }
154 #endif
155
156         fd = try_tempfile(namebuf, namebuflen, E_tmpdir, pfx);
157         if (fd != -1)
158                 return fd;
159
160         return try_tempfile(namebuf, namebuflen, G_DIR_SEPARATOR_S "tmp", pfx);
161 }