]> granicus.if.org Git - php/commitdiff
Added clear_realpath_cache and filename parameters to clearstatcache() (Jani,
authorArnaud Le Blanc <lbarnaud@php.net>
Thu, 7 Aug 2008 09:24:04 +0000 (09:24 +0000)
committerArnaud Le Blanc <lbarnaud@php.net>
Thu, 7 Aug 2008 09:24:04 +0000 (09:24 +0000)
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.

ext/standard/basic_functions.c
ext/standard/filestat.c
ext/standard/php_filestat.h
ext/standard/tests/file/bug39367.phpt
ext/standard/tests/file/clearstatcache_001.phpt [new file with mode: 0644]
ext/standard/tests/file/clearstatcache_error.phpt
main/streams/plain_wrapper.c

index 601e9dd2d901f53856e3a9ffe7eed35c35640d95..3111155a2c8c09bdffc6c18953b1f41163dfbc45 100644 (file)
@@ -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
index 259c8bf2ab975a606c14119903b5c800a41be25f..06b51c902c0567ac0d3f9841c39659886f5a243f 100644 (file)
@@ -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);
+       }
 }
 /* }}} */
 
index 4545fbf5d5c38a1722cfca2a9bf0fbf3a7263326..747b59b89eeedfcb079c7b7bc2b87597a45c385f 100644 (file)
@@ -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);
 
index 01fb5e8c84fc6bcf28a52828441ee0962f9a48f1..f3e79fcf5ed994d904832bb8b067c3611568333d 100755 (executable)
@@ -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 (file)
index 0000000..6177116
--- /dev/null
@@ -0,0 +1,45 @@
+--TEST--
+clearstatcache() optionnal parameters
+--SKIPIF--
+<?php
+if (strncmp(PHP_OS, "WIN", 3) === 0) {
+    die('skip not for Windows');
+}
+?>
+--FILE--
+<?php
+
+@rmdir(__FILE__ . "_dir1");
+@rmdir(__FILE__ . "_dir2");
+@unlink(__FILE__ . "_link1");
+@unlink(__FILE__ . "_link2");
+
+mkdir(__FILE__ . "_dir1");
+mkdir(__FILE__ . "_dir2");
+symlink(__FILE__ . "_link1", __FILE__ . "_link2");
+symlink(__FILE__ . "_dir1", __FILE__ . "_link1");
+
+var_dump(realpath(__FILE__ . "_link2"));
+passthru("rm -f " . escapeshellarg(__FILE__ . "_link1"));
+var_dump(realpath(__FILE__ . "_link2"));
+clearstatcache(false);
+var_dump(realpath(__FILE__ . "_link2"));
+clearstatcache(true, "/foo/bar");
+var_dump(realpath(__FILE__ . "_link2"));
+clearstatcache(true, __FILE__ . "_link2");
+var_dump(realpath(__FILE__ . "_link2"));
+
+?>
+--CLEAN--
+<?php
+@rmdir(__FILE__ . "_dir1");
+@rmdir(__FILE__ . "_dir2");
+@unlink(__FILE__ . "_link1");
+@unlink(__FILE__ . "_link2");
+?>
+--EXPECTF--
+%unicode|string%(%d) "%s_dir1"
+%unicode|string%(%d) "%s_dir1"
+%unicode|string%(%d) "%s_dir1"
+%unicode|string%(%d) "%s_dir1"
+bool(false)
index 1ebb08888e770e3d200cdda590f11e4922951e3d..ee7d1af18c0c210cdcdab8e4e4af97eaf4a8e3cd 100644 (file)
@@ -3,17 +3,17 @@ Test clearstatcache() function: error conditions
 --FILE--
 <?php
 /*
-   Prototype: void clearstatcache (void);
+   Prototype: void clearstatcache ([bool clear_realpath_cache[, filename]]);
    Description: clears files status cache
 */
 
 echo "*** Testing clearstatcache() function: error conditions ***\n";
-var_dump( clearstatcache("file") );  //No.of args more than expected
+var_dump( clearstatcache(0, "/foo/bar", 1) );  //No.of args more than expected
 echo "*** Done ***\n";
 ?>
 --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 ***
index a8aad6003b64d2f746f91b856e0782df37874518..39ffb86172a676a4d8d86c4e7521df514f7ad714 100644 (file)
@@ -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;
 }