diff options
| -rw-r--r-- | ext/standard/basic_functions.c | 3 | ||||
| -rw-r--r-- | ext/standard/string.c | 21 | ||||
| -rw-r--r-- | ext/standard/tests/strings/dirname_error.phpt | 12 | ||||
| -rw-r--r-- | ext/standard/tests/strings/dirname_multi.phpt | 20 |
4 files changed, 49 insertions, 7 deletions
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 488b71b900..3f03275aa5 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -2213,8 +2213,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_basename, 0, 0, 1) ZEND_ARG_INFO(0, suffix) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO(arginfo_dirname, 0) +ZEND_BEGIN_ARG_INFO_EX(arginfo_dirname, 0, 0, 1) ZEND_ARG_INFO(0, path) + ZEND_ARG_INFO(0, levels) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_pathinfo, 0, 0, 1) diff --git a/ext/standard/string.c b/ext/standard/string.c index 2a9ddb2a18..143c6f636c 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1648,21 +1648,36 @@ PHPAPI size_t php_dirname(char *path, size_t len) } /* }}} */ -/* {{{ proto string dirname(string path) +/* {{{ proto string dirname(string path[, int levels]) Returns the directory name component of the path */ PHP_FUNCTION(dirname) { char *str; zend_string *ret; size_t str_len; + zend_long levels = 1; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &str_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &levels) == FAILURE) { return; } ret = zend_string_init(str, str_len, 0); - ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len); + if (levels == 1) { + /* Defaut case */ + ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len); + + } else if (levels < 1) { + php_error_docref(NULL, E_WARNING, "Invalid argument, levels must be >= 1"); + return; + + + } else { + /* Some levels up */ + do { + ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len=ZSTR_LEN(ret)); + } while (ZSTR_LEN(ret)<str_len && --levels>0); + } RETURN_NEW_STR(ret); } /* }}} */ diff --git a/ext/standard/tests/strings/dirname_error.phpt b/ext/standard/tests/strings/dirname_error.phpt index bf6310283b..303a59b2d5 100644 --- a/ext/standard/tests/strings/dirname_error.phpt +++ b/ext/standard/tests/strings/dirname_error.phpt @@ -9,17 +9,23 @@ echo "*** Testing error conditions ***\n"; // zero arguments var_dump( dirname() ); +// Bad arg +var_dump( dirname("/var/tmp/bar.gz", 0) ); + // more than expected no. of arguments -var_dump( dirname("/var/tmp/bar.gz", ".gz") ); +var_dump( dirname("/var/tmp/bar.gz", 1, ".gz") ); echo "Done\n"; ?> --EXPECTF-- *** Testing error conditions *** -Warning: dirname() expects exactly 1 parameter, 0 given in %s on line %d +Warning: dirname() expects at least 1 parameter, 0 given in %s on line %d +NULL + +Warning: dirname(): Invalid argument, levels must be >= 1 in %s on line %d NULL -Warning: dirname() expects exactly 1 parameter, 2 given in %s on line %d +Warning: dirname() expects at most 2 parameters, 3 given in %s on line %d NULL Done diff --git a/ext/standard/tests/strings/dirname_multi.phpt b/ext/standard/tests/strings/dirname_multi.phpt new file mode 100644 index 0000000000..d0fdfac0a2 --- /dev/null +++ b/ext/standard/tests/strings/dirname_multi.phpt @@ -0,0 +1,20 @@ +--TEST-- +Test dirname() function : usage variations +--FILE-- +<?php +/* Prototype: string dirname ( string $path [, int nb]); + Description: Returns directory name component of path. +*/ +for ($i=1 ; $i<5 ; $i++) { + var_dump(dirname("/foo/bar/baz", $i)); +} +var_dump(dirname("/foo/bar/baz", PHP_INT_MAX)); +?> +Done +--EXPECT-- +string(8) "/foo/bar" +string(4) "/foo" +string(1) "/" +string(1) "/" +string(1) "/" +Done |
