]> granicus.if.org Git - php/commitdiff
Fixed directory reanming/deletion
authorDmitry Stogov <dmitry@php.net>
Sun, 20 Jul 2008 14:42:34 +0000 (14:42 +0000)
committerDmitry Stogov <dmitry@php.net>
Sun, 20 Jul 2008 14:42:34 +0000 (14:42 +0000)
12 files changed:
ext/phar/dirstream.c
ext/phar/phar.c
ext/phar/phar_internal.h
ext/phar/stream.c
ext/phar/tests/rename_dir.phpt
ext/phar/tests/rename_dir_and_mount.phpt [new file with mode: 0755]
ext/phar/tests/rmdir.phpt
ext/phar/tests/tar/rename_dir.phpt
ext/phar/tests/tar/rmdir.phpt
ext/phar/tests/zip/rename_dir.phpt
ext/phar/tests/zip/rmdir.phpt
ext/phar/util.c

index 6c2bd7231cc42c0b479a7aaa0b43752e261c9d10..4635e67fa3808e4a735068ea225765a1006b4253 100644 (file)
@@ -415,7 +415,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
        /* pre-readonly check, we need to know if this is a data phar */
        if (FAILURE == phar_split_fname(url_from, strlen(url_from), &arch, &arch_len, &entry2, &entry_len, 2, 2 TSRMLS_CC)) {
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\", no phar archive specified", url_from);
-               return FAILURE;
+               return 0;
        }
        if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
                phar = NULL;
@@ -424,24 +424,24 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
        efree(entry2);
        if (PHAR_G(readonly) && (!phar || !phar->is_data)) {
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\", write operations disabled", url_from);
-               return FAILURE;
+               return 0;
        }
 
        if ((resource = phar_parse_url(wrapper, url_from, "w", options TSRMLS_CC)) == NULL) {
-               return FAILURE;
+               return 0;
        }
 
        /* we must have at the very least phar://alias.phar/internalfile.php */
        if (!resource->scheme || !resource->host || !resource->path) {
                php_url_free(resource);
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: invalid url \"%s\"", url_from);
-               return FAILURE;
+               return 0;
        }
 
        if (strcasecmp("phar", resource->scheme)) {
                php_url_free(resource);
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: not a phar stream url \"%s\"", url_from);
-               return FAILURE;
+               return 0;
        }
 
        host_len = strlen(resource->host);
@@ -450,7 +450,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", error retrieving phar information: %s", resource->path+1, resource->host, error);
                efree(error);
                php_url_free(resource);
-               return FAILURE;
+               return 0;
        }
 
        if ((e = phar_get_entry_info_dir(phar, resource->path + 1, strlen(resource->path + 1), 2, &error, 1 TSRMLS_CC))) {
@@ -461,31 +461,31 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
                }
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", directory already exists", resource->path+1, resource->host);
                php_url_free(resource);
-               return FAILURE;
+               return 0;
        }
        if (error) {
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", resource->path+1, resource->host, error);
                efree(error);
                php_url_free(resource);
-               return FAILURE;
+               return 0;
        }
        if ((e = phar_get_entry_info_dir(phar, resource->path + 1, strlen(resource->path + 1), 0, &error, 1 TSRMLS_CC))) {
                /* entry exists as a file */
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", file already exists", resource->path+1, resource->host);
                php_url_free(resource);
-               return FAILURE;
+               return 0;
        }
        if (error) {
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", resource->path+1, resource->host, error);
                efree(error);
                php_url_free(resource);
-               return FAILURE;
+               return 0;
        }
 
        if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", unable to make cached phar writeable", resource->path+1, resource->host);
                php_url_free(resource);
-               return FAILURE;
+               return 0;
        }
 
        memset((void *) &entry, 0, sizeof(phar_entry_info));
@@ -511,17 +511,17 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, char *url_from, int mode, in
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", adding to manifest failed", entry.filename, phar->fname);
                efree(error);
                efree(entry.filename);
-               return FAILURE;
+               return 0;
        }
        phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
        if (error) {
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot create directory \"%s\" in phar \"%s\", %s", entry.filename, phar->fname, error);
                zend_hash_del(&phar->manifest, entry.filename, entry.filename_len);
                efree(error);
-               return FAILURE;
+               return 0;
        }
        phar_add_virtual_dirs(phar, entry.filename, entry.filename_len TSRMLS_CC);
-       return SUCCESS;
+       return 1;
 }
 /* }}} */
 
@@ -536,11 +536,16 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
        int arch_len, entry_len;
        php_url *resource = NULL;
        uint host_len;
+       int key_type;
+       char *key;
+       uint key_len;
+       ulong unused;
+       uint path_len;
 
        /* pre-readonly check, we need to know if this is a data phar */
        if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, &entry2, &entry_len, 2, 2 TSRMLS_CC)) {
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\", no phar archive specified, or phar archive does not exist", url);
-               return FAILURE;
+               return 0;
        }
        if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
                phar = NULL;
@@ -549,24 +554,24 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
        efree(entry2);
        if (PHAR_G(readonly) && (!phar || !phar->is_data)) {
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot rmdir directory \"%s\", write operations disabled", url);
-               return FAILURE;
+               return 0;
        }
 
        if ((resource = phar_parse_url(wrapper, url, "w", options TSRMLS_CC)) == NULL) {
-               return FAILURE;
+               return 0;
        }
 
        /* we must have at the very least phar://alias.phar/internalfile.php */
        if (!resource->scheme || !resource->host || !resource->path) {
                php_url_free(resource);
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: invalid url \"%s\"", url);
-               return FAILURE;
+               return 0;
        }
 
        if (strcasecmp("phar", resource->scheme)) {
                php_url_free(resource);
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: not a phar stream url \"%s\"", url);
-               return FAILURE;
+               return 0;
        }
 
        host_len = strlen(resource->host);
@@ -575,10 +580,12 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", error retrieving phar information: %s", resource->path+1, resource->host, error);
                efree(error);
                php_url_free(resource);
-               return FAILURE;
+               return 0;
        }
 
-       if (!(entry = phar_get_entry_info_dir(phar, resource->path + 1, strlen(resource->path) - 1, 2, &error, 1 TSRMLS_CC))) {
+       path_len = strlen(resource->path+1);
+       
+       if (!(entry = phar_get_entry_info_dir(phar, resource->path + 1, path_len, 2, &error, 1 TSRMLS_CC))) {
                if (error) {
                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", resource->path+1, resource->host, error);
                        efree(error);
@@ -586,27 +593,70 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_
                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", directory does not exist", resource->path+1, resource->host);
                }
                php_url_free(resource);
-               return FAILURE;
+               return 0;
        }
 
        /* now for the easy part */
        if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", unable to make cached phar writeable", resource->path+1, resource->host);
                php_url_free(resource);
-               return FAILURE;
+               return 0;
        }
 
-       entry->is_deleted = 1;
-       entry->is_modified = 1;
-       phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
-       if (error) {
-               php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", entry->filename, phar->fname, error);
-               php_url_free(resource);
-               efree(error);
-               return FAILURE;
+       for (zend_hash_internal_pointer_reset(&phar->manifest);
+            HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->manifest, &key, &key_len, &unused, 0, NULL));
+            zend_hash_move_forward(&phar->manifest)) {
+
+               if (!entry->is_deleted &&
+                   key_len > path_len &&
+                   memcmp(key, resource->path+1, path_len) == 0 &&
+                   IS_SLASH(key[path_len])) {
+                       php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: Directory not empty");
+                       if (entry->is_temp_dir) {
+                               efree(entry->filename);
+                               efree(entry);
+                       }
+                       php_url_free(resource);
+                       return 0;
+               }
        }
-       phar_delete_virtual_dirs(phar, resource->path + 1, strlen(resource->path) - 1 TSRMLS_CC);
+
+       for (zend_hash_internal_pointer_reset(&phar->virtual_dirs);
+            HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->virtual_dirs, &key, &key_len, &unused, 0, NULL));
+            zend_hash_move_forward(&phar->virtual_dirs)) {
+
+               if (!entry->is_deleted &&
+                   key_len > path_len &&
+                   memcmp(key, resource->path+1, path_len) == 0 &&
+                   IS_SLASH(key[path_len])) {
+                       php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: Directory not empty");
+                       if (entry->is_temp_dir) {
+                               efree(entry->filename);
+                               efree(entry);
+                       }
+                       php_url_free(resource);
+                       return 0;
+               }
+       }
+
+       if (entry->is_temp_dir) {
+               zend_hash_del(&phar->virtual_dirs, resource->path+1, path_len);
+               efree(entry->filename);
+               efree(entry);
+       } else {
+               entry->is_deleted = 1;
+               entry->is_modified = 1;
+               phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
+
+               if (error) {
+                       php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", entry->filename, phar->fname, error);
+                       php_url_free(resource);
+                       efree(error);
+                       return 0;
+               }
+       }
+
        php_url_free(resource);
-       return SUCCESS;
+       return 1;
 }
 /* }}} */
index ac370af532674b30649269bb61d4f1f94d7a682e..9fe9e05189bdcdb153e51e6c07ac3f5b2d783212 100644 (file)
@@ -431,13 +431,11 @@ void phar_entry_remove(phar_entry_data *idata, char **error TSRMLS_DC) /* {{{ */
                if (idata->fp && idata->fp != idata->phar->fp && idata->fp != idata->phar->ufp && idata->fp != idata->internal_file->fp) {
                        php_stream_close(idata->fp);
                }
-               phar_delete_virtual_dirs(idata->phar, idata->internal_file->filename, idata->internal_file->filename_len TSRMLS_CC);
                zend_hash_del(&idata->phar->manifest, idata->internal_file->filename, idata->internal_file->filename_len);
                idata->phar->refcount--;
                efree(idata);
        } else {
                idata->internal_file->is_deleted = 1;
-               phar_delete_virtual_dirs(idata->phar, idata->internal_file->filename, idata->internal_file->filename_len TSRMLS_CC);
                phar_entry_delref(idata TSRMLS_CC);
        }
 
index e2e415eeabe511036d14e43dbc093d3b5924839f..12a3a5a32c002d57f0ee542c2e3f22944b82ad9e 100755 (executable)
@@ -582,7 +582,6 @@ char *phar_decompress_filter(phar_entry_info * entry, int return_unknown);
 char *phar_compress_filter(phar_entry_info * entry, int return_unknown);
 
 void phar_add_virtual_dirs(phar_archive_data *phar, char *filename, int filename_len TSRMLS_DC);
-void phar_delete_virtual_dirs(phar_archive_data *phar, char *filename, int filename_len TSRMLS_DC);
 int phar_mount_entry(phar_archive_data *phar, char *filename, int filename_len, char *path, int path_len TSRMLS_DC);
 char *phar_find_in_include_path(char *file, int file_len, phar_archive_data **pphar TSRMLS_DC);
 char *phar_fix_filepath(char *path, int *new_len, int use_cwd TSRMLS_DC);
index f70af7143ed3ac88df0068266e5f616ec9f44c49..fe863fd1a5981d7c5ef72055b9c1ce22ec3e459d 100644 (file)
@@ -620,14 +620,16 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags,
                char *str_key;
                ulong unused;
                uint keylen;
+               HashPosition pos;
 
-               zend_hash_internal_pointer_reset(&phar->mounted_dirs);
-               while (FAILURE != zend_hash_has_more_elements(&phar->mounted_dirs)) {
-                       if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&phar->mounted_dirs, &key, &keylen, &unused, 0, NULL)) {
+               zend_hash_internal_pointer_reset_ex(&phar->mounted_dirs, &pos);
+               while (FAILURE != zend_hash_has_more_elements_ex(&phar->mounted_dirs, &pos)) {
+                       if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&phar->mounted_dirs, &key, &keylen, &unused, 0, &pos)) {
                                break;
                        }
                        PHAR_STR(key, str_key);
                        if ((int)keylen >= internal_file_len || strncmp(str_key, internal_file, keylen)) {
+                           zend_hash_move_forward_ex(&phar->mounted_dirs, &pos);
                                continue;
                        } else {
                                char *test;
@@ -644,6 +646,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags,
                                test_len = spprintf(&test, MAXPATHLEN, "%s%s", entry->tmp, internal_file + keylen);
                                if (SUCCESS != php_stream_stat_path(test, &ssbi)) {
                                        efree(test);
+                                   zend_hash_move_forward_ex(&phar->mounted_dirs, &pos);
                                        continue;
                                }
                                /* mount the file/directory just in time */
@@ -752,6 +755,8 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
        phar_archive_data *phar, *pfrom, *pto;
        phar_entry_info *entry;
        uint host_len;
+       int is_dir = 0;
+       int is_modified = 0;
 
        error = NULL;
 
@@ -872,21 +877,96 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char
                        zend_hash_del(&(phar->manifest), entry->filename, strlen(entry->filename));
                        return 0;
                }
+               is_modified = 1;
                entry->is_modified = 1;
                entry->filename_len = strlen(entry->filename);
+               is_dir = entry->is_dir;
+       } else {
+               is_dir = zend_hash_exists(&(phar->virtual_dirs), resource_from->path+1, strlen(resource_from->path)-1);
+       }
+
+       /* Rename directory. Update all nested paths */
+       if (is_dir) {
+               int key_type;
+               char *key, *new_key;
+               uint key_len, new_key_len;
+               ulong unused;
+               uint from_len = strlen(resource_from->path+1);
+               uint to_len = strlen(resource_to->path+1);
+
+               for (zend_hash_internal_pointer_reset(&phar->manifest);
+                   HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->manifest, &key, &key_len, &unused, 0, NULL)) &&
+                   SUCCESS == zend_hash_get_current_data(&phar->manifest, (void **) &entry);
+                   zend_hash_move_forward(&phar->manifest)) {
+
+                       if (!entry->is_deleted &&
+                           key_len > from_len &&
+                           memcmp(key, resource_from->path+1, from_len) == 0 &&
+                           IS_SLASH(key[from_len])) {
+
+                               new_key_len = key_len + to_len - from_len;
+                               new_key = emalloc(new_key_len+1);
+                               memcpy(new_key, resource_to->path + 1, to_len);
+                               memcpy(new_key + to_len, key + from_len, key_len - from_len);
+                               new_key[new_key_len] = 0;
+                               is_modified = 1;
+                               entry->is_modified = 1;
+                               efree(entry->filename);
+                               entry->filename = new_key;
+                               entry->filename_len = new_key_len;
+                               zend_hash_update_current_key_ex(&phar->manifest, key_type, new_key, new_key_len, 0, NULL);
+                       }
+               }               
+
+               for (zend_hash_internal_pointer_reset(&phar->virtual_dirs);
+                   HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->virtual_dirs, &key, &key_len, &unused, 0, NULL));
+                   zend_hash_move_forward(&phar->virtual_dirs)) {
+
+                       if (key_len >= from_len &&
+                           memcmp(key, resource_from->path+1, from_len) == 0 &&
+                           (key_len == from_len || IS_SLASH(key[from_len]))) {
+
+                               new_key_len = key_len + to_len - from_len;
+                               new_key = emalloc(new_key_len+1);
+                               memcpy(new_key, resource_to->path + 1, to_len);
+                               memcpy(new_key + to_len, key + from_len, key_len - from_len);
+                               new_key[new_key_len] = 0;
+                               zend_hash_update_current_key_ex(&phar->virtual_dirs, key_type, new_key, new_key_len, 0, NULL);
+                               efree(new_key);
+                       }
+               }
+
+               for (zend_hash_internal_pointer_reset(&phar->mounted_dirs);
+                   HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_ex(&phar->mounted_dirs, &key, &key_len, &unused, 0, NULL)) &&
+                   SUCCESS == zend_hash_get_current_data(&phar->mounted_dirs, (void **) &entry);
+                   zend_hash_move_forward(&phar->mounted_dirs)) {
+
+                       if (key_len >= from_len &&
+                           memcmp(key, resource_from->path+1, from_len) == 0 &&
+                           (key_len == from_len || IS_SLASH(key[from_len]))) {
+
+                               new_key_len = key_len + to_len - from_len;
+                               new_key = emalloc(new_key_len+1);
+                               memcpy(new_key, resource_to->path + 1, to_len);
+                               memcpy(new_key + to_len, key + from_len, key_len - from_len);
+                               new_key[new_key_len] = 0;
+                               zend_hash_update_current_key_ex(&phar->mounted_dirs, key_type, new_key, new_key_len, 0, NULL);
+                               efree(new_key);
+                       }
+               }
+       }
+
+       if (is_modified) {
                phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
                if (error) {
                        php_url_free(resource_from);
                        php_url_free(resource_to);
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": %s", url_from, url_to, error);
                        efree(error);
-                       zend_hash_del(&(phar->manifest), entry->filename, strlen(entry->filename));
                        return 0;
                }
-
-               phar_add_virtual_dirs(phar, resource_to->path+1, strlen(resource_to->path)-1 TSRMLS_CC);
-               phar_delete_virtual_dirs(phar, resource_from->path+1, strlen(resource_from->path)-1 TSRMLS_CC);
        }
+
        php_url_free(resource_from);
        php_url_free(resource_to);
        return 1;
index 308d2e3058b57368629d3f663f18ab5fdb793d84..0645a817d68a42e891e179a4bb2c6542a88941b1 100644 (file)
@@ -29,4 +29,4 @@ echo file_get_contents($pname . '/a/x') . "\n";
 a
 a
 
-Warning: file_get_contents(phar://%srename.phar.php/a/x): failed to open stream: phar error: "a" is not a file in phar "%srename.phar.php" in %srename.php on line %d
\ No newline at end of file
+Warning: file_get_contents(phar://%srename_dir.phar.php/a/x): failed to open stream: phar error: "a/x" is not a file in phar "%srename_dir.phar.php" in %srename_dir.php on line %d
diff --git a/ext/phar/tests/rename_dir_and_mount.phpt b/ext/phar/tests/rename_dir_and_mount.phpt
new file mode 100755 (executable)
index 0000000..b74f47b
--- /dev/null
@@ -0,0 +1,65 @@
+--TEST--
+Phar: rename_dir and mount test
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--INI--
+phar.readonly=0
+phar.require_hash=0
+--FILE--
+<?php
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
+$pname = 'phar://' . $fname;
+$file = "<?php
+Phar::mapPhar('hio');
+__HALT_COMPILER(); ?>";
+
+$files = array();
+$files['a/x'] = 'a';
+$files['a/b/x'] = 'a';
+include 'files/phar_test.inc';
+include $fname;
+
+Phar::mount("$pname/a/c", dirname(__FILE__));
+
+var_dump(file_exists($pname . '/a'));
+var_dump(file_exists($pname . '/a/x'));
+var_dump(file_exists($pname . '/a/b'));
+var_dump(file_exists($pname . '/a/b/x'));
+var_dump(file_exists($pname . '/a/c'));
+var_dump(file_exists($pname . '/a/c/'.basename(__FILE__)));
+rename($pname . '/a', $pname . '/b');
+clearstatcache();
+var_dump(file_exists($pname . '/a'));
+var_dump(file_exists($pname . '/a/x'));
+var_dump(file_exists($pname . '/a/b'));
+var_dump(file_exists($pname . '/a/b/x'));
+var_dump(file_exists($pname . '/a/c'));
+var_dump(file_exists($pname . '/a/c/'.basename(__FILE__)));
+var_dump(file_exists($pname . '/b'));
+var_dump(file_exists($pname . '/b/x'));
+var_dump(file_exists($pname . '/b/b'));
+var_dump(file_exists($pname . '/b/b/x'));
+var_dump(file_exists($pname . '/b/c'));
+var_dump(file_exists($pname . '/b/c/'.basename(__FILE__)));
+?>
+--CLEAN--
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
index f3d07362d6ee8a08e5090b05a8936816ab0257f0..ef061bf7c2c4e71744190f672ef049f3ab61d71f 100644 (file)
@@ -19,12 +19,17 @@ include 'files/phar_test.inc';
 include $fname;
 
 echo file_get_contents($pname . '/a/x') . "\n";
-rmdir($pname . '/a');
+var_dump(rmdir($pname . '/a'));
 echo file_get_contents($pname . '/a/x') . "\n";
+unlink($pname . '/a/x');
+var_dump(rmdir($pname . '/a'));
 ?>
 --CLEAN--
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
 --EXPECTF--
 a
 
-Warning: file_get_contents(phar://%srename.phar.php/a/x): failed to open stream: phar error: "a" is not a file in phar "%srename.phar.php" in %srename.php on line %d
\ No newline at end of file
+Warning: rmdir(): phar error: Directory not empty in %srmdir.php on line 14
+bool(false)
+a
+bool(true)
index 4f94ef43b41d14c50f7b8c7074f7d1946c570c42..0b9578945a6c5a9baf3d242bd2f9765f2d3e53b4 100644 (file)
@@ -39,4 +39,4 @@ echo file_get_contents($alias . '/a/x') . "\n";
 a
 a
 
-Warning: file_get_contents(phar://%srename.phar.tar/a/x): failed to open stream: phar error: "a" is not a file in phar "%srename.phar.tar" in %srename.php on line %d
+Warning: file_get_contents(phar://%srename_dir.phar.tar/a/x): failed to open stream: phar error: "a/x" is not a file in phar "%srename_dir.phar.tar" in %srename_dir.php on line %d
index 972dea8c3213891eb2c396f4dd7b1665945330f4..d08e5216145b7c5c1c1741e0875d8fdb82af2a3b 100644 (file)
@@ -29,12 +29,17 @@ $tar->close();
 include $fname;
 
 echo file_get_contents($alias . '/a/x') . "\n";
-rmdir($alias . '/a');
+var_dump(rmdir($alias . '/a'));
 echo file_get_contents($alias . '/a/x') . "\n";
+unlink($alias . '/a/x');
+var_dump(rmdir($alias . '/a'));
 ?>
 --CLEAN--
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.tar'); ?>
 --EXPECTF--
 a
 
-Warning: file_get_contents(phar://%srename.phar.tar/a/x): failed to open stream: phar error: "a" is not a file in phar "%srename.phar.tar" in %srename.php on line %d
+Warning: rmdir(): phar error: Directory not empty in %srmdir.php on line 24
+bool(false)
+a
+bool(true)
index d88eb9b0ef6ec706e1565ec84a5de4c366ffbc8f..bb03c7fd66f2d1920e0ab485ac9b2a135087a0ab 100644 (file)
@@ -31,4 +31,4 @@ echo file_get_contents($alias . '/a/x') . "\n";
 a
 a
 
-Warning: file_get_contents(phar://%srename.phar.zip/a/x): failed to open stream: phar error: "a" is not a file in phar "%srename.phar.zip" in %srename.php on line %d
\ No newline at end of file
+Warning: file_get_contents(phar://%srename_dir.phar.zip/a/x): failed to open stream: phar error: "a/x" is not a file in phar "%srename_dir.phar.zip" in %srename_dir.php on line %d
\ No newline at end of file
index c0c2cbffe50f1561df8dae60750255d60931b34f..149f0e8d6b576a3765c197d81e1ff3f4e97bdd72 100644 (file)
@@ -21,12 +21,17 @@ $phar->stopBuffering();
 include $fname;
 
 echo file_get_contents($alias . '/a/x') . "\n";
-rmdir($alias . '/a');
+var_dump(rmdir($alias . '/a'));
 echo file_get_contents($alias . '/a/x') . "\n";
+unlink($alias . '/a/x');
+var_dump(rmdir($alias . '/a'));
 ?>
 --CLEAN--
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.zip'); ?>
 --EXPECTF--
 a
 
-Warning: file_get_contents(phar://%srename.phar.zip/a/x): failed to open stream: phar error: "a" is not a file in phar "%srename.phar.zip" in %srename.php on line %d
\ No newline at end of file
+Warning: rmdir(): phar error: Directory not empty in %srmdir.php on line 16
+bool(false)
+a
+bool(true)
index 88913fbce7b210744276ff2b4f1f36db82de08bf..74cebdfc2809aaedac694bb80fd9ba10b50d9b27 100644 (file)
@@ -1950,53 +1950,14 @@ int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signat
 }
 /* }}} */
 
-/**
- * add an empty element with a char * key to a hash table, avoiding duplicates
- *
- * This is used to get a unique listing of virtual directories within a phar,
- * for iterating over opendir()ed phar directories.
- */
-static int phar_add_empty(HashTable *ht, char *arKey, uint nKeyLength)  /* {{{ */
-{
-       char **dummy;
-
-       if (SUCCESS == zend_hash_find(ht, arKey, nKeyLength, (void **)&dummy)) {
-               (*dummy)++;
-               return SUCCESS;
-       } else {
-               char *dummy = (char*)1;
-
-               return zend_hash_add(ht, arKey, nKeyLength, (char *) &dummy, sizeof(void *), NULL);
-       }
-}
-/* }}} */
-
 void phar_add_virtual_dirs(phar_archive_data *phar, char *filename, int filename_len TSRMLS_DC) /* {{{ */
 {
-       char *s = filename;
-
-       /* we use filename_len - 1 to avoid adding a virtual dir for empty directory entries */
-       for (; s - filename < filename_len - 1; s++) {
-               if (*s == '/') {
-                       phar_add_empty(&phar->virtual_dirs, filename, s - filename);
-               }
-       }
-}
-/* }}} */
+       char *s;
 
-void phar_delete_virtual_dirs(phar_archive_data *phar, char *filename, int filename_len TSRMLS_DC) /* {{{ */
-{
-       char *s = filename;
-       char **dummy;
-
-       /* we use filename_len - 1 to avoid adding a virtual dir for empty directory entries */
-       for (; s - filename < filename_len - 1; s++) {
-               if (*s == '/') {
-                       if (SUCCESS == zend_hash_find(&phar->virtual_dirs, filename, s - filename, (void **)&dummy)) {
-                               if (!--(*dummy)) {
-                                       zend_hash_del(&phar->virtual_dirs, filename, s - filename);
-                               }
-                       }
+       while ((s = zend_memrchr(filename, '/', filename_len))) {
+               filename_len = s - filename;
+               if (FAILURE == zend_hash_add_empty_element(&phar->virtual_dirs, filename, filename_len)) {
+                       break;
                }
        }
 }