ethereal to wireshark changes
[metze/wireshark/wip.git] / tempfile.c
1 /* tempfile.c
2  * Routines to create temporary files
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
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 #ifdef HAVE_WINDOWS_H
52 #include <windows.h>
53 #endif
54
55 #include "tempfile.h"
56
57 static const char *
58 setup_tmpdir(const char *dir)
59 {
60         size_t len = strlen(dir);
61         char *newdir;
62
63         /* Append path separator if necessary */
64         if (len != 0 && dir[len - 1] == G_DIR_SEPARATOR) {
65                 return dir;
66         }
67         else {
68                 newdir = g_malloc(len + 2);
69                 strcpy(newdir, dir);
70                 strcat(newdir, G_DIR_SEPARATOR_S);
71                 return newdir;
72         }
73 }
74
75 static int
76 try_tempfile(char *namebuf, int namebuflen, const char *dir, const char *pfx)
77 {
78         static const char suffix[] = "XXXXXXXXXX";
79         int namelen = strlen(dir) + strlen(pfx) + sizeof suffix;
80         int old_umask;
81         int tmp_fd;
82
83         if (namebuflen < namelen) {
84                 /* Stick in a truncated name, so that if this error is
85                    reported with the file name, you at least get
86                    something. */
87                 g_snprintf(namebuf, namebuflen, "%s%s%s", dir, pfx, suffix);
88                 errno = ENAMETOOLONG;
89                 return -1;
90         }
91         strcpy(namebuf, dir);
92         strcat(namebuf, pfx);
93         strcat(namebuf, suffix);
94
95         /* The Single UNIX Specification doesn't say that "mkstemp()"
96            creates the temporary file with mode rw-------, so we
97            won't assume that all UNIXes will do so; instead, we set
98            the umask to 0077 to take away all group and other
99            permissions, attempt to create the file, and then put
100            the umask back. */
101         old_umask = umask(0077);
102         tmp_fd = eth_mkstemp(namebuf);
103         umask(old_umask);
104         return tmp_fd;
105 }
106
107 static const char *tmpdir = NULL;
108 #ifdef _WIN32
109 static const char *temp = NULL;
110 #endif
111 static const char *E_tmpdir;
112
113 #ifndef P_tmpdir
114 #define P_tmpdir "/var/tmp"
115 #endif
116
117 int
118 create_tempfile(char *namebuf, int namebuflen, const char *pfx)
119 {
120         char *dir;
121         int fd;
122         static gboolean initialized;
123
124         if (!initialized) {
125                 if ((dir = getenv("TMPDIR")) != NULL)
126                         tmpdir = setup_tmpdir(dir);
127 #ifdef _WIN32
128                 if ((dir = getenv("TEMP")) != NULL)
129                         temp = setup_tmpdir(dir);
130 #endif
131
132                 E_tmpdir = setup_tmpdir(P_tmpdir);
133                 initialized = TRUE;
134         }
135
136         if (tmpdir != NULL) {
137                 fd = try_tempfile(namebuf, namebuflen, tmpdir, pfx);
138                 if (fd != -1)
139                         return fd;
140         }
141
142 #ifdef _WIN32
143         if (temp != NULL) {
144                 fd = try_tempfile(namebuf, namebuflen, temp, pfx);
145                 if (fd != -1)
146                         return fd;
147         }
148 #endif
149
150         fd = try_tempfile(namebuf, namebuflen, E_tmpdir, pfx);
151         if (fd != -1)
152                 return fd;
153
154         return try_tempfile(namebuf, namebuflen, G_DIR_SEPARATOR_S "tmp", pfx);
155 }