You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

289 lines
8.0 KiB

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