summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/standard/dir.c53
-rwxr-xr-xmain/php_streams.h7
-rwxr-xr-xmain/streams/streams.c59
3 files changed, 78 insertions, 41 deletions
diff --git a/ext/standard/dir.c b/ext/standard/dir.c
index 41aad5e351..077f4fdfcd 100644
--- a/ext/standard/dir.c
+++ b/ext/standard/dir.c
@@ -444,74 +444,45 @@ PHP_FUNCTION(glob)
/* }}} */
#endif
-/* {{{ php_alphasortr
-*/
-static int php_alphasortr(const struct dirent **a, const struct dirent **b)
-{
- return strcoll((*b)->d_name, (*a)->d_name);
-}
-/* }}} */
-
-/* {{{ proto array scandir(string dir [, int sorting_order])
+/* {{{ proto array scandir(string dir [, int sorting_order [, resource context]])
List files & directories inside the specified path */
PHP_FUNCTION(scandir)
{
char *dirn;
int dirn_len;
int flags = 0;
- char *path;
- struct dirent **namelist;
+ php_stream_dirent **namelist;
int n, i;
+ zval *zcontext = NULL;
+ php_stream_context *context = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &dirn, &dirn_len, &flags) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr", &dirn, &dirn_len, &flags, &zcontext) == FAILURE) {
return;
}
-#ifdef ZTS
- if (!IS_ABSOLUTE_PATH(dirn, dirn_len)) {
- path = expand_filepath(dirn, NULL TSRMLS_CC);
- } else
-#endif
- path = dirn;
-
- if (PG(safe_mode) && (!php_checkuid(path, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
- RETVAL_FALSE;
- goto err;
- }
- if (php_check_open_basedir(path TSRMLS_CC)) {
- RETVAL_FALSE;
- goto err;
+ if (zcontext) {
+ context = php_stream_context_from_zval(zcontext, 0);
}
if (!flags) {
- n = php_scandir(path, &namelist, 0, php_alphasort);
+ n = php_stream_scandir(dirn, &namelist, context, (void *) php_stream_dirent_alphasort);
} else {
- n = php_scandir(path, &namelist, 0, (void *) php_alphasortr);
+ n = php_stream_scandir(dirn, &namelist, context, (void *) php_stream_dirent_alphasortr);
}
-
if (n < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "(errno %d): %s", errno, strerror(errno));
- RETVAL_FALSE;
- goto err;
+ RETURN_FALSE;
}
array_init(return_value);
for (i = 0; i < n; i++) {
- add_next_index_string(return_value, namelist[i]->d_name, 1);
- free(namelist[i]);
+ add_next_index_string(return_value, namelist[i]->d_name, 0);
}
if (n) {
- free(namelist);
+ efree(namelist);
}
-
-err:
- if (path && path != dirn) {
- efree(path);
- }
-
- return;
}
/* }}} */
diff --git a/main/php_streams.h b/main/php_streams.h
index 2fcb1c413d..47ed1181e3 100755
--- a/main/php_streams.h
+++ b/main/php_streams.h
@@ -325,6 +325,13 @@ PHPAPI php_stream_dirent *_php_stream_readdir(php_stream *dirstream, php_stream_
#define php_stream_closedir(dirstream) php_stream_close((dirstream))
#define php_stream_rewinddir(dirstream) php_stream_rewind((dirstream))
+PHPAPI int php_stream_dirent_alphasort(const php_stream_dirent **a, const php_stream_dirent **b);
+PHPAPI int php_stream_dirent_alphasortr(const php_stream_dirent **a, const php_stream_dirent **b);
+
+PHPAPI int _php_stream_scandir(char *dirname, php_stream_dirent **namelist[], int flags, php_stream_context *context,
+ int (*compare) (const php_stream_dirent **a, const php_stream_dirent **b) TSRMLS_DC);
+#define php_stream_scandir(dirname, namelist, context, compare) _php_stream_scandir((dirname), (namelist), 0, (context), (compare) TSRMLS_CC)
+
PHPAPI int _php_stream_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC);
#define php_stream_set_option(stream, option, value, ptrvalue) _php_stream_set_option((stream), (option), (value), (ptrvalue) TSRMLS_CC)
diff --git a/main/streams/streams.c b/main/streams/streams.c
index ece1870ce1..dc7a4f37ed 100755
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -1834,6 +1834,65 @@ PHPAPI int php_stream_context_del_link(php_stream_context *context,
}
/* }}} */
+/* {{{ php_stream_dirent_alphasort
+ */
+PHPAPI int php_stream_dirent_alphasort(const php_stream_dirent **a, const php_stream_dirent **b)
+{
+ return strcoll((*a)->d_name,(*b)->d_name);
+}
+/* }}} */
+
+/* {{{ php_stream_dirent_alphasortr
+ */
+PHPAPI int php_stream_dirent_alphasortr(const php_stream_dirent **a, const php_stream_dirent **b)
+{
+ return strcoll((*b)->d_name,(*a)->d_name);
+}
+/* }}} */
+
+/* {{{ php_stream_scandir
+ */
+PHPAPI int _php_stream_scandir(char *dirname, php_stream_dirent **namelist[], int flags, php_stream_context *context,
+ int (*compare) (const php_stream_dirent **a, const php_stream_dirent **b) TSRMLS_DC)
+{
+ php_stream *stream;
+ php_stream_dirent sdp;
+ php_stream_dirent **vector = NULL;
+ int vector_size = 0;
+ int nfiles = 0;
+
+ if (!namelist) {
+ return FAILURE;
+ }
+
+ stream = php_stream_opendir(dirname, ENFORCE_SAFE_MODE | REPORT_ERRORS, context);
+ if (!stream) {
+ return FAILURE;
+ }
+
+ while (php_stream_readdir(stream, &sdp)) {
+ if (nfiles == vector_size) {
+ if (vector_size == 0) {
+ vector_size = 10;
+ } else {
+ vector_size *= 2;
+ }
+ vector = (php_stream_dirent **) erealloc(vector, vector_size * sizeof(php_stream_dirent *));
+ }
+
+ vector[nfiles++] = (php_stream_dirent*)estrndup(&sdp, sizeof(php_stream_dirent) + ((strlen(sdp.d_name) + 1) * sizeof(char)));
+ }
+ php_stream_closedir(stream);
+
+ *namelist = vector;
+
+ if (compare) {
+ qsort(*namelist, nfiles, sizeof(php_stream_dirent *), compare);
+ }
+ return nfiles;
+}
+/* }}} */
+
/*
* Local variables:
* tab-width: 4