root/main/php_open_temporary_file.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_do_open_temporary_file
  2. php_get_temporary_directory
  3. php_open_temporary_fd_ex
  4. php_open_temporary_fd
  5. php_open_temporary_file

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 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$ */
  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, zend_string **opened_path_p)
  98 {
  99         char *trailing_slash;
 100         char opened_path[MAXPATHLEN];
 101         char cwd[MAXPATHLEN];
 102         cwd_state new_state;
 103         int fd = -1;
 104 #ifndef HAVE_MKSTEMP
 105         int open_flags = O_CREAT | O_TRUNC | O_RDWR
 106 #ifdef PHP_WIN32
 107                 | _O_BINARY
 108 #endif
 109                 ;
 110 #endif
 111 
 112         if (!path || !path[0]) {
 113                 return -1;
 114         }
 115 
 116 #ifdef PHP_WIN32
 117         if (!php_win32_check_trailing_space(pfx, (const int)strlen(pfx))) {
 118                 SetLastError(ERROR_INVALID_NAME);
 119                 return -1;
 120         }
 121 #endif
 122 
 123         if (!VCWD_GETCWD(cwd, MAXPATHLEN)) {
 124                 cwd[0] = '\0';
 125         }
 126 
 127         new_state.cwd = estrdup(cwd);
 128         new_state.cwd_length = (int)strlen(cwd);
 129 
 130         if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
 131                 efree(new_state.cwd);
 132                 return -1;
 133         }
 134 
 135         if (IS_SLASH(new_state.cwd[new_state.cwd_length - 1])) {
 136                 trailing_slash = "";
 137         } else {
 138                 trailing_slash = "/";
 139         }
 140 
 141         if (snprintf(opened_path, MAXPATHLEN, "%s%s%sXXXXXX", new_state.cwd, trailing_slash, pfx) >= MAXPATHLEN) {
 142                 efree(new_state.cwd);
 143                 return -1;
 144         }
 145 
 146 #ifdef PHP_WIN32
 147 
 148         if (GetTempFileName(new_state.cwd, pfx, 0, opened_path)) {
 149                 /* Some versions of windows set the temp file to be read-only,
 150                  * which means that opening it will fail... */
 151                 if (VCWD_CHMOD(opened_path, 0600)) {
 152                         efree(new_state.cwd);
 153                         return -1;
 154                 }
 155                 fd = VCWD_OPEN_MODE(opened_path, open_flags, 0600);
 156         }
 157 
 158 #elif defined(HAVE_MKSTEMP)
 159         fd = mkstemp(opened_path);
 160 #else
 161         if (mktemp(opened_path)) {
 162                 fd = VCWD_OPEN(opened_path, open_flags);
 163         }
 164 #endif
 165 
 166         if (fd != -1 && opened_path_p) {
 167                 *opened_path_p = zend_string_init(opened_path, strlen(opened_path), 0);
 168         }
 169         efree(new_state.cwd);
 170         return fd;
 171 }
 172 /* }}} */
 173 
 174 /*
 175  *  Determine where to place temporary files.
 176  */
 177 PHPAPI const char* php_get_temporary_directory(void)
 178 {
 179         /* Did we determine the temporary directory already? */
 180         if (PG(php_sys_temp_dir)) {
 181                 return PG(php_sys_temp_dir);
 182         }
 183 
 184         /* Is there a temporary directory "sys_temp_dir" in .ini defined? */
 185         {
 186                 char *sys_temp_dir = PG(sys_temp_dir);
 187                 if (sys_temp_dir) {
 188                         int len = (int)strlen(sys_temp_dir);
 189                         if (len >= 2 && sys_temp_dir[len - 1] == DEFAULT_SLASH) {
 190                                 PG(php_sys_temp_dir) = estrndup(sys_temp_dir, len - 1);
 191                                 return PG(php_sys_temp_dir);
 192                         } else if (len >= 1 && sys_temp_dir[len - 1] != DEFAULT_SLASH) {
 193                                 PG(php_sys_temp_dir) = estrndup(sys_temp_dir, len);
 194                                 return PG(php_sys_temp_dir);
 195                         }
 196                 }
 197         }
 198 
 199 #ifdef PHP_WIN32
 200         /* We can't count on the environment variables TEMP or TMP,
 201          * and so must make the Win32 API call to get the default
 202          * directory for temporary files.  Note this call checks
 203          * the environment values TMP and TEMP (in order) first.
 204          */
 205         {
 206                 char sTemp[MAX_PATH];
 207                 DWORD len = GetTempPath(sizeof(sTemp),sTemp);
 208                 assert(0 < len);  /* should *never* fail! */
 209                 if (sTemp[len - 1] == DEFAULT_SLASH) {
 210                         PG(php_sys_temp_dir) = estrndup(sTemp, len - 1);
 211                 } else {
 212                         PG(php_sys_temp_dir) = estrndup(sTemp, len);
 213                 }
 214                 return PG(php_sys_temp_dir);
 215         }
 216 #else
 217         /* On Unix use the (usual) TMPDIR environment variable. */
 218         {
 219                 char* s = getenv("TMPDIR");
 220                 if (s && *s) {
 221                         int len = strlen(s);
 222 
 223                         if (s[len - 1] == DEFAULT_SLASH) {
 224                                 PG(php_sys_temp_dir) = estrndup(s, len - 1);
 225                         } else {
 226                                 PG(php_sys_temp_dir) = estrndup(s, len);
 227                         }
 228 
 229                         return PG(php_sys_temp_dir);
 230                 }
 231         }
 232 #ifdef P_tmpdir
 233         /* Use the standard default temporary directory. */
 234         if (P_tmpdir) {
 235                 PG(php_sys_temp_dir) = estrdup(P_tmpdir);
 236                 return PG(php_sys_temp_dir);
 237         }
 238 #endif
 239         /* Shouldn't ever(!) end up here ... last ditch default. */
 240         PG(php_sys_temp_dir) = estrdup("/tmp");
 241         return PG(php_sys_temp_dir);
 242 #endif
 243 }
 244 
 245 /* {{{ php_open_temporary_file
 246  *
 247  * Unlike tempnam(), the supplied dir argument takes precedence
 248  * over the TMPDIR environment variable
 249  * This function should do its best to return a file pointer to a newly created
 250  * unique file, on every platform.
 251  */
 252 PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_string **opened_path_p, zend_bool open_basedir_check)
 253 {
 254         int fd;
 255         const char *temp_dir;
 256 
 257         if (!pfx) {
 258                 pfx = "tmp.";
 259         }
 260         if (opened_path_p) {
 261                 *opened_path_p = NULL;
 262         }
 263 
 264         if (!dir || *dir == '\0') {
 265 def_tmp:
 266                 temp_dir = php_get_temporary_directory();
 267 
 268                 if (temp_dir && *temp_dir != '\0' && (!open_basedir_check || !php_check_open_basedir(temp_dir))) {
 269                         return php_do_open_temporary_file(temp_dir, pfx, opened_path_p);
 270                 } else {
 271                         return -1;
 272                 }
 273         }
 274 
 275         /* Try the directory given as parameter. */
 276         fd = php_do_open_temporary_file(dir, pfx, opened_path_p);
 277         if (fd == -1) {
 278                 /* Use default temporary directory. */
 279                 goto def_tmp;
 280         }
 281         return fd;
 282 }
 283 
 284 PHPAPI int php_open_temporary_fd(const char *dir, const char *pfx, zend_string **opened_path_p)
 285 {
 286         return php_open_temporary_fd_ex(dir, pfx, opened_path_p, 0);
 287 }
 288 
 289 PHPAPI FILE *php_open_temporary_file(const char *dir, const char *pfx, zend_string **opened_path_p)
 290 {
 291         FILE *fp;
 292         int fd = php_open_temporary_fd(dir, pfx, opened_path_p);
 293 
 294         if (fd == -1) {
 295                 return NULL;
 296         }
 297 
 298         fp = fdopen(fd, "r+b");
 299         if (fp == NULL) {
 300                 close(fd);
 301         }
 302 
 303         return fp;
 304 }
 305 /* }}} */
 306 
 307 /*
 308  * Local variables:
 309  * tab-width: 4
 310  * c-basic-offset: 4
 311  * End:
 312  * vim600: sw=4 ts=4 fdm=marker
 313  * vim<600: sw=4 ts=4
 314  */

/* [<][>][^][v][top][bottom][index][help] */