]> granicus.if.org Git - php/commitdiff
Fix FilesystemIterator with ./..
authorEtienne Kneuss <colder@php.net>
Fri, 16 May 2008 13:22:02 +0000 (13:22 +0000)
committerEtienne Kneuss <colder@php.net>
Fri, 16 May 2008 13:22:02 +0000 (13:22 +0000)
ext/spl/spl_directory.c
ext/spl/spl_directory.h
ext/spl/tests/dit_004.phpt [new file with mode: 0644]
ext/spl/tests/dit_005.phpt [new file with mode: 0644]

index e44a0fe985eb91215fe0f0e75019a967c9eee625..d90c0ad0e1153e92f4c42d11071f55595710ec14 100755 (executable)
@@ -212,11 +212,18 @@ static int spl_filesystem_dir_read(spl_filesystem_object *intern TSRMLS_DC) /* {
 
 #define IS_SLASH_AT(type, zs, pos) (type == IS_UNICODE ? IS_U_SLASH(zs.u[pos]) : IS_SLASH(zs.s[pos]))
 
+static inline int spl_filesystem_is_dot(const char * d_name) /* {{{ */
+{
+       return !strcmp(d_name, ".") || !strcmp(d_name, "..");
+}
+/* }}} */
+
 /* {{{ spl_filesystem_dir_open */
 /* open a directory resource */
 static void spl_filesystem_dir_open(spl_filesystem_object* intern, zend_uchar type, zstr path, int path_len TSRMLS_DC)
 {
        int options = REPORT_ERRORS;
+       int skip_dots = intern->flags & SPL_FILE_DIR_SKIPDOTS;
 
 #if HELLY_0    
        if (php_stream_is(intern->u.dir.dirp, &php_glob_stream_ops)) {
@@ -240,7 +247,9 @@ static void spl_filesystem_dir_open(spl_filesystem_object* intern, zend_uchar ty
                /* throw exception: should've been already happened */
                intern->u.dir.entry.d_name[0] = '\0';
        } else {
-               spl_filesystem_dir_read(intern TSRMLS_CC);
+               do {
+                       spl_filesystem_dir_read(intern TSRMLS_CC);
+               } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
        }
 }
 /* }}} */
@@ -299,13 +308,18 @@ static zend_object_value spl_filesystem_object_clone(zval *zobject TSRMLS_DC)
        spl_filesystem_object *intern;
        spl_filesystem_object *source;
        int index;
+       int skip_dots;
 
        old_object = zend_objects_get_address(zobject TSRMLS_CC);
        source = (spl_filesystem_object*)old_object;
 
+       skip_dots = source->flags & SPL_FILE_DIR_SKIPDOTS;
+
        new_obj_val = spl_filesystem_object_new_ex(old_object->ce, &intern TSRMLS_CC);
        new_object = &intern->std;
 
+       intern->flags = source->flags;
+
        switch (source->type) {
        case SPL_FS_INFO:
                intern->_path_type = source->_path_type;
@@ -319,7 +333,9 @@ static zend_object_value spl_filesystem_object_clone(zval *zobject TSRMLS_DC)
                spl_filesystem_dir_open(intern, source->_path_type, source->_path, source->_path_len TSRMLS_CC);
                /* read until we hit the position in which we were before */
                for(index = 0; index < source->u.dir.index; ++index) {
-                       spl_filesystem_dir_read(intern TSRMLS_CC);
+                       do {
+                               spl_filesystem_dir_read(intern TSRMLS_CC);
+                       } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
                }
                intern->u.dir.index = index;
                break;
@@ -330,7 +346,6 @@ static zend_object_value spl_filesystem_object_clone(zval *zobject TSRMLS_DC)
        
        intern->file_class = source->file_class;
        intern->info_class = source->info_class;
-       intern->flags = source->flags;
        intern->oth = source->oth;
        intern->oth_handler = source->oth_handler;
 
@@ -514,12 +529,6 @@ static spl_filesystem_object * spl_filesystem_object_create_type(int ht, spl_fil
        return NULL;
 } /* }}} */
 
-static inline int spl_filesystem_is_dot(const char * d_name) /* {{{ */
-{
-       return !strcmp(d_name, ".") || !strcmp(d_name, "..");
-}
-/* }}} */
-
 static int spl_filesystem_is_invalid_or_dot(const char * d_name) /* {{{ */
 {
        return d_name[0] == '\0' || spl_filesystem_is_dot(d_name);
@@ -614,6 +623,11 @@ void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, int ctor_flag
                flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_SELF;
                parsed = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &path, &len, &path_type);
        }
+
+       if (ctor_flags & SPL_FILE_DIR_SKIPDOTS) {
+               flags |= SPL_FILE_DIR_SKIPDOTS;
+       }
+
        if (parsed == FAILURE) {
                php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
                return;
@@ -625,6 +639,8 @@ void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, int ctor_flag
        }
 
        intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       intern->flags = flags;
+
        if ((ctor_flags & DIT_CTOR_GLOB) && (
                (path_type == IS_STRING && strstr(path.s, "glob://") != path.s) ||
                (path_type == IS_UNICODE && u_strstr(path.u, u_glob) != path.u)
@@ -637,7 +653,6 @@ void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, int ctor_flag
        }
 
        intern->u.dir.is_recursive = instanceof_function(intern->std.ce, spl_ce_RecursiveDirectoryIterator TSRMLS_CC) ? 1 : 0;
-       intern->flags = flags;
 
        php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
 }
@@ -692,9 +707,12 @@ SPL_METHOD(DirectoryIterator, current)
 SPL_METHOD(DirectoryIterator, next)
 {
        spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       int skip_dots = intern->flags & SPL_FILE_DIR_SKIPDOTS;
 
        intern->u.dir.index++;
-       spl_filesystem_dir_read(intern TSRMLS_CC);
+       do {
+               spl_filesystem_dir_read(intern TSRMLS_CC);
+       } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
        if (intern->file_name.v) {
                efree(intern->file_name.v);
                intern->file_name = NULL_ZSTR;
@@ -1183,7 +1201,7 @@ SPL_METHOD(SplFileInfo, getPathInfo)
  Cronstructs a new dir iterator from a path. */
 SPL_METHOD(FilesystemIterator, __construct)
 {
-       spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS);
+       spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS | SPL_FILE_DIR_SKIPDOTS);
 }
 /* }}} */
 
@@ -1203,30 +1221,13 @@ SPL_METHOD(FilesystemIterator, rewind)
 }
 /* }}} */
 
-/* {{{ proto void FilesystemIterator::next() U
-   Move to next entry */
-SPL_METHOD(FilesystemIterator, next)
-{
-       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
-
-       intern->u.dir.index++;
-       do {
-               spl_filesystem_dir_read(intern TSRMLS_CC);
-       } while (spl_filesystem_is_dot(intern->u.dir.entry.d_name));
-       if (intern->file_name.v) {
-               efree(intern->file_name.v);
-               intern->file_name = NULL_ZSTR;
-       }
-}
-/* }}} */
-
 /* {{{ proto int FilesystemIterator::getFlags() U
    Get handling flags */
 SPL_METHOD(FilesystemIterator, getFlags)
 {
        spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_LONG(intern->flags);
+       RETURN_LONG(intern->flags & (SPL_FILE_DIR_KEY_MODE_MASK | SPL_FILE_DIR_CURRENT_MODE_MASK));
 } /* }}} */
 
 /* {{{ proto void FilesystemIterator::setFlags(long $flags) U
@@ -1743,7 +1744,7 @@ ZEND_END_ARG_INFO()
 static const zend_function_entry spl_FilesystemIterator_functions[] = {
        SPL_ME(FilesystemIterator, __construct,   arginfo_r_dir___construct, ZEND_ACC_PUBLIC)
        SPL_ME(FilesystemIterator, rewind,        NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(FilesystemIterator, next,          NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(DirectoryIterator, next,           NULL, ZEND_ACC_PUBLIC)
        SPL_ME(FilesystemIterator, key,           NULL, ZEND_ACC_PUBLIC)
        SPL_ME(FilesystemIterator, current,       NULL, ZEND_ACC_PUBLIC)
        SPL_ME(FilesystemIterator, getFlags,      NULL, ZEND_ACC_PUBLIC)
@@ -2180,7 +2181,7 @@ SPL_METHOD(SplFileObject, getFlags)
 {
        spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_LONG(intern->flags);
+       RETURN_LONG(intern->flags & SPL_FILE_OBJECT_MASK);
 } /* }}} */
 
 /* {{{ proto void SplFileObject::setMaxLineLen(int max_len) U
index 2d3d1a674ec3f85ecbc04a1a5427e8423f54d3cf..b9ae205089a95dd21dbc0b086e034e10853c1b74 100755 (executable)
@@ -117,6 +117,7 @@ static inline spl_filesystem_object* spl_filesystem_iterator_to_object(spl_files
 #define SPL_FILE_OBJECT_READ_AHEAD         0x00000002 /* read on rewind/next */
 #define SPL_FILE_OBJECT_SKIP_EMPTY         0x00000006 /* skip empty lines */
 #define SPL_FILE_OBJECT_READ_CSV           0x00000008 /* read via fgetcsv */
+#define SPL_FILE_OBJECT_MASK               0x0000000F /* mask */
 
 #define SPL_FILE_DIR_CURRENT_AS_FILEINFO   0x00000000 /* make RecursiveDirectoryTree::current() return SplFileInfo */
 #define SPL_FILE_DIR_CURRENT_AS_SELF       0x00000010 /* make RecursiveDirectoryTree::current() return getSelf() */
@@ -129,6 +130,9 @@ static inline spl_filesystem_object* spl_filesystem_iterator_to_object(spl_files
 #define SPL_FILE_DIR_KEY_MODE_MASK         0x00000F00 /* mask RecursiveDirectoryTree::key() */
 #define SPL_FILE_DIR_KEY(intern,mode)      ((intern->flags&SPL_FILE_DIR_KEY_MODE_MASK)==mode)
 
+
+#define SPL_FILE_DIR_SKIPDOTS              0x00001000 /* Tells whether it should skip dots or not */
+
 #endif /* SPL_DIRECTORY_H */
 
 /*
diff --git a/ext/spl/tests/dit_004.phpt b/ext/spl/tests/dit_004.phpt
new file mode 100644 (file)
index 0000000..704487f
--- /dev/null
@@ -0,0 +1,26 @@
+--TEST--
+SPL: DirectoryIterator and clone
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+$a = new DirectoryIterator(__DIR__);
+$b = clone $a;
+var_dump((string)$b == (string)$a);
+var_dump($a->key(), $b->key());
+$a->next();
+$a->next();
+$a->next();
+$c = clone $a;
+var_dump((string)$c == (string)$a);
+var_dump($a->key(), $c->key());
+?>
+===DONE===
+--EXPECTF--
+bool(true)
+int(0)
+int(0)
+bool(true)
+int(3)
+int(3)
+===DONE===
diff --git a/ext/spl/tests/dit_005.phpt b/ext/spl/tests/dit_005.phpt
new file mode 100644 (file)
index 0000000..76f1214
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+SPL: FilesystemIterator and clone
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+$a = new FileSystemIterator(__DIR__);
+$b = clone $a;
+var_dump((string)$b == (string)$a);
+var_dump($a->key() == $b->key());
+$a->next();
+$a->next();
+$a->next();
+$c = clone $a;
+var_dump((string)$c == (string)$a);
+var_dump($a->key() == $c->key());
+?>
+===DONE===
+--EXPECTF--
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+===DONE===