add test for stat interception, fix stat interception

This commit is contained in:
Greg Beaver 2008-04-13 23:33:31 +00:00
parent 1972f83385
commit c22b6a76ed
2 changed files with 282 additions and 85 deletions

View File

@ -503,81 +503,79 @@ void phar_file_stat(const char *filename, php_stat_len filename_length, int type
entry = (char *)filename;
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
entry_len = (int) filename_length;
if (strstr(entry, "://")) {
if (FAILURE == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) {
efree(arch);
goto skip_phar;
}
if (SUCCESS == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) {
entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC);
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry, entry_len, (void **) &data)) {
efree(entry);
goto stat_entry;
} else {
char *save = PHAR_G(cwd), *save2 = entry;
int save_len = PHAR_G(cwd_len), save2_len = entry_len;
entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry, entry_len, (void **) &data)) {
efree(entry);
goto stat_entry;
} else {
char *save = PHAR_G(cwd), *save2 = entry;
int save_len = PHAR_G(cwd_len), save2_len = entry_len;
/* this file is not in the current directory, use the original path */
entry = (char *)filename;
PHAR_G(cwd) = "/";
PHAR_G(cwd_len) = 0;
/* clean path without cwd */
entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC);
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry, entry_len, (void **) &data)) {
PHAR_G(cwd) = save;
PHAR_G(cwd_len) = save_len;
efree(entry);
efree(save2);
goto stat_entry;
} else {
phar_archive_data *phar = *pphar;
char *key;
uint keylen;
ulong unused;
/* original not found either, this is possibly a directory relative to cwd */
zend_hash_internal_pointer_reset(&phar->manifest);
while (FAILURE != zend_hash_has_more_elements(&phar->manifest)) {
if (HASH_KEY_NON_EXISTANT !=
zend_hash_get_current_key_ex(
&phar->manifest, &key, &keylen, &unused, 0, NULL)) {
if (0 == memcmp(save2, key, save2_len)) {
PHAR_G(cwd) = save;
PHAR_G(cwd_len) = save_len;
efree(save2);
efree(entry);
/* directory found, all dirs have the same stat */
if (key[save2_len] == '/') {
sb.st_size = 0;
sb.st_mode = 0777;
sb.st_mode |= S_IFDIR; /* regular directory */
#ifdef NETWARE
sb.st_mtime.tv_sec = phar->max_timestamp;
sb.st_atime.tv_sec = phar->max_timestamp;
sb.st_ctime.tv_sec = phar->max_timestamp;
#else
sb.st_mtime = phar->max_timestamp;
sb.st_atime = phar->max_timestamp;
sb.st_ctime = phar->max_timestamp;
#endif
goto statme_baby;
}
}
}
if (SUCCESS != zend_hash_move_forward(&phar->manifest)) {
break;
}
}
}
/* this file is not in the current directory, use the original path */
entry = (char *)filename;
PHAR_G(cwd) = "/";
PHAR_G(cwd_len) = 0;
/* clean path without cwd */
entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry + 1, entry_len - 1, (void **) &data)) {
PHAR_G(cwd) = save;
PHAR_G(cwd_len) = save_len;
efree(entry);
efree(save2);
/* Error Occured */
if (!IS_EXISTS_CHECK(type)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
goto stat_entry;
} else {
phar_archive_data *phar = *pphar;
char *key;
uint keylen;
ulong unused;
/* original not found either, this is possibly a directory relative to cwd */
zend_hash_internal_pointer_reset(&phar->manifest);
while (FAILURE != zend_hash_has_more_elements(&phar->manifest)) {
if (HASH_KEY_NON_EXISTANT !=
zend_hash_get_current_key_ex(
&phar->manifest, &key, &keylen, &unused, 0, NULL)) {
if (!memcmp(save2, key, save2_len)) {
PHAR_G(cwd) = save;
PHAR_G(cwd_len) = save_len;
efree(save2);
efree(entry);
/* directory found, all dirs have the same stat */
if (key[save2_len] == '/') {
sb.st_size = 0;
sb.st_mode = 0777;
sb.st_mode |= S_IFDIR; /* regular directory */
#ifdef NETWARE
sb.st_mtime.tv_sec = phar->max_timestamp;
sb.st_atime.tv_sec = phar->max_timestamp;
sb.st_ctime.tv_sec = phar->max_timestamp;
#else
sb.st_mtime = phar->max_timestamp;
sb.st_atime = phar->max_timestamp;
sb.st_ctime = phar->max_timestamp;
#endif
goto statme_baby;
}
}
}
if (SUCCESS != zend_hash_move_forward(&phar->manifest)) {
break;
}
}
RETURN_FALSE;
}
PHAR_G(cwd) = save;
PHAR_G(cwd_len) = save_len;
efree(entry);
efree(save2);
/* Error Occured */
if (!IS_EXISTS_CHECK(type)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "l" : "", filename);
}
RETURN_FALSE;
}
stat_entry:
if (!data->is_dir) {
@ -742,7 +740,7 @@ PHAR_FUNC(phar_is_file) /* {{{ */
}
if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
char *arch, *entry, *fname;
int arch_len, entry_len, fname_len, free_filename = 0;
int arch_len, entry_len, fname_len;
fname = zend_get_executed_filename(TSRMLS_C);
/* we are checking for existence of a file within the relative path. Chances are good that this is
@ -759,17 +757,10 @@ PHAR_FUNC(phar_is_file) /* {{{ */
entry = filename;
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
entry_len = filename_len;
if (strstr(entry, "://")) {
efree(arch);
if (free_filename) {
efree(filename);
}
goto skip_phar;
}
/* retrieving a file within the current directory, so use this if possible */
if (SUCCESS == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) {
entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC);
if (zend_hash_exists(&((*pphar)->manifest), entry, entry_len)) {
entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
if (zend_hash_exists(&((*pphar)->manifest), entry + 1, entry_len - 1)) {
/* this file is not in the current directory, use the original path */
efree(entry);
efree(arch);
@ -797,7 +788,7 @@ PHAR_FUNC(phar_is_link) /* {{{ */
}
if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
char *arch, *entry, *fname;
int arch_len, entry_len, fname_len, free_filename = 0;
int arch_len, entry_len, fname_len;
fname = zend_get_executed_filename(TSRMLS_C);
/* we are checking for existence of a file within the relative path. Chances are good that this is
@ -814,19 +805,12 @@ PHAR_FUNC(phar_is_link) /* {{{ */
entry = filename;
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
entry_len = filename_len;
if (strstr(entry, "://")) {
efree(arch);
if (free_filename) {
efree(filename);
}
goto skip_phar;
}
/* retrieving a file within the current directory, so use this if possible */
if (SUCCESS == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) {
phar_entry_info *etemp;
entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC);
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry, entry_len, (void **) &etemp)) {
entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry + 1, entry_len - 1, (void **) &etemp)) {
/* this file is not in the current directory, use the original path */
efree(entry);
efree(arch);

213
ext/phar/tests/stat.phpt Normal file
View File

@ -0,0 +1,213 @@
--TEST--
Phar: test stat function interceptions
--SKIPIF--
<?php if (!extension_loaded("phar")) die("skip");?>
--INI--
phar.require_hash=1
phar.readonly=0
--FILE--
<?php
Phar::interceptFileFuncs();
var_dump(stat(""));
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
$a = new Phar($fname);
$a['index.php'] = '<?php
echo "stat\n";
var_dump(stat("dir/file1.txt"));
echo "lstat\n";
var_dump(lstat("dir/file1.txt"));
echo "fileperms\n";
var_dump(fileperms("dir/file1.txt"));
echo "fileinode\n";
var_dump(fileinode("dir/file1.txt"));
echo "filesize\n";
var_dump(filesize("dir/file1.txt"));
echo "fileowner\n";
var_dump(fileowner("dir/file1.txt"));
echo "filegroup\n";
var_dump(filegroup("dir/file1.txt"));
echo "filemtime\n";
var_dump(filemtime("dir/file1.txt"));
echo "fileatime\n";
var_dump(fileatime("dir/file1.txt"));
echo "filectime\n";
var_dump(filectime("dir/file1.txt"));
echo "filetype\n";
var_dump(filetype("dir/file1.txt"));
echo "is_writable\n";
var_dump(is_writable("dir/file1.txt"));
echo "is_writeable\n";
var_dump(is_writeable("dir/file1.txt"));
echo "is_readable\n";
var_dump(is_readable("dir/file1.txt"));
echo "is_executable\n";
var_dump(is_executable("dir/file1.txt"));
echo "file_exists\n";
var_dump(file_exists("dir/file1.txt"));
echo "is_dir\n";
var_dump(is_dir("dir/file1.txt"));
echo "is_file\n";
var_dump(is_file("dir/file1.txt"));
echo "is_link\n";
var_dump(is_link("dir/file1.txt"));
?>';
$a['dir/file1.txt'] = 'hi';
$a['dir/file2.txt'] = 'hi2';
$a['dir/file3.txt'] = 'hi3';
$a->setStub('<?php
set_include_path("phar://" . __FILE__ . "/dir" . PATH_SEPARATOR . "phar://" . __FILE__);
include "index.php";
__HALT_COMPILER();');
include $fname;
?>
===DONE===
--CLEAN--
<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
--EXPECTF--
bool(false)
stat
array(26) {
[0]=>
int(12)
[1]=>
int(51855)
[2]=>
int(33206)
[3]=>
int(1)
[4]=>
int(0)
[5]=>
int(0)
[6]=>
int(%s)
[7]=>
int(2)
[8]=>
int(%d)
[9]=>
int(%d)
[10]=>
int(%d)
[11]=>
int(%s)
[12]=>
int(%s)
["dev"]=>
int(12)
["ino"]=>
int(51855)
["mode"]=>
int(33206)
["nlink"]=>
int(1)
["uid"]=>
int(0)
["gid"]=>
int(0)
["rdev"]=>
int(%s)
["size"]=>
int(2)
["atime"]=>
int(%d)
["mtime"]=>
int(%d)
["ctime"]=>
int(%d)
["blksize"]=>
int(%s)
["blocks"]=>
int(%s)
}
lstat
array(26) {
[0]=>
int(12)
[1]=>
int(51855)
[2]=>
int(33206)
[3]=>
int(1)
[4]=>
int(0)
[5]=>
int(0)
[6]=>
int(%s)
[7]=>
int(2)
[8]=>
int(%d)
[9]=>
int(%d)
[10]=>
int(%d)
[11]=>
int(%s)
[12]=>
int(%s)
["dev"]=>
int(12)
["ino"]=>
int(51855)
["mode"]=>
int(33206)
["nlink"]=>
int(1)
["uid"]=>
int(0)
["gid"]=>
int(0)
["rdev"]=>
int(%s)
["size"]=>
int(2)
["atime"]=>
int(%d)
["mtime"]=>
int(%d)
["ctime"]=>
int(%d)
["blksize"]=>
int(%s)
["blocks"]=>
int(%s)
}
fileperms
int(33206)
fileinode
int(51855)
filesize
int(2)
fileowner
int(0)
filegroup
int(0)
filemtime
int(%d)
fileatime
int(%d)
filectime
int(%d)
filetype
string(4) "file"
is_writable
bool(true)
is_writeable
bool(false)
is_readable
bool(true)
is_executable
bool(false)
file_exists
bool(true)
is_dir
bool(false)
is_file
bool(true)
is_link
bool(false)
===DONE===