diff --git a/ext/reflection/tests/ReflectionExtension_getClassNames_basic.phpt b/ext/reflection/tests/ReflectionExtension_getClassNames_basic.phpt index 4f1da6fc6677e..f5697e0bc667d 100644 --- a/ext/reflection/tests/ReflectionExtension_getClassNames_basic.phpt +++ b/ext/reflection/tests/ReflectionExtension_getClassNames_basic.phpt @@ -8,7 +8,7 @@ $standard = new ReflectionExtension('standard'); var_dump($standard->getClassNames()); ?> --EXPECT-- -array(9) { +array(11) { [0]=> string(22) "__PHP_Incomplete_Class" [1]=> @@ -18,13 +18,17 @@ array(9) { [3]=> string(15) "FileSystemError" [4]=> - string(23) "InsufficientPermissions" + string(12) "FileNotFound" [5]=> - string(16) "TemporaryFailure" + string(12) "NotDirectory" [6]=> - string(15) "php_user_filter" + string(23) "InsufficientPermissions" [7]=> - string(9) "Directory" + string(16) "TemporaryFailure" [8]=> + string(15) "php_user_filter" + [9]=> + string(9) "Directory" + [10]=> string(14) "AssertionError" } diff --git a/ext/standard/dir.c b/ext/standard/dir.c index 69c9de886d7da..fbef40f60ce66 100644 --- a/ext/standard/dir.c +++ b/ext/standard/dir.c @@ -279,7 +279,7 @@ PHP_FUNCTION(chroot) ret = chroot(str); if (ret != 0) { - php_exception_or_warning_docref(NULL, zend_ce_filesystem_error, "%s (errno %d)", strerror(errno), errno); + handle_io_error(errno, str); RETURN_FALSE; } diff --git a/ext/standard/io_exceptions.c b/ext/standard/io_exceptions.c index a86e9b4cbe5b7..1a4e5f70e0c53 100644 --- a/ext/standard/io_exceptions.c +++ b/ext/standard/io_exceptions.c @@ -24,6 +24,8 @@ PHPAPI zend_class_entry *zend_ce_filesystem; PHPAPI zend_class_entry *zend_ce_network; PHPAPI zend_class_entry *zend_ce_filesystem_error; +PHPAPI zend_class_entry *zend_ce_file_not_found; +PHPAPI zend_class_entry *zend_ce_not_directory; PHPAPI zend_class_entry *zend_ce_insufficient_permissions; PHPAPI zend_class_entry *zend_ce_temporary_failure; @@ -42,6 +44,14 @@ PHP_MINIT_FUNCTION(io_exceptions) { zend_ce_filesystem_error = zend_register_internal_class_ex(&ce, zend_ce_exception); zend_class_implements(zend_ce_filesystem_error, 1, zend_ce_filesystem); + INIT_CLASS_ENTRY(ce, "FileNotFound", class_FileNotFound_methods); + zend_ce_file_not_found = zend_register_internal_class_ex(&ce, zend_ce_exception); + zend_class_implements(zend_ce_file_not_found, 1, zend_ce_filesystem); + + INIT_CLASS_ENTRY(ce, "NotDirectory", class_FileNotFound_methods); + zend_ce_not_directory = zend_register_internal_class_ex(&ce, zend_ce_exception); + zend_class_implements(zend_ce_not_directory, 1, zend_ce_filesystem); + INIT_CLASS_ENTRY(ce, "InsufficientPermissions", class_InsufficientPermissions_methods); zend_ce_insufficient_permissions = zend_register_internal_class_ex(&ce, zend_ce_exception); zend_class_implements(zend_ce_insufficient_permissions, 1, zend_ce_filesystem); @@ -52,3 +62,20 @@ PHP_MINIT_FUNCTION(io_exceptions) { return SUCCESS; } + +PHPAPI void handle_io_error(int error, const char *path) { + if (path == NULL) { + path = "[unknown]"; + } + switch (error) { + case ENOENT: + php_exception_or_warning_docref(NULL, zend_ce_file_not_found, "File not found: \"%s\"", path); + break; + case ENOTDIR: + php_exception_or_warning_docref(NULL, zend_ce_not_directory, "\"%s\" is not a directory", path); + break; + default: + php_exception_or_warning_docref(NULL, zend_ce_filesystem_error, "%s (path: \"%s\", errno %d)", strerror(errno), path, errno); + break; + } +} diff --git a/ext/standard/io_exceptions.h b/ext/standard/io_exceptions.h index ab653b2253277..1f4c36b8400b7 100644 --- a/ext/standard/io_exceptions.h +++ b/ext/standard/io_exceptions.h @@ -24,9 +24,13 @@ BEGIN_EXTERN_C() extern PHPAPI zend_class_entry *zend_ce_filesystem; extern PHPAPI zend_class_entry *zend_ce_network; extern PHPAPI zend_class_entry *zend_ce_filesystem_error; +extern PHPAPI zend_class_entry *zend_ce_file_not_found; +extern PHPAPI zend_class_entry *zend_ce_not_directory; extern PHPAPI zend_class_entry *zend_ce_insufficient_permissions; extern PHPAPI zend_class_entry *zend_ce_temporary_failure; END_EXTERN_C() +PHPAPI void handle_io_error(int error, const char *path); + #endif /* PHP_IO_EXCEPTION */ diff --git a/ext/standard/io_exceptions.stub.php b/ext/standard/io_exceptions.stub.php index 8e93b24c66af9..06dae6d317e14 100644 --- a/ext/standard/io_exceptions.stub.php +++ b/ext/standard/io_exceptions.stub.php @@ -9,6 +9,10 @@ interface Network extends IO {} /* Should use more specialized ones instead but for PoC will use this instead */ class FileSystemError extends Exception implements FileSystem {} +class FileNotFound extends Exception implements FileSystem {} + +class NotDirectory extends Exception implements FileSystem {} + class InsufficientPermissions extends Exception implements FileSystem {} class TemporaryFailure extends Exception implements Network {} diff --git a/ext/standard/io_exceptions_arginfo.h b/ext/standard/io_exceptions_arginfo.h index afc77e11761e5..2b8acb4bdbebf 100644 --- a/ext/standard/io_exceptions_arginfo.h +++ b/ext/standard/io_exceptions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 68880a94d8393c0d367cee9e9c18c8ac6d16d9f2 */ + * Stub hash: c4ecc9d6fb58a424dc63d5c5a039843b89273142 */ @@ -19,6 +19,16 @@ static const zend_function_entry class_FileSystemError_methods[] = { }; +static const zend_function_entry class_FileNotFound_methods[] = { + ZEND_FE_END +}; + + +static const zend_function_entry class_NotDirectory_methods[] = { + ZEND_FE_END +}; + + static const zend_function_entry class_InsufficientPermissions_methods[] = { ZEND_FE_END }; diff --git a/ext/standard/tests/dir/chroot_throw_on_error.phpt b/ext/standard/tests/dir/chroot_throw_on_error.phpt new file mode 100644 index 0000000000000..27b8ac373c590 --- /dev/null +++ b/ext/standard/tests/dir/chroot_throw_on_error.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test chroot() function error conditions with throw on error declare enabled - Non-existent directory +--SKIPIF-- + +--FILE-- +getMessage() . \PHP_EOL; +} + +?> +--EXPECTF-- +*** Testing chroot() : error conditions *** + +-- Pass chroot() an absolute path that does not exist -- +File not found: "%sidonotexist" diff --git a/ext/standard/tests/dir/chroot_throw_on_error_file_in_path.phpt b/ext/standard/tests/dir/chroot_throw_on_error_file_in_path.phpt new file mode 100644 index 0000000000000..4dc2f72ec5704 --- /dev/null +++ b/ext/standard/tests/dir/chroot_throw_on_error_file_in_path.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test chroot() function error conditions with throw on error declare enabled - Non-existent directory +--SKIPIF-- + +--FILE-- +getMessage() . \PHP_EOL; +} + +?> +--EXPECTF-- +*** Testing chroot() : error conditions *** + +-- Pass chroot() a non directory -- +"%schroot_throw_on_error_file_in_path.php" is not a directory