1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Marcus Boerger <helly@php.net> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: glob_wrapper.c 272370 2008-12-31 11:15:49Z sebastian $ */
20 :
21 : #include "php.h"
22 : #include "php_streams_int.h"
23 :
24 : #ifdef HAVE_GLOB
25 : # ifndef PHP_WIN32
26 : # include <glob.h>
27 : # else
28 : # include "win32/glob.h"
29 : # endif
30 : #endif
31 :
32 : #ifndef GLOB_ONLYDIR
33 : #define GLOB_ONLYDIR (1<<30)
34 : #define GLOB_FLAGMASK (~GLOB_ONLYDIR)
35 : #else
36 : #define GLOB_FLAGMASK (~0)
37 : #endif
38 :
39 : typedef struct {
40 : glob_t glob;
41 : size_t index;
42 : int flags;
43 : char *path;
44 : size_t path_len;
45 : char *pattern;
46 : size_t pattern_len;
47 : } glob_s_t;
48 :
49 : PHPAPI char* _php_glob_stream_get_path(php_stream *stream, int copy, int *plen STREAMS_DC TSRMLS_DC) /* {{{ */
50 9 : {
51 9 : glob_s_t *pglob = (glob_s_t *)stream->abstract;
52 :
53 9 : if (pglob && pglob->path) {
54 9 : if (plen) {
55 6 : *plen = pglob->path_len;
56 : }
57 9 : if (copy) {
58 0 : return estrndup(pglob->path, pglob->path_len);
59 : } else {
60 9 : return pglob->path;
61 : }
62 : } else {
63 0 : if (plen) {
64 0 : *plen = 0;
65 : }
66 0 : return NULL;
67 : }
68 : }
69 : /* }}} */
70 :
71 : PHPAPI char* _php_glob_stream_get_pattern(php_stream *stream, int copy, int *plen STREAMS_DC TSRMLS_DC) /* {{{ */
72 0 : {
73 0 : glob_s_t *pglob = (glob_s_t *)stream->abstract;
74 :
75 0 : if (pglob && pglob->pattern) {
76 0 : if (plen) {
77 0 : *plen = pglob->pattern_len;
78 : }
79 0 : if (copy) {
80 0 : return estrndup(pglob->pattern, pglob->pattern_len);
81 : } else {
82 0 : return pglob->pattern;
83 : }
84 : } else {
85 0 : if (plen) {
86 0 : *plen = 0;
87 : }
88 0 : return NULL;
89 : }
90 : }
91 : /* }}} */
92 :
93 : PHPAPI int _php_glob_stream_get_count(php_stream *stream, int *pflags STREAMS_DC TSRMLS_DC) /* {{{ */
94 0 : {
95 0 : glob_s_t *pglob = (glob_s_t *)stream->abstract;
96 :
97 0 : if (pglob) {
98 0 : if (pflags) {
99 0 : *pflags = pglob->flags;
100 : }
101 0 : return pglob->glob.gl_pathc;
102 : } else {
103 0 : if (pflags) {
104 0 : *pflags = 0;
105 : }
106 0 : return 0;
107 : }
108 : }
109 : /* }}} */
110 :
111 : static void php_glob_stream_path_split(glob_s_t *pglob, char *path, int get_path, char **p_file TSRMLS_DC) /* {{{ */
112 17 : {
113 17 : char *pos, *gpath = path;
114 :
115 17 : if ((pos = strrchr(path, '/')) != NULL) {
116 0 : path = pos+1;
117 : }
118 : #if defined(PHP_WIN32) || defined(NETWARE)
119 : if ((pos = strrchr(path, '\\')) != NULL) {
120 : path = pos+1;
121 : }
122 : #endif
123 :
124 17 : *p_file = path;
125 :
126 17 : if (get_path) {
127 17 : if (pglob->path) {
128 4 : efree(pglob->path);
129 : }
130 17 : if (path != gpath) {
131 0 : path--;
132 : }
133 17 : pglob->path_len = path - gpath;
134 17 : pglob->path = estrndup(gpath, pglob->path_len);
135 : }
136 17 : }
137 : /* }}} */
138 :
139 : static size_t php_glob_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */
140 13 : {
141 13 : glob_s_t *pglob = (glob_s_t *)stream->abstract;
142 13 : php_stream_dirent *ent = (php_stream_dirent*)buf;
143 : char *path;
144 :
145 : /* avoid problems if someone mis-uses the stream */
146 13 : if (count == sizeof(php_stream_dirent) && pglob) {
147 13 : if (pglob->index < pglob->glob.gl_pathc) {
148 13 : php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[pglob->index++], pglob->flags & GLOB_APPEND, &path TSRMLS_CC);
149 13 : PHP_STRLCPY(ent->d_name, path, sizeof(ent->d_name), strlen(path));
150 13 : return sizeof(php_stream_dirent);
151 : }
152 0 : pglob->index = pglob->glob.gl_pathc;
153 0 : if (pglob->path) {
154 0 : efree(pglob->path);
155 0 : pglob->path = NULL;
156 : }
157 : }
158 :
159 0 : return 0;
160 : }
161 : /* }}} */
162 :
163 : static int php_glob_stream_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{{ */
164 4 : {
165 4 : glob_s_t *pglob = (glob_s_t *)stream->abstract;
166 :
167 4 : if (pglob) {
168 4 : pglob->index = 0;
169 4 : globfree(&pglob->glob);
170 4 : if (pglob->path) {
171 4 : efree(pglob->path);
172 : }
173 4 : if (pglob->pattern) {
174 4 : efree(pglob->pattern);
175 : }
176 : }
177 4 : efree(stream->abstract);
178 4 : return 0;
179 : }
180 : /* {{{ */
181 :
182 : static int php_glob_stream_rewind(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC) /* {{{ */
183 9 : {
184 9 : glob_s_t *pglob = (glob_s_t *)stream->abstract;
185 :
186 9 : if (pglob) {
187 9 : pglob->index = 0;
188 9 : if (pglob->path) {
189 9 : efree(pglob->path);
190 9 : pglob->path = NULL;
191 : }
192 : }
193 9 : return 0;
194 : }
195 : /* }}} */
196 :
197 : php_stream_ops php_glob_stream_ops = {
198 : NULL, php_glob_stream_read,
199 : php_glob_stream_close, NULL,
200 : "glob",
201 : php_glob_stream_rewind,
202 : NULL, /* cast */
203 : NULL, /* stat */
204 : NULL /* set_option */
205 : };
206 :
207 : /* {{{ php_glob_stream_opener */
208 : static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, char *path, char *mode,
209 : int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
210 4 : {
211 : glob_s_t *pglob;
212 : int ret;
213 : char *tmp, *pos;
214 :
215 4 : if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) {
216 0 : return NULL;
217 : }
218 :
219 4 : if (!strncmp(path, "glob://", sizeof("glob://")-1)) {
220 4 : path += sizeof("glob://")-1;
221 4 : if (opened_path) {
222 0 : *opened_path = estrdup(path);
223 : }
224 : }
225 :
226 4 : pglob = ecalloc(sizeof(*pglob), 1);
227 :
228 4 : if (0 != (ret = glob(path, pglob->flags & GLOB_FLAGMASK, NULL, &pglob->glob))) {
229 : #ifdef GLOB_NOMATCH
230 0 : if (GLOB_NOMATCH != ret)
231 : #endif
232 : {
233 0 : efree(pglob);
234 0 : return NULL;
235 : }
236 : }
237 :
238 4 : pos = path;
239 4 : if ((tmp = strrchr(pos, '/')) != NULL) {
240 0 : pos = tmp+1;
241 : }
242 : #if defined(PHP_WIN32) || defined(NETWARE)
243 : if ((tmp = strrchr(pos, '\\')) != NULL) {
244 : pos = tmp+1;
245 : }
246 : #endif
247 :
248 4 : pglob->pattern_len = strlen(pos);
249 4 : pglob->pattern = estrndup(pos, pglob->pattern_len);
250 :
251 4 : pglob->flags |= GLOB_APPEND;
252 :
253 4 : if (pglob->glob.gl_pathc) {
254 4 : php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[0], 1, &tmp TSRMLS_CC);
255 : } else {
256 0 : php_glob_stream_path_split(pglob, path, 1, &tmp TSRMLS_CC);
257 : }
258 :
259 4 : return php_stream_alloc(&php_glob_stream_ops, pglob, 0, mode);
260 : }
261 : /* }}} */
262 :
263 : static php_stream_wrapper_ops php_glob_stream_wrapper_ops = {
264 : NULL,
265 : NULL,
266 : NULL,
267 : NULL,
268 : php_glob_stream_opener,
269 : "glob",
270 : NULL,
271 : NULL,
272 : NULL,
273 : NULL
274 : };
275 :
276 : php_stream_wrapper php_glob_stream_wrapper = {
277 : &php_glob_stream_wrapper_ops,
278 : NULL,
279 : 0
280 : };
281 :
282 : /*
283 : * Local variables:
284 : * tab-width: 4
285 : * c-basic-offset: 4
286 : * End:
287 : * vim600: noet sw=4 ts=4 fdm=marker
288 : * vim<600: noet sw=4 ts=4
289 : */
|