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. __declspec
  3. php_get_temporary_directory
  4. php_open_temporary_fd_ex
  5. php_open_temporary_fd
  6. php_open_temporary_file

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

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