]> granicus.if.org Git - php/commitdiff
- Add new class SplFileInfo
authorMarcus Boerger <helly@php.net>
Sat, 8 Oct 2005 15:55:04 +0000 (15:55 +0000)
committerMarcus Boerger <helly@php.net>
Sat, 8 Oct 2005 15:55:04 +0000 (15:55 +0000)
  . Make DirectoryIterator inherit it
  . Make SplFileObject inherit it

ext/spl/spl_directory.c
ext/spl/spl_directory.h

index 1af7706f899b3f3931e7a4d10895beba931e206d..c6ce47175c608ecd4a54c6baca93a6f62ec68d07 100755 (executable)
 static zend_object_handlers spl_ce_dir_handlers;
 
 /* decalre the class entry */
+PHPAPI zend_class_entry *spl_ce_SplFileInfo;
 PHPAPI zend_class_entry *spl_ce_DirectoryIterator;
 PHPAPI zend_class_entry *spl_ce_RecursiveDirectoryIterator;
 PHPAPI zend_class_entry *spl_ce_SplFileObject;
 
-static zend_object_value spl_file_object_new_ex(zend_class_entry *class_type, spl_file_object **obj TSRMLS_DC);
-static int spl_file_object_open(spl_file_object *intern, int use_include_path, int silent TSRMLS_DC);
+static void spl_filesystem_file_free_line(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */
+{
+       if (intern->u.file.current_line) {
+               efree(intern->u.file.current_line);
+               intern->u.file.current_line = NULL;
+       }
+       if (intern->u.file.current_zval) {
+               zval_ptr_dtor(&intern->u.file.current_zval);
+               intern->u.file.current_zval = NULL;
+       }
+} /* }}} */
 
-/* {{{ spl_ce_dir_object_free_storage */
-/* close all resources and the memory allocated for the object */
-static void spl_ce_dir_object_free_storage(void *object TSRMLS_DC)
+static void spl_filesystem_object_free_storage(void *object TSRMLS_DC) /* {{{ */
 {
-       spl_ce_dir_object *intern = (spl_ce_dir_object *)object;
+       spl_filesystem_object *intern = (spl_filesystem_object*)object;
 
        zend_hash_destroy(intern->std.properties);
        FREE_HASHTABLE(intern->std.properties);
@@ -67,19 +75,39 @@ static void spl_ce_dir_object_free_storage(void *object TSRMLS_DC)
        if (intern->path) {
                efree(intern->path);
        }
-       if (intern->dirp) {
-               php_stream_close(intern->dirp);
-       }
-       if (intern->path_name) {
-               efree(intern->path_name);
+       if (intern->file_name) {
+               efree(intern->file_name);
        }
-       if (intern->sub_path) {
-               efree(intern->sub_path);
+       switch(intern->type) {
+       case SPL_FS_INFO:
+               break;
+       case SPL_FS_DIR:
+               if (intern->u.dir.dirp) {
+                       php_stream_close(intern->u.dir.dirp);
+               }
+               if (intern->u.dir.sub_path) {
+                       efree(intern->u.dir.sub_path);
+               }               
+               break;
+       case SPL_FS_FILE:
+               if (intern->u.file.stream) {
+                       if (intern->u.file.zcontext) {
+/*                             zend_list_delref(Z_RESVAL_P(intern->zcontext));*/
+                       }
+                       if (!intern->u.file.stream->is_persistent) {
+                               php_stream_free(intern->u.file.stream, PHP_STREAM_FREE_CLOSE);
+                       } else {
+                               php_stream_free(intern->u.file.stream, PHP_STREAM_FREE_CLOSE_PERSISTENT);
+                       }
+                       if (intern->u.file.open_mode) {
+                               efree(intern->u.file.open_mode);
+                       }
+               }
+               spl_filesystem_file_free_line(intern TSRMLS_CC);
+               break;
        }
        efree(object);
-}
-/* }}} */
-
+} /* }}} */
 
 /* {{{ spl_ce_dir_object_new */
 /* creates the object by 
@@ -92,82 +120,138 @@ static void spl_ce_dir_object_free_storage(void *object TSRMLS_DC)
    - clone
    - new
  */
-static zend_object_value spl_ce_dir_object_new_ex(zend_class_entry *class_type, spl_ce_dir_object **obj TSRMLS_DC)
+static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_type, spl_filesystem_object **obj TSRMLS_DC)
 {
        zend_object_value retval;
-       spl_ce_dir_object *intern;
+       spl_filesystem_object *intern;
        zval *tmp;
 
-       intern = emalloc(sizeof(spl_ce_dir_object));
-       memset(intern, 0, sizeof(spl_ce_dir_object));
+       intern = emalloc(sizeof(spl_filesystem_object));
+       memset(intern, 0, sizeof(spl_filesystem_object));
        intern->std.ce = class_type;
+       /* intern->type = SPL_FS_INFO; done by set o */
        if (obj) *obj = intern;
 
        ALLOC_HASHTABLE(intern->std.properties);
        zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
        zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
 
-       retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_ce_dir_object_free_storage, NULL TSRMLS_CC);
+       retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_filesystem_object_free_storage, NULL TSRMLS_CC);
        retval.handlers = &spl_ce_dir_handlers;
        return retval;
 }
 /* }}} */
 
-
-/* {{{ spl_ce_dir_object_new */
-/* See spl_ce_dir_object_new_ex */
-static zend_object_value spl_ce_dir_object_new(zend_class_entry *class_type TSRMLS_DC)
+/* {{{ spl_filesystem_object_new */
+/* See spl_filesystem_object_new_ex */
+static zend_object_value spl_filesystem_object_new(zend_class_entry *class_type TSRMLS_DC)
 {
-       return spl_ce_dir_object_new_ex(class_type, NULL TSRMLS_CC);
+       return spl_filesystem_object_new_ex(class_type, NULL TSRMLS_CC);
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_open */
+static inline void spl_filesystem_object_get_file_name(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */
+{
+       if (!intern->file_name) {
+               switch (intern->type) {
+               case SPL_FS_INFO:
+               case SPL_FS_FILE:
+                       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Object not initialized");
+                       break;
+               case SPL_FS_DIR:
+                       intern->file_name_len = spprintf(&intern->file_name, 0, "%s/%s", intern->path, intern->u.dir.entry.d_name);
+                       break;
+               }
+       }
+} /* }}} */
+
+/* {{{ spl_filesystem_dir_open */
 /* open a directory resource */
-static void spl_ce_dir_open(spl_ce_dir_object* intern, char *path TSRMLS_DC)
+static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path TSRMLS_DC)
 {
-       int path_len = strlen(path);
-
-       intern->dirp = php_stream_opendir(path, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
+       intern->type = SPL_FS_DIR;
+       intern->path_len = strlen(path);
+       intern->u.dir.dirp = php_stream_opendir(path, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
 
-       if (path_len && (path[path_len-1] == '/' || path[path_len-1] == '\\')) {
-               intern->path = estrndup(path, --path_len);
+       if (intern->path_len && (path[intern->path_len-1] == '/' || path[intern->path_len-1] == '\\')) {
+               intern->path = estrndup(path, --intern->path_len);
        } else {
-               intern->path = estrndup(path, path_len);
+               intern->path = estrndup(path, intern->path_len);
        }
-       intern->index = 0;
+       intern->u.dir.index = 0;
 
-       if (intern->dirp == NULL) {
+       if (intern->u.dir.dirp == NULL) {
                /* throw exception: should've been already happened */
-               intern->entry.d_name[0] = '\0';
+               intern->u.dir.entry.d_name[0] = '\0';
        } else {
-               if (!php_stream_readdir(intern->dirp, &intern->entry)) {
-                       intern->entry.d_name[0] = '\0';
+               if (!php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
+                       intern->u.dir.entry.d_name[0] = '\0';
                }
        }
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_object_clone */
+static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_include_path, int silent TSRMLS_DC) /* {{{ */
+{
+       intern->type = SPL_FS_FILE;
+       intern->u.file.context = php_stream_context_from_zval(intern->u.file.zcontext, 0);
+       intern->u.file.stream = php_stream_open_wrapper_ex(intern->file_name, intern->u.file.open_mode, (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, intern->u.file.context);
+
+       if (intern->u.file.stream == NULL) {
+               if (!EG(exception)) {
+                       zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_RuntimeException), 0 TSRMLS_CC, "Cannot open file %s", intern->file_name);
+               }
+               intern->file_name = NULL; /* until here it is not a copy */
+               intern->u.file.open_mode = NULL;
+               return FAILURE;
+       }
+
+       if (intern->u.file.zcontext) {
+               zend_list_addref(Z_RESVAL_P(intern->u.file.zcontext));
+       }
+
+       intern->file_name = estrndup(intern->file_name, intern->file_name_len);
+       intern->u.file.open_mode = estrndup(intern->u.file.open_mode, intern->u.file.open_mode_len);
+
+       /* avoid reference counting in debug mode, thus do it manually */
+       ZVAL_RESOURCE(&intern->u.file.zresource, php_stream_get_resource_id(intern->u.file.stream));
+       intern->u.file.zresource.refcount = 1;
+
+       zend_hash_find(&intern->std.ce->function_table, "getcurrentline", sizeof("getcurrentline"), (void **) &intern->u.file.func_getCurr);
+
+       return SUCCESS;
+} /* }}} */
+
+/* {{{ spl_filesystem_object_clone */
 /* Local zend_object_value creation (on stack)
    Load the 'other' object 
-   Create a new empty object (See spl_ce_dir_object_new_ex)
+   Create a new empty object (See spl_filesystem_object_new_ex)
    Open the directory
    Clone other members (properties)
  */
-static zend_object_value spl_ce_dir_object_clone(zval *zobject TSRMLS_DC)
+static zend_object_value spl_filesystem_object_clone(zval *zobject TSRMLS_DC)
 {
        zend_object_value new_obj_val;
        zend_object *old_object;
        zend_object *new_object;
        zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
-       spl_ce_dir_object *intern;
+       spl_filesystem_object *intern;
 
        old_object = zend_objects_get_address(zobject TSRMLS_CC);
-       new_obj_val = spl_ce_dir_object_new_ex(old_object->ce, &intern TSRMLS_CC);
+
+       new_obj_val = spl_filesystem_object_new_ex(old_object->ce, &intern TSRMLS_CC);
        new_object = &intern->std;
 
-       spl_ce_dir_open(intern, ((spl_ce_dir_object*)old_object)->path TSRMLS_CC);
+       switch(((spl_filesystem_object*)old_object)->type) {
+       case SPL_FS_INFO:
+               break;
+       case SPL_FS_DIR:
+               spl_filesystem_dir_open(intern, ((spl_filesystem_object*)old_object)->path TSRMLS_CC);
+               break;
+       case SPL_FS_FILE:
+               php_error_docref(NULL TSRMLS_CC, E_ERROR, "An object of class %v cannot be cloned", old_object->ce->name);
+               break;
+       }
 
        zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
 
@@ -186,8 +270,7 @@ static zend_object_value spl_ce_dir_object_clone(zval *zobject TSRMLS_DC)
  */
 SPL_METHOD(DirectoryIterator, __construct)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern;
+       spl_filesystem_object *intern;
        char *path;
        int len;
 
@@ -198,8 +281,8 @@ SPL_METHOD(DirectoryIterator, __construct)
                return;
        }
 
-       intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
-       spl_ce_dir_open(intern, path TSRMLS_CC);
+       intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_dir_open(intern, path TSRMLS_CC);
 
        php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
 }
@@ -209,15 +292,14 @@ SPL_METHOD(DirectoryIterator, __construct)
    Rewind dir back to the start */
 SPL_METHOD(DirectoryIterator, rewind)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       intern->index = 0;
-       if (intern->dirp) {
-               php_stream_rewinddir(intern->dirp);
+       intern->u.dir.index = 0;
+       if (intern->u.dir.dirp) {
+               php_stream_rewinddir(intern->u.dir.dirp);
        }
-       if (!intern->dirp || !php_stream_readdir(intern->dirp, &intern->entry)) {
-               intern->entry.d_name[0] = '\0';
+       if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
+               intern->u.dir.entry.d_name[0] = '\0';
        }
 }
 /* }}} */
@@ -226,11 +308,10 @@ SPL_METHOD(DirectoryIterator, rewind)
    Return current dir entry */
 SPL_METHOD(DirectoryIterator, key)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       if (intern->dirp) {
-               RETURN_LONG(intern->index);
+       if (intern->u.dir.dirp) {
+               RETURN_LONG(intern->u.dir.index);
        } else {
                RETURN_FALSE;
        }
@@ -249,16 +330,15 @@ SPL_METHOD(DirectoryIterator, current)
    Move to next entry */
 SPL_METHOD(DirectoryIterator, next)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       intern->index++;
-       if (!intern->dirp || !php_stream_readdir(intern->dirp, &intern->entry)) {
-               intern->entry.d_name[0] = '\0';
+       intern->u.dir.index++;
+       if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
+               intern->u.dir.entry.d_name[0] = '\0';
        }
-       if (intern->path_name) {
-               efree(intern->path_name);
-               intern->path_name = NULL;
+       if (intern->file_name) {
+               efree(intern->file_name);
+               intern->file_name = NULL;
        }
 }
 /* }}} */
@@ -267,10 +347,9 @@ SPL_METHOD(DirectoryIterator, next)
    Check whether dir contains more entries */
 SPL_METHOD(DirectoryIterator, valid)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_BOOL(intern->entry.d_name[0] != '\0');
+       RETURN_BOOL(intern->u.dir.entry.d_name[0] != '\0');
 }
 /* }}} */
 
@@ -278,8 +357,7 @@ SPL_METHOD(DirectoryIterator, valid)
    Return directory path */
 SPL_METHOD(DirectoryIterator, getPath)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
        RETURN_STRING(intern->path, 1);
 }
@@ -289,33 +367,29 @@ SPL_METHOD(DirectoryIterator, getPath)
    Return filename of current dir entry */
 SPL_METHOD(DirectoryIterator, getFilename)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_STRING(intern->entry.d_name, 1);
+       RETURN_STRING(intern->u.dir.entry.d_name, 1);
 }
 /* }}} */
 
-static inline void spl_dir_get_path_name(spl_ce_dir_object *intern)
-{
-       if (!intern->path_name) {
-               intern->path_name_len = spprintf(&intern->path_name, 0, "%s/%s", intern->path, intern->entry.d_name);
-       }
-}
-
-/* {{{ proto string DirectoryIterator::getPathname()
-   Return path and filename of current dir entry */
-SPL_METHOD(DirectoryIterator, getPathname)
+/* {{{ proto string SplFileInfo::getPathname()
+   Return path and filename */
+SPL_METHOD(SplFileInfo, getPathname)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       if (intern->entry.d_name[0]) {
-               spl_dir_get_path_name(intern);
-               RETURN_STRINGL(intern->path_name, intern->path_name_len, 1);
-       } else {
-               RETURN_BOOL(0);
+       switch (intern->type) {
+       case SPL_FS_INFO:
+       case SPL_FS_FILE:
+               RETURN_STRINGL(intern->file_name, intern->file_name_len, 1);
+       case SPL_FS_DIR:
+               if (intern->u.dir.entry.d_name[0]) {
+                       spl_filesystem_object_get_file_name(intern TSRMLS_CC);
+                       RETURN_STRINGL(intern->file_name, intern->file_name_len, 1);
+               }
        }
+       RETURN_BOOL(0);
 }
 /* }}} */
 
@@ -323,11 +397,10 @@ SPL_METHOD(DirectoryIterator, getPathname)
    Return path and filename of current dir entry */
 SPL_METHOD(RecursiveDirectoryIterator, key)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       spl_dir_get_path_name(intern);
-       RETURN_STRINGL(intern->path_name, intern->path_name_len, 1);
+       spl_filesystem_object_get_file_name(intern TSRMLS_CC);
+       RETURN_STRINGL(intern->file_name, intern->file_name_len, 1);
 }
 /* }}} */
 
@@ -335,136 +408,174 @@ SPL_METHOD(RecursiveDirectoryIterator, key)
    Returns true if current entry is '.' or  '..' */
 SPL_METHOD(DirectoryIterator, isDot)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_BOOL(!strcmp(intern->entry.d_name, ".") || !strcmp(intern->entry.d_name, ".."));
+       RETURN_BOOL(!strcmp(intern->u.dir.entry.d_name, ".") || !strcmp(intern->u.dir.entry.d_name, ".."));
 }
 /* }}} */
 
-/* {{{ DirectoryFunction */
-#define DirectoryFunction(func_name, func_num) \
-SPL_METHOD(DirectoryIterator, func_name) \
+/* {{{ proto void SplFileInfo::__construct(string file_name)
+ Cronstructs a new SplFileInfo from a path. */
+/* php_set_error_handling() is used to throw exceptions in case
+   the constructor fails. Here we use this to ensure the object
+   has a valid directory resource.
+   
+   When the constructor gets called the object is already created 
+   by the engine, so we must only call 'additional' initializations.
+ */
+SPL_METHOD(SplFileInfo, __construct)
+{
+       spl_filesystem_object *intern;
+       char *path;
+       int len;
+
+       php_set_error_handling(EH_THROW, U_CLASS_ENTRY(spl_ce_RuntimeException) TSRMLS_CC);
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &len) == FAILURE) {
+               php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+               return;
+       }
+
+       intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       
+       intern->file_name = estrdup(path);
+       intern->file_name_len = len;
+       /* intern->type = SPL_FS_INFO; already set */
+
+       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ FileInfoFunction */
+#define FileInfoFunction(func_name, func_num) \
+SPL_METHOD(SplFileInfo, func_name) \
 { \
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
  \
-       spl_dir_get_path_name(intern); \
-       php_stat(intern->path_name, intern->path_name_len, func_num, return_value TSRMLS_CC); \
+       spl_filesystem_object_get_file_name(intern TSRMLS_CC); \
+       php_stat(intern->file_name, intern->file_name_len, func_num, return_value TSRMLS_CC); \
 }
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getPerms()
+/* {{{ proto int SplFileInfo::getPerms()
    Get file permissions */
-DirectoryFunction(getPerms, FS_PERMS)
+FileInfoFunction(getPerms, FS_PERMS)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getInode()
+/* {{{ proto int SplFileInfo::getInode()
    Get file inode */
-DirectoryFunction(getInode, FS_INODE)
+FileInfoFunction(getInode, FS_INODE)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getSize()
+/* {{{ proto int SplFileInfo::getSize()
    Get file size */
-DirectoryFunction(getSize, FS_SIZE)
+FileInfoFunction(getSize, FS_SIZE)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getOwner()
+/* {{{ proto int SplFileInfo::getOwner()
    Get file owner */
-DirectoryFunction(getOwner, FS_OWNER)
+FileInfoFunction(getOwner, FS_OWNER)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getGroup()
+/* {{{ proto int SplFileInfo::getGroup()
    Get file group */
-DirectoryFunction(getGroup, FS_GROUP)
+FileInfoFunction(getGroup, FS_GROUP)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getATime()
+/* {{{ proto int SplFileInfo::getATime()
    Get last access time of file */
-DirectoryFunction(getATime, FS_ATIME)
+FileInfoFunction(getATime, FS_ATIME)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getMTime()
+/* {{{ proto int SplFileInfo::getMTime()
    Get last modification time of file */
-DirectoryFunction(getMTime, FS_MTIME)
+FileInfoFunction(getMTime, FS_MTIME)
 /* }}} */
 
-/* {{{ proto int DirectoryIterator::getCTime()
+/* {{{ proto int SplFileInfo::getCTime()
    Get inode modification time of file */
-DirectoryFunction(getCTime, FS_CTIME)
+FileInfoFunction(getCTime, FS_CTIME)
 /* }}} */
 
-/* {{{ proto string DirectoryIterator::getType()
+/* {{{ proto string SplFileInfo::getType()
    Get file type */
-DirectoryFunction(getType, FS_TYPE)
+FileInfoFunction(getType, FS_TYPE)
 /* }}} */
 
-/* {{{ proto bool DirectoryIterator::isWritable()
+/* {{{ proto bool SplFileInfo::isWritable()
    Returns true if file can be written */
-DirectoryFunction(isWritable, FS_IS_W)
+FileInfoFunction(isWritable, FS_IS_W)
 /* }}} */
 
-/* {{{ proto bool DirectoryIterator::isReadable()
+/* {{{ proto bool SplFileInfo::isReadable()
    Returns true if file can be read */
-DirectoryFunction(isReadable, FS_IS_R)
+FileInfoFunction(isReadable, FS_IS_R)
 /* }}} */
 
-/* {{{ proto bool DirectoryIterator::isExecutable()
+/* {{{ proto bool SplFileInfo::isExecutable()
    Returns true if file is executable */
-DirectoryFunction(isExecutable, FS_IS_X)
+FileInfoFunction(isExecutable, FS_IS_X)
 /* }}} */
 
-/* {{{ proto bool DirectoryIterator::isFile()
+/* {{{ proto bool SplFileInfo::isFile()
    Returns true if file is a regular file */
-DirectoryFunction(isFile, FS_IS_FILE)
+FileInfoFunction(isFile, FS_IS_FILE)
 /* }}} */
 
-/* {{{ proto bool DirectoryIterator::isDir()
+/* {{{ proto bool SplFileInfo::isDir()
    Returns true if file is directory */
-DirectoryFunction(isDir, FS_IS_DIR)
+FileInfoFunction(isDir, FS_IS_DIR)
 /* }}} */
 
-/* {{{ proto bool DirectoryIterator::isLink()
+/* {{{ proto bool SplFileInfo::isLink()
    Returns true if file is symbolic link */
-DirectoryFunction(isLink, FS_IS_LINK)
+FileInfoFunction(isLink, FS_IS_LINK)
 /* }}} */
 
-/* {{{ proto SplFileObject DirectoryIterator::openFile([string mode = 'r' [, bool use_include_path  [, resource context]]])
+/* {{{ proto SplFileObject SplFileInfo::openFile([string mode = 'r' [, bool use_include_path  [, resource context]]])
    Open the current file */
-SPL_METHOD(DirectoryIterator, openFile)
+SPL_METHOD(SplFileInfo, openFile)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *dir_obj = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
-       spl_file_object *intern;
+       spl_filesystem_object *dir_obj = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern;
        zend_bool use_include_path = 0;
 
        php_set_error_handling(EH_THROW, U_CLASS_ENTRY(spl_ce_RuntimeException) TSRMLS_CC);
 
-       if (!dir_obj->entry.d_name[0]) {
-               zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_RuntimeException), 0 TSRMLS_CC, "Could not open file");
-               zval_dtor(return_value);
-               return;
+       switch (intern->type) {
+       case SPL_FS_INFO:
+       case SPL_FS_FILE:
+               break;
+       case SPL_FS_DIR:
+               if (!dir_obj->u.dir.entry.d_name[0]) {
+                       zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_RuntimeException), 0 TSRMLS_CC, "Could not open file");
+                       php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+                       zval_dtor(return_value);
+                       return;
+               }
        }
+       
+       return_value->value.obj = spl_filesystem_object_new_ex(spl_ce_SplFileObject, &intern TSRMLS_CC);
 
-       return_value->value.obj = spl_file_object_new_ex(spl_ce_SplFileObject, &intern TSRMLS_CC);
-
-       spl_dir_get_path_name(dir_obj);
-       intern->file_name = dir_obj->path_name;
-       intern->file_name_len = dir_obj->path_name_len;
+       spl_filesystem_object_get_file_name(dir_obj TSRMLS_CC);
+       intern->file_name = dir_obj->file_name;
+       intern->file_name_len = dir_obj->file_name_len;
 
-       intern->open_mode = "r";
-       intern->open_mode_len = 1;
+       intern->u.file.open_mode = "r";
+       intern->u.file.open_mode_len = 1;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sbr", 
-                       &intern->open_mode, &intern->open_mode_len, 
-                       &use_include_path, &intern->zcontext) == FAILURE) {
+                       &intern->u.file.open_mode, &intern->u.file.open_mode_len, 
+                       &use_include_path, &intern->u.file.zcontext) == FAILURE) {
                php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
                zval_dtor(return_value);
                return;
        }
 
-       if (spl_file_object_open(intern, use_include_path, 0 TSRMLS_CC) == SUCCESS) {
+       if (spl_filesystem_file_open(intern, use_include_path, 0 TSRMLS_CC) == SUCCESS) {
                Z_TYPE_P(return_value) = IS_OBJECT;
        } else {
+               php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
                zval_dtor(return_value);
                return;
        }
@@ -476,18 +587,17 @@ SPL_METHOD(DirectoryIterator, openFile)
    Rewind dir back to the start */
 SPL_METHOD(RecursiveDirectoryIterator, rewind)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       intern->index = 0;
-       if (intern->dirp) {
-               php_stream_rewinddir(intern->dirp);
+       intern->u.dir.index = 0;
+       if (intern->u.dir.dirp) {
+               php_stream_rewinddir(intern->u.dir.dirp);
        }
        do {
-               if (!intern->dirp || !php_stream_readdir(intern->dirp, &intern->entry)) {
-                       intern->entry.d_name[0] = '\0';
+               if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
+                       intern->u.dir.entry.d_name[0] = '\0';
                }
-       } while (!strcmp(intern->entry.d_name, ".") || !strcmp(intern->entry.d_name, ".."));
+       } while (!strcmp(intern->u.dir.entry.d_name, ".") || !strcmp(intern->u.dir.entry.d_name, ".."));
 }
 /* }}} */
 
@@ -495,18 +605,17 @@ SPL_METHOD(RecursiveDirectoryIterator, rewind)
    Move to next entry */
 SPL_METHOD(RecursiveDirectoryIterator, next)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       intern->index++;
+       intern->u.dir.index++;
        do {
-               if (!intern->dirp || !php_stream_readdir(intern->dirp, &intern->entry)) {
-                       intern->entry.d_name[0] = '\0';
+               if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
+                       intern->u.dir.entry.d_name[0] = '\0';
                }
-       } while (!strcmp(intern->entry.d_name, ".") || !strcmp(intern->entry.d_name, ".."));
-       if (intern->path_name) {
-               efree(intern->path_name);
-               intern->path_name = NULL;
+       } while (!strcmp(intern->u.dir.entry.d_name, ".") || !strcmp(intern->u.dir.entry.d_name, ".."));
+       if (intern->file_name) {
+               efree(intern->file_name);
+               intern->file_name = NULL;
        }
 }
 /* }}} */
@@ -516,23 +625,22 @@ SPL_METHOD(RecursiveDirectoryIterator, next)
 SPL_METHOD(RecursiveDirectoryIterator, hasChildren)
 {
        zend_bool allow_links = 0;
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        
-       if (!strcmp(intern->entry.d_name, ".") || !strcmp(intern->entry.d_name, "..")) {
+       if (!strcmp(intern->u.dir.entry.d_name, ".") || !strcmp(intern->u.dir.entry.d_name, "..")) {
                RETURN_BOOL(0);
        } else {
                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &allow_links) == FAILURE) {
                        return;
                }
-               spl_dir_get_path_name(intern);
+               spl_filesystem_object_get_file_name(intern TSRMLS_CC);
                if (!allow_links) {
-                       php_stat(intern->path_name, intern->path_name_len, FS_IS_LINK, return_value TSRMLS_CC);
+                       php_stat(intern->file_name, intern->file_name_len, FS_IS_LINK, return_value TSRMLS_CC);
                        if (zend_is_true(return_value)) {
                                RETURN_BOOL(0);
                        }
                }
-               php_stat(intern->path_name, intern->path_name_len, FS_IS_DIR, return_value TSRMLS_CC);
+               php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, return_value TSRMLS_CC);
     }
 }
 /* }}} */
@@ -541,24 +649,24 @@ SPL_METHOD(RecursiveDirectoryIterator, hasChildren)
    Returns an iterator for the current entry if it is a directory */
 SPL_METHOD(RecursiveDirectoryIterator, getChildren)
 {
-       zval *object = getThis(), zpath;
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
-       spl_ce_dir_object *subdir;
+       zval zpath;
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *subdir;
        
-       spl_dir_get_path_name(intern);
+       spl_filesystem_object_get_file_name(intern TSRMLS_CC);
 
        INIT_PZVAL(&zpath);
-       ZVAL_STRINGL(&zpath, intern->path_name, intern->path_name_len, 0);
+       ZVAL_STRINGL(&zpath, intern->file_name, intern->file_name_len, 0);
 
        spl_instantiate_arg_ex1(spl_ce_RecursiveDirectoryIterator, &return_value, 0, &zpath TSRMLS_CC);
        
-       subdir = (spl_ce_dir_object*)zend_object_store_get_object(return_value TSRMLS_CC);
+       subdir = (spl_filesystem_object*)zend_object_store_get_object(return_value TSRMLS_CC);
        if (subdir) {
-               if (intern->sub_path && intern->sub_path[0]) {
-                       subdir->sub_path_len = spprintf(&subdir->sub_path, 0, "%s/%s", intern->sub_path, intern->entry.d_name);
+               if (intern->u.dir.sub_path && intern->u.dir.sub_path[0]) {
+                       subdir->u.dir.sub_path_len = spprintf(&subdir->u.dir.sub_path, 0, "%s/%s", intern->u.dir.sub_path, intern->u.dir.entry.d_name);
                } else {
-                       subdir->sub_path_len = strlen(intern->entry.d_name);
-                       subdir->sub_path = estrndup(intern->entry.d_name, subdir->sub_path_len);
+                       subdir->u.dir.sub_path_len = strlen(intern->u.dir.entry.d_name);
+                       subdir->u.dir.sub_path = estrndup(intern->u.dir.entry.d_name, subdir->u.dir.sub_path_len);
                }
        }
 }
@@ -568,11 +676,10 @@ SPL_METHOD(RecursiveDirectoryIterator, getChildren)
    Get sub path */
 SPL_METHOD(RecursiveDirectoryIterator, getSubPath)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       if (intern->sub_path) {
-               RETURN_STRINGL(intern->sub_path, intern->sub_path_len, 1);
+       if (intern->u.dir.sub_path) {
+               RETURN_STRINGL(intern->u.dir.sub_path, intern->u.dir.sub_path_len, 1);
        } else {
                RETURN_STRINGL("", 0, 1);
        }
@@ -583,16 +690,15 @@ SPL_METHOD(RecursiveDirectoryIterator, getSubPath)
    Get sub path and file name */
 SPL_METHOD(RecursiveDirectoryIterator, getSubPathname)
 {
-       zval *object = getThis();
-       spl_ce_dir_object *intern = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        char *sub_name;
        int len;
 
-       if (intern->sub_path) {
-               len = spprintf(&sub_name, 0, "%s/%s", intern->sub_path, intern->entry.d_name);
+       if (intern->u.dir.sub_path) {
+               len = spprintf(&sub_name, 0, "%s/%s", intern->u.dir.sub_path, intern->u.dir.entry.d_name);
                RETURN_STRINGL(sub_name, len, 0);
        } else {
-               RETURN_STRING(intern->entry.d_name, 1);
+               RETURN_STRING(intern->u.dir.entry.d_name, 1);
        }
 }
 /* }}} */
@@ -601,36 +707,36 @@ SPL_METHOD(RecursiveDirectoryIterator, getSubPathname)
 typedef struct {
        zend_object_iterator  intern;
        zval                  *current;
-       spl_ce_dir_object     *object;
-} spl_ce_dir_it;
+       spl_filesystem_object *object;
+} spl_filesystem_dir_it;
 
 /* forward declarations to the iterator handlers */
-static void spl_ce_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC);
-static int spl_ce_dir_it_valid(zend_object_iterator *iter TSRMLS_DC);
-static void spl_ce_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC);
-static int spl_ce_dir_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC);
-static void spl_ce_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC);
-static void spl_ce_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC);
+static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC);
+static int spl_filesystem_dir_it_valid(zend_object_iterator *iter TSRMLS_DC);
+static void spl_filesystem_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC);
+static int spl_filesystem_dir_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC);
+static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC);
+static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC);
 
 /* iterator handler table */
-zend_object_iterator_funcs spl_ce_dir_it_funcs = {
-       spl_ce_dir_it_dtor,
-       spl_ce_dir_it_valid,
-       spl_ce_dir_it_current_data,
-       spl_ce_dir_it_current_key,
-       spl_ce_dir_it_move_forward,
-       spl_ce_dir_it_rewind
+zend_object_iterator_funcs spl_filesystem_dir_it_funcs = {
+       spl_filesystem_dir_it_dtor,
+       spl_filesystem_dir_it_valid,
+       spl_filesystem_dir_it_current_data,
+       spl_filesystem_dir_it_current_key,
+       spl_filesystem_dir_it_move_forward,
+       spl_filesystem_dir_it_rewind
 };
 
 /* {{{ spl_ce_dir_get_iterator */
-zend_object_iterator *spl_ce_dir_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
+zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator   = emalloc(sizeof(spl_ce_dir_it));
-       spl_ce_dir_object   *dir_object = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_dir_it *iterator   = emalloc(sizeof(spl_filesystem_dir_it));
+       spl_filesystem_object *dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC);
 
        object->refcount++;
        iterator->intern.data = (void*)object;
-       iterator->intern.funcs = &spl_ce_dir_it_funcs;
+       iterator->intern.funcs = &spl_filesystem_dir_it_funcs;
        iterator->current = object;
        object->refcount++;
        iterator->object = dir_object;
@@ -639,10 +745,10 @@ zend_object_iterator *spl_ce_dir_get_iterator(zend_class_entry *ce, zval *object
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_it_dtor */
-static void spl_ce_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC)
+/* {{{ spl_filesystem_dir_it_dtor */
+static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it *iterator = (spl_ce_dir_it *)iter;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
 
        zval_ptr_dtor(&iterator->current);
        zval_ptr_dtor((zval**)&iterator->intern.data);
@@ -651,139 +757,139 @@ static void spl_ce_dir_it_dtor(zend_object_iterator *iter TSRMLS_DC)
 }
 /* }}} */
        
-/* {{{ spl_ce_dir_it_valid */
-static int spl_ce_dir_it_valid(zend_object_iterator *iter TSRMLS_DC)
+/* {{{ spl_filesystem_dir_it_valid */
+static int spl_filesystem_dir_it_valid(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
 
-       return object->entry.d_name[0] != '\0' ? SUCCESS : FAILURE;
+       return object->u.dir.entry.d_name[0] != '\0' ? SUCCESS : FAILURE;
 }
 /* }}} */
 
 
-/* {{{ spl_ce_dir_it_current_data */
-static void spl_ce_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
+/* {{{ spl_filesystem_dir_it_current_data */
+static void spl_filesystem_dir_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
 {
-       spl_ce_dir_it *iterator = (spl_ce_dir_it *)iter;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
        
        *data = &iterator->current;
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_it_current_key */
-static int spl_ce_dir_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
+/* {{{ spl_filesystem_dir_it_current_key */
+static int spl_filesystem_dir_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
        
-       *int_key = object->index;
+       *int_key = object->u.dir.index;
        return HASH_KEY_IS_LONG;
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_it_move_forward */
-static void spl_ce_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
+/* {{{ spl_filesystem_dir_it_move_forward */
+static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
        
-       object->index++;
-       if (!object->dirp || !php_stream_readdir(object->dirp, &object->entry)) {
-               object->entry.d_name[0] = '\0';
+       object->u.dir.index++;
+       if (!object->u.dir.dirp || !php_stream_readdir(object->u.dir.dirp, &object->u.dir.entry)) {
+               object->u.dir.entry.d_name[0] = '\0';
        }
-       if (object->path_name) {
-               efree(object->path_name);
-               object->path_name = NULL;
+       if (object->file_name) {
+               efree(object->file_name);
+               object->file_name = NULL;
        }
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_it_rewind */
-static void spl_ce_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC)
+/* {{{ spl_filesystem_dir_it_rewind */
+static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
        
-       object->index = 0;
-       if (object->dirp) {
-               php_stream_rewinddir(object->dirp);
+       object->u.dir.index = 0;
+       if (object->u.dir.dirp) {
+               php_stream_rewinddir(object->u.dir.dirp);
        }
-       if (!object->dirp || !php_stream_readdir(object->dirp, &object->entry)) {
-               object->entry.d_name[0] = '\0';
+       if (!object->u.dir.dirp || !php_stream_readdir(object->u.dir.dirp, &object->u.dir.entry)) {
+               object->u.dir.entry.d_name[0] = '\0';
        }
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_tree_it_current_key */
-static int spl_ce_dir_tree_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
+/* {{{ spl_filesystem_tree_it_current_key */
+static int spl_filesystem_tree_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
        
-       spl_dir_get_path_name(object);
-       *str_key_len = object->path_name_len + 1;
-       *str_key = estrndup(object->path_name, object->path_name_len);
+       spl_filesystem_object_get_file_name(object TSRMLS_CC);
+       *str_key_len = object->file_name_len + 1;
+       *str_key = estrndup(object->file_name, object->file_name_len);
        return HASH_KEY_IS_STRING;
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_tree_it_move_forward */
-static void spl_ce_dir_tree_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
+/* {{{ spl_filesystem_tree_it_move_forward */
+static void spl_filesystem_tree_it_move_forward(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
        
-       object->index++;
+       object->u.dir.index++;
        do {
-               if (!object->dirp || !php_stream_readdir(object->dirp, &object->entry)) {
-                       object->entry.d_name[0] = '\0';
+               if (!object->u.dir.dirp || !php_stream_readdir(object->u.dir.dirp, &object->u.dir.entry)) {
+                       object->u.dir.entry.d_name[0] = '\0';
                }
-       } while (!strcmp(object->entry.d_name, ".") || !strcmp(object->entry.d_name, ".."));
-       if (object->path_name) {
-               efree(object->path_name);
-               object->path_name = NULL;
+       } while (!strcmp(object->u.dir.entry.d_name, ".") || !strcmp(object->u.dir.entry.d_name, ".."));
+       if (object->file_name) {
+               efree(object->file_name);
+               object->file_name = NULL;
        }
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_tree_it_rewind */
-static void spl_ce_dir_tree_it_rewind(zend_object_iterator *iter TSRMLS_DC)
+/* {{{ spl_filesystem_tree_it_rewind */
+static void spl_filesystem_tree_it_rewind(zend_object_iterator *iter TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator = (spl_ce_dir_it *)iter;
-       spl_ce_dir_object   *object   = iterator->object;
+       spl_filesystem_dir_it *iterator = (spl_filesystem_dir_it *)iter;
+       spl_filesystem_object *object   = iterator->object;
        
-       object->index = 0;
-       if (object->dirp) {
-               php_stream_rewinddir(object->dirp);
+       object->u.dir.index = 0;
+       if (object->u.dir.dirp) {
+               php_stream_rewinddir(object->u.dir.dirp);
        }
        do {
-               if (!object->dirp || !php_stream_readdir(object->dirp, &object->entry)) {
-                       object->entry.d_name[0] = '\0';
+               if (!object->u.dir.dirp || !php_stream_readdir(object->u.dir.dirp, &object->u.dir.entry)) {
+                       object->u.dir.entry.d_name[0] = '\0';
                }
-       } while (!strcmp(object->entry.d_name, ".") || !strcmp(object->entry.d_name, ".."));
+       } while (!strcmp(object->u.dir.entry.d_name, ".") || !strcmp(object->u.dir.entry.d_name, ".."));
 }
 /* }}} */
 
 /* iterator handler table */
-zend_object_iterator_funcs spl_ce_dir_tree_it_funcs = {
-       spl_ce_dir_it_dtor,
-       spl_ce_dir_it_valid,
-       spl_ce_dir_it_current_data,
-       spl_ce_dir_tree_it_current_key,
-       spl_ce_dir_tree_it_move_forward,
-       spl_ce_dir_tree_it_rewind
+zend_object_iterator_funcs spl_filesystem_tree_it_funcs = {
+       spl_filesystem_dir_it_dtor,
+       spl_filesystem_dir_it_valid,
+       spl_filesystem_dir_it_current_data,
+       spl_filesystem_tree_it_current_key,
+       spl_filesystem_tree_it_move_forward,
+       spl_filesystem_tree_it_rewind
 };
 
 /* {{{ spl_ce_dir_get_iterator */
-zend_object_iterator *spl_ce_dir_tree_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
+zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC)
 {
-       spl_ce_dir_it       *iterator   = emalloc(sizeof(spl_ce_dir_it));
-       spl_ce_dir_object   *dir_object = (spl_ce_dir_object*)zend_object_store_get_object(object TSRMLS_CC);
+       spl_filesystem_dir_it *iterator   = emalloc(sizeof(spl_filesystem_dir_it));
+       spl_filesystem_object *dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC);
 
        object->refcount++;
        iterator->intern.data = (void*)object;
-       iterator->intern.funcs = &spl_ce_dir_tree_it_funcs;
+       iterator->intern.funcs = &spl_filesystem_tree_it_funcs;
        iterator->current = object;
        object->refcount++;
        iterator->object = dir_object;
@@ -792,14 +898,28 @@ zend_object_iterator *spl_ce_dir_tree_get_iterator(zend_class_entry *ce, zval *o
 }
 /* }}} */
 
-/* {{{ spl_ce_dir_cast */
-static int spl_ce_dir_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
+/* {{{ spl_filesystem_object_cast */
+static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
 {
-       spl_ce_dir_object   *dir_object = (spl_ce_dir_object*)zend_object_store_get_object(readobj TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(readobj TSRMLS_CC);
 
-       if (type ==IS_STRING && *dir_object->entry.d_name) {
-               ZVAL_STRING(writeobj, dir_object->entry.d_name, 1);
-               return SUCCESS;
+       if (type == IS_STRING) {
+               switch (intern->type) {
+               case SPL_FS_INFO:
+               case SPL_FS_FILE:
+                       ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len, 1);
+                       return SUCCESS;
+               case SPL_FS_DIR:
+                       if (intern->u.dir.is_recursive) {
+                               spl_filesystem_object_get_file_name(intern TSRMLS_CC);
+                               ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len, 1);
+                               return SUCCESS;
+            } else if (*intern->u.dir.entry.d_name) {
+                               ZVAL_STRING(writeobj, intern->u.dir.entry.d_name, 1);
+                               return SUCCESS;
+                       }               
+                       return FAILURE;
+               }
        }
        return FAILURE;
 }
@@ -808,12 +928,12 @@ static int spl_ce_dir_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
 /* declare method parameters */
 /* supply a name and default to call by parameter */
 static
-ZEND_BEGIN_ARG_INFO(arginfo_dir___construct, 0) 
-       ZEND_ARG_INFO(0, path)  /* parameter name */
+ZEND_BEGIN_ARG_INFO(arginfo_info___construct, 0) 
+       ZEND_ARG_INFO(0, file_name)
 ZEND_END_ARG_INFO();
 
 static
-ZEND_BEGIN_ARG_INFO_EX(arginfo_dir_openFile, 0, 0, 0)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_info_openFile, 0, 0, 0)
        ZEND_ARG_INFO(0, open_mode)
        ZEND_ARG_INFO(0, use_include_path)
        ZEND_ARG_INFO(0, context)
@@ -821,38 +941,51 @@ ZEND_END_ARG_INFO();
 
 /* the method table */
 /* each method can have its own parameters and visibility */
-static zend_function_entry spl_ce_dir_class_functions[] = {
+static zend_function_entry spl_filesystem_info_class_functions[] = {
+       SPL_ME(SplFileInfo,       __construct,   arginfo_info___construct, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getPathname,   NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getPerms,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getInode,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getSize,       NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getOwner,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getGroup,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getATime,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getMTime,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getCTime,      NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       getType,       NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       isWritable,    NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       isReadable,    NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       isExecutable,  NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       isFile,        NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       isDir,         NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       isLink,        NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(SplFileInfo,       openFile,      arginfo_info_openFile, ZEND_ACC_PUBLIC)
+       SPL_MA(SplFileInfo,       __toString, SplFileInfo, getPathname, NULL, ZEND_ACC_PUBLIC)
+       {NULL, NULL, NULL}
+};
+
+static
+ZEND_BEGIN_ARG_INFO(arginfo_dir___construct, 0) 
+       ZEND_ARG_INFO(0, path)
+ZEND_END_ARG_INFO();
+
+/* the method table */
+/* each method can have its own parameters and visibility */
+static zend_function_entry spl_filesystem_dir_class_functions[] = {
        SPL_ME(DirectoryIterator, __construct,   arginfo_dir___construct, ZEND_ACC_PUBLIC)
+       SPL_ME(DirectoryIterator, getPath,       NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(DirectoryIterator, getFilename,   NULL, ZEND_ACC_PUBLIC)
+       SPL_ME(DirectoryIterator, isDot,         NULL, ZEND_ACC_PUBLIC)
        SPL_ME(DirectoryIterator, rewind,        NULL, ZEND_ACC_PUBLIC)
        SPL_ME(DirectoryIterator, valid,         NULL, ZEND_ACC_PUBLIC)
        SPL_ME(DirectoryIterator, key,           NULL, ZEND_ACC_PUBLIC)
        SPL_ME(DirectoryIterator, current,       NULL, ZEND_ACC_PUBLIC)
        SPL_ME(DirectoryIterator, next,          NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getPath,       NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getFilename,   NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getPathname,   NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getPerms,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getInode,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getSize,       NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getOwner,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getGroup,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getATime,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getMTime,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getCTime,      NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, getType,       NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isWritable,    NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isReadable,    NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isExecutable,  NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isFile,        NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isDir,         NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isLink,        NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, isDot,         NULL, ZEND_ACC_PUBLIC)
-       SPL_ME(DirectoryIterator, openFile,      arginfo_dir_openFile, ZEND_ACC_PUBLIC)
        SPL_MA(DirectoryIterator, __toString, DirectoryIterator, getFilename, NULL, ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
 };
 
-static zend_function_entry spl_ce_dir_tree_class_functions[] = {
+static zend_function_entry spl_filesystem_tree_class_functions[] = {
        SPL_ME(RecursiveDirectoryIterator, rewind,        NULL, ZEND_ACC_PUBLIC)
        SPL_ME(RecursiveDirectoryIterator, next,          NULL, ZEND_ACC_PUBLIC)
        SPL_ME(RecursiveDirectoryIterator, key,           NULL, ZEND_ACC_PUBLIC)
@@ -860,96 +993,33 @@ static zend_function_entry spl_ce_dir_tree_class_functions[] = {
        SPL_ME(RecursiveDirectoryIterator, getChildren,   NULL, ZEND_ACC_PUBLIC)
        SPL_ME(RecursiveDirectoryIterator, getSubPath,    NULL, ZEND_ACC_PUBLIC)
        SPL_ME(RecursiveDirectoryIterator, getSubPathname,NULL, ZEND_ACC_PUBLIC)
+       SPL_MA(RecursiveDirectoryIterator, __toString, SplFileInfo, getPathname, NULL, ZEND_ACC_PUBLIC)
        {NULL, NULL, NULL}
 };
 
-static void spl_file_object_free_line(spl_file_object *intern TSRMLS_DC) /* {{{ */
-{
-       if (intern->current_line) {
-               efree(intern->current_line);
-               intern->current_line = NULL;
-       }
-       if (intern->current_zval) {
-               zval_ptr_dtor(&intern->current_zval);
-               intern->current_zval = NULL;
-       }
-} /* }}} */
-
-static void spl_file_object_free_storage(void *object TSRMLS_DC) /* {{{ */
-{
-       spl_file_object *intern = (spl_file_object*)object;
-
-       zend_hash_destroy(intern->std.properties);
-       FREE_HASHTABLE(intern->std.properties);
-
-       if (intern->stream) {
-               if (intern->zcontext) {
-/*                     zend_list_delref(Z_RESVAL_P(intern->zcontext));*/
-               }
-               if (!intern->stream->is_persistent) {
-                       php_stream_free(intern->stream, PHP_STREAM_FREE_CLOSE);
-               } else {
-                       php_stream_free(intern->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT);
-               }
-               if (intern->file_name) {
-                       efree(intern->file_name);
-               }
-               if (intern->open_mode) {
-                       efree(intern->open_mode);
-               }
-       }
-       spl_file_object_free_line(intern TSRMLS_CC);
-       efree(object);
-} /* }}} */
-
-static zend_object_value spl_file_object_new_ex(zend_class_entry *class_type, spl_file_object **obj TSRMLS_DC) /* {{{ */
-{
-       zend_object_value retval;
-       spl_file_object *intern;
-       zval *tmp;
-
-       intern = emalloc(sizeof(spl_ce_dir_object));
-       memset(intern, 0, sizeof(spl_ce_dir_object));
-       intern->std.ce = class_type;
-       if (obj) *obj = intern;
-
-       ALLOC_HASHTABLE(intern->std.properties);
-       zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
-
-       retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_file_object_free_storage, NULL TSRMLS_CC);
-       retval.handlers = &spl_ce_dir_handlers;
-       return retval;
-} /* }}} */
-
-static zend_object_value spl_file_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
-{
-       return spl_file_object_new_ex(class_type, NULL TSRMLS_CC);
-} /* }}} */
-
-static int spl_file_object_read(spl_file_object *intern, int silent TSRMLS_DC) /* {{{ */
+static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent TSRMLS_DC) /* {{{ */
 {
        char *buf;
        size_t line_len;
        int len;
-       long line_add = (intern->current_line || intern->current_zval) ? 1 : 0;
+       long line_add = (intern->u.file.current_line || intern->u.file.current_zval) ? 1 : 0;
 
-       spl_file_object_free_line(intern TSRMLS_CC);
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
        
-       if (php_stream_eof(intern->stream)) {
+       if (php_stream_eof(intern->u.file.stream)) {
                if (!silent) {
                        zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_RuntimeException), 0 TSRMLS_CC, "Cannot read from file %s", intern->file_name);
                }
                return FAILURE;
        }
 
-       buf = php_stream_get_line(intern->stream, NULL, intern->max_line_len, &line_len);
+       buf = php_stream_get_line(intern->u.file.stream, NULL, intern->u.file.max_line_len, &line_len);
 
        if (!buf) {
-               intern->current_line = estrdup("");
-               intern->current_line_len = 0;
+               intern->u.file.current_line = estrdup("");
+               intern->u.file.current_line_len = 0;
        } else {
-               if (intern->flags & SPL_FILE_OBJECT_DROP_NEW_LINE) {
+               if (intern->u.file.flags & SPL_FILE_OBJECT_DROP_NEW_LINE) {
                        line_len = strcspn(buf, "\r\n");
                        buf[line_len] = '\0';
                }
@@ -959,38 +1029,38 @@ static int spl_file_object_read(spl_file_object *intern, int silent TSRMLS_DC) /
                        line_len = len;
                }
        
-               intern->current_line = buf;
-               intern->current_line_len = line_len;
+               intern->u.file.current_line = buf;
+               intern->u.file.current_line_len = line_len;
        }
-       intern->current_line_num += line_add;
+       intern->u.file.current_line_num += line_add;
 
        return SUCCESS;
 } /* }}} */
 
-static int spl_file_object_read_line(zval * this_ptr, spl_file_object *intern, int silent TSRMLS_DC) /* {{{ */
+static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, int silent TSRMLS_DC) /* {{{ */
 {
        zval *retval;
 
        /* if overloaded call the function, otherwise do it directly */
-       if (intern->func_getCurr->common.scope != spl_ce_SplFileObject) {
-               if (php_stream_eof(intern->stream)) {
+       if (intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) {
+               if (php_stream_eof(intern->u.file.stream)) {
                        if (!silent) {
                                zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_RuntimeException), 0 TSRMLS_CC, "Cannot read from file %s", intern->file_name);
                        }
                        return FAILURE;
                }
-               zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), &intern->func_getCurr, "getCurrentLine", &retval);
+               zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), &intern->u.file.func_getCurr, "getCurrentLine", &retval);
                if (retval) {
-                       if (intern->current_line || intern->current_zval) {
-                               intern->current_line_num++;
+                       if (intern->u.file.current_line || intern->u.file.current_zval) {
+                               intern->u.file.current_line_num++;
                        }
-                       spl_file_object_free_line(intern TSRMLS_CC);
+                       spl_filesystem_file_free_line(intern TSRMLS_CC);
                        if (Z_TYPE_P(retval) == IS_STRING) {
-                               intern->current_line = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
-                               intern->current_line_len = Z_STRLEN_P(retval);
+                               intern->u.file.current_line = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
+                               intern->u.file.current_line_len = Z_STRLEN_P(retval);
                        } else {
-                               MAKE_STD_ZVAL(intern->current_zval);
-                               ZVAL_ZVAL(intern->current_zval, retval, 1, 0);
+                               MAKE_STD_ZVAL(intern->u.file.current_zval);
+                               ZVAL_ZVAL(intern->u.file.current_zval, retval, 1, 0);
                        }
                        zval_ptr_dtor(&retval);
                        return SUCCESS;
@@ -998,69 +1068,41 @@ static int spl_file_object_read_line(zval * this_ptr, spl_file_object *intern, i
                        return FAILURE;
                }
        } else {
-               return spl_file_object_read(intern, silent TSRMLS_CC);
+               return spl_filesystem_file_read(intern, silent TSRMLS_CC);
        }
 } /* }}} */
 
-static void spl_file_object_rewind(spl_file_object *intern TSRMLS_DC) /* {{{ */
+static void spl_filesystem_file_rewind(spl_filesystem_object *intern TSRMLS_DC) /* {{{ */
 {
-       if (-1 == php_stream_rewind(intern->stream)) {
+       if (-1 == php_stream_rewind(intern->u.file.stream)) {
                zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_RuntimeException), 0 TSRMLS_CC, "Cannot rewind file %s", intern->file_name);
        } else {
-               spl_file_object_free_line(intern TSRMLS_CC);
-               intern->current_line_num = 0;
+               spl_filesystem_file_free_line(intern TSRMLS_CC);
+               intern->u.file.current_line_num = 0;
        }
 } /* }}} */
 
-static int spl_file_object_open(spl_file_object *intern, int use_include_path, int silent TSRMLS_DC) /* {{{ */
-{
-       intern->context = php_stream_context_from_zval(intern->zcontext, 0);
-       intern->stream = php_stream_open_wrapper_ex(intern->file_name, intern->open_mode, (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, intern->context);
-
-       if (intern->stream == NULL) {
-               if (!EG(exception)) {
-                       zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_RuntimeException), 0 TSRMLS_CC, "Cannot open file %s", intern->file_name);
-               }
-               return FAILURE;
-       }
-
-       if (intern->zcontext) {
-               zend_list_addref(Z_RESVAL_P(intern->zcontext));
-       }
-
-       intern->file_name = estrndup(intern->file_name, intern->file_name_len);
-       intern->open_mode = estrndup(intern->open_mode, intern->open_mode_len);
-
-       /* avoid reference counting in debug mode, thus do it manually */
-       ZVAL_RESOURCE(&intern->zresource, php_stream_get_resource_id(intern->stream));
-       intern->zresource.refcount = 1;
-
-       zend_hash_find(&intern->std.ce->function_table, "getcurrentline", sizeof("getcurrentline"), (void **) &intern->func_getCurr);
-
-       return SUCCESS;
-} /* }}} */
-
 /* {{{ proto void SplFileObject::__construct(string filename [, string mode = 'r' [, bool use_include_path  [, resource context]]]])
    Construct a new file reader */
 SPL_METHOD(SplFileObject, __construct)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        zend_bool use_include_path = 0;
 
        php_set_error_handling(EH_THROW, U_CLASS_ENTRY(spl_ce_RuntimeException) TSRMLS_CC);
 
-       intern->open_mode = "r";
-       intern->open_mode_len = 1;
+       intern->u.file.open_mode = "r";
+       intern->u.file.open_mode_len = 1;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sbr", 
                        &intern->file_name, &intern->file_name_len,
-                       &intern->open_mode, &intern->open_mode_len, 
-                       &use_include_path, &intern->zcontext) == FAILURE) {
+                       &intern->u.file.open_mode, &intern->u.file.open_mode_len, 
+                       &use_include_path, &intern->u.file.zcontext) == FAILURE) {
                php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
                return;
        }
        
-       spl_file_object_open(intern, use_include_path, 0 TSRMLS_CC);
+       spl_filesystem_file_open(intern, use_include_path, 0 TSRMLS_CC);
 
        php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
 } /* }}} */
@@ -1069,16 +1111,16 @@ SPL_METHOD(SplFileObject, __construct)
    Rewind the file and read the first line */
 SPL_METHOD(SplFileObject, rewind)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       spl_file_object_rewind(intern TSRMLS_CC);
+       spl_filesystem_file_rewind(intern TSRMLS_CC);
 } /* }}} */
 
 /* {{{ proto string SplFileObject::getFilename()
    Return the filename */
 SPL_METHOD(SplFileObject, getFilename)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
        RETURN_STRINGL(intern->file_name, intern->file_name_len, 1);    
 } /* }}} */
@@ -1087,45 +1129,45 @@ SPL_METHOD(SplFileObject, getFilename)
    Return whether end of file is reached */
 SPL_METHOD(SplFileObject, eof)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_BOOL(php_stream_eof(intern->stream));
+       RETURN_BOOL(php_stream_eof(intern->u.file.stream));
 } /* }}} */
 
 /* {{{ proto void SplFileObject::valid()
    Return !eof() */
 SPL_METHOD(SplFileObject, valid)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETVAL_BOOL(!php_stream_eof(intern->stream));
+       RETVAL_BOOL(!php_stream_eof(intern->u.file.stream));
 } /* }}} */
 
 /* {{{ proto string SplFileObject::fgets()
    Rturn next line from file */
 SPL_METHOD(SplFileObject, fgets)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       if (spl_file_object_read(intern, 0 TSRMLS_CC) == FAILURE) {
+       if (spl_filesystem_file_read(intern, 0 TSRMLS_CC) == FAILURE) {
                RETURN_FALSE;
        }
-       RETURN_STRINGL(intern->current_line, intern->current_line_len, 1);
+       RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len, 1);
 } /* }}} */
 
 /* {{{ proto string SplFileObject::current()
    Return current line from file */
 SPL_METHOD(SplFileObject, current)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       if (!intern->current_line) {
-               spl_file_object_read_line(getThis(), intern, 1 TSRMLS_CC);
+       if (!intern->u.file.current_line) {
+               spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC);
        }
-       if (intern->current_line) {
-               RETURN_STRINGL(intern->current_line, intern->current_line_len, 1);
-       } else if (intern->current_zval) {
-               RETURN_ZVAL(intern->current_zval, 1, 0);
+       if (intern->u.file.current_line) {
+               RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len, 1);
+       } else if (intern->u.file.current_zval) {
+               RETURN_ZVAL(intern->u.file.current_zval, 1, 0);
        }
        RETURN_FALSE;
 } /* }}} */
@@ -1134,41 +1176,41 @@ SPL_METHOD(SplFileObject, current)
    Return line number */
 SPL_METHOD(SplFileObject, key)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
 /*     Do not read the next line to support correct counting with fgetc()
        if (!intern->current_line) {
-               spl_file_object_read_line(getThis(), intern, 1 TSRMLS_CC);
+               spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC);
        } */
-       RETURN_LONG(intern->current_line_num);
+       RETURN_LONG(intern->u.file.current_line_num);
 } /* }}} */
 
 /* {{{ proto void SplFileObject::next()
    Read next line */
 SPL_METHOD(SplFileObject, next)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       spl_file_object_free_line(intern TSRMLS_CC);
-       intern->current_line_num++;
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
+       intern->u.file.current_line_num++;
 } /* }}} */
 
 /* {{{ proto void SplFileObject::setFlags(int flags)
    Set file handling flags */
 SPL_METHOD(SplFileObject, setFlags)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &intern->flags);
+       zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &intern->u.file.flags);
 } /* }}} */
 
 /* {{{ proto int SplFileObject::getFlags()
    Get file handling flags */
 SPL_METHOD(SplFileObject, getFlags)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_LONG(intern->flags);
+       RETURN_LONG(intern->u.file.flags);
 } /* }}} */
 
 /* {{{ proto void SplFileObject::setMaxLineLen(int max_len)
@@ -1177,7 +1219,7 @@ SPL_METHOD(SplFileObject, setMaxLineLen)
 {
        long max_len;
 
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &max_len) == FAILURE) {
                return;
@@ -1188,16 +1230,16 @@ SPL_METHOD(SplFileObject, setMaxLineLen)
                return;
        }
        
-       intern->max_line_len = max_len;
+       intern->u.file.max_line_len = max_len;
 } /* }}} */
 
 /* {{{ proto int SplFileObject::getMaxLineLen()
    Get maximum line length */
 SPL_METHOD(SplFileObject, getMaxLineLen)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_LONG((long)intern->max_line_len);
+       RETURN_LONG((long)intern->u.file.max_line_len);
 } /* }}} */
 
 /* {{{ proto bool SplFileObject>>hasChildren()
@@ -1214,12 +1256,12 @@ SPL_METHOD(SplFileObject, getChildren)
        /* return NULL */
 } /* }}} */
 
-static int spl_file_object_call(INTERNAL_FUNCTION_PARAMETERS, spl_file_object *intern, zend_function *func_ptr, zval *arg2) /* {{{ */
+static int spl_filesystem_file_call(INTERNAL_FUNCTION_PARAMETERS, spl_filesystem_object *intern, zend_function *func_ptr, zval *arg2) /* {{{ */
 {
        zend_fcall_info fci;
        zend_fcall_info_cache fcic;
        zval z_fname;
-       zval * zresource_ptr = &intern->zresource, *retval;
+       zval * zresource_ptr = &intern->u.file.zresource, *retval;
        int result;
 
        zval ***params = (zval***)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval**), (arg2 ? 2 : 1) * sizeof(zval**));
@@ -1261,14 +1303,14 @@ static int spl_file_object_call(INTERNAL_FUNCTION_PARAMETERS, spl_file_object *i
 { \
        zend_function *func_ptr; \
        zend_hash_find(EG(function_table), #func_name, sizeof(#func_name), (void **) &func_ptr); \
-       spl_file_object_call(INTERNAL_FUNCTION_PARAM_PASSTHRU, intern, func_ptr, arg2); \
+       spl_filesystem_file_call(INTERNAL_FUNCTION_PARAM_PASSTHRU, intern, func_ptr, arg2); \
 }
 
 /* {{{ FileFunction */
 #define FileFunction(func_name) \
 SPL_METHOD(SplFileObject, func_name) \
 { \
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
        FileFunctionCall(func_name, NULL); \
 }
 /* }}} */
@@ -1277,13 +1319,13 @@ SPL_METHOD(SplFileObject, func_name) \
    Return current line as csv */
 SPL_METHOD(SplFileObject, fgetcsv)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        zval *arg2 = NULL;
        MAKE_STD_ZVAL(arg2);
-       ZVAL_LONG(arg2, intern->max_line_len);
+       ZVAL_LONG(arg2, intern->u.file.max_line_len);
 
-       spl_file_object_free_line(intern TSRMLS_CC);
-       intern->current_line_num++;
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
+       intern->u.file.current_line_num++;
 
        FileFunctionCall(fgetcsv, arg2);
 
@@ -1300,9 +1342,9 @@ FileFunction(flock)
    Flush the file */
 SPL_METHOD(SplFileObject, fflush)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_BOOL(!php_stream_flush(intern->stream));
+       RETURN_BOOL(!php_stream_flush(intern->u.file.stream));
 } /* }}} */
 
 
@@ -1310,8 +1352,8 @@ SPL_METHOD(SplFileObject, fflush)
    Return current file position */
 SPL_METHOD(SplFileObject, ftell)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);  
-       long ret = php_stream_tell(intern->stream);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);      
+       long ret = php_stream_tell(intern->u.file.stream);
 
        if (ret == -1) {
                RETURN_FALSE;
@@ -1324,34 +1366,34 @@ SPL_METHOD(SplFileObject, ftell)
    Return current file position */
 SPL_METHOD(SplFileObject, fseek)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        long pos, whence = SEEK_SET;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &pos, &whence) == FAILURE) {
                return;
        }
 
-       spl_file_object_free_line(intern TSRMLS_CC);
-       RETURN_LONG(php_stream_seek(intern->stream, pos, whence));
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
+       RETURN_LONG(php_stream_seek(intern->u.file.stream, pos, whence));
 } /* }}} */
 
 /* {{{ proto int SplFileObject::fgetc()
    Get a character form the file */
 SPL_METHOD(SplFileObject, fgetc)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        char buf[2];
        int result;
 
-       spl_file_object_free_line(intern TSRMLS_CC);
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
 
-       result = php_stream_getc(intern->stream);
+       result = php_stream_getc(intern->u.file.stream);
 
        if (result == EOF) {
                RETVAL_FALSE;
        } else {
                if (result == '\n') {
-                       intern->current_line_num++;
+                       intern->u.file.current_line_num++;
                }
                buf[0] = result;
                buf[1] = '\0';
@@ -1364,13 +1406,13 @@ SPL_METHOD(SplFileObject, fgetc)
    Get a line from file pointer and strip HTML tags */
 SPL_METHOD(SplFileObject, fgetss)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        zval *arg2 = NULL;
        MAKE_STD_ZVAL(arg2);
-       ZVAL_LONG(arg2, intern->max_line_len);
+       ZVAL_LONG(arg2, intern->u.file.max_line_len);
 
-       spl_file_object_free_line(intern TSRMLS_CC);
-       intern->current_line_num++;
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
+       intern->u.file.current_line_num++;
 
        FileFunctionCall(fgetss, arg2);
 
@@ -1381,19 +1423,19 @@ SPL_METHOD(SplFileObject, fgetss)
    Output all remaining data from a file pointer */
 SPL_METHOD(SplFileObject, fpassthru)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       RETURN_LONG(php_stream_passthru(intern->stream));
+       RETURN_LONG(php_stream_passthru(intern->u.file.stream));
 } /* }}} */
 
 /* {{{ proto bool SplFileObject::fscanf(string format [, string ...])
    Implements a mostly ANSI compatible fscanf() */
 SPL_METHOD(SplFileObject, fscanf)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       spl_file_object_free_line(intern TSRMLS_CC);
-       intern->current_line_num++;
+       spl_filesystem_file_free_line(intern TSRMLS_CC);
+       intern->u.file.current_line_num++;
 
        FileFunctionCall(fscanf, NULL);
 }
@@ -1403,7 +1445,7 @@ SPL_METHOD(SplFileObject, fscanf)
    Binary-safe file write */
 SPL_METHOD(SplFileObject, fwrite)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        char *str;
        int str_len;
        int ret;
@@ -1423,12 +1465,12 @@ SPL_METHOD(SplFileObject, fwrite)
        if (PG(magic_quotes_runtime)) {
                str = estrndup(str, str_len);
                php_stripslashes(str, &str_len TSRMLS_CC);
-               ret = php_stream_write(intern->stream, str, str_len);
+               ret = php_stream_write(intern->u.file.stream, str, str_len);
                efree(str);
                RETURN_LONG(ret);
        }
 
-       RETURN_LONG(php_stream_write(intern->stream, str, str_len));
+       RETURN_LONG(php_stream_write(intern->u.file.stream, str, str_len));
 } /* }}} */
 
 /* {{{ proto bool SplFileObject::fstat()
@@ -1440,26 +1482,26 @@ FileFunction(fstat)
    Truncate file to 'size' length */
 SPL_METHOD(SplFileObject, ftruncate)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        long size;
        
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &size) == FAILURE) {
                return;
        }
 
-       if (!php_stream_truncate_supported(intern->stream)) {
+       if (!php_stream_truncate_supported(intern->u.file.stream)) {
                zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_LogicException), 0 TSRMLS_CC, "Can't truncate file %s", intern->file_name);
                RETURN_FALSE;
        }
        
-       RETURN_BOOL(0 == php_stream_truncate_set_size(intern->stream, size));
+       RETURN_BOOL(0 == php_stream_truncate_set_size(intern->u.file.stream, size));
 } /* }}} */
 
 /* {{{ proto void SplFileObject::seek(int line_pos)
    Seek to specified line */
 SPL_METHOD(SplFileObject, seek)
 {
-       spl_file_object *intern = (spl_file_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
        long line_pos;
        
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &line_pos) == FAILURE) {
@@ -1470,10 +1512,10 @@ SPL_METHOD(SplFileObject, seek)
                RETURN_FALSE;           
        }
        
-       spl_file_object_rewind(intern TSRMLS_CC);
+       spl_filesystem_file_rewind(intern TSRMLS_CC);
        
-       while(intern->current_line_num < line_pos) {
-               spl_file_object_read_line(getThis(), intern, 1 TSRMLS_CC);
+       while(intern->u.file.current_line_num < line_pos) {
+               spl_filesystem_file_read_line(getThis(), intern, 1 TSRMLS_CC);
        }
 }
 
@@ -1539,7 +1581,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_seek, 0, 0, 1)
        ZEND_ARG_INFO(0, line_pos)
 ZEND_END_ARG_INFO();
 
-static zend_function_entry spl_file_object_class_functions[] = {
+static zend_function_entry spl_filesystem_file_class_functions[] = {
        SPL_ME(SplFileObject, __construct,    arginfo_file_object___construct,   ZEND_ACC_PUBLIC)
        SPL_ME(SplFileObject, getFilename,    NULL, ZEND_ACC_PUBLIC)
        SPL_ME(SplFileObject, rewind,         NULL, ZEND_ACC_PUBLIC)
@@ -1578,20 +1620,22 @@ static zend_function_entry spl_file_object_class_functions[] = {
  */
 PHP_MINIT_FUNCTION(spl_directory)
 {
-       REGISTER_SPL_STD_CLASS_EX(DirectoryIterator, spl_ce_dir_object_new, spl_ce_dir_class_functions);
+       REGISTER_SPL_STD_CLASS_EX(SplFileInfo, spl_filesystem_object_new, spl_filesystem_info_class_functions);
+
+       REGISTER_SPL_SUB_CLASS_EX(DirectoryIterator, SplFileInfo, spl_filesystem_object_new, spl_filesystem_dir_class_functions);
        zend_class_implements(spl_ce_DirectoryIterator TSRMLS_CC, 1, zend_ce_iterator);
        memcpy(&spl_ce_dir_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
-       spl_ce_dir_handlers.clone_obj = spl_ce_dir_object_clone;
-       spl_ce_dir_handlers.cast_object = spl_ce_dir_cast;
+       spl_ce_dir_handlers.clone_obj = spl_filesystem_object_clone;
+       spl_ce_dir_handlers.cast_object = spl_filesystem_object_cast;
 
-       spl_ce_DirectoryIterator->get_iterator = spl_ce_dir_get_iterator;
+       spl_ce_DirectoryIterator->get_iterator = spl_filesystem_dir_get_iterator;
 
-       REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, DirectoryIterator, spl_ce_dir_object_new, spl_ce_dir_tree_class_functions);
+       REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, DirectoryIterator, spl_filesystem_object_new, spl_filesystem_tree_class_functions);
        REGISTER_SPL_IMPLEMENTS(RecursiveDirectoryIterator, RecursiveIterator);
 
-       spl_ce_RecursiveDirectoryIterator->get_iterator = spl_ce_dir_tree_get_iterator;
+       spl_ce_RecursiveDirectoryIterator->get_iterator = spl_filesystem_tree_get_iterator;
 
-       REGISTER_SPL_STD_CLASS_EX(SplFileObject, spl_file_object_new, spl_file_object_class_functions);
+       REGISTER_SPL_SUB_CLASS_EX(SplFileObject, SplFileInfo, spl_filesystem_object_new, spl_filesystem_file_class_functions);
        REGISTER_SPL_IMPLEMENTS(SplFileObject, RecursiveIterator);
        REGISTER_SPL_IMPLEMENTS(SplFileObject, SeekableIterator);
 
index 10922da6d2cd4e20415bfec097fade0854343364..2d1ab9ca2be5f0d1a7b136a5afdbe244bee2e892 100755 (executable)
 #include "php.h"
 #include "php_spl.h"
 
+extern PHPAPI zend_class_entry *spl_ce_SplFileInfo;
 extern PHPAPI zend_class_entry *spl_ce_DirectoryIterator;
 extern PHPAPI zend_class_entry *spl_ce_RecursiveDirectoryIterator;
 extern PHPAPI zend_class_entry *spl_ce_SplFileObject;
 
 PHP_MINIT_FUNCTION(spl_directory);
 
-typedef struct _spl_ce_dir_object {
-       zend_object       std;
-       php_stream        *dirp;
-       php_stream_dirent entry;
-       char              *path;
-       char              *path_name;
-       int               path_name_len;
-       char              *sub_path;
-       int               sub_path_len;
-       int               index;
-} spl_ce_dir_object;
+typedef enum {
+       SPL_FS_INFO,
+       SPL_FS_DIR,
+       SPL_FS_FILE,
+} SPL_FS_OBJ_TYPE;
 
-typedef struct _spl_file_object {
+typedef struct _spl_filesystem_object {
        zend_object        std;
-       php_stream         *stream;
-       php_stream_context *context;
-       zval               *zcontext;
+       char               *path;
+       int                path_len;
        char               *file_name;
-       int                file_name_len;
-       char               *open_mode;
-       int                open_mode_len;
-       zval               *current_zval;
-       char               *current_line;
-       size_t             current_line_len;
-       size_t             max_line_len;
-       long               current_line_num;
-       long               flags;
-       zval               zresource;
-       zend_function      *func_getCurr;
-} spl_file_object;
+       int                file_name_len; 
+       SPL_FS_OBJ_TYPE    type;
+       union {
+               struct {
+                       php_stream         *dirp;
+                       php_stream_dirent  entry;
+                       char               *sub_path;
+                       int                sub_path_len;
+                       int                index;
+                       int                is_recursive;
+               } dir;
+               struct {
+                       php_stream         *stream;
+                       php_stream_context *context;
+                       zval               *zcontext;
+                       char               *open_mode;
+                       int                open_mode_len;
+                       zval               *current_zval;
+                       char               *current_line;
+                       size_t             current_line_len;
+                       size_t             max_line_len;
+                       long               current_line_num;
+                       long               flags;
+                       zval               zresource;
+                       zend_function      *func_getCurr;
+               } file;
+       } u;
+} spl_filesystem_object;
 
 #define SPL_FILE_OBJECT_DROP_NEW_LINE      0x00000001 /* drop new lines */