PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/ext/spl/spl_directory.c

https://github.com/php/php-src
C | 2799 lines | 2253 code | 302 blank | 244 comment | 383 complexity | 60533fe3073db502dd06e2e4876e3b9a MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1

Large files files are truncated, but you can click here to view the full 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. #ifdef HAVE_CONFIG_H
  17. # include "config.h"
  18. #endif
  19. #include "php.h"
  20. #include "php_ini.h"
  21. #include "ext/standard/file.h"
  22. #include "ext/standard/php_filestat.h"
  23. #include "ext/standard/flock_compat.h"
  24. #include "ext/standard/scanf.h"
  25. #include "ext/standard/php_string.h"
  26. #include "zend_exceptions.h"
  27. #include "zend_interfaces.h"
  28. #include "php_spl.h"
  29. #include "spl_functions.h"
  30. #include "spl_engine.h"
  31. #include "spl_iterators.h"
  32. #include "spl_directory.h"
  33. #include "spl_directory_arginfo.h"
  34. #include "spl_exceptions.h"
  35. #define SPL_HAS_FLAG(flags, test_flag) ((flags & test_flag) ? 1 : 0)
  36. /* declare the class handlers */
  37. static zend_object_handlers spl_filesystem_object_handlers;
  38. /* includes handler to validate object state when retrieving methods */
  39. static zend_object_handlers spl_filesystem_object_check_handlers;
  40. /* decalre the class entry */
  41. PHPAPI zend_class_entry *spl_ce_SplFileInfo;
  42. PHPAPI zend_class_entry *spl_ce_DirectoryIterator;
  43. PHPAPI zend_class_entry *spl_ce_FilesystemIterator;
  44. PHPAPI zend_class_entry *spl_ce_RecursiveDirectoryIterator;
  45. PHPAPI zend_class_entry *spl_ce_GlobIterator;
  46. PHPAPI zend_class_entry *spl_ce_SplFileObject;
  47. PHPAPI zend_class_entry *spl_ce_SplTempFileObject;
  48. #define CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(spl_filesystem_object_pointer) \
  49. if (!(spl_filesystem_object_pointer)->u.file.stream) { \
  50. zend_throw_error(NULL, "Object not initialized"); \
  51. RETURN_THROWS(); \
  52. }
  53. #define CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern) \
  54. if (!(intern)->u.dir.dirp) { \
  55. zend_throw_error(NULL, "Object not initialized"); \
  56. RETURN_THROWS(); \
  57. }
  58. static void spl_filesystem_file_free_line(spl_filesystem_object *intern) /* {{{ */
  59. {
  60. if (intern->u.file.current_line) {
  61. efree(intern->u.file.current_line);
  62. intern->u.file.current_line = NULL;
  63. }
  64. if (!Z_ISUNDEF(intern->u.file.current_zval)) {
  65. zval_ptr_dtor(&intern->u.file.current_zval);
  66. ZVAL_UNDEF(&intern->u.file.current_zval);
  67. }
  68. } /* }}} */
  69. static void spl_filesystem_object_destroy_object(zend_object *object) /* {{{ */
  70. {
  71. spl_filesystem_object *intern = spl_filesystem_from_obj(object);
  72. zend_objects_destroy_object(object);
  73. switch(intern->type) {
  74. case SPL_FS_DIR:
  75. if (intern->u.dir.dirp) {
  76. php_stream_close(intern->u.dir.dirp);
  77. intern->u.dir.dirp = NULL;
  78. }
  79. break;
  80. case SPL_FS_FILE:
  81. if (intern->u.file.stream) {
  82. /*
  83. if (intern->u.file.zcontext) {
  84. zend_list_delref(Z_RESVAL_P(intern->zcontext));
  85. }
  86. */
  87. if (!intern->u.file.stream->is_persistent) {
  88. php_stream_close(intern->u.file.stream);
  89. } else {
  90. php_stream_pclose(intern->u.file.stream);
  91. }
  92. intern->u.file.stream = NULL;
  93. ZVAL_UNDEF(&intern->u.file.zresource);
  94. }
  95. break;
  96. default:
  97. break;
  98. }
  99. } /* }}} */
  100. static void spl_filesystem_object_free_storage(zend_object *object) /* {{{ */
  101. {
  102. spl_filesystem_object *intern = spl_filesystem_from_obj(object);
  103. if (intern->oth_handler && intern->oth_handler->dtor) {
  104. intern->oth_handler->dtor(intern);
  105. }
  106. zend_object_std_dtor(&intern->std);
  107. if (intern->path) {
  108. zend_string_release(intern->path);
  109. }
  110. if (intern->file_name) {
  111. zend_string_release(intern->file_name);
  112. }
  113. switch(intern->type) {
  114. case SPL_FS_INFO:
  115. break;
  116. case SPL_FS_DIR:
  117. if (intern->u.dir.sub_path) {
  118. zend_string_release(intern->u.dir.sub_path);
  119. }
  120. break;
  121. case SPL_FS_FILE:
  122. if (intern->u.file.open_mode) {
  123. zend_string_release(intern->u.file.open_mode);
  124. }
  125. if (intern->orig_path) {
  126. zend_string_release(intern->orig_path);
  127. }
  128. spl_filesystem_file_free_line(intern);
  129. break;
  130. }
  131. } /* }}} */
  132. /* {{{ spl_ce_dir_object_new */
  133. /* creates the object by
  134. - allocating memory
  135. - initializing the object members
  136. - storing the object
  137. - setting it's handlers
  138. called from
  139. - clone
  140. - new
  141. */
  142. static zend_object *spl_filesystem_object_new_ex(zend_class_entry *class_type)
  143. {
  144. spl_filesystem_object *intern;
  145. intern = emalloc(sizeof(spl_filesystem_object) + zend_object_properties_size(class_type));
  146. memset(intern, 0,
  147. MAX(XtOffsetOf(spl_filesystem_object, u.dir.entry),
  148. XtOffsetOf(spl_filesystem_object, u.file.escape) + sizeof(int)));
  149. /* intern->type = SPL_FS_INFO; done by set 0 */
  150. intern->file_class = spl_ce_SplFileObject;
  151. intern->info_class = spl_ce_SplFileInfo;
  152. zend_object_std_init(&intern->std, class_type);
  153. object_properties_init(&intern->std, class_type);
  154. intern->std.handlers = &spl_filesystem_object_handlers;
  155. return &intern->std;
  156. }
  157. /* }}} */
  158. /* {{{ spl_filesystem_object_new */
  159. /* See spl_filesystem_object_new_ex */
  160. static zend_object *spl_filesystem_object_new(zend_class_entry *class_type)
  161. {
  162. return spl_filesystem_object_new_ex(class_type);
  163. }
  164. /* }}} */
  165. /* {{{ spl_filesystem_object_new_check */
  166. static zend_object *spl_filesystem_object_new_check(zend_class_entry *class_type)
  167. {
  168. spl_filesystem_object *ret = spl_filesystem_from_obj(spl_filesystem_object_new_ex(class_type));
  169. ret->std.handlers = &spl_filesystem_object_check_handlers;
  170. return &ret->std;
  171. }
  172. /* }}} */
  173. PHPAPI char* spl_filesystem_object_get_path(spl_filesystem_object *intern, size_t *len) /* {{{ */
  174. {
  175. #ifdef HAVE_GLOB
  176. if (intern->type == SPL_FS_DIR) {
  177. if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
  178. return php_glob_stream_get_path(intern->u.dir.dirp, len);
  179. }
  180. }
  181. #endif
  182. if (len) {
  183. *len = intern->path ? ZSTR_LEN(intern->path) : 0;
  184. }
  185. return intern->path ? ZSTR_VAL(intern->path) : NULL;
  186. } /* }}} */
  187. static inline int spl_filesystem_object_get_file_name(spl_filesystem_object *intern) /* {{{ */
  188. {
  189. if (intern->file_name) {
  190. /* already known */
  191. return SUCCESS;
  192. }
  193. switch (intern->type) {
  194. case SPL_FS_INFO:
  195. case SPL_FS_FILE:
  196. zend_throw_error(NULL, "Object not initialized");
  197. return FAILURE;
  198. break;
  199. case SPL_FS_DIR:
  200. {
  201. size_t name_len;
  202. size_t path_len = 0;
  203. char *path;
  204. char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
  205. path = spl_filesystem_object_get_path(intern, &path_len);
  206. /* if there is parent path, amend it, otherwise just use the given path as is */
  207. name_len = strlen(intern->u.dir.entry.d_name);
  208. if (path_len == 0) {
  209. intern->file_name = zend_string_init(intern->u.dir.entry.d_name, name_len, 0);
  210. } else {
  211. zend_string *file_name = zend_string_alloc(path_len + 1 + name_len, 0);
  212. memcpy(ZSTR_VAL(file_name), path, path_len);
  213. ZSTR_VAL(file_name)[path_len] = slash;
  214. memcpy(ZSTR_VAL(file_name) + path_len + 1, intern->u.dir.entry.d_name, name_len);
  215. ZSTR_VAL(file_name)[path_len + 1 + name_len] = 0;
  216. intern->file_name = file_name;
  217. }
  218. }
  219. break;
  220. }
  221. return SUCCESS;
  222. } /* }}} */
  223. static int spl_filesystem_dir_read(spl_filesystem_object *intern) /* {{{ */
  224. {
  225. if (intern->file_name) {
  226. /* invalidate */
  227. zend_string_release(intern->file_name);
  228. intern->file_name = NULL;
  229. }
  230. if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
  231. intern->u.dir.entry.d_name[0] = '\0';
  232. return 0;
  233. } else {
  234. return 1;
  235. }
  236. }
  237. /* }}} */
  238. #define IS_SLASH_AT(zs, pos) (IS_SLASH(zs[pos]))
  239. static inline int spl_filesystem_is_dot(const char * d_name) /* {{{ */
  240. {
  241. return !strcmp(d_name, ".") || !strcmp(d_name, "..");
  242. }
  243. /* }}} */
  244. /* {{{ spl_filesystem_dir_open */
  245. /* open a directory resource
  246. * Can emit an E_WARNING as it reports errors from php_stream_opendir() */
  247. static void spl_filesystem_dir_open(spl_filesystem_object* intern, zend_string *path)
  248. {
  249. int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
  250. intern->type = SPL_FS_DIR;
  251. intern->u.dir.dirp = php_stream_opendir(ZSTR_VAL(path), REPORT_ERRORS, FG(default_context));
  252. if (ZSTR_LEN(path) > 1 && IS_SLASH_AT(ZSTR_VAL(path), ZSTR_LEN(path)-1)) {
  253. intern->path = zend_string_init(ZSTR_VAL(path), ZSTR_LEN(path)-1, 0);
  254. } else {
  255. intern->path = zend_string_copy(path);
  256. }
  257. intern->u.dir.index = 0;
  258. if (EG(exception) || intern->u.dir.dirp == NULL) {
  259. intern->u.dir.entry.d_name[0] = '\0';
  260. if (!EG(exception)) {
  261. /* open failed w/out notice (turned to exception due to EH_THROW) */
  262. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  263. "Failed to open directory \"%s\"", ZSTR_VAL(path));
  264. }
  265. } else {
  266. do {
  267. spl_filesystem_dir_read(intern);
  268. } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
  269. }
  270. }
  271. /* }}} */
  272. /* Can generate E_WARNINGS as we report errors from stream initialized via
  273. * php_stream_open_wrapper_ex() */
  274. static zend_result spl_filesystem_file_open(spl_filesystem_object *intern, bool use_include_path) /* {{{ */
  275. {
  276. zval tmp;
  277. intern->type = SPL_FS_FILE;
  278. php_stat(intern->file_name, FS_IS_DIR, &tmp);
  279. if (Z_TYPE(tmp) == IS_TRUE) {
  280. zend_string_release(intern->u.file.open_mode);
  281. intern->u.file.open_mode = NULL;
  282. intern->file_name = NULL;
  283. zend_throw_exception_ex(spl_ce_LogicException, 0, "Cannot use SplFileObject with directories");
  284. return FAILURE;
  285. }
  286. intern->u.file.context = php_stream_context_from_zval(intern->u.file.zcontext, 0);
  287. intern->u.file.stream = php_stream_open_wrapper_ex(ZSTR_VAL(intern->file_name), ZSTR_VAL(intern->u.file.open_mode), (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, intern->u.file.context);
  288. if (!ZSTR_LEN(intern->file_name) || !intern->u.file.stream) {
  289. if (!EG(exception)) {
  290. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot open file '%s'", ZSTR_VAL(intern->file_name));
  291. }
  292. zend_string_release(intern->u.file.open_mode);
  293. intern->u.file.open_mode = NULL;
  294. intern->file_name = NULL; /* until here it is not a copy */
  295. return FAILURE;
  296. }
  297. /*
  298. if (intern->u.file.zcontext) {
  299. //zend_list_addref(Z_RES_VAL(intern->u.file.zcontext));
  300. Z_ADDREF_P(intern->u.file.zcontext);
  301. }
  302. */
  303. if (ZSTR_LEN(intern->file_name) > 1 && IS_SLASH_AT(ZSTR_VAL(intern->file_name), ZSTR_LEN(intern->file_name)-1)) {
  304. intern->file_name = zend_string_init(ZSTR_VAL(intern->file_name), ZSTR_LEN(intern->file_name)-1, 0);
  305. } else {
  306. intern->file_name = zend_string_copy(intern->file_name);
  307. }
  308. intern->orig_path = zend_string_init(intern->u.file.stream->orig_path, strlen(intern->u.file.stream->orig_path), 0);
  309. /* avoid reference counting in debug mode, thus do it manually */
  310. ZVAL_RES(&intern->u.file.zresource, intern->u.file.stream->res);
  311. /*!!! TODO: maybe bug?
  312. Z_SET_REFCOUNT(intern->u.file.zresource, 1);
  313. */
  314. intern->u.file.delimiter = ',';
  315. intern->u.file.enclosure = '"';
  316. intern->u.file.escape = (unsigned char) '\\';
  317. intern->u.file.func_getCurr = zend_hash_str_find_ptr(&intern->std.ce->function_table, "getcurrentline", sizeof("getcurrentline") - 1);
  318. return SUCCESS;
  319. } /* }}} */
  320. /* {{{ spl_filesystem_object_clone */
  321. /* Local zend_object creation (on stack)
  322. Load the 'other' object
  323. Create a new empty object (See spl_filesystem_object_new_ex)
  324. Open the directory
  325. Clone other members (properties)
  326. */
  327. static zend_object *spl_filesystem_object_clone(zend_object *old_object)
  328. {
  329. zend_object *new_object;
  330. spl_filesystem_object *intern;
  331. spl_filesystem_object *source;
  332. int index, skip_dots;
  333. source = spl_filesystem_from_obj(old_object);
  334. new_object = spl_filesystem_object_new_ex(old_object->ce);
  335. intern = spl_filesystem_from_obj(new_object);
  336. intern->flags = source->flags;
  337. switch (source->type) {
  338. case SPL_FS_INFO:
  339. intern->path = zend_string_copy(source->path);
  340. intern->file_name = zend_string_copy(source->file_name);
  341. break;
  342. case SPL_FS_DIR:
  343. spl_filesystem_dir_open(intern, source->path);
  344. /* read until we hit the position in which we were before */
  345. skip_dots = SPL_HAS_FLAG(source->flags, SPL_FILE_DIR_SKIPDOTS);
  346. for(index = 0; index < source->u.dir.index; ++index) {
  347. do {
  348. spl_filesystem_dir_read(intern);
  349. } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
  350. }
  351. intern->u.dir.index = index;
  352. break;
  353. case SPL_FS_FILE:
  354. ZEND_UNREACHABLE();
  355. }
  356. intern->file_class = source->file_class;
  357. intern->info_class = source->info_class;
  358. intern->oth = source->oth;
  359. intern->oth_handler = source->oth_handler;
  360. zend_objects_clone_members(new_object, old_object);
  361. if (intern->oth_handler && intern->oth_handler->clone) {
  362. intern->oth_handler->clone(source, intern);
  363. }
  364. return new_object;
  365. }
  366. /* }}} */
  367. static void spl_filesystem_info_set_filename(spl_filesystem_object *intern, zend_string *path) /* {{{ */
  368. {
  369. size_t path_len;
  370. if (intern->file_name) {
  371. zend_string_release(intern->file_name);
  372. }
  373. path_len = ZSTR_LEN(path);
  374. if (path_len > 1 && IS_SLASH_AT(ZSTR_VAL(path), path_len-1)) {
  375. path_len--;
  376. intern->file_name = zend_string_init(ZSTR_VAL(path), path_len, 0);
  377. } else {
  378. intern->file_name = zend_string_copy(path);
  379. }
  380. while (path_len > 1 && !IS_SLASH_AT(ZSTR_VAL(path), path_len-1)) {
  381. path_len--;
  382. }
  383. if (path_len) {
  384. path_len--;
  385. }
  386. if (intern->path) {
  387. zend_string_release(intern->path);
  388. }
  389. intern->path = zend_string_init(ZSTR_VAL(path), path_len, 0);
  390. } /* }}} */
  391. static spl_filesystem_object *spl_filesystem_object_create_info(spl_filesystem_object *source, zend_string *file_path, zend_class_entry *ce, zval *return_value) /* {{{ */
  392. {
  393. spl_filesystem_object *intern;
  394. zval arg1;
  395. if (!file_path || !ZSTR_LEN(file_path)) {
  396. #ifdef PHP_WIN32
  397. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot create SplFileInfo for empty path");
  398. #endif
  399. return NULL;
  400. }
  401. ce = ce ? ce : source->info_class;
  402. intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));
  403. RETVAL_OBJ(&intern->std);
  404. if (ce->constructor->common.scope != spl_ce_SplFileInfo) {
  405. ZVAL_STR_COPY(&arg1, file_path);
  406. zend_call_method_with_1_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1);
  407. zval_ptr_dtor(&arg1);
  408. } else {
  409. spl_filesystem_info_set_filename(intern, file_path);
  410. }
  411. return intern;
  412. } /* }}} */
  413. static spl_filesystem_object *spl_filesystem_object_create_type(int num_args, spl_filesystem_object *source, int type, zend_class_entry *ce, zval *return_value) /* {{{ */
  414. {
  415. spl_filesystem_object *intern;
  416. bool use_include_path = 0;
  417. zval arg1, arg2;
  418. zend_error_handling error_handling;
  419. switch (source->type) {
  420. case SPL_FS_INFO:
  421. case SPL_FS_FILE:
  422. break;
  423. case SPL_FS_DIR:
  424. if (!source->u.dir.entry.d_name[0]) {
  425. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Could not open file");
  426. return NULL;
  427. }
  428. }
  429. switch (type) {
  430. case SPL_FS_INFO:
  431. ce = ce ? ce : source->info_class;
  432. intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));
  433. RETVAL_OBJ(&intern->std);
  434. if (spl_filesystem_object_get_file_name(source) != SUCCESS) {
  435. return NULL;
  436. }
  437. if (ce->constructor->common.scope != spl_ce_SplFileInfo) {
  438. ZVAL_STR_COPY(&arg1, source->file_name);
  439. zend_call_method_with_1_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1);
  440. zval_ptr_dtor(&arg1);
  441. } else {
  442. char *path;
  443. size_t path_len;
  444. intern->file_name = zend_string_copy(source->file_name);
  445. path = spl_filesystem_object_get_path(source, &path_len);
  446. if (source->path && ZSTR_VAL(source->path) == path) {
  447. intern->path = zend_string_copy(source->path);
  448. } else {
  449. intern->path = zend_string_init(path, path_len, 0);
  450. }
  451. }
  452. break;
  453. case SPL_FS_FILE:
  454. {
  455. ce = ce ? ce : source->file_class;
  456. zend_string *open_mode = ZSTR_CHAR('r');
  457. zval *resource = NULL;
  458. if (zend_parse_parameters(num_args, "|Sbr!",
  459. &open_mode, &use_include_path, &resource) == FAILURE
  460. ) {
  461. return NULL;
  462. }
  463. intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));
  464. RETVAL_OBJ(&intern->std);
  465. if (spl_filesystem_object_get_file_name(source) != SUCCESS) {
  466. return NULL;
  467. }
  468. if (ce->constructor->common.scope != spl_ce_SplFileObject) {
  469. ZVAL_STR_COPY(&arg1, source->file_name);
  470. ZVAL_STR_COPY(&arg2, open_mode);
  471. zend_call_method_with_2_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1, &arg2);
  472. zval_ptr_dtor(&arg1);
  473. zval_ptr_dtor(&arg2);
  474. } else {
  475. char *path;
  476. size_t path_len;
  477. intern->file_name = source->file_name;
  478. path = spl_filesystem_object_get_path(source, &path_len);
  479. if (source->path && ZSTR_VAL(source->path) == path) {
  480. intern->path = zend_string_copy(source->path);
  481. } else {
  482. intern->path = zend_string_init(path, path_len, 0);
  483. }
  484. intern->u.file.open_mode = zend_string_copy(open_mode);
  485. intern->u.file.zcontext = resource;
  486. /* spl_filesystem_file_open() can generate E_WARNINGs which we want to promote to exceptions */
  487. zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
  488. if (spl_filesystem_file_open(intern, use_include_path) == FAILURE) {
  489. zend_restore_error_handling(&error_handling);
  490. zval_ptr_dtor(return_value);
  491. ZVAL_NULL(return_value);
  492. return NULL;
  493. }
  494. zend_restore_error_handling(&error_handling);
  495. }
  496. break;
  497. }
  498. case SPL_FS_DIR:
  499. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Operation not supported");
  500. return NULL;
  501. }
  502. return NULL;
  503. } /* }}} */
  504. static int spl_filesystem_is_invalid_or_dot(const char * d_name) /* {{{ */
  505. {
  506. return d_name[0] == '\0' || spl_filesystem_is_dot(d_name);
  507. }
  508. /* }}} */
  509. static zend_string *spl_filesystem_object_get_pathname(spl_filesystem_object *intern) { /* {{{ */
  510. switch (intern->type) {
  511. case SPL_FS_INFO:
  512. case SPL_FS_FILE:
  513. return intern->file_name;
  514. case SPL_FS_DIR:
  515. if (intern->u.dir.entry.d_name[0]) {
  516. spl_filesystem_object_get_file_name(intern);
  517. return intern->file_name;
  518. }
  519. }
  520. return NULL;
  521. }
  522. /* }}} */
  523. static inline HashTable *spl_filesystem_object_get_debug_info(zend_object *object) /* {{{ */
  524. {
  525. spl_filesystem_object *intern = spl_filesystem_from_obj(object);
  526. zval tmp;
  527. HashTable *rv;
  528. zend_string *pnstr;
  529. zend_string *path;
  530. char stmp[2];
  531. if (!intern->std.properties) {
  532. rebuild_object_properties(&intern->std);
  533. }
  534. rv = zend_array_dup(intern->std.properties);
  535. pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "pathName", sizeof("pathName")-1);
  536. path = spl_filesystem_object_get_pathname(intern);
  537. if (path) {
  538. ZVAL_STR_COPY(&tmp, path);
  539. } else {
  540. ZVAL_EMPTY_STRING(&tmp);
  541. }
  542. zend_symtable_update(rv, pnstr, &tmp);
  543. zend_string_release_ex(pnstr, 0);
  544. if (intern->file_name) {
  545. size_t path_len;
  546. pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "fileName", sizeof("fileName")-1);
  547. spl_filesystem_object_get_path(intern, &path_len);
  548. if (path_len && path_len < ZSTR_LEN(intern->file_name)) {
  549. ZVAL_STRINGL(&tmp, ZSTR_VAL(intern->file_name) + path_len + 1, ZSTR_LEN(intern->file_name) - (path_len + 1));
  550. } else {
  551. ZVAL_STR_COPY(&tmp, intern->file_name);
  552. }
  553. zend_symtable_update(rv, pnstr, &tmp);
  554. zend_string_release_ex(pnstr, 0);
  555. }
  556. if (intern->type == SPL_FS_DIR) {
  557. #ifdef HAVE_GLOB
  558. pnstr = spl_gen_private_prop_name(spl_ce_DirectoryIterator, "glob", sizeof("glob")-1);
  559. if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
  560. ZVAL_STR_COPY(&tmp, intern->path);
  561. } else {
  562. ZVAL_FALSE(&tmp);
  563. }
  564. zend_symtable_update(rv, pnstr, &tmp);
  565. zend_string_release_ex(pnstr, 0);
  566. #endif
  567. pnstr = spl_gen_private_prop_name(spl_ce_RecursiveDirectoryIterator, "subPathName", sizeof("subPathName")-1);
  568. if (intern->u.dir.sub_path) {
  569. ZVAL_STR_COPY(&tmp, intern->u.dir.sub_path);
  570. } else {
  571. ZVAL_EMPTY_STRING(&tmp);
  572. }
  573. zend_symtable_update(rv, pnstr, &tmp);
  574. zend_string_release_ex(pnstr, 0);
  575. }
  576. if (intern->type == SPL_FS_FILE) {
  577. pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "openMode", sizeof("openMode")-1);
  578. ZVAL_STR_COPY(&tmp, intern->u.file.open_mode);
  579. zend_symtable_update(rv, pnstr, &tmp);
  580. zend_string_release_ex(pnstr, 0);
  581. stmp[1] = '\0';
  582. stmp[0] = intern->u.file.delimiter;
  583. pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "delimiter", sizeof("delimiter")-1);
  584. ZVAL_STRINGL(&tmp, stmp, 1);
  585. zend_symtable_update(rv, pnstr, &tmp);
  586. zend_string_release_ex(pnstr, 0);
  587. stmp[0] = intern->u.file.enclosure;
  588. pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "enclosure", sizeof("enclosure")-1);
  589. ZVAL_STRINGL(&tmp, stmp, 1);
  590. zend_symtable_update(rv, pnstr, &tmp);
  591. zend_string_release_ex(pnstr, 0);
  592. }
  593. return rv;
  594. }
  595. /* }}} */
  596. zend_function *spl_filesystem_object_get_method_check(zend_object **object, zend_string *method, const zval *key) /* {{{ */
  597. {
  598. spl_filesystem_object *fsobj = spl_filesystem_from_obj(*object);
  599. if (fsobj->u.dir.dirp == NULL && fsobj->orig_path == NULL) {
  600. zend_function *func;
  601. zend_string *tmp = zend_string_init("_bad_state_ex", sizeof("_bad_state_ex") - 1, 0);
  602. func = zend_std_get_method(object, tmp, NULL);
  603. zend_string_release_ex(tmp, 0);
  604. return func;
  605. }
  606. return zend_std_get_method(object, method, key);
  607. }
  608. /* }}} */
  609. #define DIT_CTOR_FLAGS 0x00000001
  610. #define DIT_CTOR_GLOB 0x00000002
  611. void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, zend_long ctor_flags) /* {{{ */
  612. {
  613. spl_filesystem_object *intern;
  614. zend_string *path;
  615. int parsed;
  616. zend_long flags = (ctor_flags & ~DIT_CTOR_FLAGS);
  617. zend_error_handling error_handling;
  618. if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_FLAGS)) {
  619. flags |= SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO;
  620. parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &path, &flags);
  621. } else {
  622. flags |= SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_SELF;
  623. parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "P", &path);
  624. }
  625. if (parsed == FAILURE) {
  626. RETURN_THROWS();
  627. }
  628. if (ZSTR_LEN(path) == 0) {
  629. zend_argument_value_error(1, "cannot be empty");
  630. RETURN_THROWS();
  631. }
  632. intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  633. if (intern->path) {
  634. /* object is already initialized */
  635. zend_throw_error(NULL, "Directory object is already initialized");
  636. RETURN_THROWS();
  637. }
  638. intern->flags = flags;
  639. /* spl_filesystem_dir_open() may emit an E_WARNING */
  640. zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);
  641. #ifdef HAVE_GLOB
  642. if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_GLOB) && memcmp(ZSTR_VAL(path), "glob://", sizeof("glob://")-1) != 0) {
  643. path = zend_strpprintf(0, "glob://%s", ZSTR_VAL(path));
  644. spl_filesystem_dir_open(intern, path);
  645. zend_string_release(path);
  646. } else
  647. #endif
  648. {
  649. spl_filesystem_dir_open(intern, path);
  650. }
  651. zend_restore_error_handling(&error_handling);
  652. intern->u.dir.is_recursive = instanceof_function(intern->std.ce, spl_ce_RecursiveDirectoryIterator) ? 1 : 0;
  653. }
  654. /* }}} */
  655. /* {{{ Cronstructs a new dir iterator from a path. */
  656. PHP_METHOD(DirectoryIterator, __construct)
  657. {
  658. spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  659. }
  660. /* }}} */
  661. /* {{{ Rewind dir back to the start */
  662. PHP_METHOD(DirectoryIterator, rewind)
  663. {
  664. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  665. if (zend_parse_parameters_none() == FAILURE) {
  666. RETURN_THROWS();
  667. }
  668. CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern);
  669. intern->u.dir.index = 0;
  670. php_stream_rewinddir(intern->u.dir.dirp);
  671. spl_filesystem_dir_read(intern);
  672. }
  673. /* }}} */
  674. /* {{{ Return current dir entry */
  675. PHP_METHOD(DirectoryIterator, key)
  676. {
  677. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  678. if (zend_parse_parameters_none() == FAILURE) {
  679. RETURN_THROWS();
  680. }
  681. CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern);
  682. RETURN_LONG(intern->u.dir.index);
  683. }
  684. /* }}} */
  685. /* {{{ Return this (needed for Iterator interface) */
  686. PHP_METHOD(DirectoryIterator, current)
  687. {
  688. if (zend_parse_parameters_none() == FAILURE) {
  689. RETURN_THROWS();
  690. }
  691. CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(Z_SPLFILESYSTEM_P(ZEND_THIS));
  692. RETURN_OBJ_COPY(Z_OBJ_P(ZEND_THIS));
  693. }
  694. /* }}} */
  695. /* {{{ Move to next entry */
  696. PHP_METHOD(DirectoryIterator, next)
  697. {
  698. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  699. int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
  700. if (zend_parse_parameters_none() == FAILURE) {
  701. RETURN_THROWS();
  702. }
  703. CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern);
  704. intern->u.dir.index++;
  705. do {
  706. spl_filesystem_dir_read(intern);
  707. } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
  708. if (intern->file_name) {
  709. zend_string_release(intern->file_name);
  710. intern->file_name = NULL;
  711. }
  712. }
  713. /* }}} */
  714. /* {{{ Seek to the given position */
  715. PHP_METHOD(DirectoryIterator, seek)
  716. {
  717. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  718. zval retval;
  719. zend_long pos;
  720. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &pos) == FAILURE) {
  721. RETURN_THROWS();
  722. }
  723. CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern);
  724. if (intern->u.dir.index > pos) {
  725. /* we first rewind */
  726. zend_call_method_with_0_params(Z_OBJ_P(ZEND_THIS), Z_OBJCE_P(ZEND_THIS), &intern->u.dir.func_rewind, "rewind", NULL);
  727. }
  728. while (intern->u.dir.index < pos) {
  729. int valid = 0;
  730. zend_call_method_with_0_params(Z_OBJ_P(ZEND_THIS), Z_OBJCE_P(ZEND_THIS), &intern->u.dir.func_valid, "valid", &retval);
  731. valid = zend_is_true(&retval);
  732. zval_ptr_dtor(&retval);
  733. if (!valid) {
  734. zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Seek position " ZEND_LONG_FMT " is out of range", pos);
  735. RETURN_THROWS();
  736. }
  737. zend_call_method_with_0_params(Z_OBJ_P(ZEND_THIS), Z_OBJCE_P(ZEND_THIS), &intern->u.dir.func_next, "next", NULL);
  738. }
  739. } /* }}} */
  740. /* {{{ Check whether dir contains more entries */
  741. PHP_METHOD(DirectoryIterator, valid)
  742. {
  743. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  744. if (zend_parse_parameters_none() == FAILURE) {
  745. RETURN_THROWS();
  746. }
  747. CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern);
  748. RETURN_BOOL(intern->u.dir.entry.d_name[0] != '\0');
  749. }
  750. /* }}} */
  751. /* {{{ Return the path */
  752. PHP_METHOD(SplFileInfo, getPath)
  753. {
  754. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  755. char *path;
  756. size_t path_len;
  757. if (zend_parse_parameters_none() == FAILURE) {
  758. RETURN_THROWS();
  759. }
  760. path = spl_filesystem_object_get_path(intern, &path_len);
  761. if (path) {
  762. RETURN_STRINGL(path, path_len);
  763. } else {
  764. RETURN_EMPTY_STRING();
  765. }
  766. }
  767. /* }}} */
  768. /* {{{ Return filename only */
  769. PHP_METHOD(SplFileInfo, getFilename)
  770. {
  771. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  772. size_t path_len;
  773. if (zend_parse_parameters_none() == FAILURE) {
  774. RETURN_THROWS();
  775. }
  776. if (!intern->file_name) {
  777. zend_throw_error(NULL, "Object not initialized");
  778. RETURN_THROWS();
  779. }
  780. spl_filesystem_object_get_path(intern, &path_len);
  781. if (path_len && path_len < ZSTR_LEN(intern->file_name)) {
  782. RETURN_STRINGL(ZSTR_VAL(intern->file_name) + path_len + 1, ZSTR_LEN(intern->file_name) - (path_len + 1));
  783. } else {
  784. RETURN_STR_COPY(intern->file_name);
  785. }
  786. }
  787. /* }}} */
  788. /* {{{ Return filename of current dir entry */
  789. PHP_METHOD(DirectoryIterator, getFilename)
  790. {
  791. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  792. if (zend_parse_parameters_none() == FAILURE) {
  793. RETURN_THROWS();
  794. }
  795. CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern);
  796. RETURN_STRING(intern->u.dir.entry.d_name);
  797. }
  798. /* }}} */
  799. /* {{{ Returns file extension component of path */
  800. PHP_METHOD(SplFileInfo, getExtension)
  801. {
  802. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  803. char *fname = NULL;
  804. const char *p;
  805. size_t flen;
  806. size_t path_len;
  807. size_t idx;
  808. zend_string *ret;
  809. if (zend_parse_parameters_none() == FAILURE) {
  810. RETURN_THROWS();
  811. }
  812. if (!intern->file_name) {
  813. zend_throw_error(NULL, "Object not initialized");
  814. RETURN_THROWS();
  815. }
  816. spl_filesystem_object_get_path(intern, &path_len);
  817. if (path_len && path_len < ZSTR_LEN(intern->file_name)) {
  818. fname = ZSTR_VAL(intern->file_name) + path_len + 1;
  819. flen = ZSTR_LEN(intern->file_name) - (path_len + 1);
  820. } else {
  821. fname = ZSTR_VAL(intern->file_name);
  822. flen = ZSTR_LEN(intern->file_name);
  823. }
  824. ret = php_basename(fname, flen, NULL, 0);
  825. p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
  826. if (p) {
  827. idx = p - ZSTR_VAL(ret);
  828. RETVAL_STRINGL(ZSTR_VAL(ret) + idx + 1, ZSTR_LEN(ret) - idx - 1);
  829. zend_string_release_ex(ret, 0);
  830. return;
  831. } else {
  832. zend_string_release_ex(ret, 0);
  833. RETURN_EMPTY_STRING();
  834. }
  835. }
  836. /* }}}*/
  837. /* {{{ Returns the file extension component of path */
  838. PHP_METHOD(DirectoryIterator, getExtension)
  839. {
  840. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  841. const char *p;
  842. size_t idx;
  843. zend_string *fname;
  844. if (zend_parse_parameters_none() == FAILURE) {
  845. RETURN_THROWS();
  846. }
  847. CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern);
  848. fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), NULL, 0);
  849. p = zend_memrchr(ZSTR_VAL(fname), '.', ZSTR_LEN(fname));
  850. if (p) {
  851. idx = p - ZSTR_VAL(fname);
  852. RETVAL_STRINGL(ZSTR_VAL(fname) + idx + 1, ZSTR_LEN(fname) - idx - 1);
  853. zend_string_release_ex(fname, 0);
  854. } else {
  855. zend_string_release_ex(fname, 0);
  856. RETURN_EMPTY_STRING();
  857. }
  858. }
  859. /* }}} */
  860. /* {{{ Returns filename component of path */
  861. PHP_METHOD(SplFileInfo, getBasename)
  862. {
  863. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  864. char *fname, *suffix = 0;
  865. size_t flen;
  866. size_t slen = 0, path_len;
  867. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) {
  868. RETURN_THROWS();
  869. }
  870. if (!intern->file_name) {
  871. zend_throw_error(NULL, "Object not initialized");
  872. RETURN_THROWS();
  873. }
  874. spl_filesystem_object_get_path(intern, &path_len);
  875. if (path_len && path_len < ZSTR_LEN(intern->file_name)) {
  876. fname = ZSTR_VAL(intern->file_name) + path_len + 1;
  877. flen = ZSTR_LEN(intern->file_name) - (path_len + 1);
  878. } else {
  879. fname = ZSTR_VAL(intern->file_name);
  880. flen = ZSTR_LEN(intern->file_name);
  881. }
  882. RETURN_STR(php_basename(fname, flen, suffix, slen));
  883. }
  884. /* }}}*/
  885. /* {{{ Returns filename component of current dir entry */
  886. PHP_METHOD(DirectoryIterator, getBasename)
  887. {
  888. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  889. char *suffix = 0;
  890. size_t slen = 0;
  891. zend_string *fname;
  892. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) {
  893. RETURN_THROWS();
  894. }
  895. CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern);
  896. fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), suffix, slen);
  897. RETVAL_STR(fname);
  898. }
  899. /* }}} */
  900. /* {{{ Return path and filename */
  901. PHP_METHOD(SplFileInfo, getPathname)
  902. {
  903. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  904. zend_string *path;
  905. if (zend_parse_parameters_none() == FAILURE) {
  906. RETURN_THROWS();
  907. }
  908. path = spl_filesystem_object_get_pathname(intern);
  909. if (path) {
  910. RETURN_STR_COPY(path);
  911. } else {
  912. RETURN_EMPTY_STRING();
  913. }
  914. }
  915. /* }}} */
  916. /* {{{ Return getPathname() or getFilename() depending on flags */
  917. PHP_METHOD(FilesystemIterator, key)
  918. {
  919. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  920. if (zend_parse_parameters_none() == FAILURE) {
  921. RETURN_THROWS();
  922. }
  923. if (SPL_FILE_DIR_KEY(intern, SPL_FILE_DIR_KEY_AS_FILENAME)) {
  924. RETURN_STRING(intern->u.dir.entry.d_name);
  925. } else {
  926. if (spl_filesystem_object_get_file_name(intern) != SUCCESS) {
  927. RETURN_THROWS();
  928. }
  929. RETURN_STR_COPY(intern->file_name);
  930. }
  931. }
  932. /* }}} */
  933. /* {{{ Return getFilename(), getFileInfo() or $this depending on flags */
  934. PHP_METHOD(FilesystemIterator, current)
  935. {
  936. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  937. if (zend_parse_parameters_none() == FAILURE) {
  938. RETURN_THROWS();
  939. }
  940. if (SPL_FILE_DIR_CURRENT(intern, SPL_FILE_DIR_CURRENT_AS_PATHNAME)) {
  941. if (spl_filesystem_object_get_file_name(intern) != SUCCESS) {
  942. RETURN_THROWS();
  943. }
  944. RETURN_STR_COPY(intern->file_name);
  945. } else if (SPL_FILE_DIR_CURRENT(intern, SPL_FILE_DIR_CURRENT_AS_FILEINFO)) {
  946. if (spl_filesystem_object_get_file_name(intern) != SUCCESS) {
  947. RETURN_THROWS();
  948. }
  949. spl_filesystem_object_create_type(0, intern, SPL_FS_INFO, NULL, return_value);
  950. } else {
  951. RETURN_OBJ_COPY(Z_OBJ_P(ZEND_THIS));
  952. }
  953. }
  954. /* }}} */
  955. /* {{{ Returns true if current entry is '.' or '..' */
  956. PHP_METHOD(DirectoryIterator, isDot)
  957. {
  958. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  959. if (zend_parse_parameters_none() == FAILURE) {
  960. RETURN_THROWS();
  961. }
  962. CHECK_DIRECTORY_ITERATOR_IS_INITIALIZED(intern);
  963. RETURN_BOOL(spl_filesystem_is_dot(intern->u.dir.entry.d_name));
  964. }
  965. /* }}} */
  966. /* {{{ Cronstructs a new SplFileInfo from a path. */
  967. /* When the constructor gets called the object is already created
  968. by the engine, so we must only call 'additional' initializations.
  969. */
  970. PHP_METHOD(SplFileInfo, __construct)
  971. {
  972. spl_filesystem_object *intern;
  973. zend_string *path;
  974. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &path) == FAILURE) {
  975. RETURN_THROWS();
  976. }
  977. intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  978. spl_filesystem_info_set_filename(intern, path);
  979. /* intern->type = SPL_FS_INFO; already set */
  980. }
  981. /* }}} */
  982. /* {{{ FileInfoFunction */
  983. #define FileInfoFunction(func_name, func_num) \
  984. PHP_METHOD(SplFileInfo, func_name) \
  985. { \
  986. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); \
  987. zend_error_handling error_handling; \
  988. if (zend_parse_parameters_none() == FAILURE) { \
  989. RETURN_THROWS(); \
  990. } \
  991. if (spl_filesystem_object_get_file_name(intern) != SUCCESS) { \
  992. RETURN_THROWS(); \
  993. } \
  994. zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);\
  995. php_stat(intern->file_name, func_num, return_value); \
  996. zend_restore_error_handling(&error_handling); \
  997. }
  998. /* }}} */
  999. /* {{{ Get file permissions */
  1000. FileInfoFunction(getPerms, FS_PERMS)
  1001. /* }}} */
  1002. /* {{{ Get file inode */
  1003. FileInfoFunction(getInode, FS_INODE)
  1004. /* }}} */
  1005. /* {{{ Get file size */
  1006. FileInfoFunction(getSize, FS_SIZE)
  1007. /* }}} */
  1008. /* {{{ Get file owner */
  1009. FileInfoFunction(getOwner, FS_OWNER)
  1010. /* }}} */
  1011. /* {{{ Get file group */
  1012. FileInfoFunction(getGroup, FS_GROUP)
  1013. /* }}} */
  1014. /* {{{ Get last access time of file */
  1015. FileInfoFunction(getATime, FS_ATIME)
  1016. /* }}} */
  1017. /* {{{ Get last modification time of file */
  1018. FileInfoFunction(getMTime, FS_MTIME)
  1019. /* }}} */
  1020. /* {{{ Get inode modification time of file */
  1021. FileInfoFunction(getCTime, FS_CTIME)
  1022. /* }}} */
  1023. /* {{{ Get file type */
  1024. FileInfoFunction(getType, FS_TYPE)
  1025. /* }}} */
  1026. /* {{{ Returns true if file can be written */
  1027. FileInfoFunction(isWritable, FS_IS_W)
  1028. /* }}} */
  1029. /* {{{ Returns true if file can be read */
  1030. FileInfoFunction(isReadable, FS_IS_R)
  1031. /* }}} */
  1032. /* {{{ Returns true if file is executable */
  1033. FileInfoFunction(isExecutable, FS_IS_X)
  1034. /* }}} */
  1035. /* {{{ Returns true if file is a regular file */
  1036. FileInfoFunction(isFile, FS_IS_FILE)
  1037. /* }}} */
  1038. /* {{{ Returns true if file is directory */
  1039. FileInfoFunction(isDir, FS_IS_DIR)
  1040. /* }}} */
  1041. /* {{{ Returns true if file is symbolic link */
  1042. FileInfoFunction(isLink, FS_IS_LINK)
  1043. /* }}} */
  1044. /* {{{ Return the target of a symbolic link */
  1045. PHP_METHOD(SplFileInfo, getLinkTarget)
  1046. {
  1047. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1048. ssize_t ret;
  1049. char buff[MAXPATHLEN];
  1050. if (zend_parse_parameters_none() == FAILURE) {
  1051. RETURN_THROWS();
  1052. }
  1053. if (intern->file_name == NULL) {
  1054. if (spl_filesystem_object_get_file_name(intern) != SUCCESS) {
  1055. RETURN_THROWS();
  1056. }
  1057. }
  1058. #if defined(PHP_WIN32) || defined(HAVE_SYMLINK)
  1059. if (intern->file_name == NULL) {
  1060. zend_value_error("Filename cannot be empty");
  1061. RETURN_THROWS();
  1062. }
  1063. if (!IS_ABSOLUTE_PATH(ZSTR_VAL(intern->file_name), ZSTR_LEN(intern->file_name))) {
  1064. char expanded_path[MAXPATHLEN];
  1065. if (!expand_filepath_with_mode(ZSTR_VAL(intern->file_name), expanded_path, NULL, 0, CWD_EXPAND )) {
  1066. php_error_docref(NULL, E_WARNING, "No such file or directory");
  1067. RETURN_FALSE;
  1068. }
  1069. ret = php_sys_readlink(expanded_path, buff, MAXPATHLEN - 1);
  1070. } else {
  1071. ret = php_sys_readlink(ZSTR_VAL(intern->file_name), buff, MAXPATHLEN-1);
  1072. }
  1073. #else
  1074. ret = -1; /* always fail if not implemented */
  1075. #endif
  1076. if (ret == -1) {
  1077. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Unable to read link %s, error: %s", ZSTR_VAL(intern->file_name), strerror(errno));
  1078. RETVAL_FALSE;
  1079. } else {
  1080. /* Append NULL to the end of the string */
  1081. buff[ret] = '\0';
  1082. RETVAL_STRINGL(buff, ret);
  1083. }
  1084. }
  1085. /* }}} */
  1086. /* {{{ Return the resolved path */
  1087. PHP_METHOD(SplFileInfo, getRealPath)
  1088. {
  1089. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1090. char buff[MAXPATHLEN];
  1091. char *filename;
  1092. if (zend_parse_parameters_none() == FAILURE) {
  1093. RETURN_THROWS();
  1094. }
  1095. if (intern->type == SPL_FS_DIR && !intern->file_name && intern->u.dir.entry.d_name[0]) {
  1096. if (spl_filesystem_object_get_file_name(intern) != SUCCESS) {
  1097. RETURN_THROWS();
  1098. }
  1099. }
  1100. if (intern->orig_path) {
  1101. filename = ZSTR_VAL(intern->orig_path);
  1102. } else {
  1103. filename = intern->file_name ? ZSTR_VAL(intern->file_name) : NULL;
  1104. }
  1105. if (filename && VCWD_REALPATH(filename, buff)) {
  1106. #ifdef ZTS
  1107. if (VCWD_ACCESS(buff, F_OK)) {
  1108. RETVAL_FALSE;
  1109. } else
  1110. #endif
  1111. RETVAL_STRING(buff);
  1112. } else {
  1113. RETVAL_FALSE;
  1114. }
  1115. }
  1116. /* }}} */
  1117. /* {{{ Open the current file */
  1118. PHP_METHOD(SplFileInfo, openFile)
  1119. {
  1120. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1121. spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_FILE, NULL, return_value);
  1122. }
  1123. /* }}} */
  1124. /* {{{ Class to use in openFile() */
  1125. PHP_METHOD(SplFileInfo, setFileClass)
  1126. {
  1127. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1128. zend_class_entry *ce = spl_ce_SplFileObject;
  1129. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == FAILURE) {
  1130. RETURN_THROWS();
  1131. }
  1132. intern->file_class = ce;
  1133. }
  1134. /* }}} */
  1135. /* {{{ Class to use in getFileInfo(), getPathInfo() */
  1136. PHP_METHOD(SplFileInfo, setInfoClass)
  1137. {
  1138. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1139. zend_class_entry *ce = spl_ce_SplFileInfo;
  1140. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == FAILURE) {
  1141. RETURN_THROWS();
  1142. }
  1143. intern->info_class = ce;
  1144. }
  1145. /* }}} */
  1146. /* {{{ Get/copy file info */
  1147. PHP_METHOD(SplFileInfo, getFileInfo)
  1148. {
  1149. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1150. zend_class_entry *ce = intern->info_class;
  1151. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C!", &ce) == FAILURE) {
  1152. RETURN_THROWS();
  1153. }
  1154. spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_INFO, ce, return_value);
  1155. }
  1156. /* }}} */
  1157. /* {{{ Get/copy file info */
  1158. PHP_METHOD(SplFileInfo, getPathInfo)
  1159. {
  1160. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1161. zend_class_entry *ce = intern->info_class;
  1162. zend_string *path;
  1163. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C!", &ce) == FAILURE) {
  1164. RETURN_THROWS();
  1165. }
  1166. path = spl_filesystem_object_get_pathname(intern);
  1167. if (path && ZSTR_LEN(path)) {
  1168. zend_string *dpath = zend_string_init(ZSTR_VAL(path), ZSTR_LEN(path), 0);
  1169. ZSTR_LEN(dpath) = php_dirname(ZSTR_VAL(dpath), ZSTR_LEN(path));
  1170. spl_filesystem_object_create_info(intern, dpath, ce, return_value);
  1171. zend_string_release(dpath);
  1172. }
  1173. }
  1174. /* }}} */
  1175. /* {{{ */
  1176. PHP_METHOD(SplFileInfo, __debugInfo)
  1177. {
  1178. if (zend_parse_parameters_none() == FAILURE) {
  1179. return;
  1180. }
  1181. RETURN_ARR(spl_filesystem_object_get_debug_info(Z_OBJ_P(ZEND_THIS)));
  1182. } /* }}} */
  1183. /* {{{ */
  1184. PHP_METHOD(SplFileInfo, _bad_state_ex)
  1185. {
  1186. zend_throw_error(NULL, "The parent constructor was not called: the object is in an invalid state");
  1187. }
  1188. /* }}} */
  1189. /* {{{ Cronstructs a new dir iterator from a path. */
  1190. PHP_METHOD(FilesystemIterator, __construct)
  1191. {
  1192. spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS | SPL_FILE_DIR_SKIPDOTS);
  1193. }
  1194. /* }}} */
  1195. /* {{{ Rewind dir back to the start */
  1196. PHP_METHOD(FilesystemIterator, rewind)
  1197. {
  1198. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1199. int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
  1200. if (zend_parse_parameters_none() == FAILURE) {
  1201. RETURN_THROWS();
  1202. }
  1203. intern->u.dir.index = 0;
  1204. if (intern->u.dir.dirp) {
  1205. php_stream_rewinddir(intern->u.dir.dirp);
  1206. }
  1207. do {
  1208. spl_filesystem_dir_read(intern);
  1209. } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
  1210. }
  1211. /* }}} */
  1212. /* {{{ Get handling flags */
  1213. PHP_METHOD(FilesystemIterator, getFlags)
  1214. {
  1215. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1216. if (zend_parse_parameters_none() == FAILURE) {
  1217. RETURN_THROWS();
  1218. }
  1219. RETURN_LONG(intern->flags & (SPL_FILE_DIR_KEY_MODE_MASK | SPL_FILE_DIR_CURRENT_MODE_MASK | SPL_FILE_DIR_OTHERS_MASK));
  1220. } /* }}} */
  1221. /* {{{ Set handling flags */
  1222. PHP_METHOD(FilesystemIterator, setFlags)
  1223. {
  1224. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1225. zend_long flags;
  1226. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &flags) == FAILURE) {
  1227. RETURN_THROWS();
  1228. }
  1229. intern->flags &= ~(SPL_FILE_DIR_KEY_MODE_MASK|SPL_FILE_DIR_CURRENT_MODE_MASK|SPL_FILE_DIR_OTHERS_MASK);
  1230. intern->flags |= ((SPL_FILE_DIR_KEY_MODE_MASK|SPL_FILE_DIR_CURRENT_MODE_MASK|SPL_FILE_DIR_OTHERS_MASK) & flags);
  1231. } /* }}} */
  1232. /* {{{ Returns whether current entry is a directory and not '.' or '..' */
  1233. PHP_METHOD(RecursiveDirectoryIterator, hasChildren)
  1234. {
  1235. bool allow_links = 0;
  1236. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1237. ZEND_PARSE_PARAMETERS_START(0, 1)
  1238. Z_PARAM_OPTIONAL
  1239. Z_PARAM_BOOL(allow_links)
  1240. ZEND_PARSE_PARAMETERS_END();
  1241. if (spl_filesystem_is_invalid_or_dot(intern->u.dir.entry.d_name)) {
  1242. RETURN_FALSE;
  1243. } else {
  1244. if (spl_filesystem_object_get_file_name(intern) != SUCCESS) {
  1245. RETURN_THROWS();
  1246. }
  1247. php_stat(intern->file_name, FS_LPERMS, return_value);
  1248. if (Z_TYPE_P(return_value) == IS_FALSE) {
  1249. return;
  1250. } else if (!S_ISLNK(Z_LVAL_P(return_value))) {
  1251. RETURN_BOOL(S_ISDIR(Z_LVAL_P(return_value)));
  1252. } else {
  1253. if (!allow_links
  1254. && !(intern->flags & SPL_FILE_DIR_FOLLOW_SYMLINKS)) {
  1255. RETURN_FALSE;
  1256. }
  1257. php_stat(intern->file_name, FS_IS_DIR, return_value);
  1258. }
  1259. }
  1260. }
  1261. /* }}} */
  1262. /* {{{ Returns an iterator for the current entry if it is a directory */
  1263. PHP_METHOD(RecursiveDirectoryIterator, getChildren)
  1264. {
  1265. zval zpath, zflags;
  1266. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1267. spl_filesystem_object *subdir;
  1268. char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
  1269. if (zend_parse_parameters_none() == FAILURE) {
  1270. RETURN_THROWS();
  1271. }
  1272. if (spl_filesystem_object_get_file_name(intern) != SUCCESS) {
  1273. RETURN_THROWS();
  1274. }
  1275. ZVAL_LONG(&zflags, intern->flags);
  1276. ZVAL_STR_COPY(&zpath, intern->file_name);
  1277. spl_instantiate_arg_ex2(Z_OBJCE_P(ZEND_THIS), return_value, &zpath, &zflags);
  1278. zval_ptr_dtor(&zpath);
  1279. subdir = Z_SPLFILESYSTEM_P(return_value);
  1280. if (subdir) {
  1281. size_t name_len = strlen(intern->u.dir.entry.d_name);
  1282. if (intern->u.dir.sub_path && ZSTR_LEN(intern->u.dir.sub_path)) {
  1283. zend_string *sub_path = zend_string_alloc(ZSTR_LEN(intern->u.dir.sub_path) + 1 + name_len, 0);
  1284. memcpy(ZSTR_VAL(sub_path), ZSTR_VAL(intern->u.dir.sub_path), ZSTR_LEN(intern->u.dir.sub_path));
  1285. ZSTR_VAL(sub_path)[ZSTR_LEN(intern->u.dir.sub_path)] = slash;
  1286. memcpy(ZSTR_VAL(sub_path) + ZSTR_LEN(intern->u.dir.sub_path) + 1, intern->u.dir.entry.d_name, name_len);
  1287. ZSTR_VAL(sub_path)[ZSTR_LEN(intern->u.dir.sub_path) + 1 + name_len] = 0;
  1288. subdir->u.dir.sub_path = sub_path;
  1289. } else {
  1290. subdir->u.dir.sub_path = zend_string_init(intern->u.dir.entry.d_name, name_len, 0);
  1291. }
  1292. subdir->info_class = intern->info_class;
  1293. subdir->file_class = intern->file_class;
  1294. subdir->oth = intern->oth;
  1295. }
  1296. }
  1297. /* }}} */
  1298. /* {{{ Get sub path */
  1299. PHP_METHOD(RecursiveDirectoryIterator, getSubPath)
  1300. {
  1301. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1302. if (zend_parse_parameters_none() == FAILURE) {
  1303. RETURN_THROWS();
  1304. }
  1305. if (intern->u.dir.sub_path) {
  1306. RETURN_STR_COPY(intern->u.dir.sub_path);
  1307. } else {
  1308. RETURN_EMPTY_STRING();
  1309. }
  1310. }
  1311. /* }}} */
  1312. /* {{{ Get sub path and file name */
  1313. PHP_METHOD(RecursiveDirectoryIterator, getSubPathname)
  1314. {
  1315. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1316. char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
  1317. if (zend_parse_parameters_none() == FAILURE) {
  1318. RETURN_THROWS();
  1319. }
  1320. if (intern->u.dir.sub_path) {
  1321. RETURN_NEW_STR(strpprintf(0, "%s%c%s", ZSTR_VAL(intern->u.dir.sub_path), slash, intern->u.dir.entry.d_name));
  1322. } else {
  1323. RETURN_STRING(intern->u.dir.entry.d_name);
  1324. }
  1325. }
  1326. /* }}} */
  1327. /* {{{ Cronstructs a new dir iterator from a path. */
  1328. PHP_METHOD(RecursiveDirectoryIterator, __construct)
  1329. {
  1330. spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS);
  1331. }
  1332. /* }}} */
  1333. #ifdef HAVE_GLOB
  1334. /* {{{ Cronstructs a new dir iterator from a glob expression (no glob:// needed). */
  1335. PHP_METHOD(GlobIterator, __construct)
  1336. {
  1337. spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS|DIT_CTOR_GLOB);
  1338. }
  1339. /* }}} */
  1340. /* {{{ Return the number of directories and files found by globbing */
  1341. PHP_METHOD(GlobIterator, count)
  1342. {
  1343. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1344. if (zend_parse_parameters_none() == FAILURE) {
  1345. RETURN_THROWS();
  1346. }
  1347. if (intern->u.dir.dirp && php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
  1348. RETURN_LONG(php_glob_stream_get_count(intern->u.dir.dirp, NULL));
  1349. } else {
  1350. /* should not happen */
  1351. // TODO ZEND_ASSERT ?
  1352. php_error_docref(NULL, E_ERROR, "GlobIterator lost glob state");
  1353. }
  1354. }
  1355. /* }}} */
  1356. #endif /* HAVE_GLOB */
  1357. /* {{{ forward declarations to the iterator handlers */
  1358. static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter);
  1359. static int spl_filesystem_dir_it_valid(zend_object_iterator *iter);
  1360. static zval *spl_filesystem_dir_it_current_data(zend_object_iterator *iter);
  1361. static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key);
  1362. static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter);
  1363. static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter);
  1364. /* iterator handler table */
  1365. static const zend_object_iterator_funcs spl_filesystem_dir_it_funcs = {
  1366. spl_filesystem_dir_it_dtor,
  1367. spl_filesystem_dir_it_valid,
  1368. spl_filesystem_dir_it_current_data,
  1369. spl_filesystem_dir_it_current_key,
  1370. spl_filesystem_dir_it_move_forward,
  1371. spl_filesystem_dir_it_rewind,
  1372. NULL,
  1373. NULL, /* get_gc */
  1374. };
  1375. /* }}} */
  1376. /* {{{ spl_ce_dir_get_iterator */
  1377. zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
  1378. {
  1379. spl_filesystem_iterator *iterator;
  1380. spl_filesystem_object *dir_object;
  1381. if (by_ref) {
  1382. zend_throw_error(NULL, "An iterator cannot be used with foreach by reference");
  1383. return NULL;
  1384. }
  1385. dir_object = Z_SPLFILESYSTEM_P(object);
  1386. iterator = spl_filesystem_object_to_iterator(dir_object);
  1387. ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object));
  1388. iterator->intern.funcs = &spl_filesystem_dir_it_funcs;
  1389. /* ->current must be initialized; rewind doesn't set it and valid
  1390. * doesn't check whether it's set */
  1391. iterator->current = *object;
  1392. return &iterator->intern;
  1393. }
  1394. /* }}} */
  1395. /* {{{ spl_filesystem_dir_it_dtor */
  1396. static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter)
  1397. {
  1398. spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
  1399. zval_ptr_dtor(&iterator->intern.data);
  1400. }
  1401. /* }}} */
  1402. /* {{{ spl_filesystem_dir_it_valid */
  1403. static int spl_filesystem_dir_it_valid(zend_object_iterator *iter)
  1404. {
  1405. spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
  1406. return object->u.dir.entry.d_name[0] != '\0' ? SUCCESS : FAILURE;
  1407. }
  1408. /* }}} */
  1409. /* {{{ spl_filesystem_dir_it_current_data */
  1410. static zval *spl_filesystem_dir_it_current_data(zend_object_iterator *iter)
  1411. {
  1412. spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
  1413. return &iterator->current;
  1414. }
  1415. /* }}} */
  1416. /* {{{ spl_filesystem_dir_it_current_key */
  1417. static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key)
  1418. {
  1419. spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
  1420. ZVAL_LONG(key, object->u.dir.index);
  1421. }
  1422. /* }}} */
  1423. /* {{{ spl_filesystem_dir_it_move_forward */
  1424. static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter)
  1425. {
  1426. spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
  1427. object->u.dir.index++;
  1428. spl_filesystem_dir_read(object);
  1429. if (object->file_name) {
  1430. zend_string_release(object->file_name);
  1431. object->file_name = NULL;
  1432. }
  1433. }
  1434. /* }}} */
  1435. /* {{{ spl_filesystem_dir_it_rewind */
  1436. static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter)
  1437. {
  1438. spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
  1439. object->u.dir.index = 0;
  1440. if (object->u.dir.dirp) {
  1441. php_stream_rewinddir(object->u.dir.dirp);
  1442. }
  1443. spl_filesystem_dir_read(object);
  1444. }
  1445. /* }}} */
  1446. /* {{{ spl_filesystem_tree_it_dtor */
  1447. static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter)
  1448. {
  1449. spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
  1450. zval_ptr_dtor(&iterator->intern.data);
  1451. zval_ptr_dtor(&iterator->current);
  1452. }
  1453. /* }}} */
  1454. /* {{{ spl_filesystem_tree_it_current_data */
  1455. static zval *spl_filesystem_tree_it_current_data(zend_object_iterator *iter)
  1456. {
  1457. spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
  1458. spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator);
  1459. if (SPL_FILE_DIR_CURRENT(object, SPL_FILE_DIR_CURRENT_AS_PATHNAME)) {
  1460. if (Z_ISUNDEF(iterator->current)) {
  1461. if (spl_filesystem_object_get_file_name(object) != SUCCESS) {
  1462. return NULL;
  1463. }
  1464. ZVAL_STR_COPY(&iterator->current, object->file_name);
  1465. }
  1466. return &iterator->current;
  1467. } else if (SPL_FILE_DIR_CURRENT(object, SPL_FILE_DIR_CURRENT_AS_FILEINFO)) {
  1468. if (Z_ISUNDEF(iterator->current)) {
  1469. if (spl_filesystem_object_get_file_name(object) != SUCCESS) {
  1470. return NULL;
  1471. }
  1472. spl_filesystem_object_create_type(0, object, SPL_FS_INFO, NULL, &iterator->current);
  1473. }
  1474. return &iterator->current;
  1475. }

Large files files are truncated, but you can click here to view the full file