]> granicus.if.org Git - php/commitdiff
- Add glob stream wrapper
authorMarcus Boerger <helly@php.net>
Sat, 3 Mar 2007 20:41:12 +0000 (20:41 +0000)
committerMarcus Boerger <helly@php.net>
Sat, 3 Mar 2007 20:41:12 +0000 (20:41 +0000)
configure.in
ext/standard/basic_functions.c
main/php_streams.h
main/streams/glob_wrapper.c [new file with mode: 0755]
main/streams/php_stream_glob_wrapper.h [new file with mode: 0755]
main/streams/plain_wrapper.c

index ef91543db2c92404baa880cbd5eba13ed998a871..7450e236dc985ef41137d0ba8237ae192968fe03 100644 (file)
@@ -1229,7 +1229,7 @@ PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c php_sprintf.c \
 
 PHP_ADD_SOURCES(main/streams, streams.c cast.c memory.c filter.c \
        plain_wrapper.c userspace.c transports.c xp_socket.c mmap.c \
-       unicode_filter.c )
+       unicode_filter.c  glob_wrapper.c)
 
 PHP_ADD_SOURCES(/main, internal_functions.c,, sapi)
 
index d60d8556a7488a41ee37cf6c6dbeb43eb6b5022e..36b84f9d7eb12798d02ff537ee21ac390ba6f930 100644 (file)
@@ -4064,6 +4064,7 @@ PHP_MINIT_FUNCTION(basic)
 
        php_register_url_stream_wrapper("php", &php_stream_php_wrapper TSRMLS_CC);
        php_register_url_stream_wrapper("file", &php_plain_files_wrapper TSRMLS_CC);
+       php_register_url_stream_wrapper("glob", &php_glob_stream_wrapper TSRMLS_CC);
        php_register_url_stream_wrapper("data", &php_stream_rfc2397_wrapper TSRMLS_CC);
 #ifndef PHP_CURL_URL_WRAPPERS
        php_register_url_stream_wrapper("http", &php_stream_http_wrapper TSRMLS_CC);
index 0d0cf1750be5eccec99706bc8aff3dc4fb852cb1..0d3da88bd3bfc57a256291597e0f68db4c6a38b1 100755 (executable)
@@ -545,6 +545,7 @@ END_EXTERN_C()
 
 #include "streams/php_stream_transport.h"
 #include "streams/php_stream_plain_wrapper.h"
+#include "streams/php_stream_glob_wrapper.h"
 #include "streams/php_stream_userspace.h"
 #include "streams/php_stream_mmap.h"
 
@@ -614,6 +615,9 @@ END_EXTERN_C()
 /* get (or create) a persistent version of the stream */
 #define STREAM_OPEN_PERSISTENT 2048
 
+/* use glob stream for directory open in plain files stream */
+#define STREAM_USE_GLOB_DIR_OPEN 4096
+
 /* Antique - no longer has meaning */
 #define IGNORE_URL_WIN 0
 
diff --git a/main/streams/glob_wrapper.c b/main/streams/glob_wrapper.c
new file mode 100755 (executable)
index 0000000..2635383
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 5                                                        |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997-2007 The PHP Group                                |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 3.01 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.php.net/license/3_01.txt                                  |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Authors: Marcus Boerger <helly@php.net>                              |
+   +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#include "php.h"
+#include "php_streams_int.h"
+
+#ifdef HAVE_GLOB
+# ifndef PHP_WIN32
+#  include <glob.h>
+# else
+#  include "win32/glob.h"
+# endif
+#endif
+
+#ifndef GLOB_ONLYDIR
+#define GLOB_ONLYDIR (1<<30)
+#define GLOB_FLAGMASK (~GLOB_ONLYDIR)
+#else
+#define GLOB_FLAGMASK (~0)
+#endif
+
+typedef struct {
+       glob_t   glob;
+       size_t   index;
+       int      flags;
+       char     *path;
+       size_t   path_len;
+} glob_s_t;
+
+PHPAPI char* _php_glob_stream_get_path(php_stream *stream, int copy, int *plen STREAMS_DC TSRMLS_DC) /* {{{ */
+{
+       glob_s_t *pglob = (glob_s_t *)stream->abstract;
+       
+       if (pglob && pglob->path) {
+               if (plen) {
+                       *plen = pglob->path_len;
+               }
+               if (copy) {
+                       return estrndup(pglob->path, pglob->path_len);
+               } else {
+                       return pglob->path;
+               }
+       } else {
+               if (plen) {
+                       *plen = 0;
+               }
+               return NULL;
+       }
+}
+/* }}} */
+
+static void php_glob_stream_path_split(glob_s_t *pglob, char *path, int get_path, char **p_file TSRMLS_DC) /* {{{ */
+{
+       char *pos, *gpath = path;
+
+       if ((pos = strrchr(path, '/')) != NULL) {
+               path = pos+1;
+       }
+#if defined(PHP_WIN32) || defined(NETWARE)
+       if ((pos = strrchr(path, '\\')) != NULL) {
+       if (pos != NULL) {
+               path = pos+1;
+       }
+#endif
+
+       *p_file = path;
+
+       if (get_path) {
+               if (pglob->path) {
+                       efree(pglob->path);
+               }
+               pglob->path_len = path - gpath;
+               pglob->path = estrndup(gpath, pglob->path_len);
+       }
+}
+/* }}} */
+
+static size_t php_glob_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */
+{
+       glob_s_t *pglob = (glob_s_t *)stream->abstract;
+       php_stream_dirent *ent = (php_stream_dirent*)buf;
+       char *path;
+
+       /* avoid problems if someone mis-uses the stream */
+       if (count == sizeof(php_stream_dirent) && pglob) {
+               if (pglob->index < pglob->glob.gl_pathc) {
+                       php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[pglob->index++], pglob->flags & GLOB_APPEND, &path TSRMLS_CC);
+                       PHP_STRLCPY(ent->d_name, path, sizeof(ent->d_name), strlen(path));
+                       return sizeof(php_stream_dirent);
+               }
+               pglob->index = pglob->glob.gl_pathc;
+               if (pglob->path) {
+                       efree(pglob->path);
+                       pglob->path = NULL;
+               }
+       }
+
+       return 0;
+}
+/* }}} */
+
+static int php_glob_stream_close(php_stream *stream, int close_handle TSRMLS_DC)  /* {{{ */
+{
+       glob_s_t *pglob = (glob_s_t *)stream->abstract;
+
+       if (pglob) {
+               pglob->index = 0;
+               globfree(&pglob->glob);
+               if (pglob->path) {
+                       efree(pglob->path);
+               }
+       }
+       efree(stream->abstract);
+       return 0;
+}
+/* {{{ */
+
+static int php_glob_stream_rewind(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC) /* {{{ */
+{
+       glob_s_t *pglob = (glob_s_t *)stream->abstract;
+
+       if (pglob) {
+               pglob->index = 0;
+               if (pglob->path) {
+                       efree(pglob->path);
+                       pglob->path = NULL;
+               }
+       }
+       return 0;
+}
+/* }}} */
+
+static php_stream_ops  php_glob_stream_ops = {
+       NULL, php_glob_stream_read,
+       php_glob_stream_close, NULL,
+       "glob",
+       php_glob_stream_rewind,
+       NULL, /* cast */
+       NULL, /* stat */
+       NULL  /* set_option */
+};
+
+ /* {{{ php_glob_stream_opener */
+static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, char *path, char *mode,
+               int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
+{
+       glob_s_t *pglob;
+       int ret;
+       char *tmp;
+
+       if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) {
+               return NULL;
+       }
+
+       if (!strncmp(path, "glob://", sizeof("glob://")-1)) {
+               path += sizeof("glob://")-1;
+               if (opened_path) {
+                       *opened_path = estrdup(path);
+               }
+       }
+
+       pglob = ecalloc(sizeof(*pglob), 1);
+       
+       if (0 != (ret = glob(path, pglob->flags & GLOB_FLAGMASK, NULL, &pglob->glob))) {
+#ifdef GLOB_NOMATCH
+               if (GLOB_NOMATCH != ret)
+#endif
+               {
+                       efree(pglob);
+                       return NULL;
+               }
+       }
+
+#ifdef GLOB_APPEND
+       if ((pglob->flags & GLOB_APPEND) == 0)
+#endif
+       {
+               if (pglob->glob.gl_pathc) {
+                       php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[0], 1, &tmp TSRMLS_CC);
+               } else {
+                       php_glob_stream_path_split(pglob, path, 1, &tmp TSRMLS_CC);
+               }
+       }
+
+       return php_stream_alloc(&php_glob_stream_ops, pglob, 0, mode);
+}
+/* }}} */
+
+static php_stream_wrapper_ops php_glob_stream_wrapper_ops = {
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       php_glob_stream_opener,
+       "glob",
+       NULL,
+       NULL,
+       NULL,
+       NULL
+};
+
+php_stream_wrapper php_glob_stream_wrapper = {
+       &php_glob_stream_wrapper_ops,
+       NULL,
+       0
+};
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/main/streams/php_stream_glob_wrapper.h b/main/streams/php_stream_glob_wrapper.h
new file mode 100755 (executable)
index 0000000..00bba9a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+   +----------------------------------------------------------------------+
+   | PHP Version 5                                                        |
+   +----------------------------------------------------------------------+
+   | Copyright (c) 1997-2007 The PHP Group                                |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 3.01 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.php.net/license/3_01.txt                                  |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Author: Marcus Boerger <helly@php.net>                               |
+   +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+PHPAPI extern php_stream_wrapper php_glob_stream_wrapper;
+
+BEGIN_EXTERN_C()
+
+PHPAPI char* _php_glob_stream_get_path(php_stream *stream, int copy, int *plen STREAMS_DC TSRMLS_DC);
+#define php_glob_stream_get_path(stream, copy, plen)   _php_glob_stream_get_path((stream), (copy), (plen) STREAMS_CC TSRMLS_CC)
+
+END_EXTERN_C()
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
index 268883848185b3ffda2c00f029b4bf503b6dec1f..40fe2a9a77e58d614e1e838a0291c78fcc95d2a1 100644 (file)
@@ -836,6 +836,10 @@ static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, char
        DIR *dir = NULL;
        php_stream *stream = NULL;
 
+       if (options & STREAM_USE_GLOB_DIR_OPEN) {
+               return php_glob_stream_wrapper.wops->dir_opener(&php_glob_stream_wrapper, path, mode, options, opened_path, context STREAMS_REL_CC TSRMLS_CC);
+       }
+
        if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) {
                return NULL;
        }