1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2007 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Author: Zeev Suraski <zeev@zend.com> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: php_open_temporary_file.c,v 1.34.2.1.2.7 2007/02/07 21:07:31 tony2001 Exp $ */
20 :
21 : #include "php.h"
22 :
23 : #include <errno.h>
24 : #include <sys/types.h>
25 : #include <sys/stat.h>
26 : #include <fcntl.h>
27 :
28 : #ifdef PHP_WIN32
29 : #define O_RDONLY _O_RDONLY
30 : #include "win32/param.h"
31 : #include "win32/winutil.h"
32 : #elif defined(NETWARE)
33 : #ifdef USE_WINSOCK
34 : #include <novsock2.h>
35 : #else
36 : #include <sys/socket.h>
37 : #endif
38 : #include <sys/param.h>
39 : #else
40 : #include <sys/param.h>
41 : #include <sys/socket.h>
42 : #include <netinet/in.h>
43 : #include <netdb.h>
44 : #if HAVE_ARPA_INET_H
45 : #include <arpa/inet.h>
46 : #endif
47 : #endif
48 : #ifdef HAVE_SYS_TIME_H
49 : #include <sys/time.h>
50 : #endif
51 :
52 : #ifdef HAVE_SYS_FILE_H
53 : #include <sys/file.h>
54 : #endif
55 :
56 : #if !defined(P_tmpdir)
57 : #define P_tmpdir ""
58 : #endif
59 :
60 : /* {{{ php_do_open_temporary_file */
61 :
62 : /* Loosely based on a tempnam() implementation by UCLA */
63 :
64 : /*
65 : * Copyright (c) 1988, 1993
66 : * The Regents of the University of California. All rights reserved.
67 : *
68 : * Redistribution and use in source and binary forms, with or without
69 : * modification, are permitted provided that the following conditions
70 : * are met:
71 : * 1. Redistributions of source code must retain the above copyright
72 : * notice, this list of conditions and the following disclaimer.
73 : * 2. Redistributions in binary form must reproduce the above copyright
74 : * notice, this list of conditions and the following disclaimer in the
75 : * documentation and/or other materials provided with the distribution.
76 : * 3. All advertising materials mentioning features or use of this software
77 : * must display the following acknowledgement:
78 : * This product includes software developed by the University of
79 : * California, Berkeley and its contributors.
80 : * 4. Neither the name of the University nor the names of its contributors
81 : * may be used to endorse or promote products derived from this software
82 : * without specific prior written permission.
83 : *
84 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
85 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
86 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
87 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
88 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
89 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
90 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
91 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
92 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
93 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
94 : * SUCH DAMAGE.
95 : */
96 :
97 : static int php_do_open_temporary_file(const char *path, const char *pfx, char **opened_path_p TSRMLS_DC)
98 1 : {
99 : char *trailing_slash;
100 : char *opened_path;
101 1 : int path_len = 0;
102 1 : int fd = -1;
103 : #ifndef HAVE_MKSTEMP
104 : int open_flags = O_CREAT | O_TRUNC | O_RDWR
105 : #ifdef PHP_WIN32
106 : | _O_BINARY
107 : #endif
108 : ;
109 : #endif
110 :
111 1 : if (!path) {
112 0 : return -1;
113 : }
114 :
115 1 : path_len = strlen(path);
116 :
117 1 : if (!path_len || IS_SLASH(path[path_len - 1])) {
118 0 : trailing_slash = "";
119 : } else {
120 1 : trailing_slash = "/";
121 : }
122 :
123 1 : if (spprintf(&opened_path, 0, "%s%s%sXXXXXX", path, trailing_slash, pfx) >= MAXPATHLEN) {
124 0 : efree(opened_path);
125 0 : return -1;
126 : }
127 :
128 : #ifdef PHP_WIN32
129 : if (GetTempFileName(path, pfx, 0, opened_path)) {
130 : /* Some versions of windows set the temp file to be read-only,
131 : * which means that opening it will fail... */
132 : VCWD_CHMOD(opened_path, 0600);
133 : fd = VCWD_OPEN_MODE(opened_path, open_flags, 0600);
134 : }
135 : #elif defined(HAVE_MKSTEMP)
136 1 : fd = mkstemp(opened_path);
137 : #else
138 : if (mktemp(opened_path)) {
139 : fd = VCWD_OPEN(opened_path, open_flags);
140 : }
141 : #endif
142 1 : if (fd == -1 || !opened_path_p) {
143 0 : efree(opened_path);
144 : } else {
145 1 : *opened_path_p = opened_path;
146 : }
147 1 : return fd;
148 : }
149 : /* }}} */
150 :
151 : /* Cache the chosen temporary directory. */
152 : static char* temporary_directory;
153 :
154 : PHPAPI void php_shutdown_temporary_directory()
155 219 : {
156 219 : if (temporary_directory) {
157 1 : free(temporary_directory);
158 1 : temporary_directory = NULL;
159 : }
160 219 : }
161 :
162 : /*
163 : * Determine where to place temporary files.
164 : */
165 : PHPAPI const char* php_get_temporary_directory(void)
166 1 : {
167 : /* Did we determine the temporary directory already? */
168 1 : if (temporary_directory) {
169 0 : return temporary_directory;
170 : }
171 :
172 : #ifdef PHP_WIN32
173 : /* We can't count on the environment variables TEMP or TMP,
174 : * and so must make the Win32 API call to get the default
175 : * directory for temporary files. Note this call checks
176 : * the environment values TMP and TEMP (in order) first.
177 : */
178 : {
179 : char sTemp[MAX_PATH];
180 : DWORD n = GetTempPath(sizeof(sTemp),sTemp);
181 : assert(0 < n); /* should *never* fail! */
182 : temporary_directory = strdup(sTemp);
183 : return temporary_directory;
184 : }
185 : #else
186 : /* On Unix use the (usual) TMPDIR environment variable. */
187 : {
188 1 : char* s = getenv("TMPDIR");
189 1 : if (s) {
190 0 : temporary_directory = strdup(s);
191 0 : return temporary_directory;
192 : }
193 : }
194 : #ifdef P_tmpdir
195 : /* Use the standard default temporary directory. */
196 : if (P_tmpdir) {
197 1 : temporary_directory = strdup(P_tmpdir);
198 1 : return temporary_directory;
199 : }
200 : #endif
201 : /* Shouldn't ever(!) end up here ... last ditch default. */
202 : temporary_directory = strdup("/tmp");
203 : return temporary_directory;
204 : #endif
205 : }
206 :
207 : /* {{{ php_open_temporary_file
208 : *
209 : * Unlike tempnam(), the supplied dir argument takes precedence
210 : * over the TMPDIR environment variable
211 : * This function should do its best to return a file pointer to a newly created
212 : * unique file, on every platform.
213 : */
214 : PHPAPI int php_open_temporary_fd(const char *dir, const char *pfx, char **opened_path_p TSRMLS_DC)
215 1 : {
216 : int fd;
217 : const char *temp_dir;
218 :
219 1 : if (!pfx) {
220 0 : pfx = "tmp.";
221 : }
222 1 : if (opened_path_p) {
223 1 : *opened_path_p = NULL;
224 : }
225 :
226 1 : if (!dir || *dir == '\0') {
227 0 : def_tmp:
228 0 : temp_dir = php_get_temporary_directory();
229 :
230 0 : if (temp_dir && *temp_dir != '\0' && !php_check_open_basedir(temp_dir TSRMLS_CC)) {
231 0 : return php_do_open_temporary_file(temp_dir, pfx, opened_path_p TSRMLS_CC);
232 : } else {
233 0 : return -1;
234 : }
235 : }
236 :
237 : /* Try the directory given as parameter. */
238 1 : fd = php_do_open_temporary_file(dir, pfx, opened_path_p TSRMLS_CC);
239 1 : if (fd == -1) {
240 : /* Use default temporary directory. */
241 0 : goto def_tmp;
242 : }
243 1 : return fd;
244 : }
245 :
246 : PHPAPI FILE *php_open_temporary_file(const char *dir, const char *pfx, char **opened_path_p TSRMLS_DC)
247 0 : {
248 : FILE *fp;
249 0 : int fd = php_open_temporary_fd(dir, pfx, opened_path_p TSRMLS_CC);
250 :
251 0 : if (fd == -1) {
252 0 : return NULL;
253 : }
254 :
255 0 : fp = fdopen(fd, "r+b");
256 0 : if (fp == NULL) {
257 0 : close(fd);
258 : }
259 :
260 0 : return fp;
261 : }
262 : /* }}} */
263 :
264 : /*
265 : * Local variables:
266 : * tab-width: 4
267 : * c-basic-offset: 4
268 : * End:
269 : * vim600: sw=4 ts=4 fdm=marker
270 : * vim<600: sw=4 ts=4
271 : */
|