This source file includes following definitions.
- php_set_default_dir
- PHP_RINIT_FUNCTION
- PHP_MINIT_FUNCTION
- _php_do_opendir
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_NAMED_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include "php.h"
24 #include "fopen_wrappers.h"
25 #include "file.h"
26 #include "php_dir.h"
27 #include "php_string.h"
28 #include "php_scandir.h"
29 #include "basic_functions.h"
30
31 #ifdef HAVE_DIRENT_H
32 #include <dirent.h>
33 #endif
34
35 #if HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38
39 #include <errno.h>
40
41 #ifdef PHP_WIN32
42 #include "win32/readdir.h"
43 #endif
44
45
46 #ifdef HAVE_GLOB
47 #ifndef PHP_WIN32
48 #include <glob.h>
49 #else
50 #include "win32/glob.h"
51 #endif
52 #endif
53
54 typedef struct {
55 zend_resource *default_dir;
56 } php_dir_globals;
57
58 #ifdef ZTS
59 #define DIRG(v) ZEND_TSRMG(dir_globals_id, php_dir_globals *, v)
60 int dir_globals_id;
61 #else
62 #define DIRG(v) (dir_globals.v)
63 php_dir_globals dir_globals;
64 #endif
65
66 #if 0
67 typedef struct {
68 int id;
69 DIR *dir;
70 } php_dir;
71
72 static int le_dirp;
73 #endif
74
75 static zend_class_entry *dir_class_entry_ptr;
76
77 #define FETCH_DIRP() \
78 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &id) == FAILURE) { \
79 return; \
80 } \
81 if (ZEND_NUM_ARGS() == 0) { \
82 myself = getThis(); \
83 if (myself) { \
84 if ((tmp = zend_hash_str_find(Z_OBJPROP_P(myself), "handle", sizeof("handle")-1)) == NULL) { \
85 php_error_docref(NULL, E_WARNING, "Unable to find my handle property"); \
86 RETURN_FALSE; \
87 } \
88 if ((dirp = (php_stream *)zend_fetch_resource_ex(tmp, "Directory", php_file_le_stream())) == NULL) { \
89 RETURN_FALSE; \
90 } \
91 } else { \
92 if (!DIRG(default_dir) || \
93 (dirp = (php_stream *)zend_fetch_resource(DIRG(default_dir), "Directory", php_file_le_stream())) == NULL) { \
94 RETURN_FALSE; \
95 } \
96 } \
97 } else { \
98 if ((dirp = (php_stream *)zend_fetch_resource(Z_RES_P(id), "Directory", php_file_le_stream())) == NULL) { \
99 RETURN_FALSE; \
100 } \
101 }
102
103
104 ZEND_BEGIN_ARG_INFO_EX(arginfo_dir, 0, 0, 0)
105 ZEND_ARG_INFO(0, dir_handle)
106 ZEND_END_ARG_INFO()
107
108
109 static const zend_function_entry php_dir_class_functions[] = {
110 PHP_FALIAS(close, closedir, arginfo_dir)
111 PHP_FALIAS(rewind, rewinddir, arginfo_dir)
112 PHP_NAMED_FE(read, php_if_readdir, arginfo_dir)
113 {NULL, NULL, NULL}
114 };
115
116
117 static void php_set_default_dir(zend_resource *res)
118 {
119 if (DIRG(default_dir)) {
120 zend_list_delete(DIRG(default_dir));
121 }
122
123 if (res) {
124 GC_REFCOUNT(res)++;
125 }
126
127 DIRG(default_dir) = res;
128 }
129
130 PHP_RINIT_FUNCTION(dir)
131 {
132 DIRG(default_dir) = NULL;
133 return SUCCESS;
134 }
135
136 PHP_MINIT_FUNCTION(dir)
137 {
138 static char dirsep_str[2], pathsep_str[2];
139 zend_class_entry dir_class_entry;
140
141 INIT_CLASS_ENTRY(dir_class_entry, "Directory", php_dir_class_functions);
142 dir_class_entry_ptr = zend_register_internal_class(&dir_class_entry);
143
144 #ifdef ZTS
145 ts_allocate_id(&dir_globals_id, sizeof(php_dir_globals), NULL, NULL);
146 #endif
147
148 dirsep_str[0] = DEFAULT_SLASH;
149 dirsep_str[1] = '\0';
150 REGISTER_STRING_CONSTANT("DIRECTORY_SEPARATOR", dirsep_str, CONST_CS|CONST_PERSISTENT);
151
152 pathsep_str[0] = ZEND_PATHS_SEPARATOR;
153 pathsep_str[1] = '\0';
154 REGISTER_STRING_CONSTANT("PATH_SEPARATOR", pathsep_str, CONST_CS|CONST_PERSISTENT);
155
156 REGISTER_LONG_CONSTANT("SCANDIR_SORT_ASCENDING", PHP_SCANDIR_SORT_ASCENDING, CONST_CS | CONST_PERSISTENT);
157 REGISTER_LONG_CONSTANT("SCANDIR_SORT_DESCENDING", PHP_SCANDIR_SORT_DESCENDING, CONST_CS | CONST_PERSISTENT);
158 REGISTER_LONG_CONSTANT("SCANDIR_SORT_NONE", PHP_SCANDIR_SORT_NONE, CONST_CS | CONST_PERSISTENT);
159
160 #ifdef HAVE_GLOB
161
162 #ifdef GLOB_BRACE
163 REGISTER_LONG_CONSTANT("GLOB_BRACE", GLOB_BRACE, CONST_CS | CONST_PERSISTENT);
164 #else
165 # define GLOB_BRACE 0
166 #endif
167
168 #ifdef GLOB_MARK
169 REGISTER_LONG_CONSTANT("GLOB_MARK", GLOB_MARK, CONST_CS | CONST_PERSISTENT);
170 #else
171 # define GLOB_MARK 0
172 #endif
173
174 #ifdef GLOB_NOSORT
175 REGISTER_LONG_CONSTANT("GLOB_NOSORT", GLOB_NOSORT, CONST_CS | CONST_PERSISTENT);
176 #else
177 # define GLOB_NOSORT 0
178 #endif
179
180 #ifdef GLOB_NOCHECK
181 REGISTER_LONG_CONSTANT("GLOB_NOCHECK", GLOB_NOCHECK, CONST_CS | CONST_PERSISTENT);
182 #else
183 # define GLOB_NOCHECK 0
184 #endif
185
186 #ifdef GLOB_NOESCAPE
187 REGISTER_LONG_CONSTANT("GLOB_NOESCAPE", GLOB_NOESCAPE, CONST_CS | CONST_PERSISTENT);
188 #else
189 # define GLOB_NOESCAPE 0
190 #endif
191
192 #ifdef GLOB_ERR
193 REGISTER_LONG_CONSTANT("GLOB_ERR", GLOB_ERR, CONST_CS | CONST_PERSISTENT);
194 #else
195 # define GLOB_ERR 0
196 #endif
197
198 #ifndef GLOB_ONLYDIR
199 # define GLOB_ONLYDIR (1<<30)
200 # define GLOB_EMULATE_ONLYDIR
201 # define GLOB_FLAGMASK (~GLOB_ONLYDIR)
202 #else
203 # define GLOB_FLAGMASK (~0)
204 #endif
205
206
207 #define GLOB_AVAILABLE_FLAGS (0 | GLOB_BRACE | GLOB_MARK | GLOB_NOSORT | GLOB_NOCHECK | GLOB_NOESCAPE | GLOB_ERR | GLOB_ONLYDIR)
208
209 REGISTER_LONG_CONSTANT("GLOB_ONLYDIR", GLOB_ONLYDIR, CONST_CS | CONST_PERSISTENT);
210 REGISTER_LONG_CONSTANT("GLOB_AVAILABLE_FLAGS", GLOB_AVAILABLE_FLAGS, CONST_CS | CONST_PERSISTENT);
211
212 #endif
213
214 return SUCCESS;
215 }
216
217
218
219 static void _php_do_opendir(INTERNAL_FUNCTION_PARAMETERS, int createobject)
220 {
221 char *dirname;
222 size_t dir_len;
223 zval *zcontext = NULL;
224 php_stream_context *context = NULL;
225 php_stream *dirp;
226
227 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|r", &dirname, &dir_len, &zcontext) == FAILURE) {
228 RETURN_NULL();
229 }
230
231 context = php_stream_context_from_zval(zcontext, 0);
232
233 dirp = php_stream_opendir(dirname, REPORT_ERRORS, context);
234
235 if (dirp == NULL) {
236 RETURN_FALSE;
237 }
238
239 dirp->flags |= PHP_STREAM_FLAG_NO_FCLOSE;
240
241 php_set_default_dir(dirp->res);
242
243 if (createobject) {
244 object_init_ex(return_value, dir_class_entry_ptr);
245 add_property_stringl(return_value, "path", dirname, dir_len);
246 add_property_resource(return_value, "handle", dirp->res);
247 php_stream_auto_cleanup(dirp);
248 } else {
249 php_stream_to_zval(dirp, return_value);
250 }
251 }
252
253
254
255
256 PHP_FUNCTION(opendir)
257 {
258 _php_do_opendir(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
259 }
260
261
262
263
264 PHP_FUNCTION(getdir)
265 {
266 _php_do_opendir(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
267 }
268
269
270
271
272 PHP_FUNCTION(closedir)
273 {
274 zval *id = NULL, *tmp, *myself;
275 php_stream *dirp;
276 zend_resource *res;
277
278 FETCH_DIRP();
279
280 if (!(dirp->flags & PHP_STREAM_FLAG_IS_DIR)) {
281 php_error_docref(NULL, E_WARNING, "%pd is not a valid Directory resource", dirp->res->handle);
282 RETURN_FALSE;
283 }
284
285 res = dirp->res;
286 zend_list_close(dirp->res);
287
288 if (res == DIRG(default_dir)) {
289 php_set_default_dir(NULL);
290 }
291 }
292
293
294 #if defined(HAVE_CHROOT) && !defined(ZTS) && ENABLE_CHROOT_FUNC
295
296
297 PHP_FUNCTION(chroot)
298 {
299 char *str;
300 int ret;
301 size_t str_len;
302
303 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &str, &str_len) == FAILURE) {
304 RETURN_FALSE;
305 }
306
307 ret = chroot(str);
308 if (ret != 0) {
309 php_error_docref(NULL, E_WARNING, "%s (errno %d)", strerror(errno), errno);
310 RETURN_FALSE;
311 }
312
313 php_clear_stat_cache(1, NULL, 0);
314
315 ret = chdir("/");
316
317 if (ret != 0) {
318 php_error_docref(NULL, E_WARNING, "%s (errno %d)", strerror(errno), errno);
319 RETURN_FALSE;
320 }
321
322 RETURN_TRUE;
323 }
324
325 #endif
326
327
328
329 PHP_FUNCTION(chdir)
330 {
331 char *str;
332 int ret;
333 size_t str_len;
334
335 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &str, &str_len) == FAILURE) {
336 RETURN_FALSE;
337 }
338
339 if (php_check_open_basedir(str)) {
340 RETURN_FALSE;
341 }
342 ret = VCWD_CHDIR(str);
343
344 if (ret != 0) {
345 php_error_docref(NULL, E_WARNING, "%s (errno %d)", strerror(errno), errno);
346 RETURN_FALSE;
347 }
348
349 if (BG(CurrentStatFile) && !IS_ABSOLUTE_PATH(BG(CurrentStatFile), strlen(BG(CurrentStatFile)))) {
350 efree(BG(CurrentStatFile));
351 BG(CurrentStatFile) = NULL;
352 }
353 if (BG(CurrentLStatFile) && !IS_ABSOLUTE_PATH(BG(CurrentLStatFile), strlen(BG(CurrentLStatFile)))) {
354 efree(BG(CurrentLStatFile));
355 BG(CurrentLStatFile) = NULL;
356 }
357
358 RETURN_TRUE;
359 }
360
361
362
363
364 PHP_FUNCTION(getcwd)
365 {
366 char path[MAXPATHLEN];
367 char *ret=NULL;
368
369 if (zend_parse_parameters_none() == FAILURE) {
370 return;
371 }
372
373 #if HAVE_GETCWD
374 ret = VCWD_GETCWD(path, MAXPATHLEN);
375 #elif HAVE_GETWD
376 ret = VCWD_GETWD(path);
377 #endif
378
379 if (ret) {
380 RETURN_STRING(path);
381 } else {
382 RETURN_FALSE;
383 }
384 }
385
386
387
388
389 PHP_FUNCTION(rewinddir)
390 {
391 zval *id = NULL, *tmp, *myself;
392 php_stream *dirp;
393
394 FETCH_DIRP();
395
396 if (!(dirp->flags & PHP_STREAM_FLAG_IS_DIR)) {
397 php_error_docref(NULL, E_WARNING, "%pd is not a valid Directory resource", dirp->res->handle);
398 RETURN_FALSE;
399 }
400
401 php_stream_rewinddir(dirp);
402 }
403
404
405
406
407 PHP_NAMED_FUNCTION(php_if_readdir)
408 {
409 zval *id = NULL, *tmp, *myself;
410 php_stream *dirp;
411 php_stream_dirent entry;
412
413 FETCH_DIRP();
414
415 if (!(dirp->flags & PHP_STREAM_FLAG_IS_DIR)) {
416 php_error_docref(NULL, E_WARNING, "%pd is not a valid Directory resource", dirp->res->handle);
417 RETURN_FALSE;
418 }
419
420 if (php_stream_readdir(dirp, &entry)) {
421 RETURN_STRINGL(entry.d_name, strlen(entry.d_name));
422 }
423 RETURN_FALSE;
424 }
425
426
427 #ifdef HAVE_GLOB
428
429
430 PHP_FUNCTION(glob)
431 {
432 int cwd_skip = 0;
433 #ifdef ZTS
434 char cwd[MAXPATHLEN];
435 char work_pattern[MAXPATHLEN];
436 char *result;
437 #endif
438 char *pattern = NULL;
439 size_t pattern_len;
440 zend_long flags = 0;
441 glob_t globbuf;
442 int n;
443 int ret;
444 zend_bool basedir_limit = 0;
445
446 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &pattern, &pattern_len, &flags) == FAILURE) {
447 return;
448 }
449
450 if (pattern_len >= MAXPATHLEN) {
451 php_error_docref(NULL, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
452 RETURN_FALSE;
453 }
454
455 if ((GLOB_AVAILABLE_FLAGS & flags) != flags) {
456 php_error_docref(NULL, E_WARNING, "At least one of the passed flags is invalid or not supported on this platform");
457 RETURN_FALSE;
458 }
459
460 #ifdef ZTS
461 if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
462 result = VCWD_GETCWD(cwd, MAXPATHLEN);
463 if (!result) {
464 cwd[0] = '\0';
465 }
466 #ifdef PHP_WIN32
467 if (IS_SLASH(*pattern)) {
468 cwd[2] = '\0';
469 }
470 #endif
471 cwd_skip = (int)strlen(cwd)+1;
472
473 snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
474 pattern = work_pattern;
475 }
476 #endif
477
478
479 memset(&globbuf, 0, sizeof(glob_t));
480 globbuf.gl_offs = 0;
481 if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) {
482 #ifdef GLOB_NOMATCH
483 if (GLOB_NOMATCH == ret) {
484
485
486
487
488
489
490
491
492 goto no_results;
493 }
494 #endif
495 RETURN_FALSE;
496 }
497
498
499 if (!globbuf.gl_pathc || !globbuf.gl_pathv) {
500 no_results:
501 #ifndef PHP_WIN32
502
503
504
505
506
507 if (PG(open_basedir) && *PG(open_basedir)) {
508 if (php_check_open_basedir_ex(pattern, 0)) {
509 RETURN_FALSE;
510 }
511 }
512 #endif
513 array_init(return_value);
514 return;
515 }
516
517 array_init(return_value);
518 for (n = 0; n < globbuf.gl_pathc; n++) {
519 if (PG(open_basedir) && *PG(open_basedir)) {
520 if (php_check_open_basedir_ex(globbuf.gl_pathv[n], 0)) {
521 basedir_limit = 1;
522 continue;
523 }
524 }
525
526
527
528
529
530
531
532
533 if (flags & GLOB_ONLYDIR) {
534 zend_stat_t s;
535
536 if (0 != VCWD_STAT(globbuf.gl_pathv[n], &s)) {
537 continue;
538 }
539
540 if (S_IFDIR != (s.st_mode & S_IFMT)) {
541 continue;
542 }
543 }
544 add_next_index_string(return_value, globbuf.gl_pathv[n]+cwd_skip);
545 }
546
547 globfree(&globbuf);
548
549 if (basedir_limit && !zend_hash_num_elements(Z_ARRVAL_P(return_value))) {
550 zval_dtor(return_value);
551 RETURN_FALSE;
552 }
553 }
554
555 #endif
556
557
558
559 PHP_FUNCTION(scandir)
560 {
561 char *dirn;
562 size_t dirn_len;
563 zend_long flags = 0;
564 zend_string **namelist;
565 int n, i;
566 zval *zcontext = NULL;
567 php_stream_context *context = NULL;
568
569 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|lr", &dirn, &dirn_len, &flags, &zcontext) == FAILURE) {
570 return;
571 }
572
573 if (dirn_len < 1) {
574 php_error_docref(NULL, E_WARNING, "Directory name cannot be empty");
575 RETURN_FALSE;
576 }
577
578 if (zcontext) {
579 context = php_stream_context_from_zval(zcontext, 0);
580 }
581
582 if (flags == PHP_SCANDIR_SORT_ASCENDING) {
583 n = php_stream_scandir(dirn, &namelist, context, (void *) php_stream_dirent_alphasort);
584 } else if (flags == PHP_SCANDIR_SORT_NONE) {
585 n = php_stream_scandir(dirn, &namelist, context, NULL);
586 } else {
587 n = php_stream_scandir(dirn, &namelist, context, (void *) php_stream_dirent_alphasortr);
588 }
589 if (n < 0) {
590 php_error_docref(NULL, E_WARNING, "(errno %d): %s", errno, strerror(errno));
591 RETURN_FALSE;
592 }
593
594 array_init(return_value);
595
596 for (i = 0; i < n; i++) {
597 add_next_index_str(return_value, namelist[i]);
598 }
599
600 if (n) {
601 efree(namelist);
602 }
603 }
604
605
606
607
608
609
610
611
612
613