Annotation of embedaddon/php/main/php_open_temporary_file.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.4 ! misho       5:    | Copyright (c) 1997-2014 The PHP Group                                |
1.1       misho       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: 
1.1.1.2   misho      19: /* $Id$ */
1.1       misho      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 = strdup(cwd);
                    128:        new_state.cwd_length = strlen(cwd);
                    129: 
1.1.1.2   misho     130:        if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH TSRMLS_CC)) {
1.1       misho     131:                free(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:                free(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:                        free(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:        free(new_state.cwd);
                    174:        return fd;
                    175: }
                    176: /* }}} */
                    177: 
                    178: /* Cache the chosen temporary directory. */
                    179: static char* temporary_directory;
                    180: 
                    181: PHPAPI void php_shutdown_temporary_directory(void)
                    182: {
                    183:        if (temporary_directory) {
                    184:                free(temporary_directory);
                    185:                temporary_directory = NULL;
                    186:        }
                    187: }
                    188: 
                    189: /*
                    190:  *  Determine where to place temporary files.
                    191:  */
                    192: PHPAPI const char* php_get_temporary_directory(void)
                    193: {
                    194:        /* Did we determine the temporary directory already? */
                    195:        if (temporary_directory) {
                    196:                return temporary_directory;
                    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:                        temporary_directory = zend_strndup(sTemp, len - 1);
                    211:                } else {
                    212:                        temporary_directory = zend_strndup(sTemp, len);
                    213:                }
                    214:                return temporary_directory;
                    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:                                temporary_directory = zend_strndup(s, len - 1);
                    225:                        } else {
                    226:                                temporary_directory = zend_strndup(s, len);
                    227:                        }
                    228: 
                    229:                        return temporary_directory;
                    230:                }
                    231:        }
                    232: #ifdef P_tmpdir
                    233:        /* Use the standard default temporary directory. */
                    234:        if (P_tmpdir) {
                    235:                temporary_directory = strdup(P_tmpdir);
                    236:                return temporary_directory;
                    237:        }
                    238: #endif
                    239:        /* Shouldn't ever(!) end up here ... last ditch default. */
                    240:        temporary_directory = strdup("/tmp");
                    241:        return temporary_directory;
                    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, char **opened_path_p, zend_bool open_basedir_check TSRMLS_DC)
                    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 TSRMLS_CC))) {
                    269:                        return php_do_open_temporary_file(temp_dir, pfx, opened_path_p TSRMLS_CC);
                    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 TSRMLS_CC);
                    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, char **opened_path_p TSRMLS_DC)
                    285: {
                    286:        return php_open_temporary_fd_ex(dir, pfx, opened_path_p, 0 TSRMLS_CC);
                    287: }
                    288: 
                    289: PHPAPI FILE *php_open_temporary_file(const char *dir, const char *pfx, char **opened_path_p TSRMLS_DC)
                    290: {
                    291:        FILE *fp;
                    292:        int fd = php_open_temporary_fd(dir, pfx, opened_path_p TSRMLS_CC);
                    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:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>