From: Arnaud Le Blanc Date: Thu, 7 Aug 2008 09:24:04 +0000 (+0000) Subject: Added clear_realpath_cache and filename parameters to clearstatcache() (Jani, X-Git-Tag: BEFORE_HEAD_NS_CHANGE~834 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a51e5ebaeb8d9cbe1488d110564d0055dd3edf5c;p=php Added clear_realpath_cache and filename parameters to clearstatcache() (Jani, Arnaud) [DOC] clearstatcache() now defaults to not affect the realpath cache. clearstatcache() now takes two optionnal parameters, clear_realpath_cache to clear the realpath cache (defaults to false), and filename to clear only the given filename from the cache. --- diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 601e9dd2d9..3111155a2c 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1494,7 +1494,9 @@ ZEND_END_ARG_INFO() #endif static -ZEND_BEGIN_ARG_INFO(arginfo_clearstatcache, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_clearstatcache, 0, 0, 0) + ZEND_ARG_INFO(0, clear_realpath_cache) + ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() static diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c index 259c8bf2ab..06b51c902c 100644 --- a/ext/standard/filestat.c +++ b/ext/standard/filestat.c @@ -780,8 +780,11 @@ PHP_FUNCTION(touch) /* {{{ php_clear_stat_cache() */ -PHPAPI void php_clear_stat_cache(TSRMLS_D) +PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, int filename_len TSRMLS_DC) { + /* always clear CurrentStatFile and CurrentLStatFile even if filename is not NULL + * as it may contains 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)); BG(CurrentStatFile) = NULL; @@ -790,18 +793,40 @@ PHPAPI void php_clear_stat_cache(TSRMLS_D) efree(BG(CurrentLStatFile)); BG(CurrentLStatFile) = NULL; } - realpath_cache_clean(TSRMLS_C); + if (clear_realpath_cache) { + if (filename != NULL) { + realpath_cache_del(filename, filename_len TSRMLS_CC); + } else { + realpath_cache_clean(TSRMLS_C); + } + } } /* }}} */ -/* {{{ proto void clearstatcache(void) +/* {{{ proto void clearstatcache([bool clear_realpath_cache[, string filename]]) Clear file stat cache */ PHP_FUNCTION(clearstatcache) { - if (zend_parse_parameters_none() == FAILURE) { + zend_bool clear_realpath_cache = 0; + char *filename = NULL; + zend_uchar filename_type; + int filename_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bt", &clear_realpath_cache, &filename, &filename_len, &filename_type) == FAILURE) { return; } - php_clear_stat_cache(TSRMLS_C); + + if (filename && filename_type == IS_UNICODE) { + if (FAILURE == php_stream_path_encode(NULL, &filename, &filename_len, (UChar*)filename, filename_len, REPORT_ERRORS, FG(default_context))) { + RETURN_FALSE; + } + } + + php_clear_stat_cache(clear_realpath_cache, filename, filename_len TSRMLS_CC); + + if (filename && filename_type == IS_UNICODE) { + efree(filename); + } } /* }}} */ diff --git a/ext/standard/php_filestat.h b/ext/standard/php_filestat.h index 4545fbf5d5..747b59b89e 100644 --- a/ext/standard/php_filestat.h +++ b/ext/standard/php_filestat.h @@ -87,7 +87,7 @@ typedef unsigned int php_stat_len; typedef int php_stat_len; #endif -PHPAPI void php_clear_stat_cache(TSRMLS_D); +PHPAPI void php_clear_stat_cache(zend_bool clear_realpath_cache, const char *filename, int filename_len TSRMLS_DC); PHPAPI void php_stat(const char *filename, php_stat_len filename_length, int type, zval *return_value TSRMLS_DC); PHPAPI void php_u_stat(zend_uchar filename_type, const zstr filename, php_stat_len filename_length, int type, php_stream_context *context, zval *return_value TSRMLS_DC); diff --git a/ext/standard/tests/file/bug39367.phpt b/ext/standard/tests/file/bug39367.phpt index 01fb5e8c84..f3e79fcf5e 100755 --- a/ext/standard/tests/file/bug39367.phpt +++ b/ext/standard/tests/file/bug39367.phpt @@ -19,7 +19,7 @@ function test() { echo file_get_contents('/tmp/1link')."\n"; unlink('/tmp/1link'); - clearstatcache(); + clearstatcache(true); echo file_get_contents('/tmp/1link')."\n"; diff --git a/ext/standard/tests/file/clearstatcache_001.phpt b/ext/standard/tests/file/clearstatcache_001.phpt new file mode 100644 index 0000000000..6177116fab --- /dev/null +++ b/ext/standard/tests/file/clearstatcache_001.phpt @@ -0,0 +1,45 @@ +--TEST-- +clearstatcache() optionnal parameters +--SKIPIF-- + +--FILE-- + +--CLEAN-- + +--EXPECTF-- +%unicode|string%(%d) "%s_dir1" +%unicode|string%(%d) "%s_dir1" +%unicode|string%(%d) "%s_dir1" +%unicode|string%(%d) "%s_dir1" +bool(false) diff --git a/ext/standard/tests/file/clearstatcache_error.phpt b/ext/standard/tests/file/clearstatcache_error.phpt index 1ebb08888e..ee7d1af18c 100644 --- a/ext/standard/tests/file/clearstatcache_error.phpt +++ b/ext/standard/tests/file/clearstatcache_error.phpt @@ -3,17 +3,17 @@ Test clearstatcache() function: error conditions --FILE-- --EXPECTF-- *** Testing clearstatcache() function: error conditions *** -Warning: clearstatcache() expects exactly 0 parameters, 1 given in %s on line %d +Warning: clearstatcache() expects at most 2 parameters, 3 given in %s on line %d NULL *** Done *** diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index a8aad6003b..39ffb86172 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -1025,8 +1025,8 @@ static int php_plain_files_unlink(php_stream_wrapper *wrapper, char *url, int op return 0; } - /* Clear stat cache */ - php_clear_stat_cache(TSRMLS_C); + /* Clear stat cache (and realpath cache) */ + php_clear_stat_cache(1, NULL, 0 TSRMLS_CC); return 1; } @@ -1092,8 +1092,8 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, char *url_from, c return 0; } - /* Clear stat cache */ - php_clear_stat_cache(TSRMLS_C); + /* Clear stat cache (and realpath cache) */ + php_clear_stat_cache(1, NULL, 0 TSRMLS_CC); return 1; } @@ -1202,8 +1202,8 @@ static int php_plain_files_rmdir(php_stream_wrapper *wrapper, char *url, int opt return 0; } - /* Clear stat cache */ - php_clear_stat_cache(TSRMLS_C); + /* Clear stat cache (and realpath cache) */ + php_clear_stat_cache(1, NULL, 0 TSRMLS_CC); return 1; }