diff options
Diffstat (limited to 'ext/standard/filestat.c')
-rw-r--r-- | ext/standard/filestat.c | 108 |
1 files changed, 79 insertions, 29 deletions
diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c index 303e919c19..0b488df4b2 100644 --- a/ext/standard/filestat.c +++ b/ext/standard/filestat.c @@ -88,11 +88,11 @@ PHP_RINIT_FUNCTION(filestat) /* {{{ */ PHP_RSHUTDOWN_FUNCTION(filestat) /* {{{ */ { if (BG(CurrentStatFile)) { - efree (BG(CurrentStatFile)); + zend_string_release(BG(CurrentStatFile)); BG(CurrentStatFile) = NULL; } if (BG(CurrentLStatFile)) { - efree (BG(CurrentLStatFile)); + zend_string_release(BG(CurrentLStatFile)); BG(CurrentLStatFile) = NULL; } return SUCCESS; @@ -594,7 +594,7 @@ PHP_FUNCTION(touch) char *filename; size_t filename_len; zend_long filetime = 0, fileatime = 0; - zend_bool filetime_is_null = 1, fileatime_is_null = 1; + bool filetime_is_null = 1, fileatime_is_null = 1; int ret; FILE *file; struct utimbuf newtimebuf; @@ -674,17 +674,17 @@ PHP_FUNCTION(touch) #endif /* {{{ php_clear_stat_cache() */ -PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, size_t filename_len) +PHPAPI void php_clear_stat_cache(bool clear_realpath_cache, const char *filename, size_t filename_len) { /* always clear CurrentStatFile and CurrentLStatFile even if filename is not NULL * as it may contain outdated data (e.g. "nlink" for a directory when deleting a file * in this directory, as shown by lstat_stat_variation9.phpt) */ if (BG(CurrentStatFile)) { - efree(BG(CurrentStatFile)); + zend_string_release(BG(CurrentStatFile)); BG(CurrentStatFile) = NULL; } if (BG(CurrentLStatFile)) { - efree(BG(CurrentLStatFile)); + zend_string_release(BG(CurrentLStatFile)); BG(CurrentLStatFile) = NULL; } if (clear_realpath_cache) { @@ -700,7 +700,7 @@ PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *fil /* {{{ Clear file stat cache */ PHP_FUNCTION(clearstatcache) { - zend_bool clear_realpath_cache = 0; + bool clear_realpath_cache = 0; char *filename = NULL; size_t filename_len = 0; @@ -720,26 +720,27 @@ PHP_FUNCTION(clearstatcache) #define IS_ACCESS_CHECK(__t) (IS_ABLE_CHECK(type) || (__t) == FS_EXISTS) /* {{{ php_stat */ -PHPAPI void php_stat(const char *filename, size_t filename_length, int type, zval *return_value) +PHPAPI void php_stat(zend_string *filename, int type, zval *return_value) { zend_stat_t *stat_sb; php_stream_statbuf ssb; int flags = 0, rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */ - const char *local; - php_stream_wrapper *wrapper; + const char *local = NULL; + php_stream_wrapper *wrapper = NULL; - if (!filename_length || CHECK_NULL_PATH(filename, filename_length)) { - if (filename_length && !IS_EXISTS_CHECK(type)) { - php_error_docref(NULL, E_WARNING, "Filename contains null byte"); + if (IS_ACCESS_CHECK(type)) { + if (!ZSTR_LEN(filename) || CHECK_NULL_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename))) { + if (ZSTR_LEN(filename) && !IS_EXISTS_CHECK(type)) { + php_error_docref(NULL, E_WARNING, "Filename contains null byte"); + } + RETURN_FALSE; } - RETURN_FALSE; - } - if ((wrapper = php_stream_locate_url_wrapper(filename, &local, 0)) == &php_plain_files_wrapper && php_check_open_basedir(local)) { - RETURN_FALSE; - } + if ((wrapper = php_stream_locate_url_wrapper(ZSTR_VAL(filename), &local, 0)) == &php_plain_files_wrapper + && php_check_open_basedir(local)) { + RETURN_FALSE; + } - if (IS_ACCESS_CHECK(type)) { if (wrapper == &php_plain_files_wrapper) { switch (type) { @@ -774,13 +775,63 @@ PHPAPI void php_stat(const char *filename, size_t filename_length, int type, zva flags |= PHP_STREAM_URL_STAT_QUIET; } - if (php_stream_stat_path_ex((char *)filename, flags, &ssb, NULL)) { - /* Error Occurred */ - if (!IS_EXISTS_CHECK(type)) { - php_error_docref(NULL, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename); + do { + /* Try to hit the cache first */ + if (flags & PHP_STREAM_URL_STAT_LINK) { + if (filename == BG(CurrentLStatFile) + || (BG(CurrentLStatFile) + && zend_string_equal_content(filename, BG(CurrentLStatFile)))) { + memcpy(&ssb, &BG(lssb), sizeof(php_stream_statbuf)); + break; + } + } else { + if (filename == BG(CurrentStatFile) + || (BG(CurrentStatFile) + && zend_string_equal_content(filename, BG(CurrentStatFile)))) { + memcpy(&ssb, &BG(ssb), sizeof(php_stream_statbuf)); + break; + } } - RETURN_FALSE; - } + + if (!wrapper) { + if (!ZSTR_LEN(filename) || CHECK_NULL_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename))) { + if (ZSTR_LEN(filename) && !IS_EXISTS_CHECK(type)) { + php_error_docref(NULL, E_WARNING, "Filename contains null byte"); + } + RETURN_FALSE; + } + + if ((wrapper = php_stream_locate_url_wrapper(ZSTR_VAL(filename), &local, 0)) == &php_plain_files_wrapper + && php_check_open_basedir(local)) { + RETURN_FALSE; + } + } + + if (!wrapper + || !wrapper->wops->url_stat + || wrapper->wops->url_stat(wrapper, local, flags | PHP_STREAM_URL_STAT_IGNORE_OPEN_BASEDIR, &ssb, NULL)) { + /* Error Occurred */ + if (!IS_EXISTS_CHECK(type)) { + php_error_docref(NULL, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", ZSTR_VAL(filename)); + } + RETURN_FALSE; + } + + /* Drop into cache */ + if (flags & PHP_STREAM_URL_STAT_LINK) { + if (BG(CurrentLStatFile)) { + zend_string_release(BG(CurrentLStatFile)); + } + BG(CurrentLStatFile) = zend_string_copy(filename); + memcpy(&BG(lssb), &ssb, sizeof(php_stream_statbuf)); + } else { + if (BG(CurrentStatFile)) { + zend_string_release(BG(CurrentStatFile)); + } + BG(CurrentStatFile) = zend_string_copy(filename); + memcpy(&BG(ssb), &ssb, sizeof(php_stream_statbuf)); + } + } while (0); stat_sb = &ssb.sb; @@ -936,14 +987,13 @@ PHPAPI void php_stat(const char *filename, size_t filename_length, int type, zva /* {{{ FileFunction(name, funcnum) */ #define FileFunction(name, funcnum) \ ZEND_NAMED_FUNCTION(name) { \ - char *filename; \ - size_t filename_len; \ + zend_string *filename; \ \ ZEND_PARSE_PARAMETERS_START(1, 1) \ - Z_PARAM_STRING(filename, filename_len) \ + Z_PARAM_STR(filename) \ ZEND_PARSE_PARAMETERS_END(); \ \ - php_stat(filename, filename_len, funcnum, return_value); \ + php_stat(filename, funcnum, return_value); \ } /* }}} */ |