php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
glob_wrapper.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Marcus Boerger <helly@php.net> |
14 +----------------------------------------------------------------------+
15 */
16
17#include "php.h"
18#include "php_streams_int.h"
19
20#ifdef HAVE_GLOB
21# ifndef PHP_WIN32
22# include <glob.h>
23# else
24# include "win32/glob.h"
25# endif
26#endif
27
28#ifdef HAVE_GLOB
29#ifndef GLOB_ONLYDIR
30#define GLOB_ONLYDIR (1<<30)
31#define GLOB_FLAGMASK (~GLOB_ONLYDIR)
32#else
33#define GLOB_FLAGMASK (~0)
34#endif
35
36typedef struct {
38 size_t index;
39 int flags;
40 char *path;
41 size_t path_len;
42 char *pattern;
43 size_t pattern_len;
44 size_t *open_basedir_indexmap;
45 size_t open_basedir_indexmap_size;
46 bool open_basedir_used;
47} glob_s_t;
48
49PHPAPI char* _php_glob_stream_get_path(php_stream *stream, size_t *plen STREAMS_DC) /* {{{ */
50{
51 glob_s_t *pglob = (glob_s_t *)stream->abstract;
52
53 if (pglob && pglob->path) {
54 if (plen) {
55 *plen = pglob->path_len;
56 }
57 return pglob->path;
58 } else {
59 if (plen) {
60 *plen = 0;
61 }
62 return NULL;
63 }
64}
65/* }}} */
66
67PHPAPI char* _php_glob_stream_get_pattern(php_stream *stream, size_t *plen STREAMS_DC) /* {{{ */
68{
69 glob_s_t *pglob = (glob_s_t *)stream->abstract;
70
71 if (pglob && pglob->pattern) {
72 if (plen) {
73 *plen = pglob->pattern_len;
74 }
75 return pglob->pattern;
76 } else {
77 if (plen) {
78 *plen = 0;
79 }
80 return NULL;
81 }
82}
83/* }}} */
84
85static inline int php_glob_stream_get_result_count(glob_s_t *pglob)
86{
87 return pglob->open_basedir_used ? (int) pglob->open_basedir_indexmap_size : pglob->glob.gl_pathc;
88}
89
90PHPAPI int _php_glob_stream_get_count(php_stream *stream, int *pflags STREAMS_DC) /* {{{ */
91{
92 glob_s_t *pglob = (glob_s_t *)stream->abstract;
93
94 if (pglob) {
95 if (pflags) {
96 *pflags = pglob->flags;
97 }
98 return php_glob_stream_get_result_count(pglob);
99 } else {
100 if (pflags) {
101 *pflags = 0;
102 }
103 return 0;
104 }
105}
106/* }}} */
107
108static void php_glob_stream_path_split(glob_s_t *pglob, const char *path, int get_path, const char **p_file) /* {{{ */
109{
110 const char *pos, *gpath = path;
111
112 if ((pos = strrchr(path, '/')) != NULL) {
113 path = pos+1;
114 }
115#ifdef PHP_WIN32
116 if ((pos = strrchr(path, '\\')) != NULL) {
117 path = pos+1;
118 }
119#endif
120
121 *p_file = path;
122
123 if (get_path) {
124 if (pglob->path) {
125 efree(pglob->path);
126 }
127 if ((path - gpath) > 1) {
128 path--;
129 }
130 pglob->path_len = path - gpath;
131 pglob->path = estrndup(gpath, pglob->path_len);
132 }
133}
134/* }}} */
135
136static ssize_t php_glob_stream_read(php_stream *stream, char *buf, size_t count) /* {{{ */
137{
138 glob_s_t *pglob = (glob_s_t *)stream->abstract;
140 const char *path;
141 int glob_result_count;
142 size_t index;
143
144 /* avoid problems if someone mis-uses the stream */
145 if (count == sizeof(php_stream_dirent) && pglob) {
146 glob_result_count = php_glob_stream_get_result_count(pglob);
147 if (pglob->index < (size_t) glob_result_count) {
148 index = pglob->open_basedir_used && pglob->open_basedir_indexmap ?
149 pglob->open_basedir_indexmap[pglob->index] : pglob->index;
150 php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[index], pglob->flags & GLOB_APPEND, &path);
151 ++pglob->index;
152 PHP_STRLCPY(ent->d_name, path, sizeof(ent->d_name), strlen(path));
153 ent->d_type = DT_UNKNOWN;
154 return sizeof(php_stream_dirent);
155 }
156 pglob->index = glob_result_count;
157 if (pglob->path) {
158 efree(pglob->path);
159 pglob->path = NULL;
160 }
161 }
162
163 return -1;
164}
165/* }}} */
166
167static int php_glob_stream_close(php_stream *stream, int close_handle) /* {{{ */
168{
169 glob_s_t *pglob = (glob_s_t *)stream->abstract;
170
171 if (pglob) {
172 pglob->index = 0;
173 globfree(&pglob->glob);
174 if (pglob->path) {
175 efree(pglob->path);
176 }
177 if (pglob->pattern) {
178 efree(pglob->pattern);
179 }
180 if (pglob->open_basedir_indexmap) {
181 efree(pglob->open_basedir_indexmap);
182 }
183 }
184 efree(stream->abstract);
185 return 0;
186}
187/* {{{ */
188
189static int php_glob_stream_rewind(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffs) /* {{{ */
190{
191 glob_s_t *pglob = (glob_s_t *)stream->abstract;
192
193 if (pglob) {
194 pglob->index = 0;
195 if (pglob->path) {
196 efree(pglob->path);
197 pglob->path = NULL;
198 }
199 }
200 return 0;
201}
202/* }}} */
203
205 NULL, php_glob_stream_read,
206 php_glob_stream_close, NULL,
207 "glob",
208 php_glob_stream_rewind,
209 NULL, /* cast */
210 NULL, /* stat */
211 NULL /* set_option */
212};
213
214 /* {{{ php_glob_stream_opener */
215static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, const char *path, const char *mode,
217{
218 glob_s_t *pglob;
219 int ret, i;
220 const char *tmp, *pos;
221
222 if (!strncmp(path, "glob://", sizeof("glob://")-1)) {
223 path += sizeof("glob://")-1;
224 if (opened_path) {
225 *opened_path = zend_string_init(path, strlen(path), 0);
226 }
227 }
228 const char *pattern = path;
229#ifdef ZTS
230 char cwd[MAXPATHLEN];
231 char work_pattern[MAXPATHLEN];
232 char *result;
233 size_t cwd_skip = 0;
234 if (!IS_ABSOLUTE_PATH(path, strlen(path))) {
236 if (!result) {
237 cwd[0] = '\0';
238 }
239# ifdef PHP_WIN32
240 if (IS_SLASH(*path)) {
241 cwd[2] = '\0';
242 }
243# endif
244 cwd_skip = strlen(cwd)+1;
245
246 snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, path);
247 pattern = work_pattern;
248 }
249#endif
250
251 pglob = ecalloc(1, sizeof(*pglob));
252
253 if (0 != (ret = glob(pattern, pglob->flags & GLOB_FLAGMASK, NULL, &pglob->glob))) {
254#ifdef GLOB_NOMATCH
255 if (GLOB_NOMATCH != ret)
256#endif
257 {
258 efree(pglob);
259 return NULL;
260 }
261 }
262
263#ifdef ZTS
264 if (cwd_skip > 0) {
265 /* strip prepended CWD */
266 for (i = 0; i < pglob->glob.gl_pathc; i++) {
267 char *p = pglob->glob.gl_pathv[i];
268 char *q = p + cwd_skip;
269 char *e = p + strlen(pglob->glob.gl_pathv[i]) - 1;
270 while (q <= e) {
271 *p++ = *q++;
272 }
273 *p = '\0';
274 }
275 }
276#endif
277
278 /* if open_basedir in use, check and filter restricted paths */
280 pglob->open_basedir_used = true;
281 for (i = 0; i < pglob->glob.gl_pathc; i++) {
282 if (!php_check_open_basedir_ex(pglob->glob.gl_pathv[i], 0)) {
283 if (!pglob->open_basedir_indexmap) {
284 pglob->open_basedir_indexmap = (size_t *) safe_emalloc(
285 pglob->glob.gl_pathc, sizeof(size_t), 0);
286 }
287 pglob->open_basedir_indexmap[pglob->open_basedir_indexmap_size++] = i;
288 }
289 }
290 }
291
292 pos = path;
293 if ((tmp = strrchr(pos, '/')) != NULL) {
294 pos = tmp+1;
295 }
296#ifdef PHP_WIN32
297 if ((tmp = strrchr(pos, '\\')) != NULL) {
298 pos = tmp+1;
299 }
300#endif
301
302 pglob->pattern_len = strlen(pos);
303 pglob->pattern = estrndup(pos, pglob->pattern_len);
304
305 pglob->flags |= GLOB_APPEND;
306
307 if (pglob->glob.gl_pathc) {
308 php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[0], 1, &tmp);
309 } else {
310 php_glob_stream_path_split(pglob, path, 1, &tmp);
311 }
312
313 return php_stream_alloc(&php_glob_stream_ops, pglob, 0, mode);
314}
315/* }}} */
316
317static const php_stream_wrapper_ops php_glob_stream_wrapper_ops = {
318 NULL,
319 NULL,
320 NULL,
321 NULL,
322 php_glob_stream_opener,
323 "glob",
324 NULL,
325 NULL,
326 NULL,
327 NULL,
328 NULL
329};
330
332 &php_glob_stream_wrapper_ops,
333 NULL,
334 0
335};
336#endif /* HAVE_GLOB */
strrchr(string $haystack, string $needle, bool $before_needle=false)
count(Countable|array $value, int $mode=COUNT_NORMAL)
glob(string $pattern, int $flags=0)
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
PHPAPI int php_check_open_basedir_ex(const char *path, int warn)
zend_long offset
char * mode
#define NULL
Definition gdcache.h:45
PHPAPI void globfree(glob_t *pglob)
Definition glob.c:777
#define GLOB_APPEND
Definition glob.h:73
#define GLOB_NOMATCH
Definition glob.h:94
char * cwd
#define PHP_STRLCPY(dst, src, size, src_size)
Definition php.h:142
#define PHPAPI
Definition php.h:71
unsigned const char * pos
Definition php_ffi.h:52
PHP_JSON_API size_t int options
Definition php_json.h:102
PHPAPI char * _php_glob_stream_get_pattern(php_stream *stream, size_t *plen STREAMS_DC)
PHPAPI int _php_glob_stream_get_count(php_stream *stream, int *pflags STREAMS_DC)
PHPAPI char * _php_glob_stream_get_path(php_stream *stream, size_t *plen STREAMS_DC)
PHPAPI const php_stream_wrapper php_glob_stream_wrapper
PHPAPI const php_stream_ops php_glob_stream_ops
struct _php_stream_wrapper_ops php_stream_wrapper_ops
struct _php_stream php_stream
Definition php_streams.h:96
struct _php_stream_context php_stream_context
Definition php_streams.h:98
struct _php_stream_dirent php_stream_dirent
#define STREAMS_DC
Definition php_streams.h:53
#define STREAM_DISABLE_OPEN_BASEDIR
struct _php_stream_ops php_stream_ops
struct _php_stream_wrapper php_stream_wrapper
Definition php_streams.h:97
#define php_stream_alloc(ops, thisptr, persistent_id, mode)
#define DT_UNKNOWN
Definition readdir.h:19
p
Definition session.c:1105
unsigned char d_type
char d_name[MAXPATHLEN]
void * abstract
Definition dce.c:49
Definition glob.h:51
#define estrndup(s, length)
Definition zend_alloc.h:165
#define ecalloc(nmemb, size)
Definition zend_alloc.h:158
#define efree(ptr)
Definition zend_alloc.h:155
#define safe_emalloc(nmemb, size, offset)
Definition zend_alloc.h:154
strlen(string $string)
strncmp(string $string1, string $string2, int $length)
#define snprintf
int32_t zend_off_t
Definition zend_long.h:44
struct _zend_string zend_string
#define IS_SLASH(c)
#define DEFAULT_SLASH
#define IS_ABSOLUTE_PATH(path, len)
#define VCWD_GETCWD(buff, size)
#define MAXPATHLEN
bool result
zval * ret