php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
spl_directory.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 | Author: Marcus Boerger <helly@php.net> |
14 +----------------------------------------------------------------------+
15 */
16
17#ifdef HAVE_CONFIG_H
18# include "config.h"
19#endif
20
21#include "php.h"
22#include "ext/standard/file.h"
25#include "ext/standard/scanf.h"
26#include "ext/standard/php_string.h" /* For php_basename() */
27#include "zend_attributes.h"
28#include "zend_exceptions.h"
29#include "zend_interfaces.h"
30
31#include "spl_iterators.h"
32#include "spl_directory.h"
34#include "spl_exceptions.h"
35#include "spl_functions.h" /* For spl_set_private_debug_info_property() */
36
37#define SPL_HAS_FLAG(flags, test_flag) ((flags & test_flag) ? 1 : 0)
38
39/* declare the class handlers */
40static zend_object_handlers spl_filesystem_object_handlers;
41/* includes handler to validate object state when retrieving methods */
42static zend_object_handlers spl_filesystem_object_check_handlers;
43
44/* decalre the class entry */
52
53/* Object helper */
54static inline spl_filesystem_object *spl_filesystem_from_obj(zend_object *obj) /* {{{ */ {
55 return (spl_filesystem_object*)((char*)(obj) - XtOffsetOf(spl_filesystem_object, std));
56}
57/* }}} */
58
59/* define an overloaded iterator structure */
65
66static inline spl_filesystem_iterator* spl_filesystem_object_to_iterator(spl_filesystem_object *obj)
67{
69
70 it = ecalloc(1, sizeof(spl_filesystem_iterator));
71 it->object = (void *)obj;
73 return it;
74}
75
76static inline spl_filesystem_object* spl_filesystem_iterator_to_object(spl_filesystem_iterator *it)
77{
78 return (spl_filesystem_object*)it->object;
79}
80
81#define CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(spl_filesystem_object_pointer) \
82 if (!(spl_filesystem_object_pointer)->u.file.stream) { \
83 zend_throw_error(NULL, "Object not initialized"); \
84 RETURN_THROWS(); \
85 }
86
87#define CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern) \
88 if (!(intern)->u.dir.dirp) { \
89 zend_throw_error(NULL, "Object not initialized"); \
90 RETURN_THROWS(); \
91 }
92
93static void spl_filesystem_file_free_line(spl_filesystem_object *intern) /* {{{ */
94{
95 if (intern->u.file.current_line) {
96 zend_string_release_ex(intern->u.file.current_line, /* persistent */ false);
97 intern->u.file.current_line = NULL;
98 }
99 if (!Z_ISUNDEF(intern->u.file.current_zval)) {
101 ZVAL_UNDEF(&intern->u.file.current_zval);
102 }
103} /* }}} */
104
105static void spl_filesystem_object_destroy_object(zend_object *object) /* {{{ */
106{
107 spl_filesystem_object *intern = spl_filesystem_from_obj(object);
108
110
111 switch(intern->type) {
112 case SPL_FS_DIR:
113 if (intern->u.dir.dirp) {
114 php_stream_close(intern->u.dir.dirp);
115 intern->u.dir.dirp = NULL;
116 }
117 break;
118 case SPL_FS_FILE:
119 if (intern->u.file.stream) {
120 /*
121 if (intern->u.file.zcontext) {
122 zend_list_delref(Z_RESVAL_P(intern->zcontext));
123 }
124 */
125 if (!intern->u.file.stream->is_persistent) {
126 php_stream_close(intern->u.file.stream);
127 } else {
129 }
130 intern->u.file.stream = NULL;
131 ZVAL_UNDEF(&intern->u.file.zresource);
132 }
133 break;
134 default:
135 break;
136 }
137} /* }}} */
138
139static void spl_filesystem_object_free_storage(zend_object *object) /* {{{ */
140{
141 spl_filesystem_object *intern = spl_filesystem_from_obj(object);
142
143 if (intern->oth_handler && intern->oth_handler->dtor) {
144 intern->oth_handler->dtor(intern);
145 }
146
147 zend_object_std_dtor(&intern->std);
148
149 if (intern->path) {
150 zend_string_release(intern->path);
151 }
152 if (intern->file_name) {
153 zend_string_release(intern->file_name);
154 }
155 switch(intern->type) {
156 case SPL_FS_INFO:
157 break;
158 case SPL_FS_DIR:
159 if (intern->u.dir.sub_path) {
160 zend_string_release(intern->u.dir.sub_path);
161 }
162 break;
163 case SPL_FS_FILE:
164 if (intern->u.file.open_mode) {
165 zend_string_release(intern->u.file.open_mode);
166 }
167 if (intern->orig_path) {
168 zend_string_release(intern->orig_path);
169 }
170 spl_filesystem_file_free_line(intern);
171 break;
172 }
173} /* }}} */
174
175/* {{{ spl_ce_dir_object_new */
176/* creates the object by
177 - allocating memory
178 - initializing the object members
179 - storing the object
180 - setting it's handlers
181
182 called from
183 - clone
184 - new
185 */
186static zend_object *spl_filesystem_object_new(zend_class_entry *class_type)
187{
188 spl_filesystem_object *intern;
189
190 intern = emalloc(sizeof(spl_filesystem_object) + zend_object_properties_size(class_type));
191 /* Avoid initializing the entirety of spl_filesystem_object.u.dir.entry. */
192 memset(intern, 0,
194 XtOffsetOf(spl_filesystem_object, u.file.escape) + sizeof(int)));
195 /* intern->type = SPL_FS_INFO; done by set 0 */
198
199 zend_object_std_init(&intern->std, class_type);
200 object_properties_init(&intern->std, class_type);
201
202 return &intern->std;
203}
204/* }}} */
205
206static inline bool spl_intern_is_glob(const spl_filesystem_object *intern)
207{
208 /* NULL check on `dirp` is necessary as destructors may interfere. */
209 return intern->u.dir.dirp && php_stream_is(intern->u.dir.dirp, &php_glob_stream_ops);
210}
211
213{
214#ifdef HAVE_GLOB
215 if (intern->type == SPL_FS_DIR && spl_intern_is_glob(intern)) {
216 size_t len = 0;
217 char *tmp = php_glob_stream_get_path(intern->u.dir.dirp, &len);
218 if (len == 0) {
219 return NULL;
220 }
221 return zend_string_init(tmp, len, /* persistent */ false);
222 }
223#endif
224 if (!intern->path) {
225 return NULL;
226 }
227 return zend_string_copy(intern->path);
228} /* }}} */
229
230static zend_result spl_filesystem_object_get_file_name(spl_filesystem_object *intern) /* {{{ */
231{
232 if (intern->file_name) {
233 /* already known */
234 return SUCCESS;
235 }
236
237 switch (intern->type) {
238 case SPL_FS_INFO:
239 case SPL_FS_FILE:
240 zend_throw_error(NULL, "Object not initialized");
241 return FAILURE;
242 case SPL_FS_DIR: {
243 size_t name_len;
244 zend_string *path;
245 char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
246
247 path = spl_filesystem_object_get_path(intern);
248 /* if there is parent path, amend it, otherwise just use the given path as is */
249 name_len = strlen(intern->u.dir.entry.d_name);
250 if (!path) {
251 intern->file_name = zend_string_init(intern->u.dir.entry.d_name, name_len, 0);
252 return SUCCESS;
253 }
254
255 ZEND_ASSERT(ZSTR_LEN(path) != 0);
257 ZSTR_VAL(path), ZSTR_LEN(path), &slash, 1, intern->u.dir.entry.d_name, name_len);
258 zend_string_release_ex(path, /* persistent */ false);
259 break;
260 }
261 }
262 return SUCCESS;
263} /* }}} */
264
265/* TODO Make void or have callers check return value */
266static bool spl_filesystem_dir_read(spl_filesystem_object *intern) /* {{{ */
267{
268 if (intern->file_name) {
269 /* invalidate */
270 zend_string_release(intern->file_name);
271 intern->file_name = NULL;
272 }
273 if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
274 intern->u.dir.entry.d_name[0] = '\0';
275 return 0;
276 } else {
277 return 1;
278 }
279}
280/* }}} */
281
282#define IS_SLASH_AT(zs, pos) (IS_SLASH(zs[pos]))
283
284static inline bool spl_filesystem_is_dot(const char * d_name) /* {{{ */
285{
286 return !strcmp(d_name, ".") || !strcmp(d_name, "..");
287}
288/* }}} */
289
290/* {{{ spl_filesystem_dir_open */
291/* open a directory resource
292 * Can emit an E_WARNING as it reports errors from php_stream_opendir() */
293static void spl_filesystem_dir_open(spl_filesystem_object* intern, zend_string *path)
294{
295 bool skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
296
297 intern->type = SPL_FS_DIR;
298 intern->u.dir.dirp = php_stream_opendir(ZSTR_VAL(path), REPORT_ERRORS, FG(default_context));
299
300 if (ZSTR_LEN(path) > 1 && IS_SLASH_AT(ZSTR_VAL(path), ZSTR_LEN(path)-1)) {
301 intern->path = zend_string_init(ZSTR_VAL(path), ZSTR_LEN(path)-1, 0);
302 } else {
303 intern->path = zend_string_copy(path);
304 }
305 intern->u.dir.index = 0;
306
307 if (EG(exception) || intern->u.dir.dirp == NULL) {
308 intern->u.dir.entry.d_name[0] = '\0';
309 if (!EG(exception)) {
310 /* open failed w/out notice (turned to exception due to EH_THROW) */
312 "Failed to open directory \"%s\"", ZSTR_VAL(path));
313 }
314 } else {
315 do {
316 spl_filesystem_dir_read(intern);
317 } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
318 }
319}
320/* }}} */
321
322/* Can generate E_WARNINGS as we report errors from stream initialized via
323 * php_stream_open_wrapper_ex() */
324static zend_result spl_filesystem_file_open(spl_filesystem_object *intern, bool use_include_path) /* {{{ */
325{
326 zval tmp;
327
328 intern->type = SPL_FS_FILE;
329 php_stat(intern->file_name, FS_IS_DIR, &tmp);
330 if (Z_TYPE(tmp) == IS_TRUE) {
331 zend_string_release(intern->u.file.open_mode);
332 intern->u.file.open_mode = NULL;
333 intern->file_name = NULL;
334 zend_throw_exception_ex(spl_ce_LogicException, 0, "Cannot use SplFileObject with directories");
335 return FAILURE;
336 }
337
340
341 if (!ZSTR_LEN(intern->file_name) || !intern->u.file.stream) {
342 if (!EG(exception)) {
343 zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot open file '%s'", ZSTR_VAL(intern->file_name));
344 }
345 zend_string_release(intern->u.file.open_mode);
346 intern->u.file.open_mode = NULL;
347 intern->file_name = NULL; /* until here it is not a copy */
348 return FAILURE;
349 }
350
351 /* prevent closing the stream outside of SplFileObject */
353
354 /*
355 if (intern->u.file.zcontext) {
356 //zend_list_addref(Z_RES_VAL(intern->u.file.zcontext));
357 Z_ADDREF_P(intern->u.file.zcontext);
358 }
359 */
360
361 if (ZSTR_LEN(intern->file_name) > 1 && IS_SLASH_AT(ZSTR_VAL(intern->file_name), ZSTR_LEN(intern->file_name)-1)) {
362 intern->file_name = zend_string_init(ZSTR_VAL(intern->file_name), ZSTR_LEN(intern->file_name)-1, 0);
363 } else {
364 intern->file_name = zend_string_copy(intern->file_name);
365 }
366
367 intern->orig_path = zend_string_init(intern->u.file.stream->orig_path, strlen(intern->u.file.stream->orig_path), 0);
368
369 /* avoid reference counting in debug mode, thus do it manually */
370 ZVAL_RES(&intern->u.file.zresource, intern->u.file.stream->res);
374
375 intern->u.file.delimiter = ',';
376 intern->u.file.enclosure = '"';
377 intern->u.file.escape = (unsigned char) '\\';
378 intern->u.file.is_escape_default = true;
379
380 intern->u.file.func_getCurr = zend_hash_str_find_ptr(&intern->std.ce->function_table, "getcurrentline", sizeof("getcurrentline") - 1);
381
382 return SUCCESS;
383} /* }}} */
384
385/* {{{ spl_filesystem_object_clone */
386/* Local zend_object creation (on stack)
387 Load the 'other' object
388 Create a new empty object (See spl_filesystem_object_new)
389 Open the directory
390 Clone other members (properties)
391 */
392static zend_object *spl_filesystem_object_clone(zend_object *old_object)
393{
394 zend_object *new_object;
395 spl_filesystem_object *intern;
396 spl_filesystem_object *source;
397
398 source = spl_filesystem_from_obj(old_object);
399 new_object = spl_filesystem_object_new(old_object->ce);
400 intern = spl_filesystem_from_obj(new_object);
401
402 intern->flags = source->flags;
403
404 switch (source->type) {
405 case SPL_FS_INFO:
406 if (source->path != NULL) {
407 intern->path = zend_string_copy(source->path);
408 }
409 if (source->file_name != NULL) {
410 intern->file_name = zend_string_copy(source->file_name);
411 }
412 break;
413 case SPL_FS_DIR: {
414 spl_filesystem_dir_open(intern, source->path);
415 /* read until we hit the position in which we were before */
416 bool skip_dots = SPL_HAS_FLAG(source->flags, SPL_FILE_DIR_SKIPDOTS);
417 int index;
418 for (index = 0; index < source->u.dir.index; ++index) {
419 do {
420 spl_filesystem_dir_read(intern);
421 } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
422 }
423 intern->u.dir.index = index;
424 break;
425 }
426 case SPL_FS_FILE:
428 }
429
430 intern->file_class = source->file_class;
431 intern->info_class = source->info_class;
432 intern->oth = source->oth;
433 intern->oth_handler = source->oth_handler;
434
435 zend_objects_clone_members(new_object, old_object);
436
437 if (intern->oth_handler && intern->oth_handler->clone) {
438 intern->oth_handler->clone(source, intern);
439 }
440
441 return new_object;
442}
443/* }}} */
444
445static void spl_filesystem_info_set_filename(spl_filesystem_object *intern, zend_string *path) /* {{{ */
446{
447 size_t path_len;
448
449 if (intern->file_name) {
450 zend_string_release(intern->file_name);
451 }
452
453 path_len = ZSTR_LEN(path);
454 if (path_len > 1 && IS_SLASH_AT(ZSTR_VAL(path), path_len-1)) {
455 do {
456 path_len--;
457 } while (path_len > 1 && IS_SLASH_AT(ZSTR_VAL(path), path_len - 1));
458 intern->file_name = zend_string_init(ZSTR_VAL(path), path_len, 0);
459 } else {
460 intern->file_name = zend_string_copy(path);
461 }
462 while (path_len > 1 && !IS_SLASH_AT(ZSTR_VAL(path), path_len-1)) {
463 path_len--;
464 }
465 if (path_len) {
466 path_len--;
467 }
468
469 if (intern->path) {
470 zend_string_release(intern->path);
471 }
472 intern->path = zend_string_init(ZSTR_VAL(path), path_len, 0);
473} /* }}} */
474
475// TODO Do not pass return_value pointer but actually use value returned by function at call site?
476static spl_filesystem_object *spl_filesystem_object_create_info(zend_string *file_path, zend_class_entry *ce, zval *return_value) /* {{{ */
477{
478 spl_filesystem_object *intern;
479 zval arg1;
480
481 ZEND_ASSERT(file_path && ZSTR_LEN(file_path) > 0);
482 ZEND_ASSERT(ce != NULL);
483
484 intern = spl_filesystem_from_obj(spl_filesystem_object_new(ce));
485 RETVAL_OBJ(&intern->std);
486
488 ZVAL_STR_COPY(&arg1, file_path);
489 zend_call_method_with_1_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1);
491 } else {
492 spl_filesystem_info_set_filename(intern, file_path);
493 }
494
495 return intern;
496} /* }}} */
497
498static spl_filesystem_object *spl_filesystem_object_create_type(int num_args, spl_filesystem_object *source, int type, zend_class_entry *ce, zval *return_value) /* {{{ */
499{
500 spl_filesystem_object *intern;
501 bool use_include_path = 0;
502 zval arg1, arg2;
503 zend_error_handling error_handling;
504
505 switch (source->type) {
506 case SPL_FS_INFO:
507 case SPL_FS_FILE:
508 break;
509 case SPL_FS_DIR:
510 if (!source->u.dir.entry.d_name[0]) {
511 zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Could not open file");
512 return NULL;
513 }
514 }
515
516 switch (type) {
517 case SPL_FS_INFO:
518 ce = ce ? ce : source->info_class;
519
520 intern = spl_filesystem_from_obj(spl_filesystem_object_new(ce));
521 RETVAL_OBJ(&intern->std);
522
523 if (spl_filesystem_object_get_file_name(source) == FAILURE) {
524 return NULL;
525 }
526
528 ZVAL_STR_COPY(&arg1, source->file_name);
529 zend_call_method_with_1_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1);
531 } else {
532 intern->file_name = zend_string_copy(source->file_name);
533 intern->path = spl_filesystem_object_get_path(source);
534 }
535 break;
536 case SPL_FS_FILE:
537 {
538 ce = ce ? ce : source->file_class;
539
540 zend_string *open_mode = ZSTR_CHAR('r');
541 zval *resource = NULL;
542
543 if (zend_parse_parameters(num_args, "|Sbr!",
544 &open_mode, &use_include_path, &resource) == FAILURE
545 ) {
546 return NULL;
547 }
548
549 intern = spl_filesystem_from_obj(spl_filesystem_object_new(ce));
550 RETVAL_OBJ(&intern->std);
551
552 if (spl_filesystem_object_get_file_name(source) == FAILURE) {
553 return NULL;
554 }
555
557 ZVAL_STR_COPY(&arg1, source->file_name);
558 ZVAL_STR_COPY(&arg2, open_mode);
559 zend_call_method_with_2_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1, &arg2);
562 } else {
563 intern->file_name = source->file_name;
564 intern->path = spl_filesystem_object_get_path(source);
565 intern->u.file.open_mode = zend_string_copy(open_mode);
566 intern->u.file.zcontext = resource;
567
568 /* spl_filesystem_file_open() can generate E_WARNINGs which we want to promote to exceptions */
570 if (spl_filesystem_file_open(intern, use_include_path) == FAILURE) {
571 zend_restore_error_handling(&error_handling);
574 return NULL;
575 }
576 zend_restore_error_handling(&error_handling);
577 }
578 break;
579 }
580 case SPL_FS_DIR:
581 zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Operation not supported");
582 return NULL;
583 }
584 return NULL;
585} /* }}} */
586
587static bool spl_filesystem_is_invalid_or_dot(const char * d_name) /* {{{ */
588{
589 return d_name[0] == '\0' || spl_filesystem_is_dot(d_name);
590}
591/* }}} */
592
593static zend_string *spl_filesystem_object_get_pathname(spl_filesystem_object *intern) { /* {{{ */
594 switch (intern->type) {
595 case SPL_FS_INFO:
596 case SPL_FS_FILE:
597 return intern->file_name;
598 case SPL_FS_DIR:
599 if (intern->u.dir.entry.d_name[0]) {
600 spl_filesystem_object_get_file_name(intern);
601 return intern->file_name;
602 }
603 }
604 return NULL;
605}
606/* }}} */
607
608static inline HashTable *spl_filesystem_object_get_debug_info(zend_object *object) /* {{{ */
609{
610 spl_filesystem_object *intern = spl_filesystem_from_obj(object);
611 zval tmp;
612 HashTable *debug_info;
613 zend_string *path_name;
614
615 // TODO Do zend_new_array() + zend_hash_copy() trick?
616 debug_info = zend_array_dup(zend_std_get_properties_ex(&intern->std));
617
618 path_name = spl_filesystem_object_get_pathname(intern);
619 if (path_name) {
620 ZVAL_STR_COPY(&tmp, path_name);
621 } else {
622 ZVAL_EMPTY_STRING(&tmp);
623 }
624 /* IMPORTANT: Do not free path_name as spl_filesystem_object_get_pathname()
625 * updates/sets the intern->file_name and returns the pointer to
626 * intern->file_name which must remain allocated. */
627 spl_set_private_debug_info_property(spl_ce_SplFileInfo, "pathName", strlen("pathName"), debug_info, &tmp);
628
629 if (intern->file_name) {
631 if (path && ZSTR_LEN(path) && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) {
632 /* +1 to skip the trailing / of the path in the file name */
633 ZVAL_STRINGL(&tmp, ZSTR_VAL(intern->file_name) + ZSTR_LEN(path) + 1, ZSTR_LEN(intern->file_name) - (ZSTR_LEN(path) + 1));
634 } else {
635 ZVAL_STR_COPY(&tmp, intern->file_name);
636 }
637 if (path) {
638 zend_string_release_ex(path, /* persistent */ false);
639 }
640
641 spl_set_private_debug_info_property(spl_ce_SplFileInfo, "fileName", strlen("fileName"), debug_info, &tmp);
642 }
643 if (intern->type == SPL_FS_DIR) {
644#ifdef HAVE_GLOB
645 if (spl_intern_is_glob(intern)) {
646 ZVAL_STR_COPY(&tmp, intern->path);
647 } else {
648 ZVAL_FALSE(&tmp);
649 }
650 spl_set_private_debug_info_property(spl_ce_DirectoryIterator, "glob", strlen("glob"), debug_info, &tmp);
651#endif
652 if (intern->u.dir.sub_path) {
653 ZVAL_STR_COPY(&tmp, intern->u.dir.sub_path);
654 } else {
655 ZVAL_EMPTY_STRING(&tmp);
656 }
657 spl_set_private_debug_info_property(spl_ce_RecursiveDirectoryIterator, "subPathName", strlen("subPathName"), debug_info, &tmp);
658 }
659 if (intern->type == SPL_FS_FILE) {
660 ZVAL_STR_COPY(&tmp, intern->u.file.open_mode);
661 spl_set_private_debug_info_property(spl_ce_SplFileObject, "openMode", strlen("openMode"), debug_info, &tmp);
662
663 ZVAL_STR(&tmp, ZSTR_CHAR((zend_uchar)intern->u.file.delimiter));
664 spl_set_private_debug_info_property(spl_ce_SplFileObject, "delimiter", strlen("delimiter"), debug_info, &tmp);
665
666 ZVAL_STR(&tmp, ZSTR_CHAR((zend_uchar)intern->u.file.enclosure));
667 spl_set_private_debug_info_property(spl_ce_SplFileObject, "enclosure", strlen("enclosure"), debug_info, &tmp);
668 }
669
670 return debug_info;
671}
672/* }}} */
673
674static zend_function *spl_filesystem_object_get_method_check(zend_object **object, zend_string *method, const zval *key) /* {{{ */
675{
676 spl_filesystem_object *fsobj = spl_filesystem_from_obj(*object);
677
678 if (fsobj->u.dir.dirp == NULL && fsobj->orig_path == NULL) {
679 zend_throw_error(NULL, "The parent constructor was not called: the object is in an invalid state");
680 return NULL;
681 }
682
683 return zend_std_get_method(object, method, key);
684}
685/* }}} */
686
687#define DIT_CTOR_FLAGS 0x00000001
688#define DIT_CTOR_GLOB 0x00000002
689
690static void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, zend_long ctor_flags) /* {{{ */
691{
692 spl_filesystem_object *intern;
693 zend_string *path;
694 zend_result parsed;
695 zend_long flags = (ctor_flags & ~DIT_CTOR_FLAGS);
696 zend_error_handling error_handling;
697
698 if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_FLAGS)) {
700 parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &path, &flags);
701 } else {
703 parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "P", &path);
704 }
705 if (parsed == FAILURE) {
707 }
708
709 if (ZSTR_LEN(path) == 0) {
712 }
713
714 intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
715 if (intern->path) {
716 /* object is already initialized */
717 zend_throw_error(NULL, "Directory object is already initialized");
719 }
720 intern->flags = flags;
721
722 /* spl_filesystem_dir_open() may emit an E_WARNING */
724#ifdef HAVE_GLOB
725 if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_GLOB) && !zend_string_starts_with_literal(path, "glob://")) {
726 path = zend_strpprintf(0, "glob://%s", ZSTR_VAL(path));
727 spl_filesystem_dir_open(intern, path);
728 zend_string_release(path);
729 } else
730#endif
731 {
732 spl_filesystem_dir_open(intern, path);
733
734 }
735 zend_restore_error_handling(&error_handling);
736}
737/* }}} */
738
739/* {{{ Cronstructs a new dir iterator from a path. */
741{
742 spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
743}
744/* }}} */
745
746/* {{{ Rewind dir back to the start */
748{
749 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
750
753 }
754
756 intern->u.dir.index = 0;
758 spl_filesystem_dir_read(intern);
759}
760/* }}} */
761
762/* {{{ Return current dir entry */
764{
765 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
766
769 }
770
772 RETURN_LONG(intern->u.dir.index);
773}
774/* }}} */
775
776/* {{{ Return this (needed for Iterator interface) */
786/* }}} */
787
788/* {{{ Move to next entry */
790{
791 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
792 bool skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
793
796 }
797
799 intern->u.dir.index++;
800 do {
801 spl_filesystem_dir_read(intern);
802 } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
803 if (intern->file_name) {
804 zend_string_release(intern->file_name);
805 intern->file_name = NULL;
806 }
807}
808/* }}} */
809
810/* {{{ Seek to the given position */
812{
813 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
814 zval retval;
816
819 }
820
822 if (intern->u.dir.index > pos) {
823 /* we first rewind */
824 zend_call_method_with_0_params(Z_OBJ_P(ZEND_THIS), Z_OBJCE_P(ZEND_THIS), &intern->u.dir.func_rewind, "rewind", NULL);
825 }
826
827 while (intern->u.dir.index < pos) {
828 bool valid = false;
829 zend_call_method_with_0_params(Z_OBJ_P(ZEND_THIS), Z_OBJCE_P(ZEND_THIS), &intern->u.dir.func_valid, "valid", &retval);
830 valid = zend_is_true(&retval);
832 if (!valid) {
833 zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Seek position " ZEND_LONG_FMT " is out of range", pos);
835 }
836 zend_call_method_with_0_params(Z_OBJ_P(ZEND_THIS), Z_OBJCE_P(ZEND_THIS), &intern->u.dir.func_next, "next", NULL);
837 }
838} /* }}} */
839
840/* {{{ Check whether dir contains more entries */
842{
843 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
844
847 }
848
850 RETURN_BOOL(intern->u.dir.entry.d_name[0] != '\0');
851}
852/* }}} */
853
854/* {{{ Return the path */
856{
857 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
858 zend_string *path;
859
862 }
863
864 path = spl_filesystem_object_get_path(intern);
865 if (path) {
866 RETURN_STR(path);
867 } else {
869 }
870}
871/* }}} */
872
873/* {{{ Return filename only */
875{
876 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
877 zend_string *path;
878
881 }
882
883 if (!intern->file_name) {
884 zend_throw_error(NULL, "Object not initialized");
886 }
887
888 path = spl_filesystem_object_get_path(intern);
889
890 if (path && ZSTR_LEN(path) && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) {
891 /* +1 to skip the trailing / of the path in the file name */
892 size_t path_len = ZSTR_LEN(path) + 1;
893 RETVAL_STRINGL(ZSTR_VAL(intern->file_name) + path_len, ZSTR_LEN(intern->file_name) - path_len);
894 } else {
895 RETVAL_STR_COPY(intern->file_name);
896 }
897 if (path) {
898 zend_string_release_ex(path, /* persistent */ false);
899 }
900}
901/* }}} */
902
903/* {{{ Return filename of current dir entry */
905{
906 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
907
910 }
911
913 RETURN_STRING(intern->u.dir.entry.d_name);
914}
915/* }}} */
916
917/* {{{ Returns file extension component of path */
919{
920 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
921 char *fname = NULL;
922 const char *p;
923 size_t flen;
924 zend_string *path;
925 size_t idx;
927
930 }
931
932 if (!intern->file_name) {
933 zend_throw_error(NULL, "Object not initialized");
935 }
936
937 path = spl_filesystem_object_get_path(intern);
938
939 if (path && ZSTR_LEN(path) && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) {
940 fname = ZSTR_VAL(intern->file_name) + ZSTR_LEN(path) + 1;
941 flen = ZSTR_LEN(intern->file_name) - (ZSTR_LEN(path) + 1);
942 } else {
943 fname = ZSTR_VAL(intern->file_name);
944 flen = ZSTR_LEN(intern->file_name);
945 }
946 if (path) {
947 zend_string_release_ex(path, /* persistent */ false);
948 }
949
950 ret = php_basename(fname, flen, NULL, 0);
951
952 p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
953 if (p) {
954 idx = p - ZSTR_VAL(ret);
955 RETVAL_STRINGL(ZSTR_VAL(ret) + idx + 1, ZSTR_LEN(ret) - idx - 1);
957 return;
958 } else {
961 }
962}
963/* }}}*/
964
965/* {{{ Returns the file extension component of path */
967{
968 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
969 const char *p;
970 size_t idx;
971 zend_string *fname;
972
975 }
976
978 fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), NULL, 0);
979
980 p = zend_memrchr(ZSTR_VAL(fname), '.', ZSTR_LEN(fname));
981 if (p) {
982 idx = p - ZSTR_VAL(fname);
983 RETVAL_STRINGL(ZSTR_VAL(fname) + idx + 1, ZSTR_LEN(fname) - idx - 1);
984 zend_string_release_ex(fname, 0);
985 } else {
986 zend_string_release_ex(fname, 0);
988 }
989}
990/* }}} */
991
992/* {{{ Returns filename component of path */
994{
995 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
996 char *fname, *suffix = 0;
997 size_t flen;
998 size_t slen = 0;
999 zend_string *path;
1000
1001 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) {
1002 RETURN_THROWS();
1003 }
1004
1005 if (!intern->file_name) {
1006 zend_throw_error(NULL, "Object not initialized");
1007 RETURN_THROWS();
1008 }
1009
1010 path = spl_filesystem_object_get_path(intern);
1011
1012 if (path && ZSTR_LEN(path) && ZSTR_LEN(path) < ZSTR_LEN(intern->file_name)) {
1013 /* +1 to skip the trailing / of the path in the file name */
1014 fname = ZSTR_VAL(intern->file_name) + ZSTR_LEN(path) + 1;
1015 flen = ZSTR_LEN(intern->file_name) - (ZSTR_LEN(path) + 1);
1016 } else {
1017 fname = ZSTR_VAL(intern->file_name);
1018 flen = ZSTR_LEN(intern->file_name);
1019 }
1020 if (path) {
1021 zend_string_release_ex(path, /* persistent */ false);
1022 }
1023
1024 RETURN_STR(php_basename(fname, flen, suffix, slen));
1025}
1026/* }}}*/
1027
1028/* {{{ Returns filename component of current dir entry */
1030{
1031 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1032 char *suffix = 0;
1033 size_t slen = 0;
1034 zend_string *fname;
1035
1036 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) {
1037 RETURN_THROWS();
1038 }
1039
1041 fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), suffix, slen);
1042
1043 RETURN_STR(fname);
1044}
1045/* }}} */
1046
1047/* {{{ Return path and filename */
1049{
1050 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1051 zend_string *path;
1052
1054 RETURN_THROWS();
1055 }
1056 path = spl_filesystem_object_get_pathname(intern);
1057 if (path) {
1058 RETURN_STR_COPY(path);
1059 } else {
1061 }
1062}
1063/* }}} */
1064
1065/* {{{ Return getPathname() or getFilename() depending on flags */
1067{
1068 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1069
1071 RETURN_THROWS();
1072 }
1073
1075 RETURN_STRING(intern->u.dir.entry.d_name);
1076 } else {
1077 if (spl_filesystem_object_get_file_name(intern) == FAILURE) {
1078 RETURN_THROWS();
1079 }
1080 RETURN_STR_COPY(intern->file_name);
1081 }
1082}
1083/* }}} */
1084
1085/* {{{ Return getFilename(), getFileInfo() or $this depending on flags */
1087{
1088 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1089
1091 RETURN_THROWS();
1092 }
1093
1095 if (spl_filesystem_object_get_file_name(intern) == FAILURE) {
1096 RETURN_THROWS();
1097 }
1098 RETURN_STR_COPY(intern->file_name);
1100 if (spl_filesystem_object_get_file_name(intern) == FAILURE) {
1101 RETURN_THROWS();
1102 }
1103 spl_filesystem_object_create_type(0, intern, SPL_FS_INFO, NULL, return_value);
1104 } else {
1106 }
1107}
1108/* }}} */
1109
1110/* {{{ Returns true if current entry is '.' or '..' */
1112{
1113 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1114
1116 RETURN_THROWS();
1117 }
1118
1120 RETURN_BOOL(spl_filesystem_is_dot(intern->u.dir.entry.d_name));
1121}
1122/* }}} */
1123
1124/* {{{ Constructs a new SplFileInfo from a path. */
1125/* When the constructor gets called the object is already created
1126 by the engine, so we must only call 'additional' initializations.
1127 */
1129{
1130 spl_filesystem_object *intern;
1131 zend_string *path;
1132
1133 if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &path) == FAILURE) {
1134 RETURN_THROWS();
1135 }
1136
1137 intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1138
1139 spl_filesystem_info_set_filename(intern, path);
1140
1141 /* intern->type = SPL_FS_INFO; already set */
1142}
1143/* }}} */
1144
1145/* {{{ FileInfoFunction */
1146#define FileInfoFunction(func_name, func_num) \
1147PHP_METHOD(SplFileInfo, func_name) \
1148{ \
1149 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); \
1150 zend_error_handling error_handling; \
1151 if (zend_parse_parameters_none() == FAILURE) { \
1152 RETURN_THROWS(); \
1153 } \
1154 if (spl_filesystem_object_get_file_name(intern) == FAILURE) { \
1155 RETURN_THROWS(); \
1156 } \
1157 zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);\
1158 php_stat(intern->file_name, func_num, return_value); \
1159 zend_restore_error_handling(&error_handling); \
1160}
1161/* }}} */
1162
1163/* {{{ Get file permissions */
1165/* }}} */
1166
1167/* {{{ Get file inode */
1168FileInfoFunction(getInode, FS_INODE)
1169/* }}} */
1170
1171/* {{{ Get file size */
1172FileInfoFunction(getSize, FS_SIZE)
1173/* }}} */
1174
1175/* {{{ Get file owner */
1176FileInfoFunction(getOwner, FS_OWNER)
1177/* }}} */
1178
1179/* {{{ Get file group */
1180FileInfoFunction(getGroup, FS_GROUP)
1181/* }}} */
1182
1183/* {{{ Get last access time of file */
1184FileInfoFunction(getATime, FS_ATIME)
1185/* }}} */
1186
1187/* {{{ Get last modification time of file */
1188FileInfoFunction(getMTime, FS_MTIME)
1189/* }}} */
1190
1191/* {{{ Get inode modification time of file */
1192FileInfoFunction(getCTime, FS_CTIME)
1193/* }}} */
1194
1195/* {{{ Get file type */
1196FileInfoFunction(getType, FS_TYPE)
1197/* }}} */
1198
1199/* {{{ Returns true if file can be written */
1200FileInfoFunction(isWritable, FS_IS_W)
1201/* }}} */
1202
1203/* {{{ Returns true if file can be read */
1204FileInfoFunction(isReadable, FS_IS_R)
1205/* }}} */
1206
1207/* {{{ Returns true if file is executable */
1208FileInfoFunction(isExecutable, FS_IS_X)
1209/* }}} */
1210
1211/* {{{ Returns true if file is a regular file */
1213/* }}} */
1214
1215/* {{{ Returns true if file is directory */
1217/* }}} */
1218
1219/* {{{ Returns true if file is symbolic link */
1221/* }}} */
1222
1223/* {{{ Return the target of a symbolic link */
1224PHP_METHOD(SplFileInfo, getLinkTarget)
1225{
1226 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1227 ssize_t ret;
1228 char buff[MAXPATHLEN];
1229
1231 RETURN_THROWS();
1232 }
1233
1234 if (intern->file_name == NULL) {
1235 if (spl_filesystem_object_get_file_name(intern) == FAILURE) {
1236 RETURN_THROWS();
1237 }
1238 }
1239#if defined(PHP_WIN32) || defined(HAVE_SYMLINK)
1240 if (intern->file_name == NULL) {
1241 zend_value_error("Filename must not be empty");
1242 RETURN_THROWS();
1243 }
1244 if (!IS_ABSOLUTE_PATH(ZSTR_VAL(intern->file_name), ZSTR_LEN(intern->file_name))) {
1245 char expanded_path[MAXPATHLEN];
1246 if (!expand_filepath_with_mode(ZSTR_VAL(intern->file_name), expanded_path, NULL, 0, CWD_EXPAND )) {
1247 php_error_docref(NULL, E_WARNING, "No such file or directory");
1249 }
1250 ret = php_sys_readlink(expanded_path, buff, MAXPATHLEN - 1);
1251 } else {
1252 ret = php_sys_readlink(ZSTR_VAL(intern->file_name), buff, MAXPATHLEN-1);
1253 }
1254#else
1255 ret = -1; /* always fail if not implemented */
1256#endif
1257
1258 if (ret == -1) {
1259 zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Unable to read link %s, error: %s", ZSTR_VAL(intern->file_name), strerror(errno));
1261 } else {
1262 /* Append NULL to the end of the string */
1263 buff[ret] = '\0';
1264
1265 RETVAL_STRINGL(buff, ret);
1266 }
1267}
1268/* }}} */
1269
1270/* {{{ Return the resolved path */
1272{
1273 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1274 char buff[MAXPATHLEN];
1275 char *filename;
1276
1278 RETURN_THROWS();
1279 }
1280
1281 if (intern->type == SPL_FS_DIR && !intern->file_name && intern->u.dir.entry.d_name[0]) {
1282 if (spl_filesystem_object_get_file_name(intern) == FAILURE) {
1283 RETURN_THROWS();
1284 }
1285 }
1286
1287 if (intern->orig_path) {
1288 filename = ZSTR_VAL(intern->orig_path);
1289 } else {
1290 filename = intern->file_name ? ZSTR_VAL(intern->file_name) : NULL;
1291 }
1292
1293
1294 if (filename && VCWD_REALPATH(filename, buff)) {
1295#ifdef ZTS
1296 if (VCWD_ACCESS(buff, F_OK)) {
1298 } else
1299#endif
1300 RETURN_STRING(buff);
1301 } else {
1303 }
1304}
1305/* }}} */
1306
1307/* {{{ Open the current file */
1309{
1310 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1311
1312 spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_FILE, NULL, return_value);
1313}
1314/* }}} */
1315
1316/* {{{ Class to use in openFile() */
1318{
1319 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1321
1322 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == FAILURE) {
1323 RETURN_THROWS();
1324 }
1325
1326 intern->file_class = ce;
1327}
1328/* }}} */
1329
1330/* {{{ Class to use in getFileInfo(), getPathInfo() */
1332{
1333 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1335
1336 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == FAILURE) {
1337 RETURN_THROWS();
1338 }
1339
1340 intern->info_class = ce;
1341}
1342/* }}} */
1343
1344/* {{{ Get/copy file info */
1346{
1347 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1348 zend_class_entry *ce = intern->info_class;
1349
1350 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C!", &ce) == FAILURE) {
1351 RETURN_THROWS();
1352 }
1353
1354 spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_INFO, ce, return_value);
1355}
1356/* }}} */
1357
1358/* {{{ Get/copy file info */
1360{
1361 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1362 zend_class_entry *ce = NULL;
1363 zend_string *path;
1364
1365 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C!", &ce) == FAILURE) {
1366 RETURN_THROWS();
1367 }
1368
1369 if (ce == NULL) {
1370 ce = intern->info_class;
1371 } else if (!instanceof_function(ce, spl_ce_SplFileInfo)) {
1372 zend_argument_type_error(1, "must be a class name derived from %s or null, %s given", ZSTR_VAL(spl_ce_SplFileInfo->name), ZSTR_VAL(ce->name));
1373 RETURN_THROWS();
1374 }
1375
1376 path = spl_filesystem_object_get_pathname(intern);
1377 if (path && ZSTR_LEN(path)) {
1378 zend_string *dpath = zend_string_init(ZSTR_VAL(path), ZSTR_LEN(path), 0);
1379 ZSTR_LEN(dpath) = zend_dirname(ZSTR_VAL(dpath), ZSTR_LEN(path));
1380 spl_filesystem_object_create_info(dpath, ce, return_value);
1381 zend_string_release(dpath);
1382 }
1383}
1384/* }}} */
1385
1386/* {{{ */
1388{
1390 RETURN_THROWS();
1391 }
1392
1393 RETURN_ARR(spl_filesystem_object_get_debug_info(Z_OBJ_P(ZEND_THIS)));
1394} /* }}} */
1395
1396/* {{{ */
1398{
1400 RETURN_THROWS();
1401 }
1402 zend_throw_error(NULL, "The parent constructor was not called: the object is in an invalid state");
1403 RETURN_THROWS();
1404}
1405/* }}} */
1406
1407/* {{{ Constructs a new dir iterator from a path. */
1409{
1410 spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS | SPL_FILE_DIR_SKIPDOTS);
1411}
1412/* }}} */
1413
1414/* {{{ Rewind dir back to the start */
1416{
1417 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1418 bool skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
1419
1421 RETURN_THROWS();
1422 }
1423
1424 intern->u.dir.index = 0;
1425 if (intern->u.dir.dirp) {
1426 php_stream_rewinddir(intern->u.dir.dirp);
1427 }
1428 do {
1429 spl_filesystem_dir_read(intern);
1430 } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
1431}
1432/* }}} */
1433
1434/* {{{ Get handling flags */
1436{
1437 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1438
1440 RETURN_THROWS();
1441 }
1442
1444} /* }}} */
1445
1446/* {{{ Set handling flags */
1459
1460/* {{{ Returns whether current entry is a directory and not '.' or '..' */
1462{
1463 bool allow_links = 0;
1464 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1465
1468 Z_PARAM_BOOL(allow_links)
1470
1471 if (spl_filesystem_is_invalid_or_dot(intern->u.dir.entry.d_name)) {
1473 } else {
1474 if (intern->u.dir.entry.d_type == DT_DIR) {
1476 } else if (intern->u.dir.entry.d_type == DT_REG) {
1478 }
1479 if (spl_filesystem_object_get_file_name(intern) == FAILURE) {
1480 RETURN_THROWS();
1481 }
1483 if (Z_TYPE_P(return_value) == IS_FALSE) {
1484 return;
1485 } else if (!S_ISLNK(Z_LVAL_P(return_value))) {
1487 } else {
1488 if (!allow_links
1489 && !(intern->flags & SPL_FILE_DIR_FOLLOW_SYMLINKS)) {
1491 }
1493 }
1494 }
1495}
1496/* }}} */
1497
1498/* {{{ Returns an iterator for the current entry if it is a directory */
1500{
1501 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1502 spl_filesystem_object *subdir;
1503 char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
1504
1506 RETURN_THROWS();
1507 }
1508
1509 if (spl_filesystem_object_get_file_name(intern) == FAILURE) {
1510 RETURN_THROWS();
1511 }
1512
1513 zval params[2];
1514 ZVAL_STR_COPY(&params[0], intern->file_name);
1515 ZVAL_LONG(&params[1], intern->flags);
1516
1518 zval_ptr_dtor_str(&params[0]);
1519 if (is_initialized == FAILURE) {
1520 RETURN_THROWS();
1521 }
1522
1523 subdir = spl_filesystem_from_obj(Z_OBJ_P(return_value));
1524 if (subdir) {
1525 size_t name_len = strlen(intern->u.dir.entry.d_name);
1526 if (intern->u.dir.sub_path && ZSTR_LEN(intern->u.dir.sub_path)) {
1527 zend_string *sub_path = zend_string_alloc(ZSTR_LEN(intern->u.dir.sub_path) + 1 + name_len, 0);
1528 memcpy(ZSTR_VAL(sub_path), ZSTR_VAL(intern->u.dir.sub_path), ZSTR_LEN(intern->u.dir.sub_path));
1529 ZSTR_VAL(sub_path)[ZSTR_LEN(intern->u.dir.sub_path)] = slash;
1530 memcpy(ZSTR_VAL(sub_path) + ZSTR_LEN(intern->u.dir.sub_path) + 1, intern->u.dir.entry.d_name, name_len);
1531 ZSTR_VAL(sub_path)[ZSTR_LEN(intern->u.dir.sub_path) + 1 + name_len] = 0;
1532 subdir->u.dir.sub_path = sub_path;
1533 } else {
1534 subdir->u.dir.sub_path = zend_string_init(intern->u.dir.entry.d_name, name_len, 0);
1535 }
1536 subdir->info_class = intern->info_class;
1537 subdir->file_class = intern->file_class;
1538 subdir->oth = intern->oth;
1539 }
1540}
1541/* }}} */
1542
1543/* {{{ Get sub path */
1545{
1546 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1547
1549 RETURN_THROWS();
1550 }
1551
1552 if (intern->u.dir.sub_path) {
1553 RETURN_STR_COPY(intern->u.dir.sub_path);
1554 } else {
1556 }
1557}
1558/* }}} */
1559
1560/* {{{ Get sub path and file name */
1562{
1563 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1564 char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
1565
1567 RETURN_THROWS();
1568 }
1569
1570 if (intern->u.dir.sub_path) {
1571 RETURN_NEW_STR(strpprintf(0, "%s%c%s", ZSTR_VAL(intern->u.dir.sub_path), slash, intern->u.dir.entry.d_name));
1572 } else {
1573 RETURN_STRING(intern->u.dir.entry.d_name);
1574 }
1575}
1576/* }}} */
1577
1578/* {{{ Cronstructs a new dir iterator from a path. */
1580{
1581 spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS);
1582}
1583/* }}} */
1584
1585#ifdef HAVE_GLOB
1586/* {{{ Cronstructs a new dir iterator from a glob expression (no glob:// needed). */
1587PHP_METHOD(GlobIterator, __construct)
1588{
1589 spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS|DIT_CTOR_GLOB);
1590}
1591/* }}} */
1592
1593/* {{{ Return the number of directories and files found by globbing */
1595{
1596 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
1597
1599 RETURN_THROWS();
1600 }
1601
1602 if (spl_intern_is_glob(intern)) {
1604 } else {
1605 /* This can happen by abusing destructors. */
1606 /* TODO: relax this from E_ERROR to an exception */
1607 php_error_docref(NULL, E_ERROR, "GlobIterator lost glob state");
1608 }
1609}
1610/* }}} */
1611#endif /* HAVE_GLOB */
1612
1613/* {{{ forward declarations to the iterator handlers */
1614static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter);
1615static zend_result spl_filesystem_dir_it_valid(zend_object_iterator *iter);
1616static zval *spl_filesystem_dir_it_current_data(zend_object_iterator *iter);
1617static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key);
1618static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter);
1619static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter);
1620
1621/* iterator handler table */
1622static const zend_object_iterator_funcs spl_filesystem_dir_it_funcs = {
1623 spl_filesystem_dir_it_dtor,
1624 spl_filesystem_dir_it_valid,
1625 spl_filesystem_dir_it_current_data,
1626 spl_filesystem_dir_it_current_key,
1627 spl_filesystem_dir_it_move_forward,
1628 spl_filesystem_dir_it_rewind,
1629 NULL,
1630 NULL, /* get_gc */
1631};
1632/* }}} */
1633
1634/* {{{ spl_ce_dir_get_iterator */
1635static zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
1636{
1637 spl_filesystem_iterator *iterator;
1638 spl_filesystem_object *dir_object;
1639
1640 if (by_ref) {
1641 zend_throw_error(NULL, "An iterator cannot be used with foreach by reference");
1642 return NULL;
1643 }
1644 dir_object = spl_filesystem_from_obj(Z_OBJ_P(object));
1645 iterator = spl_filesystem_object_to_iterator(dir_object);
1646 ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object));
1647 iterator->intern.funcs = &spl_filesystem_dir_it_funcs;
1648 /* ->current must be initialized; rewind doesn't set it and valid
1649 * doesn't check whether it's set */
1650 iterator->current = *object;
1651
1652 return &iterator->intern;
1653}
1654/* }}} */
1655
1656/* {{{ spl_filesystem_dir_it_dtor */
1657static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter)
1658{
1660 zval_ptr_dtor(&iterator->intern.data);
1661}
1662/* }}} */
1663
1664/* {{{ spl_filesystem_dir_it_valid */
1665static zend_result spl_filesystem_dir_it_valid(zend_object_iterator *iter)
1666{
1667 spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
1668
1669 return object->u.dir.entry.d_name[0] != '\0' ? SUCCESS : FAILURE;
1670}
1671/* }}} */
1672
1673/* {{{ spl_filesystem_dir_it_current_data */
1674static zval *spl_filesystem_dir_it_current_data(zend_object_iterator *iter)
1675{
1677
1678 return &iterator->current;
1679}
1680/* }}} */
1681
1682/* {{{ spl_filesystem_dir_it_current_key */
1683static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key)
1684{
1685 spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
1686
1687 ZVAL_LONG(key, object->u.dir.index);
1688}
1689/* }}} */
1690
1691/* {{{ spl_filesystem_dir_it_move_forward */
1692static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter)
1693{
1694 spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
1695
1696 object->u.dir.index++;
1697 spl_filesystem_dir_read(object);
1698 if (object->file_name) {
1699 zend_string_release(object->file_name);
1700 object->file_name = NULL;
1701 }
1702}
1703/* }}} */
1704
1705/* {{{ spl_filesystem_dir_it_rewind */
1706static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter)
1707{
1708 spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
1709
1710 object->u.dir.index = 0;
1711 if (object->u.dir.dirp) {
1712 php_stream_rewinddir(object->u.dir.dirp);
1713 }
1714 spl_filesystem_dir_read(object);
1715}
1716/* }}} */
1717
1718/* {{{ spl_filesystem_tree_it_dtor */
1719static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter)
1720{
1722 zval_ptr_dtor(&iterator->intern.data);
1723 zval_ptr_dtor(&iterator->current);
1724}
1725/* }}} */
1726
1727/* {{{ spl_filesystem_tree_it_current_data */
1728static zval *spl_filesystem_tree_it_current_data(zend_object_iterator *iter)
1729{
1731 spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator);
1732
1734 if (Z_ISUNDEF(iterator->current)) {
1735 if (spl_filesystem_object_get_file_name(object) == FAILURE) {
1736 return NULL;
1737 }
1738 ZVAL_STR_COPY(&iterator->current, object->file_name);
1739 }
1740 return &iterator->current;
1742 if (Z_ISUNDEF(iterator->current)) {
1743 if (spl_filesystem_object_get_file_name(object) == FAILURE) {
1744 return NULL;
1745 }
1746 spl_filesystem_object_create_type(0, object, SPL_FS_INFO, NULL, &iterator->current);
1747 }
1748 return &iterator->current;
1749 } else {
1750 return &iterator->intern.data;
1751 }
1752}
1753/* }}} */
1754
1755/* {{{ spl_filesystem_tree_it_current_key */
1756static void spl_filesystem_tree_it_current_key(zend_object_iterator *iter, zval *key)
1757{
1758 spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
1759
1761 ZVAL_STRING(key, object->u.dir.entry.d_name);
1762 } else {
1763 if (spl_filesystem_object_get_file_name(object) == FAILURE) {
1764 return;
1765 }
1766 ZVAL_STR_COPY(key, object->file_name);
1767 }
1768}
1769/* }}} */
1770
1771/* {{{ spl_filesystem_tree_it_move_forward */
1772static void spl_filesystem_tree_it_move_forward(zend_object_iterator *iter)
1773{
1775 spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator);
1776 bool skip_dots = SPL_HAS_FLAG(object->flags, SPL_FILE_DIR_SKIPDOTS);
1777
1778 object->u.dir.index++;
1779 do {
1780 spl_filesystem_dir_read(object);
1781 } while (skip_dots && spl_filesystem_is_dot(object->u.dir.entry.d_name));
1782 if (object->file_name) {
1783 zend_string_release(object->file_name);
1784 object->file_name = NULL;
1785 }
1786 if (!Z_ISUNDEF(iterator->current)) {
1787 zval_ptr_dtor(&iterator->current);
1788 ZVAL_UNDEF(&iterator->current);
1789 }
1790}
1791/* }}} */
1792
1793/* {{{ spl_filesystem_tree_it_rewind */
1794static void spl_filesystem_tree_it_rewind(zend_object_iterator *iter)
1795{
1797 spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator);
1798 bool skip_dots = SPL_HAS_FLAG(object->flags, SPL_FILE_DIR_SKIPDOTS);
1799
1800 object->u.dir.index = 0;
1801 if (object->u.dir.dirp) {
1802 php_stream_rewinddir(object->u.dir.dirp);
1803 }
1804 do {
1805 spl_filesystem_dir_read(object);
1806 } while (skip_dots && spl_filesystem_is_dot(object->u.dir.entry.d_name));
1807 if (!Z_ISUNDEF(iterator->current)) {
1808 zval_ptr_dtor(&iterator->current);
1809 ZVAL_UNDEF(&iterator->current);
1810 }
1811}
1812/* }}} */
1813
1814/* {{{ iterator handler table */
1815static const zend_object_iterator_funcs spl_filesystem_tree_it_funcs = {
1816 spl_filesystem_tree_it_dtor,
1817 spl_filesystem_dir_it_valid,
1818 spl_filesystem_tree_it_current_data,
1819 spl_filesystem_tree_it_current_key,
1820 spl_filesystem_tree_it_move_forward,
1821 spl_filesystem_tree_it_rewind,
1822 NULL,
1823 NULL, /* get_gc */
1824};
1825/* }}} */
1826
1827/* {{{ spl_ce_dir_get_iterator */
1828static zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
1829{
1830 spl_filesystem_iterator *iterator;
1831 spl_filesystem_object *dir_object;
1832
1833 if (by_ref) {
1834 zend_throw_error(NULL, "An iterator cannot be used with foreach by reference");
1835 return NULL;
1836 }
1837 dir_object = spl_filesystem_from_obj(Z_OBJ_P(object));
1838 iterator = spl_filesystem_object_to_iterator(dir_object);
1839
1840 ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object));
1841 iterator->intern.funcs = &spl_filesystem_tree_it_funcs;
1842
1843 return &iterator->intern;
1844}
1845/* }}} */
1846
1847static ZEND_COLD void spl_filesystem_file_cannot_read(spl_filesystem_object *intern)
1848{
1849 zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", ZSTR_VAL(intern->file_name));
1850}
1851
1852static zend_result spl_filesystem_file_read_ex(spl_filesystem_object *intern, bool silent, zend_long line_add, bool csv)
1853{
1854 char *buf;
1855 size_t line_len = 0;
1856
1857 spl_filesystem_file_free_line(intern);
1858
1859 if (php_stream_eof(intern->u.file.stream)) {
1860 if (!silent) {
1861 spl_filesystem_file_cannot_read(intern);
1862 }
1863 return FAILURE;
1864 }
1865
1866 if (intern->u.file.max_line_len > 0) {
1867 buf = safe_emalloc((intern->u.file.max_line_len + 1), sizeof(char), 0);
1868 if (php_stream_get_line(intern->u.file.stream, buf, intern->u.file.max_line_len + 1, &line_len) == NULL) {
1869 efree(buf);
1870 buf = NULL;
1871 } else {
1872 buf[line_len] = '\0';
1873 }
1874 } else {
1875 buf = php_stream_get_line(intern->u.file.stream, NULL, 0, &line_len);
1876 }
1877
1878 if (!buf) {
1879 intern->u.file.current_line = ZSTR_EMPTY_ALLOC();
1880 } else {
1881 if (!csv && SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_DROP_NEW_LINE)) {
1882 if (line_len > 0 && buf[line_len - 1] == '\n') {
1883 line_len--;
1884 if (line_len > 0 && buf[line_len - 1] == '\r') {
1885 line_len--;
1886 }
1887 buf[line_len] = '\0';
1888 }
1889 }
1890
1891 intern->u.file.current_line = zend_string_init(buf, line_len, /* persistent */ false);
1892 efree(buf);
1893 }
1894 intern->u.file.current_line_num += line_add;
1895
1896 return SUCCESS;
1897} /* }}} */
1898
1899static inline zend_result spl_filesystem_file_read(spl_filesystem_object *intern, bool silent, bool csv)
1900{
1901 zend_long line_add = (intern->u.file.current_line) ? 1 : 0;
1902 return spl_filesystem_file_read_ex(intern, silent, line_add, csv);
1903}
1904
1905static bool is_line_empty(const spl_filesystem_object *intern)
1906{
1907 const char *current_line = ZSTR_VAL(intern->u.file.current_line);
1908 size_t current_line_len = ZSTR_LEN(intern->u.file.current_line);
1909 return current_line_len == 0 || (
1912 && (
1913 (current_line_len == 1 && current_line[0] == '\n')
1914 || (current_line_len == 2 && current_line[0] == '\r' && current_line[1] == '\n')
1915 )
1916 );
1917}
1918
1919static zend_result spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, int escape, zval *return_value, bool silent) /* {{{ */
1920{
1921 do {
1922 zend_result ret = spl_filesystem_file_read(intern, silent, /* csv */ true);
1923 if (ret != SUCCESS) {
1924 return ret;
1925 }
1926 } while (is_line_empty(intern) && SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY));
1927
1928 /* We need to duplicate the current line content as php_fgetcsv() will free it.
1929 * This is because it might reach the end of the line when it's in an enclosure and
1930 * thus must fetch the next line from the stream */
1931 size_t buf_len = ZSTR_LEN(intern->u.file.current_line);
1932 char *buf = estrndup(ZSTR_VAL(intern->u.file.current_line), buf_len);
1933
1934 if (!Z_ISUNDEF(intern->u.file.current_zval)) {
1935 zval_ptr_dtor(&intern->u.file.current_zval);
1936 ZVAL_UNDEF(&intern->u.file.current_zval);
1937 }
1938
1939 HashTable *values = php_fgetcsv(intern->u.file.stream, delimiter, enclosure, escape, buf_len, buf);
1940 if (values == NULL) {
1941 values = php_bc_fgetcsv_empty_line();
1942 }
1943 ZVAL_ARR(&intern->u.file.current_zval, values);
1944 if (return_value) {
1946 }
1947 return SUCCESS;
1948}
1949/* }}} */
1950
1951static zend_result spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_object *intern, bool silent) /* {{{ */
1952{
1953 zval retval;
1954
1955 /* 1) use fgetcsv? 2) overloaded call the function, 3) do it directly */
1957 return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, intern->u.file.escape, NULL, silent);
1958 }
1960 spl_filesystem_file_free_line(intern);
1961
1962 if (php_stream_eof(intern->u.file.stream)) {
1963 if (!silent) {
1964 spl_filesystem_file_cannot_read(intern);
1965 }
1966 return FAILURE;
1967 }
1968 zend_call_method_with_0_params(Z_OBJ_P(this_ptr), Z_OBJCE_P(this_ptr), &intern->u.file.func_getCurr, "getCurrentLine", &retval);
1969 if (Z_ISUNDEF(retval)) {
1970 return FAILURE;
1971 }
1972
1973 if (Z_TYPE(retval) != IS_STRING) {
1974 zend_type_error("%s::getCurrentLine(): Return value must be of type string, %s returned",
1977 return FAILURE;
1978 }
1979
1980 if (intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)) {
1981 intern->u.file.current_line_num++;
1982 }
1983 spl_filesystem_file_free_line(intern);
1984 intern->u.file.current_line = zend_string_copy(Z_STR(retval));
1986 return SUCCESS;
1987 } else {
1988 return spl_filesystem_file_read(intern, silent, /* csv */ false);
1989 }
1990} /* }}} */
1991
1992static zend_result spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, bool silent) /* {{{ */
1993{
1994 zend_result ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent);
1995
1996 while (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY) && ret == SUCCESS && is_line_empty(intern)) {
1997 spl_filesystem_file_free_line(intern);
1998 ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent);
1999 }
2000
2001 return ret;
2002}
2003/* }}} */
2004
2005static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *intern) /* {{{ */
2006{
2007 if (!intern->u.file.stream) {
2008 zend_throw_error(NULL, "Object not initialized");
2009 return;
2010 }
2011 if (-1 == php_stream_rewind(intern->u.file.stream)) {
2012 zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot rewind file %s", ZSTR_VAL(intern->file_name));
2013 return;
2014 }
2015
2016 spl_filesystem_file_free_line(intern);
2017 intern->u.file.current_line_num = 0;
2018
2020 spl_filesystem_file_read_line(this_ptr, intern, true);
2021 }
2022} /* }}} */
2023
2024/* {{{ Construct a new file object */
2026{
2027 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2028 zend_string *file_name = NULL;
2029 zend_string *open_mode = ZSTR_CHAR('r');
2030 zval *stream_context = NULL;
2031 bool use_include_path = 0;
2032 size_t path_len;
2033 zend_error_handling error_handling;
2034
2035 if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|Sbr!", &file_name, &open_mode, &use_include_path, &stream_context) == FAILURE) {
2036 RETURN_THROWS();
2037 }
2038
2039 /* Prevent reinitialization of Object */
2040 if (UNEXPECTED(intern->u.file.stream)) {
2041 zend_throw_error(NULL, "Cannot call constructor twice");
2042 RETURN_THROWS();
2043 }
2044
2045 intern->u.file.open_mode = zend_string_copy(open_mode);
2046 /* file_name and zcontext are copied by spl_filesystem_file_open() */
2047 intern->file_name = file_name;
2048 intern->u.file.zcontext = stream_context;
2049
2050 /* spl_filesystem_file_open() can generate E_WARNINGs which we want to promote to exceptions */
2052 zend_result retval = spl_filesystem_file_open(intern, use_include_path);
2053 zend_restore_error_handling(&error_handling);
2054 if (retval == FAILURE) {
2055 RETURN_THROWS();
2056 }
2057
2058 path_len = strlen(intern->u.file.stream->orig_path);
2059
2060 if (path_len > 1 && IS_SLASH_AT(intern->u.file.stream->orig_path, path_len-1)) {
2061 path_len--;
2062 }
2063
2064 while (path_len > 1 && !IS_SLASH_AT(intern->u.file.stream->orig_path, path_len-1)) {
2065 path_len--;
2066 }
2067
2068 if (path_len) {
2069 path_len--;
2070 }
2071
2072 intern->path = zend_string_init(intern->u.file.stream->orig_path, path_len, 0);
2073} /* }}} */
2074
2075/* {{{ Construct a new temp file object */
2077{
2078 zend_string *file_name;
2079 zend_long max_memory = PHP_STREAM_MAX_MEM;
2080 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2081 zend_error_handling error_handling;
2082
2083 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &max_memory) == FAILURE) {
2084 RETURN_THROWS();
2085 }
2086
2087 /* Prevent reinitialization of Object */
2088 if (UNEXPECTED(intern->u.file.stream)) {
2089 zend_throw_error(NULL, "Cannot call constructor twice");
2090 RETURN_THROWS();
2091 }
2092
2093 if (max_memory < 0) {
2094 file_name = ZSTR_INIT_LITERAL("php://memory", 0);
2095 } else if (ZEND_NUM_ARGS()) {
2096 file_name = zend_strpprintf(0, "php://temp/maxmemory:" ZEND_LONG_FMT, max_memory);
2097 } else {
2098 file_name = ZSTR_INIT_LITERAL("php://temp", 0);
2099 }
2100 intern->file_name = file_name;
2101 intern->u.file.open_mode = ZSTR_INIT_LITERAL("wb", 0);
2102
2103 /* spl_filesystem_file_open() can generate E_WARNINGs which we want to promote to exceptions */
2105 if (spl_filesystem_file_open(intern, /* use_include_path */ false) == SUCCESS) {
2106 intern->path = ZSTR_EMPTY_ALLOC();
2107 }
2108 zend_string_release(file_name);
2109 zend_restore_error_handling(&error_handling);
2110} /* }}} */
2111
2112/* {{{ Rewind the file and read the first line */
2114{
2115 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2116
2118 RETURN_THROWS();
2119 }
2120
2121 spl_filesystem_file_rewind(ZEND_THIS, intern);
2122} /* }}} */
2123
2124/* {{{ Return whether end of file is reached */
2126{
2127 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2128
2130 RETURN_THROWS();
2131 }
2132
2134
2136} /* }}} */
2137
2138/* {{{ Return !eof() */
2140{
2141 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2142
2144 RETURN_THROWS();
2145 }
2146
2148 RETURN_BOOL(intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval));
2149 }
2150 if (!intern->u.file.stream) {
2152 }
2154} /* }}} */
2155
2156/* {{{ Return next line from file */
2158{
2159 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2160
2162 RETURN_THROWS();
2163 }
2164
2166
2167 if (spl_filesystem_file_read_ex(intern, /* silent */ false, /* line_add */ 1, /* csv */ false) == FAILURE) {
2168 RETURN_THROWS();
2169 }
2171} /* }}} */
2172
2173/* {{{ Return current line from file */
2175{
2176 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2177
2179 RETURN_THROWS();
2180 }
2181
2183
2184 if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) {
2185 spl_filesystem_file_read_line(ZEND_THIS, intern, true);
2186 }
2187 if (intern->u.file.current_line && (!SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || Z_ISUNDEF(intern->u.file.current_zval))) {
2189 } else if (!Z_ISUNDEF(intern->u.file.current_zval)) {
2192 RETURN_COPY(&intern->u.file.current_zval);
2193 }
2195} /* }}} */
2196
2197/* {{{ Return line number */
2199{
2200 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2201
2203 RETURN_THROWS();
2204 }
2205
2206 /* Do not read the next line to support correct counting with fgetc()
2207 if (!intern->u.file.current_line) {
2208 spl_filesystem_file_read_line(ZEND_THIS, intern);
2209 } */
2211} /* }}} */
2212
2213/* {{{ Read next line */
2215{
2216 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2217
2219 RETURN_THROWS();
2220 }
2221
2222 spl_filesystem_file_free_line(intern);
2224 spl_filesystem_file_read_line(ZEND_THIS, intern, true);
2225 }
2226 intern->u.file.current_line_num++;
2227} /* }}} */
2228
2229/* {{{ Set file handling flags */
2231{
2232 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2233
2234 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &intern->flags) == FAILURE) {
2235 RETURN_THROWS();
2236 }
2237} /* }}} */
2238
2239/* {{{ Get file handling flags */
2241{
2242 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2243
2245 RETURN_THROWS();
2246 }
2247
2249} /* }}} */
2250
2251/* {{{ Set maximum line length */
2253{
2254 zend_long max_len;
2255
2256 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2257
2258 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &max_len) == FAILURE) {
2259 RETURN_THROWS();
2260 }
2261
2262 if (max_len < 0) {
2263 zend_argument_value_error(1, "must be greater than or equal to 0");
2264 RETURN_THROWS();
2265 }
2266
2267 intern->u.file.max_line_len = max_len;
2268} /* }}} */
2269
2270/* {{{ Get maximum line length */
2272{
2273 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2274
2276 RETURN_THROWS();
2277 }
2278
2280} /* }}} */
2281
2282/* {{{ Return false */
2284{
2286 RETURN_THROWS();
2287 }
2288
2290} /* }}} */
2291
2292/* {{{ Read NULL */
2294{
2296 RETURN_THROWS();
2297 }
2298 /* return NULL */
2299} /* }}} */
2300
2301static int spl_csv_enclosure_param_handling(const zend_string* escape_str, const spl_filesystem_object *intern, uint32_t arg_num)
2302{
2303 if (escape_str == NULL) {
2304 if (intern->u.file.is_escape_default) {
2305 php_error_docref(NULL, E_DEPRECATED, "the $escape parameter must be provided,"
2306 " as its default value will change,"
2307 " either explicitly or via SplFileObject::setCsvControl()");
2308 if (UNEXPECTED(EG(exception))) {
2309 return PHP_CSV_ESCAPE_ERROR;
2310 }
2311 }
2312 return intern->u.file.escape;
2313 } else {
2314 return php_csv_handle_escape_argument(escape_str, arg_num);
2315 }
2316}
2317
2318/* {{{ Return current line as CSV */
2320{
2321 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2322 char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure;
2323 char *delim = NULL, *enclo = NULL;
2324 size_t d_len = 0, e_len = 0;
2325 zend_string *escape_str = NULL;
2326
2327 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ssS", &delim, &d_len, &enclo, &e_len, &escape_str) == FAILURE) {
2328 RETURN_THROWS();
2329 }
2330
2332
2333 if (delim) {
2334 if (d_len != 1) {
2335 zend_argument_value_error(1, "must be a single character");
2336 RETURN_THROWS();
2337 }
2338 delimiter = delim[0];
2339 }
2340 if (enclo) {
2341 if (e_len != 1) {
2342 zend_argument_value_error(2, "must be a single character");
2343 RETURN_THROWS();
2344 }
2345 enclosure = enclo[0];
2346 }
2347 int escape_char = spl_csv_enclosure_param_handling(escape_str, intern, 3);
2348 if (escape_char == PHP_CSV_ESCAPE_ERROR) {
2349 RETURN_THROWS();
2350 }
2351
2352 if (spl_filesystem_file_read_csv(intern, delimiter, enclosure, escape_char, return_value, true) == FAILURE) {
2354 }
2355}
2356/* }}} */
2357
2358/* {{{ Output a field array as a CSV line */
2360{
2361 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2362 char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure;
2363 char *delim = NULL, *enclo = NULL;
2364 size_t d_len = 0, e_len = 0;
2365 zend_long ret;
2366 zval *fields = NULL;
2367 zend_string *escape_str = NULL;
2368 zend_string *eol = NULL;
2369
2370 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|ssSS", &fields, &delim, &d_len, &enclo, &e_len, &escape_str, &eol) == FAILURE) {
2371 RETURN_THROWS();
2372 }
2373
2374 if (delim) {
2375 if (d_len != 1) {
2376 zend_argument_value_error(2, "must be a single character");
2377 RETURN_THROWS();
2378 }
2379 delimiter = delim[0];
2380 }
2381 if (enclo) {
2382 if (e_len != 1) {
2383 zend_argument_value_error(3, "must be a single character");
2384 RETURN_THROWS();
2385 }
2386 enclosure = enclo[0];
2387 }
2388 int escape_char = spl_csv_enclosure_param_handling(escape_str, intern, 4);
2389 if (escape_char == PHP_CSV_ESCAPE_ERROR) {
2390 RETURN_THROWS();
2391 }
2392
2393 ret = php_fputcsv(intern->u.file.stream, fields, delimiter, enclosure, escape_char, eol);
2394 if (ret < 0) {
2396 }
2398}
2399/* }}} */
2400
2401/* {{{ Set the delimiter, enclosure and escape character used in fgetcsv */
2403{
2404 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2405 char delimiter = ',', enclosure = '"';
2406 char *delim = NULL, *enclo = NULL;
2407 size_t d_len = 0, e_len = 0;
2408 zend_string *escape_str = NULL;
2409
2410 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ssS", &delim, &d_len, &enclo, &e_len, &escape_str) == FAILURE) {
2411 RETURN_THROWS();
2412 }
2413
2414 if (delim) {
2415 if (d_len != 1) {
2416 zend_argument_value_error(1, "must be a single character");
2417 RETURN_THROWS();
2418 }
2419 delimiter = delim[0];
2420 }
2421 if (enclo) {
2422 if (e_len != 1) {
2423 zend_argument_value_error(2, "must be a single character");
2424 RETURN_THROWS();
2425 }
2426 enclosure = enclo[0];
2427 }
2428 int escape_char = php_csv_handle_escape_argument(escape_str, 3);
2429 if (escape_char == PHP_CSV_ESCAPE_ERROR) {
2430 RETURN_THROWS();
2431 }
2432 if (escape_str != NULL) {
2433 intern->u.file.is_escape_default = false;
2434 }
2435
2436 intern->u.file.delimiter = delimiter;
2437 intern->u.file.enclosure = enclosure;
2438 intern->u.file.escape = escape_char;
2439}
2440/* }}} */
2441
2442/* {{{ Get the delimiter, enclosure and escape character used in fgetcsv */
2444{
2445 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2446 char delimiter[2], enclosure[2], escape[2];
2447
2449 RETURN_THROWS();
2450 }
2451
2453
2454 delimiter[0] = intern->u.file.delimiter;
2455 delimiter[1] = '\0';
2456 enclosure[0] = intern->u.file.enclosure;
2457 enclosure[1] = '\0';
2458 if (intern->u.file.escape == PHP_CSV_NO_ESCAPE) {
2459 escape[0] = '\0';
2460 } else {
2461 escape[0] = (unsigned char) intern->u.file.escape;
2462 escape[1] = '\0';
2463 }
2464
2468}
2469/* }}} */
2470
2471/* {{{ Portable file locking */
2473{
2474 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2475 zval *wouldblock = NULL;
2476 zend_long operation = 0;
2477
2478 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|z", &operation, &wouldblock) == FAILURE) {
2479 RETURN_THROWS();
2480 }
2481
2483
2484 php_flock_common(intern->u.file.stream, operation, 1, wouldblock, return_value);
2485}
2486/* }}} */
2487
2488/* {{{ Flush the file */
2490{
2491 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2492
2494 RETURN_THROWS();
2495 }
2496
2498
2500} /* }}} */
2501
2502/* {{{ Return current file position */
2504{
2505 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2506 zend_long ret;
2507
2509 RETURN_THROWS();
2510 }
2511
2513
2514 ret = php_stream_tell(intern->u.file.stream);
2515
2516 if (ret == -1) {
2518 } else {
2520 }
2521} /* }}} */
2522
2523/* {{{ Seek to a position */
2525{
2526 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2527 zend_long pos, whence = SEEK_SET;
2528
2529 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &pos, &whence) == FAILURE) {
2530 RETURN_THROWS();
2531 }
2532
2534
2535 spl_filesystem_file_free_line(intern);
2536 RETURN_LONG(php_stream_seek(intern->u.file.stream, pos, (int)whence));
2537} /* }}} */
2538
2539/* {{{ Get a character from the file */
2541{
2542 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2543
2545 RETURN_THROWS();
2546 }
2547
2549
2550 spl_filesystem_file_free_line(intern);
2551
2552 int result = php_stream_getc(intern->u.file.stream);
2553
2554 if (result == EOF) {
2556 }
2557 if (result == '\n') {
2558 intern->u.file.current_line_num++;
2559 }
2560
2562} /* }}} */
2563
2564/* {{{ Output all remaining data from a file pointer */
2566{
2567 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2568
2570 RETURN_THROWS();
2571 }
2572
2574
2576} /* }}} */
2577
2578/* {{{ Implements a mostly ANSI compatible fscanf() */
2580{
2581 uint32_t num_varargs = 0;
2582 zend_string *format_str;
2583 zval *varargs= NULL;
2584 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2585
2586 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S*", &format_str, &varargs, &num_varargs) == FAILURE) {
2587 RETURN_THROWS();
2588 }
2589
2591
2592 /* Get next line */
2593 if (spl_filesystem_file_read(intern, /* silent */ false, /* csv */ false) == FAILURE) {
2594 RETURN_THROWS();
2595 }
2596
2597 int result = php_sscanf_internal(ZSTR_VAL(intern->u.file.current_line), ZSTR_VAL(format_str), (int)num_varargs, varargs, 0, return_value);
2598
2601 }
2602}
2603/* }}} */
2604
2605/* {{{ Binary-safe file write */
2607{
2608 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2609 char *str;
2610 size_t str_len;
2611 zend_long length = 0;
2612 ssize_t written;
2613
2614 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &length) == FAILURE) {
2615 RETURN_THROWS();
2616 }
2617
2619
2620 if (ZEND_NUM_ARGS() > 1) {
2621 if (length >= 0) {
2622 str_len = MIN((size_t)length, str_len);
2623 } else {
2624 /* Negative length given, nothing to write */
2625 str_len = 0;
2626 }
2627 }
2628 if (!str_len) {
2629 RETURN_LONG(0);
2630 }
2631
2632 written = php_stream_write(intern->u.file.stream, str, str_len);
2633 if (written < 0) {
2635 }
2636 RETURN_LONG(written);
2637} /* }}} */
2638
2640{
2641 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2642 zend_long length = 0;
2643 zend_string *str;
2644
2645 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &length) == FAILURE) {
2646 RETURN_THROWS();
2647 }
2648
2650
2651 if (length <= 0) {
2652 zend_argument_value_error(1, "must be greater than 0");
2653 RETURN_THROWS();
2654 }
2655
2656 str = php_stream_read_to_str(intern->u.file.stream, length);
2657 if (!str) {
2659 }
2660 RETURN_STR(str);
2661}
2662
2663/* {{{ Stat() on a filehandle */
2665{
2666 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2667
2669 RETURN_THROWS();
2670 }
2671
2673
2675}
2676/* }}} */
2677
2678/* {{{ Truncate file to 'size' length */
2680{
2681 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2683
2685 RETURN_THROWS();
2686 }
2687
2689
2690 if (size < 0) {
2691 zend_argument_value_error(1, "must be greater than or equal to 0");
2692 RETURN_THROWS();
2693 }
2694
2695
2697 zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't truncate file %s", ZSTR_VAL(intern->file_name));
2698 RETURN_THROWS();
2699 }
2700
2702} /* }}} */
2703
2704/* {{{ Seek to specified line */
2706{
2707 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2708 zend_long line_pos, i;
2709
2710 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &line_pos) == FAILURE) {
2711 RETURN_THROWS();
2712 }
2713
2715
2716 if (line_pos < 0) {
2717 zend_argument_value_error(1, "must be greater than or equal to 0");
2718 RETURN_THROWS();
2719 }
2720
2721 spl_filesystem_file_rewind(ZEND_THIS, intern);
2722
2723 for (i = 0; i < line_pos; i++) {
2724 if (spl_filesystem_file_read_line(ZEND_THIS, intern, true) == FAILURE) {
2725 return;
2726 }
2727 }
2728 if (line_pos > 0 && !SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
2729 intern->u.file.current_line_num++;
2730 spl_filesystem_file_free_line(intern);
2731 }
2732} /* }}} */
2733
2735{
2737 RETURN_THROWS();
2738 }
2739
2740 spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2741
2743
2744 if (!intern->u.file.current_line) {
2746 zend_result result = spl_filesystem_file_read_line(ZEND_THIS, intern, false);
2747 if (UNEXPECTED(result != SUCCESS)) {
2748 RETURN_THROWS();
2749 }
2750 }
2751
2753}
2754
2755/* {{{ PHP_MINIT_FUNCTION(spl_directory) */
2757{
2758 spl_ce_SplFileInfo = register_class_SplFileInfo(zend_ce_stringable);
2759 spl_ce_SplFileInfo->create_object = spl_filesystem_object_new;
2760 spl_ce_SplFileInfo->default_object_handlers = &spl_filesystem_object_handlers;
2761
2762 memcpy(&spl_filesystem_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
2763 spl_filesystem_object_handlers.offset = XtOffsetOf(spl_filesystem_object, std);
2764 spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone;
2765 spl_filesystem_object_handlers.dtor_obj = spl_filesystem_object_destroy_object;
2766 spl_filesystem_object_handlers.free_obj = spl_filesystem_object_free_storage;
2767
2768 spl_ce_DirectoryIterator = register_class_DirectoryIterator(spl_ce_SplFileInfo, spl_ce_SeekableIterator);
2769 spl_ce_DirectoryIterator->create_object = spl_filesystem_object_new;
2770 spl_ce_DirectoryIterator->get_iterator = spl_filesystem_dir_get_iterator;
2771
2772 spl_ce_FilesystemIterator = register_class_FilesystemIterator(spl_ce_DirectoryIterator);
2773 spl_ce_FilesystemIterator->create_object = spl_filesystem_object_new;
2774 spl_ce_FilesystemIterator->get_iterator = spl_filesystem_tree_get_iterator;
2775
2776 spl_ce_RecursiveDirectoryIterator = register_class_RecursiveDirectoryIterator(spl_ce_FilesystemIterator, spl_ce_RecursiveIterator);
2777 spl_ce_RecursiveDirectoryIterator->create_object = spl_filesystem_object_new;
2778
2779 memcpy(&spl_filesystem_object_check_handlers, &spl_filesystem_object_handlers, sizeof(zend_object_handlers));
2780 spl_filesystem_object_check_handlers.clone_obj = NULL;
2781 spl_filesystem_object_check_handlers.get_method = spl_filesystem_object_get_method_check;
2782
2783#ifdef HAVE_GLOB
2784 spl_ce_GlobIterator = register_class_GlobIterator(spl_ce_FilesystemIterator, zend_ce_countable);
2785 spl_ce_GlobIterator->create_object = spl_filesystem_object_new;
2786 spl_ce_GlobIterator->default_object_handlers = &spl_filesystem_object_check_handlers;
2787#endif
2788
2790 spl_ce_SplFileObject->default_object_handlers = &spl_filesystem_object_check_handlers;
2791 spl_ce_SplFileObject->create_object = spl_filesystem_object_new;
2792
2793 spl_ce_SplTempFileObject = register_class_SplTempFileObject(spl_ce_SplFileObject);
2794 spl_ce_SplTempFileObject->create_object = spl_filesystem_object_new;
2795
2796 return SUCCESS;
2797}
2798/* }}} */
size_t len
Definition apprentice.c:174
bool exception
Definition assert.c:30
rewind($stream)
ftruncate($stream, int $size)
fgetc($stream)
fputcsv($stream, array $fields, string $separator=",", string $enclosure="\"", string $escape="\\", string $eol="\n")
fgetcsv($stream, ?int $length=null, string $separator=",", string $enclosure="\"", string $escape="\\")
fstat($stream)
fseek($stream, int $offset, int $whence=SEEK_SET)
fwrite($stream, string $data, ?int $length=null)
ftell($stream)
count(Countable|array $value, int $mode=COUNT_NORMAL)
fscanf($stream, string $format, mixed &... $vars)
fread($stream, int $length)
fflush($stream)
flock($stream, int $operation, &$would_block=null)
fpassthru($stream)
fgets($stream, ?int $length=null)
uint32_t u
Definition cdf.c:78
zend_ffi_type * type
Definition ffi.c:3812
new_type size
Definition ffi.c:4365
memcpy(ptr1, ptr2, size)
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
PHPAPI void php_fstat(php_stream *stream, zval *return_value)
Definition file.c:1369
PHPAPI HashTable * php_bc_fgetcsv_empty_line(void)
Definition file.c:1886
PHPAPI HashTable * php_fgetcsv(php_stream *stream, char delimiter, char enclosure, int escape_char, size_t buf_len, char *buf)
Definition file.c:1895
PHPAPI int php_csv_handle_escape_argument(const zend_string *escape_str, uint32_t arg_num)
Definition file.c:1656
PHPAPI ssize_t php_fputcsv(php_stream *stream, zval *fields, char delimiter, char enclosure, int escape_char, zend_string *eol_str)
Definition file.c:1739
PHPAPI void php_flock_common(php_stream *stream, zend_long operation, uint32_t operation_arg_num, zval *wouldblock, zval *return_value)
Definition file.c:188
PHPAPI void php_stat(zend_string *filename, int type, zval *return_value)
Definition filestat.c:743
PHPAPI char * expand_filepath_with_mode(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len, int realpath_mode)
bool use_include_path
#define SEEK_SET
Definition gd_io_file.c:20
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
#define F_OK
Definition ioutil.h:86
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
#define next(ls)
Definition minilua.c:2661
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_METHOD
Definition php.h:365
#define PHPAPI
Definition php.h:71
unsigned const char * pos
Definition php_ffi.h:52
#define FS_IS_W
#define FS_SIZE
#define FS_GROUP
#define FS_IS_X
#define FS_TYPE
#define FS_INODE
#define FS_IS_DIR
#define FS_IS_R
#define FS_MTIME
#define FS_OWNER
#define FS_PERMS
#define FS_LPERMS
#define FS_IS_FILE
#define FS_ATIME
#define FS_CTIME
#define FS_IS_LINK
#define PHP_STREAM_MAX_MEM
unsigned char key[REFLECTION_KEY_LEN]
#define php_stream_context_from_zval(zcontext, nocontext)
#define php_glob_stream_get_path(stream, plen)
#define php_glob_stream_get_count(stream, pflags)
PHPAPI const php_stream_ops php_glob_stream_ops
#define php_stream_truncate_supported(stream)
#define php_stream_pclose(stream)
#define REPORT_ERRORS
#define php_stream_readdir(dirstream, dirent)
#define php_stream_rewind(stream)
#define php_stream_get_line(stream, buf, maxlen, retlen)
#define php_stream_getc(stream)
#define php_stream_seek(stream, offset, whence)
#define php_stream_flush(stream)
PHPAPI zend_string * php_stream_read_to_str(php_stream *stream, size_t len)
Definition streams.c:792
#define php_stream_opendir(path, options, context)
#define php_stream_truncate_set_size(stream, size)
#define php_stream_eof(stream)
#define php_stream_open_wrapper_ex(path, mode, options, opened, context)
#define php_stream_close(stream)
#define php_stream_is(stream, anops)
#define php_stream_tell(stream)
#define php_stream_rewinddir(dirstream)
#define PHP_STREAM_FLAG_NO_FCLOSE
#define USE_PATH
#define php_stream_passthru(stream)
#define php_stream_write(stream, buf, count)
PHPAPI zend_string * php_basename(const char *s, size_t len, const char *suffix, size_t sufflen)
Definition string.c:1372
HashTable seek
Definition phpdbg.h:233
#define DT_DIR
Definition readdir.h:20
#define DT_REG
Definition readdir.h:21
PHPAPI int php_sscanf_internal(char *string, char *format, int argCount, zval *args, int varStart, zval *return_value)
Definition scanf.c:574
#define SCAN_ERROR_WRONG_PARAM_COUNT
Definition scanf.h:31
zval * current
Definition session.c:1024
p
Definition session.c:1105
PHPAPI zend_class_entry * spl_ce_FilesystemIterator
PHPAPI zend_string * spl_filesystem_object_get_path(const spl_filesystem_object *intern)
#define DIT_CTOR_GLOB
#define IS_SLASH_AT(zs, pos)
PHPAPI zend_class_entry * spl_ce_SplFileObject
#define CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern)
#define CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(spl_filesystem_object_pointer)
PHPAPI zend_class_entry * spl_ce_SplTempFileObject
#define DIT_CTOR_FLAGS
PHPAPI zend_class_entry * spl_ce_SplFileInfo
PHPAPI zend_class_entry * spl_ce_GlobIterator
PHPAPI zend_class_entry * spl_ce_DirectoryIterator
#define SPL_HAS_FLAG(flags, test_flag)
PHPAPI zend_class_entry * spl_ce_RecursiveDirectoryIterator
#define FileInfoFunction(func_name, func_num)
@ SPL_FS_INFO
@ SPL_FS_FILE
@ SPL_FS_DIR
#define SPL_FILE_DIR_OTHERS_MASK
#define SPL_FILE_DIR_KEY_MODE_MASK
#define SPL_FILE_DIR_FOLLOW_SYMLINKS
struct _spl_filesystem_object spl_filesystem_object
#define SPL_FILE_DIR_KEY(intern, mode)
#define SPL_FILE_DIR_CURRENT_AS_SELF
#define SPL_FILE_DIR_KEY_AS_PATHNAME
#define SPL_FILE_DIR_CURRENT_MODE_MASK
#define SPL_FILE_OBJECT_SKIP_EMPTY
#define SPL_FILE_OBJECT_READ_CSV
#define SPL_FILE_OBJECT_MASK
#define SPL_FILE_OBJECT_DROP_NEW_LINE
#define SPL_FILE_DIR_KEY_AS_FILENAME
#define SPL_FILE_DIR_SKIPDOTS
#define SPL_FILE_DIR_UNIXPATHS
#define SPL_FILE_DIR_CURRENT_AS_PATHNAME
#define SPL_FILE_DIR_CURRENT_AS_FILEINFO
#define SPL_FILE_DIR_CURRENT(intern, mode)
#define SPL_FILE_OBJECT_READ_AHEAD
PHPAPI zend_class_entry * spl_ce_LogicException
PHPAPI zend_class_entry * spl_ce_RuntimeException
PHPAPI zend_class_entry * spl_ce_UnexpectedValueException
PHPAPI zend_class_entry * spl_ce_OutOfBoundsException
void spl_set_private_debug_info_property(const zend_class_entry *ce, const char *property, size_t property_len, HashTable *debug_info, zval *value)
PHPAPI zend_class_entry * spl_ce_RecursiveIterator
PHPAPI zend_class_entry * spl_ce_SeekableIterator
#define strpprintf
Definition spprintf.h:30
#define PHP_CSV_NO_ESCAPE
Definition file.h:47
#define PHP_CSV_ESCAPE_ERROR
Definition file.h:48
#define FG(v)
Definition file.h:117
unsigned char d_type
char d_name[MAXPATHLEN]
uint16_t is_persistent
uint32_t flags
zend_resource * res
char * orig_path
zend_function * func_next
SPL_FS_OBJ_TYPE type
zend_function * func_rewind
zend_function * func_valid
php_stream_context * context
zend_string * current_line
zend_string * file_name
php_stream_dirent entry
const spl_other_handler * oth_handler
zend_class_entry * file_class
zend_string * orig_path
zend_string * open_mode
union _spl_filesystem_object::@054265167067030002056020365222237177377222266163 u
zend_function * func_getCurr
struct _spl_filesystem_object::@054265167067030002056020365222237177377222266163::@257240036270267375207030141122200245165352304006 dir
zend_class_entry * info_class
struct _spl_filesystem_object::@054265167067030002056020365222237177377222266163::@333212215061307125335046006116147322016236071114 file
spl_foreign_dtor_t dtor
spl_foreign_clone_t clone
zend_string * name
Definition zend.h:149
zend_function * constructor
Definition zend.h:172
HashTable function_table
Definition zend.h:163
const zend_object_iterator_funcs * funcs
zend_class_entry * ce
Definition zend_types.h:560
zend_object_iterator intern
zend_class_entry * scope
struct _zend_function::@236135173067030250234125302313220025134003177336 common
#define errno
ZEND_API zend_string * zend_strpprintf(size_t max_len, const char *format,...)
Definition zend.c:353
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API ZEND_COLD void zend_type_error(const char *format,...)
Definition zend.c:1824
ZEND_API ZEND_COLD void zend_value_error(const char *format,...)
Definition zend.c:1849
#define INTERNAL_FUNCTION_PARAMETERS
Definition zend.h:49
@ EH_THROW
Definition zend.h:433
ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current)
Definition zend_API.c:5242
ZEND_API void zend_restore_error_handling(zend_error_handling *saved)
Definition zend_API.c:5253
#define INTERNAL_FUNCTION_PARAM_PASSTHRU
Definition zend.h:50
ZEND_API const char * zend_zval_value_name(const zval *arg)
Definition zend_API.c:148
ZEND_API zend_result object_init_with_constructor(zval *arg, zend_class_entry *class_type, uint32_t param_count, zval *params, HashTable *named_params)
Definition zend_API.c:1855
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type)
Definition zend_API.c:1688
ZEND_API ZEND_COLD void zend_argument_must_not_be_empty_error(uint32_t arg_num)
Definition zend_API.c:443
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:423
ZEND_API zend_result add_next_index_string(zval *arg, const char *str)
Definition zend_API.c:2186
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define RETURN_STRING(s)
Definition zend_API.h:1043
#define RETURN_COPY(zv)
Definition zend_API.h:1054
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
#define ZVAL_STRING(z, s)
Definition zend_API.h:956
#define RETVAL_STR_COPY(s)
Definition zend_API.h:1016
#define RETURN_ARR(r)
Definition zend_API.h:1050
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define zend_parse_parameters_none()
Definition zend_API.h:353
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define RETURN_LONG(l)
Definition zend_API.h:1037
#define RETURN_BOOL(b)
Definition zend_API.h:1035
#define RETURN_NEW_STR(s)
Definition zend_API.h:1041
#define RETURN_OBJ_COPY(r)
Definition zend_API.h:1053
#define RETURN_THROWS()
Definition zend_API.h:1060
#define RETURN_STR(s)
Definition zend_API.h:1039
#define RETVAL_OBJ(r)
Definition zend_API.h:1026
#define ZEND_THIS
Definition zend_API.h:523
#define Z_PARAM_BOOL(dest)
Definition zend_API.h:1726
#define RETURN_EMPTY_STRING()
Definition zend_API.h:1047
#define ZVAL_STRINGL(z, s, l)
Definition zend_API.h:952
#define WRONG_PARAM_COUNT
Definition zend_API.h:529
#define RETVAL_FALSE
Definition zend_API.h:1032
#define RETURN_TRUE
Definition zend_API.h:1059
#define RETVAL_STRINGL(s, l)
Definition zend_API.h:1018
#define RETURN_STR_COPY(s)
Definition zend_API.h:1042
#define array_init(arg)
Definition zend_API.h:537
#define ZVAL_EMPTY_STRING(z)
Definition zend_API.h:961
#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
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
strlen(string $string)
strcmp(string $string1, string $string2)
uint32_t num_args
zend_string_release_ex(func->internal_function.function_name, 0)
ZEND_API size_t zend_dirname(char *path, size_t len)
#define E_ERROR
Definition zend_errors.h:23
#define E_WARNING
Definition zend_errors.h:24
#define E_DEPRECATED
Definition zend_errors.h:37
ZEND_API ZEND_COLD zend_object * zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code, const char *format,...)
union _zend_function zend_function
#define EG(v)
ZEND_API HashTable *ZEND_FASTCALL zend_array_dup(HashTable *source)
Definition zend_hash.c:2438
ZEND_API zend_class_entry * zend_ce_countable
ZEND_API zend_class_entry * zend_ce_stringable
ZEND_API void zend_iterator_init(zend_object_iterator *iter)
struct _zend_object_iterator zend_object_iterator
struct _zend_object_iterator_funcs zend_object_iterator_funcs
int32_t zend_long
Definition zend_long.h:42
#define ZEND_LONG_FMT
Definition zend_long.h:87
struct _zend_string zend_string
ZEND_API zend_function * zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key)
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API void zend_objects_destroy_object(zend_object *object)
ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object, zend_object *old_object)
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)
#define MIN(a, b)
#define XtOffsetOf(s_type, field)
#define ZEND_ASSERT(c)
#define ZEND_UNREACHABLE()
#define ZEND_COLD
#define UNEXPECTED(condition)
#define MAX(a, b)
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
ZEND_API zend_string * zend_string_concat3(const char *str1, size_t str1_len, const char *str2, size_t str2_len, const char *str3, size_t str3_len)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_INIT_LITERAL(s, persistent)
#define ZSTR_EMPTY_ALLOC()
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define zend_string_starts_with_literal(str, prefix)
#define ZSTR_CHAR(c)
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_TRUE
Definition zend_types.h:603
#define ZVAL_STR(z, s)
#define ZVAL_FALSE(z)
#define ZVAL_UNDEF(z)
#define IS_FALSE
Definition zend_types.h:602
#define ZVAL_NULL(z)
#define ZVAL_LONG(z, l)
#define IS_STRING
Definition zend_types.h:606
#define ZVAL_STR_COPY(z, s)
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_OBJ_P(zval_p)
Definition zend_types.h:990
#define IS_ARRAY
Definition zend_types.h:607
#define Z_ISUNDEF(zval)
Definition zend_types.h:956
#define Z_STR(zval)
Definition zend_types.h:971
#define ZVAL_RES(z, r)
#define Z_OBJCE_P(zval_p)
@ FAILURE
Definition zend_types.h:61
#define ZVAL_ARR(z, a)
#define ZVAL_COPY(z, v)
#define ZVAL_OBJ_COPY(z, o)
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
unsigned char zend_uchar
Definition zend_types.h:57
#define Z_ISREF(zval)
Definition zend_types.h:953
struct _zend_object_handlers zend_object_handlers
Definition zend_types.h:88
#define Z_TYPE(zval)
Definition zend_types.h:659
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
#define DEFAULT_SLASH
#define S_ISDIR(mode)
#define IS_ABSOLUTE_PATH(path, len)
#define CWD_EXPAND
#define S_ISLNK(mode)
#define MAXPATHLEN
#define VCWD_ACCESS(pathname, mode)
#define VCWD_REALPATH(path, real_path)
zval retval
zval * return_value
zval * arg1
zval * arg2
uint32_t arg_num
zend_string * name
bool result
object
zval * ret