diff options
-rw-r--r-- | ext/spl/config.m4 | 1 | ||||
-rw-r--r-- | ext/spl/spl_directory.c | 225 | ||||
-rw-r--r-- | ext/spl/tests/SplFileObject_fstat_with_basic_fstat_disabled.phpt | 64 | ||||
-rw-r--r-- | ext/standard/file.c | 33 | ||||
-rw-r--r-- | ext/standard/file.h | 1 | ||||
-rw-r--r-- | ext/standard/flock_compat.c | 11 | ||||
-rw-r--r-- | ext/standard/flock_compat.h | 11 |
7 files changed, 185 insertions, 161 deletions
diff --git a/ext/spl/config.m4 b/ext/spl/config.m4 index 8e0d31f3e2..6e6973646d 100644 --- a/ext/spl/config.m4 +++ b/ext/spl/config.m4 @@ -1,3 +1,4 @@ PHP_NEW_EXTENSION(spl, php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fixedarray.c, no,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_INSTALL_HEADERS([ext/spl], [php_spl.h spl_array.h spl_directory.h spl_engine.h spl_exceptions.h spl_functions.h spl_iterators.h spl_observer.h spl_dllist.h spl_heap.h spl_fixedarray.h]) PHP_ADD_EXTENSION_DEP(spl, pcre, true) +PHP_ADD_EXTENSION_DEP(spl, standard, true) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 0836e18bc4..e7bc262da5 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -20,10 +20,11 @@ #include "php.h" #include "php_ini.h" -#include "ext/standard/info.h" #include "ext/standard/file.h" +#include "ext/standard/php_filestat.h" +#include "ext/standard/flock_compat.h" +#include "ext/standard/scanf.h" #include "ext/standard/php_string.h" -#include "zend_compile.h" #include "zend_exceptions.h" #include "zend_interfaces.h" @@ -35,12 +36,6 @@ #include "spl_directory_arginfo.h" #include "spl_exceptions.h" -#include "php.h" -#include "fopen_wrappers.h" - -#include "ext/standard/basic_functions.h" -#include "ext/standard/php_filestat.h" - #define SPL_HAS_FLAG(flags, test_flag) ((flags & test_flag) ? 1 : 0) /* declare the class handlers */ @@ -57,6 +52,13 @@ PHPAPI zend_class_entry *spl_ce_GlobIterator; PHPAPI zend_class_entry *spl_ce_SplFileObject; PHPAPI zend_class_entry *spl_ce_SplTempFileObject; +// TODO Use standard Error +#define CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(spl_filesystem_object_pointer) \ + if (!(spl_filesystem_object_pointer)->u.file.stream) { \ + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); \ + RETURN_THROWS(); \ + } + static void spl_filesystem_file_free_line(spl_filesystem_object *intern) /* {{{ */ { if (intern->u.file.current_line) { @@ -1901,64 +1903,6 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent) / return SUCCESS; } /* }}} */ -static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function *func_ptr, int pass_num_args, zval *return_value, zval *arg2) /* {{{ */ -{ - zend_fcall_info fci; - zend_fcall_info_cache fcic; - zval *zresource_ptr = &intern->u.file.zresource, *params; - int result; - int num_args = pass_num_args + (arg2 ? 2 : 1); - - if (Z_ISUNDEF_P(zresource_ptr)) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - return FAILURE; - } - - params = (zval*)safe_emalloc(num_args, sizeof(zval), 0); - params[0] = *zresource_ptr; - - if (arg2) { - params[1] = *arg2; - } - - if (zend_get_parameters_array_ex(pass_num_args, params + (arg2 ? 2 : 1)) != SUCCESS) { - efree(params); - WRONG_PARAM_COUNT_WITH_RETVAL(FAILURE); - } - - fci.size = sizeof(fci); - fci.object = NULL; - fci.retval = return_value; - fci.param_count = num_args; - fci.params = params; - fci.named_params = NULL; - ZVAL_STR(&fci.function_name, func_ptr->common.function_name); - - fcic.function_handler = func_ptr; - fcic.called_scope = NULL; - fcic.object = NULL; - - result = zend_call_function(&fci, &fcic); - - if (result == FAILURE || Z_ISUNDEF_P(return_value)) { - RETVAL_FALSE; - } - - efree(params); - return result; -} /* }}} */ - -#define FileFunctionCall(func_name, pass_num_args, arg2) /* {{{ */ \ -{ \ - zend_function *func_ptr; \ - func_ptr = (zend_function *)zend_hash_str_find_ptr(EG(function_table), #func_name, sizeof(#func_name) - 1); \ - if (func_ptr == NULL) { \ - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Internal error, function %s() not found. Please report", #func_name); \ - return; \ - } \ - spl_filesystem_file_call(intern, func_ptr, pass_num_args, return_value, arg2); \ -} /* }}} */ - static int spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, int escape, zval *return_value) /* {{{ */ { int ret = SUCCESS; @@ -2075,7 +2019,7 @@ static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *intern) /* {{{ */ { - if(!intern->u.file.stream) { + if (!intern->u.file.stream) { zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); return; } @@ -2203,10 +2147,7 @@ PHP_METHOD(SplFileObject, eof) RETURN_THROWS(); } - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); RETURN_BOOL(php_stream_eof(intern->u.file.stream)); } /* }}} */ @@ -2239,10 +2180,7 @@ PHP_METHOD(SplFileObject, fgets) RETURN_THROWS(); } - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); if (spl_filesystem_file_read(intern, 0) == FAILURE) { RETURN_FALSE; @@ -2259,10 +2197,7 @@ PHP_METHOD(SplFileObject, current) RETURN_THROWS(); } - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) { spl_filesystem_file_read_line(ZEND_THIS, intern, 1); @@ -2382,15 +2317,6 @@ PHP_METHOD(SplFileObject, getChildren) /* return NULL */ } /* }}} */ -/* {{{ FileFunction */ -#define FileFunction(func_name) \ -PHP_METHOD(SplFileObject, func_name) \ -{ \ - spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); \ - FileFunctionCall(func_name, ZEND_NUM_ARGS(), NULL); \ -} -/* }}} */ - /* {{{ Return current line as csv */ PHP_METHOD(SplFileObject, fgetcsv) { @@ -2402,10 +2328,7 @@ PHP_METHOD(SplFileObject, fgetcsv) if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) { - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); switch(ZEND_NUM_ARGS()) { @@ -2570,8 +2493,43 @@ PHP_METHOD(SplFileObject, getCsvControl) } /* }}} */ -/* {{{ Portable file locking */ -FileFunction(flock) +static int flock_values[] = { LOCK_SH, LOCK_EX, LOCK_UN }; + +/* {{{ Portable file locking, copy pasted from ext/standard/file.c flock() function. + * This is done to prevent this to fail if flock is disabled via disable_functions */ +PHP_METHOD(SplFileObject, flock) +{ + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + zval *wouldblock = NULL; + int act; + zend_long operation = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|z", &operation, &wouldblock) == FAILURE) { + RETURN_THROWS(); + } + + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); + + act = operation & PHP_LOCK_UN; + if (act < 1 || act > 3) { + zend_argument_value_error(1, "must be either LOCK_SH, LOCK_EX, or LOCK_UN"); + RETURN_THROWS(); + } + + if (wouldblock) { + ZEND_TRY_ASSIGN_REF_LONG(wouldblock, 0); + } + + /* flock_values contains all possible actions if (operation & PHP_LOCK_NB) we won't block on the lock */ + act = flock_values[act - 1] | (operation & PHP_LOCK_NB ? LOCK_NB : 0); + if (php_stream_lock(intern->u.file.stream, act)) { + if (operation && errno == EWOULDBLOCK && wouldblock) { + ZEND_TRY_ASSIGN_REF_LONG(wouldblock, 1); + } + RETURN_FALSE; + } + RETURN_TRUE; +} /* }}} */ /* {{{ Flush the file */ @@ -2579,10 +2537,7 @@ PHP_METHOD(SplFileObject, fflush) { spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); RETURN_BOOL(!php_stream_flush(intern->u.file.stream)); } /* }}} */ @@ -2593,10 +2548,7 @@ PHP_METHOD(SplFileObject, ftell) spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); zend_long ret; - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); ret = php_stream_tell(intern->u.file.stream); @@ -2617,10 +2569,7 @@ PHP_METHOD(SplFileObject, fseek) RETURN_THROWS(); } - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); spl_filesystem_file_free_line(intern); RETURN_LONG(php_stream_seek(intern->u.file.stream, pos, (int)whence)); @@ -2633,10 +2582,7 @@ PHP_METHOD(SplFileObject, fgetc) char buf[2]; int result; - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); spl_filesystem_file_free_line(intern); @@ -2660,10 +2606,7 @@ PHP_METHOD(SplFileObject, fpassthru) { spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); RETURN_LONG(php_stream_passthru(intern->u.file.stream)); } /* }}} */ @@ -2671,17 +2614,27 @@ PHP_METHOD(SplFileObject, fpassthru) /* {{{ Implements a mostly ANSI compatible fscanf() */ PHP_METHOD(SplFileObject, fscanf) { + int result, num_varargs = 0; + zend_string *format_str; + zval *varargs= NULL; spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S*", &format_str, &varargs, &num_varargs) == FAILURE) { RETURN_THROWS(); } - spl_filesystem_file_free_line(intern); - intern->u.file.current_line_num++; + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); - FileFunctionCall(fscanf, ZEND_NUM_ARGS(), NULL); + /* Get next line */ + if (spl_filesystem_file_read(intern, 0) == FAILURE) { + RETURN_THROWS(); + } + + result = php_sscanf_internal(intern->u.file.current_line, ZSTR_VAL(format_str), num_varargs, varargs, 0, return_value); + + if (SCAN_ERROR_WRONG_PARAM_COUNT == result) { + WRONG_PARAM_COUNT; + } } /* }}} */ @@ -2698,10 +2651,7 @@ PHP_METHOD(SplFileObject, fwrite) RETURN_THROWS(); } - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); if (ZEND_NUM_ARGS() > 1) { if (length >= 0) { @@ -2732,10 +2682,7 @@ PHP_METHOD(SplFileObject, fread) RETURN_THROWS(); } - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); if (length <= 0) { php_error_docref(NULL, E_WARNING, "Length parameter must be greater than 0"); @@ -2750,7 +2697,18 @@ PHP_METHOD(SplFileObject, fread) } /* {{{ Stat() on a filehandle */ -FileFunction(fstat) +PHP_METHOD(SplFileObject, fstat) +{ + spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); + + php_fstat(intern->u.file.stream, return_value); +} /* }}} */ /* {{{ Truncate file to 'size' length */ @@ -2763,10 +2721,7 @@ PHP_METHOD(SplFileObject, ftruncate) RETURN_THROWS(); } - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); if (!php_stream_truncate_supported(intern->u.file.stream)) { zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't truncate file %s", intern->file_name); @@ -2785,10 +2740,8 @@ PHP_METHOD(SplFileObject, seek) if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &line_pos) == FAILURE) { RETURN_THROWS(); } - if(!intern->u.file.stream) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); - RETURN_THROWS(); - } + + CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); if (line_pos < 0) { zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't seek file %s to negative line " ZEND_LONG_FMT, intern->file_name, line_pos); diff --git a/ext/spl/tests/SplFileObject_fstat_with_basic_fstat_disabled.phpt b/ext/spl/tests/SplFileObject_fstat_with_basic_fstat_disabled.phpt new file mode 100644 index 0000000000..dda7f1e428 --- /dev/null +++ b/ext/spl/tests/SplFileObject_fstat_with_basic_fstat_disabled.phpt @@ -0,0 +1,64 @@ +--TEST-- +SplFileObject::fstat when fstat() has been disabled. +--INI-- +disable_functions="fstat" +--FILE-- +<?php +$obj = New SplFileObject(__DIR__.'/SplFileObject_testinput.csv'); +var_dump($obj->fstat()); +?> +--EXPECTF-- +array(26) { + [0]=> + int(%i) + [1]=> + int(%i) + [2]=> + int(%i) + [3]=> + int(%i) + [4]=> + int(%i) + [5]=> + int(%i) + [6]=> + int(%i) + [7]=> + int(%i) + [8]=> + int(%i) + [9]=> + int(%i) + [10]=> + int(%i) + [11]=> + int(%i) + [12]=> + int(%i) + ["dev"]=> + int(%i) + ["ino"]=> + int(%i) + ["mode"]=> + int(%i) + ["nlink"]=> + int(%i) + ["uid"]=> + int(%i) + ["gid"]=> + int(%i) + ["rdev"]=> + int(%i) + ["size"]=> + int(%i) + ["atime"]=> + int(%i) + ["mtime"]=> + int(%i) + ["ctime"]=> + int(%i) + ["blksize"]=> + int(%i) + ["blocks"]=> + int(%i) +} diff --git a/ext/standard/file.c b/ext/standard/file.c index 9c08d16329..d402c60acf 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -344,7 +344,7 @@ PHP_FUNCTION(flock) PHP_STREAM_TO_ZVAL(stream, res); - act = operation & 3; + act = operation & PHP_LOCK_UN; if (act < 1 || act > 3) { zend_argument_value_error(2, "must be either LOCK_SH, LOCK_EX, or LOCK_UN"); RETURN_THROWS(); @@ -354,7 +354,7 @@ PHP_FUNCTION(flock) ZEND_TRY_ASSIGN_REF_LONG(wouldblock, 0); } - /* flock_values contains all possible actions if (operation & 4) we won't block on the lock */ + /* flock_values contains all possible actions if (operation & PHP_LOCK_NB) we won't block on the lock */ act = flock_values[act - 1] | (operation & PHP_LOCK_NB ? LOCK_NB : 0); if (php_stream_lock(stream, act)) { if (operation && errno == EWOULDBLOCK && wouldblock) { @@ -1487,26 +1487,16 @@ PHP_FUNCTION(ftruncate) RETURN_BOOL(0 == php_stream_truncate_set_size(stream, size)); } /* }}} */ - -/* {{{ Stat() on a filehandle */ -PHP_FUNCTION(fstat) +PHPAPI void php_fstat(php_stream *stream, zval *return_value) { - zval *fp; + php_stream_statbuf stat_ssb; zval stat_dev, stat_ino, stat_mode, stat_nlink, stat_uid, stat_gid, stat_rdev, stat_size, stat_atime, stat_mtime, stat_ctime, stat_blksize, stat_blocks; - php_stream *stream; - php_stream_statbuf stat_ssb; char *stat_sb_names[13] = { "dev", "ino", "mode", "nlink", "uid", "gid", "rdev", "size", "atime", "mtime", "ctime", "blksize", "blocks" }; - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(fp) - ZEND_PARSE_PARAMETERS_END(); - - PHP_STREAM_TO_ZVAL(stream, fp); - if (php_stream_stat(stream, &stat_ssb)) { RETURN_FALSE; } @@ -1568,6 +1558,21 @@ PHP_FUNCTION(fstat) zend_hash_str_add_new(Z_ARRVAL_P(return_value), stat_sb_names[11], strlen(stat_sb_names[11]), &stat_blksize); zend_hash_str_add_new(Z_ARRVAL_P(return_value), stat_sb_names[12], strlen(stat_sb_names[12]), &stat_blocks); } + +/* {{{ Stat() on a filehandle */ +PHP_FUNCTION(fstat) +{ + zval *fp; + php_stream *stream; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_RESOURCE(fp) + ZEND_PARSE_PARAMETERS_END(); + + PHP_STREAM_TO_ZVAL(stream, fp); + + php_fstat(stream, return_value); +} /* }}} */ /* {{{ Copy a file */ diff --git a/ext/standard/file.h b/ext/standard/file.h index 28f906e0ba..1faf667a00 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -43,6 +43,7 @@ PHPAPI int php_copy_file_ex(const char *src, const char *dest, int src_chk); PHPAPI int php_copy_file_ctx(const char *src, const char *dest, int src_chk, php_stream_context *ctx); PHPAPI int php_mkdir_ex(const char *dir, zend_long mode, int options); PHPAPI int php_mkdir(const char *dir, zend_long mode); +PHPAPI void php_fstat(php_stream *stream, zval *return_value); #define PHP_CSV_NO_ESCAPE EOF PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, int escape_char, size_t buf_len, char *buf, zval *return_value); diff --git a/ext/standard/flock_compat.c b/ext/standard/flock_compat.c index 6751aedfc1..7b0ad2df23 100644 --- a/ext/standard/flock_compat.c +++ b/ext/standard/flock_compat.c @@ -18,17 +18,6 @@ #include <errno.h> #include "ext/standard/flock_compat.h" -#if HAVE_STRUCT_FLOCK -#include <unistd.h> -#include <fcntl.h> -#include <sys/file.h> -#endif - -#ifdef PHP_WIN32 -#include <io.h> -#include "config.w32.h" -#endif - #ifndef HAVE_FLOCK PHPAPI int flock(int fd, int operation) { diff --git a/ext/standard/flock_compat.h b/ext/standard/flock_compat.h index 7c875792c6..11ed38b4ba 100644 --- a/ext/standard/flock_compat.h +++ b/ext/standard/flock_compat.h @@ -17,6 +17,17 @@ #ifndef FLOCK_COMPAT_H #define FLOCK_COMPAT_H +#if HAVE_STRUCT_FLOCK +#include <unistd.h> +#include <fcntl.h> +#include <sys/file.h> +#endif + +#ifdef PHP_WIN32 +#include <io.h> +#include "config.w32.h" +#endif + /* php_flock internally uses fcntl whether or not flock is available * This way our php_flock even works on NFS files. * More info: /usr/src/linux/Documentation |