Skip to content
Closed
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Zend/zend_virtual_cwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ static void cwd_globals_ctor(virtual_cwd_globals *cwd_g) /* {{{ */
cwd_g->realpath_cache_size = 0;
cwd_g->realpath_cache_size_limit = REALPATH_CACHE_SIZE;
cwd_g->realpath_cache_ttl = REALPATH_CACHE_TTL;
cwd_g->enable_stat_cache = 1;
memset(cwd_g->realpath_cache, 0, sizeof(cwd_g->realpath_cache));
}
/* }}} */
Expand Down
1 change: 1 addition & 0 deletions Zend/zend_virtual_cwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ typedef struct _virtual_cwd_globals {
zend_long realpath_cache_size;
zend_long realpath_cache_size_limit;
zend_long realpath_cache_ttl;
bool enable_stat_cache;
realpath_cache_bucket *realpath_cache[1024];
} virtual_cwd_globals;

Expand Down
53 changes: 53 additions & 0 deletions ext/standard/tests/file/bug28790.cache.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
--TEST--
Bug #28790: Add php.ini option to disable stat cache (with cache)
--CREDITS--
jnoll <jnoll [at] prim [dot] hu>
Kevin Lyda <kevin [at] lyda [dot] ie>
--FILE--
<?php

$php = '"'.getenv('TEST_PHP_EXECUTABLE').'"';
$phpfile = getenv('TEST_PHP_EXECUTABLE');
$impossiblefile = $phpfile.DIRECTORY_SEPARATOR.'bug28790.impossible';
$testfile = __DIR__.DIRECTORY_SEPARATOR.'bug28790.file';

function all_the_stats($filename, $message) {
if (@lstat($filename)) {
print("lstat: $message.\n");
}
if (@stat($filename)) {
print("stat: $message.\n");
}
}

// Windows can use / for dir separators, so let's do that.
$qtestfile = str_replace("\\", "/", "$testfile");
passthru($php.' -n -r "touch(\\"'.$qtestfile.'\\");"');
all_the_stats("$testfile", "testfile exists");
passthru($php.' -n -r "unlink(\\"'.$qtestfile.'\\");"');
all_the_stats("$testfile", "testfile exists (it shouldn't)");
if (!@stat("$impossiblefile")) {
print("stat impossiblefile does not exist.\n");
}
all_the_stats("$testfile", "testfile exists (it shouldn't)");
if (is_file("$phpfile")) {
print("is_file(stat): php binary exists.\n");
}
all_the_stats("$testfile", "testfile exists (it shouldn't)");
if (lstat("$phpfile")) {
print("lstat: php binary exists.\n");
}
all_the_stats("$testfile", "testfile exists (it shouldn't)");

?>
--EXPECT--
lstat: testfile exists.
stat: testfile exists.
lstat: testfile exists (it shouldn't).
stat: testfile exists (it shouldn't).
stat impossiblefile does not exist.
lstat: testfile exists (it shouldn't).
stat: testfile exists (it shouldn't).
is_file(stat): php binary exists.
lstat: testfile exists (it shouldn't).
lstat: php binary exists.
50 changes: 50 additions & 0 deletions ext/standard/tests/file/bug28790.no-cache.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
--TEST--
Bug #28790: Add php.ini option to disable stat cache (without cache)
--CREDITS--
jnoll <jnoll [at] prim [dot] hu>
Kevin Lyda <kevin [at] lyda [dot] ie>
--INI--
enable_stat_cache = False
--FILE--
<?php

$php = '"'.getenv('TEST_PHP_EXECUTABLE').'"';
$phpfile = getenv('TEST_PHP_EXECUTABLE');
$impossiblefile = $phpfile.DIRECTORY_SEPARATOR.'bug28790.impossible';
$testfile = __DIR__.DIRECTORY_SEPARATOR.'bug28790.file';

function all_the_stats($filename, $message) {
if (@lstat($filename)) {
print("lstat: $message.\n");
}
if (@stat($filename)) {
print("stat: $message.\n");
}
}

// Windows can use / for dir separators, so let's do that.
$qtestfile = str_replace("\\", "/", "$testfile");
passthru($php.' -n -r "touch(\\"'.$qtestfile.'\\");"');
all_the_stats("$testfile", "testfile exists");
passthru($php.' -n -r "unlink(\\"'.$qtestfile.'\\");"');
all_the_stats("$testfile", "testfile exists (it shouldn't)");
if (!@stat("$impossiblefile")) {
print("stat impossiblefile does not exist.\n");
}
all_the_stats("$testfile", "testfile exists (it shouldn't)");
if (is_file("$phpfile")) {
print("is_file(stat): php binary exists.\n");
}
all_the_stats("$testfile", "testfile exists (it shouldn't)");
if (lstat("$phpfile")) {
print("lstat: php binary exists.\n");
}
all_the_stats("$testfile", "testfile exists (it shouldn't)");

?>
--EXPECT--
lstat: testfile exists.
stat: testfile exists.
stat impossiblefile does not exist.
is_file(stat): php binary exists.
lstat: php binary exists.
1 change: 1 addition & 0 deletions main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,7 @@ PHP_INI_BEGIN()

STD_PHP_INI_ENTRY("realpath_cache_size", "4096K", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_ttl, virtual_cwd_globals, cwd_globals)
STD_PHP_INI_BOOLEAN("enable_stat_cache", "1", PHP_INI_SYSTEM, OnUpdateBool, enable_stat_cache, virtual_cwd_globals, cwd_globals)

STD_PHP_INI_ENTRY("user_ini.filename", ".user.ini", PHP_INI_SYSTEM, OnUpdateString, user_ini_filename, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("user_ini.cache_ttl", "300", PHP_INI_SYSTEM, OnUpdateLong, user_ini_cache_ttl, php_core_globals, core_globals)
Expand Down
4 changes: 2 additions & 2 deletions main/streams/streams.c
Original file line number Diff line number Diff line change
Expand Up @@ -1959,7 +1959,7 @@ PHPAPI int _php_stream_stat_path(const char *path, int flags, php_stream_statbuf

memset(ssb, 0, sizeof(*ssb));

if (!(flags & PHP_STREAM_URL_STAT_NOCACHE)) {
if (CWDG(enable_stat_cache) && !(flags & PHP_STREAM_URL_STAT_NOCACHE)) {
/* Try to hit the cache first */
if (flags & PHP_STREAM_URL_STAT_LINK) {
if (BG(CurrentLStatFile) && strcmp(path, BG(CurrentLStatFile)) == 0) {
Expand All @@ -1978,7 +1978,7 @@ PHPAPI int _php_stream_stat_path(const char *path, int flags, php_stream_statbuf
if (wrapper && wrapper->wops->url_stat) {
ret = wrapper->wops->url_stat(wrapper, path_to_open, flags, ssb, context);
if (ret == 0) {
if (!(flags & PHP_STREAM_URL_STAT_NOCACHE)) {
if (CWDG(enable_stat_cache) && !(flags & PHP_STREAM_URL_STAT_NOCACHE)) {
/* Drop into cache */
if (flags & PHP_STREAM_URL_STAT_LINK) {
if (BG(CurrentLStatFile)) {
Expand Down
6 changes: 6 additions & 0 deletions php.ini-development
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,12 @@ disable_classes =
; http://php.net/realpath-cache-ttl
;realpath_cache_ttl = 120

; Allows user to disable the "stat cache." By default php remembers the
; results of the last call to stat() and lstat() and functions that call
; it underneath. Setting this to False disables that behaviour.
; http://php.net/enable-stat-cache
;enable_stat_cache = On

; Enables or disables the circular reference collector.
; http://php.net/zend.enable-gc
zend.enable_gc = On
Expand Down
6 changes: 6 additions & 0 deletions php.ini-production
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,12 @@ disable_classes =
; http://php.net/realpath-cache-ttl
;realpath_cache_ttl = 120

; Allows user to disable the "stat cache." By default php remembers the
; results of the last call to stat() and lstat() and functions that call
; it underneath. Setting this to True disables that behaviour.
; http://php.net/enable-stat-cache
;enable_stat_cache = On

; Enables or disables the circular reference collector.
; http://php.net/zend.enable-gc
zend.enable_gc = On
Expand Down