PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - main - php_open_temporary_file.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 55 69 79.7 %
Date: 2016-07-19 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "php_open_temporary_file.h"
      23             : 
      24             : #include <errno.h>
      25             : #include <sys/types.h>
      26             : #include <sys/stat.h>
      27             : #include <fcntl.h>
      28             : 
      29             : #ifdef PHP_WIN32
      30             : #define O_RDONLY _O_RDONLY
      31             : #include "win32/param.h"
      32             : #include "win32/winutil.h"
      33             : #elif defined(NETWARE)
      34             : #ifdef USE_WINSOCK
      35             : #include <novsock2.h>
      36             : #else
      37             : #include <sys/socket.h>
      38             : #endif
      39             : #include <sys/param.h>
      40             : #else
      41             : #include <sys/param.h>
      42             : #include <sys/socket.h>
      43             : #include <netinet/in.h>
      44             : #include <netdb.h>
      45             : #if HAVE_ARPA_INET_H
      46             : #include <arpa/inet.h>
      47             : #endif
      48             : #endif
      49             : #ifdef HAVE_SYS_TIME_H
      50             : #include <sys/time.h>
      51             : #endif
      52             : 
      53             : #ifdef HAVE_SYS_FILE_H
      54             : #include <sys/file.h>
      55             : #endif
      56             : 
      57             : #if !defined(P_tmpdir)
      58             : #define P_tmpdir ""
      59             : #endif
      60             : 
      61             : /* {{{ php_do_open_temporary_file */
      62             : 
      63             : /* Loosely based on a tempnam() implementation by UCLA */
      64             : 
      65             : /*
      66             :  * Copyright (c) 1988, 1993
      67             :  *      The Regents of the University of California.  All rights reserved.
      68             :  *
      69             :  * Redistribution and use in source and binary forms, with or without
      70             :  * modification, are permitted provided that the following conditions
      71             :  * are met:
      72             :  * 1. Redistributions of source code must retain the above copyright
      73             :  *    notice, this list of conditions and the following disclaimer.
      74             :  * 2. Redistributions in binary form must reproduce the above copyright
      75             :  *    notice, this list of conditions and the following disclaimer in the
      76             :  *    documentation and/or other materials provided with the distribution.
      77             :  * 3. All advertising materials mentioning features or use of this software
      78             :  *    must display the following acknowledgement:
      79             :  *      This product includes software developed by the University of
      80             :  *      California, Berkeley and its contributors.
      81             :  * 4. Neither the name of the University nor the names of its contributors
      82             :  *    may be used to endorse or promote products derived from this software
      83             :  *    without specific prior written permission.
      84             :  *
      85             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      86             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      87             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      88             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      89             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      90             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      91             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      92             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      93             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      94             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      95             :  * SUCH DAMAGE.
      96             :  */
      97             : 
      98       15237 : static int php_do_open_temporary_file(const char *path, const char *pfx, zend_string **opened_path_p)
      99             : {
     100             :         char *trailing_slash;
     101             : #ifdef PHP_WIN32
     102             :         char *opened_path = NULL;
     103             :         size_t opened_path_len;
     104             :         wchar_t *cwdw, *pfxw, pathw[MAXPATHLEN];
     105             : #else
     106             :         char opened_path[MAXPATHLEN];
     107             : #endif
     108             :         char cwd[MAXPATHLEN];
     109             :         cwd_state new_state;
     110       15237 :         int fd = -1;
     111             : #ifndef HAVE_MKSTEMP
     112             :         int open_flags = O_CREAT | O_TRUNC | O_RDWR
     113             : #ifdef PHP_WIN32
     114             :                 | _O_BINARY
     115             : #endif
     116             :                 ;
     117             : #endif
     118             : 
     119       15237 :         if (!path || !path[0]) {
     120           0 :                 return -1;
     121             :         }
     122             : 
     123             : #ifdef PHP_WIN32
     124             :         if (!php_win32_check_trailing_space(pfx, (const int)strlen(pfx))) {
     125             :                 SetLastError(ERROR_INVALID_NAME);
     126             :                 return -1;
     127             :         }
     128             : #endif
     129             : 
     130       15237 :         if (!VCWD_GETCWD(cwd, MAXPATHLEN)) {
     131           0 :                 cwd[0] = '\0';
     132             :         }
     133             : 
     134       15237 :         new_state.cwd = estrdup(cwd);
     135       15237 :         new_state.cwd_length = (int)strlen(cwd);
     136             : 
     137       15237 :         if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
     138          11 :                 efree(new_state.cwd);
     139          11 :                 return -1;
     140             :         }
     141             : 
     142       15226 :         if (IS_SLASH(new_state.cwd[new_state.cwd_length - 1])) {
     143           0 :                 trailing_slash = "";
     144             :         } else {
     145       15226 :                 trailing_slash = "/";
     146             :         }
     147             : 
     148             : #ifndef PHP_WIN32
     149       15226 :         if (snprintf(opened_path, MAXPATHLEN, "%s%s%sXXXXXX", new_state.cwd, trailing_slash, pfx) >= MAXPATHLEN) {
     150           0 :                 efree(new_state.cwd);
     151           0 :                 return -1;
     152             :         }
     153             : #endif
     154             : 
     155             : #ifdef PHP_WIN32
     156             :         cwdw = php_win32_ioutil_any_to_w(new_state.cwd);
     157             :         pfxw = php_win32_ioutil_any_to_w(pfx);
     158             :         if (!cwdw || !pfxw) {
     159             :                 free(cwdw);
     160             :                 free(pfxw);
     161             :                 efree(new_state.cwd);
     162             :                 return -1;
     163             :         }
     164             : 
     165             :         if (GetTempFileNameW(cwdw, pfxw, 0, pathw)) {
     166             :                 opened_path = php_win32_ioutil_conv_w_to_any(pathw, PHP_WIN32_CP_IGNORE_LEN, &opened_path_len);
     167             :                 if (!opened_path || opened_path_len >= MAXPATHLEN) {
     168             :                         free(cwdw);
     169             :                         free(pfxw);
     170             :                         efree(new_state.cwd);
     171             :                         return -1;
     172             :                 }
     173             :                 assert(strlen(opened_path) == opened_path_len);
     174             : 
     175             :                 /* Some versions of windows set the temp file to be read-only,
     176             :                  * which means that opening it will fail... */
     177             :                 if (VCWD_CHMOD(opened_path, 0600)) {
     178             :                         free(cwdw);
     179             :                         free(pfxw);
     180             :                         efree(new_state.cwd);
     181             :                         free(opened_path);
     182             :                         return -1;
     183             :                 }
     184             :                 fd = VCWD_OPEN_MODE(opened_path, open_flags, 0600);
     185             :         }
     186             : 
     187             :         free(cwdw);
     188             :         free(pfxw);
     189             : #elif defined(HAVE_MKSTEMP)
     190       15226 :         fd = mkstemp(opened_path);
     191             : #else
     192             :         if (mktemp(opened_path)) {
     193             :                 fd = VCWD_OPEN(opened_path, open_flags);
     194             :         }
     195             : #endif
     196             : 
     197             : #ifdef PHP_WIN32
     198             :         if (fd != -1 && opened_path_p) {
     199             :                 *opened_path_p = zend_string_init(opened_path, opened_path_len, 0);
     200             :         }
     201             :         free(opened_path);
     202             : #else
     203       15226 :         if (fd != -1 && opened_path_p) {
     204       29684 :                 *opened_path_p = zend_string_init(opened_path, strlen(opened_path), 0);
     205             :         }
     206             : #endif
     207       15226 :         efree(new_state.cwd);
     208       15226 :         return fd;
     209             : }
     210             : /* }}} */
     211             : 
     212             : /*
     213             :  *  Determine where to place temporary files.
     214             :  */
     215       15383 : PHPAPI const char* php_get_temporary_directory(void)
     216             : {
     217             :         /* Did we determine the temporary directory already? */
     218       15383 :         if (PG(php_sys_temp_dir)) {
     219       14840 :                 return PG(php_sys_temp_dir);
     220             :         }
     221             : 
     222             :         /* Is there a temporary directory "sys_temp_dir" in .ini defined? */
     223             :         {
     224         543 :                 char *sys_temp_dir = PG(sys_temp_dir);
     225         543 :                 if (sys_temp_dir) {
     226           2 :                         int len = (int)strlen(sys_temp_dir);
     227           2 :                         if (len >= 2 && sys_temp_dir[len - 1] == DEFAULT_SLASH) {
     228           0 :                                 PG(php_sys_temp_dir) = estrndup(sys_temp_dir, len - 1);
     229           0 :                                 return PG(php_sys_temp_dir);
     230           2 :                         } else if (len >= 1 && sys_temp_dir[len - 1] != DEFAULT_SLASH) {
     231           2 :                                 PG(php_sys_temp_dir) = estrndup(sys_temp_dir, len);
     232           2 :                                 return PG(php_sys_temp_dir);
     233             :                         }
     234             :                 }
     235             :         }
     236             : 
     237             : #ifdef PHP_WIN32
     238             :         /* We can't count on the environment variables TEMP or TMP,
     239             :          * and so must make the Win32 API call to get the default
     240             :          * directory for temporary files.  Note this call checks
     241             :          * the environment values TMP and TEMP (in order) first.
     242             :          */
     243             :         {
     244             :                 wchar_t sTemp[MAXPATHLEN];
     245             :                 char *tmp;
     246             :                 size_t len = GetTempPathW(MAXPATHLEN, sTemp);
     247             :                 assert(0 < len);  /* should *never* fail! */
     248             : 
     249             :                 if (NULL == (tmp = php_win32_ioutil_conv_w_to_any(sTemp, len, &len))) {
     250             :                         return NULL;
     251             :                 }
     252             : 
     253             :                 PG(php_sys_temp_dir) = estrndup(tmp, len - 1);
     254             : 
     255             :                 free(tmp);
     256             :                 return PG(php_sys_temp_dir);
     257             :         }
     258             : #else
     259             :         /* On Unix use the (usual) TMPDIR environment variable. */
     260             :         {
     261         541 :                 char* s = getenv("TMPDIR");
     262         541 :                 if (s && *s) {
     263           0 :                         int len = strlen(s);
     264             : 
     265           0 :                         if (s[len - 1] == DEFAULT_SLASH) {
     266           0 :                                 PG(php_sys_temp_dir) = estrndup(s, len - 1);
     267             :                         } else {
     268           0 :                                 PG(php_sys_temp_dir) = estrndup(s, len);
     269             :                         }
     270             : 
     271           0 :                         return PG(php_sys_temp_dir);
     272             :                 }
     273             :         }
     274             : #ifdef P_tmpdir
     275             :         /* Use the standard default temporary directory. */
     276             :         if (P_tmpdir) {
     277         541 :                 PG(php_sys_temp_dir) = estrdup(P_tmpdir);
     278         541 :                 return PG(php_sys_temp_dir);
     279             :         }
     280             : #endif
     281             :         /* Shouldn't ever(!) end up here ... last ditch default. */
     282             :         PG(php_sys_temp_dir) = estrdup("/tmp");
     283             :         return PG(php_sys_temp_dir);
     284             : #endif
     285             : }
     286             : 
     287             : /* {{{ php_open_temporary_file
     288             :  *
     289             :  * Unlike tempnam(), the supplied dir argument takes precedence
     290             :  * over the TMPDIR environment variable
     291             :  * This function should do its best to return a file pointer to a newly created
     292             :  * unique file, on every platform.
     293             :  */
     294       14844 : PHPAPI int php_open_temporary_fd_ex(const char *dir, const char *pfx, zend_string **opened_path_p, uint32_t flags)
     295             : {
     296             :         int fd;
     297             :         const char *temp_dir;
     298             : 
     299       14844 :         if (!pfx) {
     300           1 :                 pfx = "tmp.";
     301             :         }
     302       14844 :         if (opened_path_p) {
     303       14844 :                 *opened_path_p = NULL;
     304             :         }
     305             : 
     306       14844 :         if (!dir || *dir == '\0') {
     307             : def_tmp:
     308       14549 :                 temp_dir = php_get_temporary_directory();
     309             : 
     310       14549 :                 if (temp_dir && *temp_dir != '\0' && (!(flags & PHP_TMP_FILE_OPEN_BASEDIR_CHECK) || !php_check_open_basedir(temp_dir))) {
     311       14548 :                         return php_do_open_temporary_file(temp_dir, pfx, opened_path_p);
     312             :                 } else {
     313           1 :                         return -1;
     314             :                 }
     315             :         }
     316             : 
     317             :         /* Try the directory given as parameter. */
     318         689 :         fd = php_do_open_temporary_file(dir, pfx, opened_path_p);
     319         689 :         if (fd == -1) {
     320             :                 /* Use default temporary directory. */
     321         394 :                 if (!(flags & PHP_TMP_FILE_SILENT)) {
     322         394 :                         php_error_docref(NULL, E_NOTICE, "file created in the system's temporary directory");
     323             :                 }
     324         394 :                 goto def_tmp;
     325             :         }
     326         295 :         return fd;
     327             : }
     328             : 
     329       14104 : PHPAPI int php_open_temporary_fd(const char *dir, const char *pfx, zend_string **opened_path_p)
     330             : {
     331       14104 :         return php_open_temporary_fd_ex(dir, pfx, opened_path_p, 0);
     332             : }
     333             : 
     334           1 : PHPAPI FILE *php_open_temporary_file(const char *dir, const char *pfx, zend_string **opened_path_p)
     335             : {
     336             :         FILE *fp;
     337           1 :         int fd = php_open_temporary_fd(dir, pfx, opened_path_p);
     338             : 
     339           1 :         if (fd == -1) {
     340           0 :                 return NULL;
     341             :         }
     342             : 
     343           1 :         fp = fdopen(fd, "r+b");
     344           1 :         if (fp == NULL) {
     345           0 :                 close(fd);
     346             :         }
     347             : 
     348           1 :         return fp;
     349             : }
     350             : /* }}} */
     351             : 
     352             : /*
     353             :  * Local variables:
     354             :  * tab-width: 4
     355             :  * c-basic-offset: 4
     356             :  * End:
     357             :  * vim600: sw=4 ts=4 fdm=marker
     358             :  * vim<600: sw=4 ts=4
     359             :  */

Generated by: LCOV version 1.10

Generated at Wed, 20 Jul 2016 02:56:32 +0000 (4 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.