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