From abde85c420aea422b93613d2fe120c72d29ae945 Mon Sep 17 00:00:00 2001 From: Greg Beaver Date: Wed, 9 Jan 2008 03:47:22 +0000 Subject: [PATCH] add rmdir() support, add rmdir to dir test fix *extremely* ancient problem where phar_wrapper_stat always returned success indicating the file existed rename phar_destroy_manifest to phar_destroy_manifest_entry --- ext/phar/dirstream.c | 3 +++ ext/phar/phar.c | 18 ++++++++++++------ ext/phar/phar_internal.h | 2 +- ext/phar/stream.c | 21 ++++++++++++--------- ext/phar/tar.c | 2 +- ext/phar/tests/dir.phpt | 18 +++++++++++++++++- ext/phar/zip.c | 2 +- 7 files changed, 47 insertions(+), 19 deletions(-) diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index d52eb7ca39..3b20144b05 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -549,13 +549,16 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, char *url, int options, php_ /* now for the easy part */ entry->is_deleted = 1; + entry->is_modified = 1; phar_flush(phar, 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); + php_url_free(resource); efree(error); return FAILURE; } + php_url_free(resource); return SUCCESS; } /* }}} */ diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 04b8908068..157b6b0fcb 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -279,7 +279,7 @@ static void destroy_phar_data(void *pDest) /* {{{ */ /** * destructor for the manifest hash, frees each file's entry */ -void destroy_phar_manifest(void *pDest) /* {{{ */ +void destroy_phar_manifest_entry(void *pDest) /* {{{ */ { phar_entry_info *entry = (phar_entry_info *)pDest; TSRMLS_FETCH(); @@ -1312,7 +1312,7 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int /* set up our manifest */ zend_hash_init(&mydata->manifest, sizeof(phar_entry_info), - zend_get_hash_value, destroy_phar_manifest, 0); + zend_get_hash_value, destroy_phar_manifest_entry, 0); offset = 0; for (manifest_index = 0; manifest_index < manifest_count; manifest_index++) { if (buffer + 4 > endbuffer) { @@ -1542,7 +1542,7 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a *pphar = mydata; } zend_hash_init(&mydata->manifest, sizeof(phar_entry_info), - zend_get_hash_value, destroy_phar_manifest, 0); + zend_get_hash_value, destroy_phar_manifest_entry, 0); mydata->fname_len = fname_len; mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len); mydata->alias_len = alias ? alias_len : fname_len; @@ -2464,7 +2464,8 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err entry->metadata_str.len = 0; } - offset += 4 + entry->filename_len + sizeof(entry_buffer) + entry->metadata_str.len; + /* 32 bits for filename length, length of filename, manifest + metadata, and add 1 for trailing / if a directory */ + offset += 4 + entry->filename_len + sizeof(entry_buffer) + entry->metadata_str.len + (entry->is_dir ? 1 : 0); /* compress and rehash as necessary */ if (oldfile && !entry->is_modified) { @@ -2655,7 +2656,12 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err /* remove this from the new phar */ continue; } - phar_set_32(entry_buffer, entry->filename_len); + if (entry->is_dir) { + /* add 1 for trailing slash */ + phar_set_32(entry_buffer, entry->filename_len + 1); + } else { + phar_set_32(entry_buffer, entry->filename_len); + } if (4 != php_stream_write(newfile, entry_buffer, 4) || entry->filename_len != php_stream_write(newfile, entry->filename, entry->filename_len)) { if (closeoldfile) { @@ -2673,7 +2679,7 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err } php_stream_close(newfile); if (error) { - spprintf(error, 0, "unable to write filename of file \"%s\" to manifest of new phar \"%s\"", entry->filename, archive->fname); + spprintf(error, 0, "unable to write filename of directory \"%s\" to manifest of new phar \"%s\"", entry->filename, archive->fname); } return EOF; } diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 2b7c7b185c..0b168ac040 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -307,7 +307,7 @@ int phar_open_loaded(char *fname, int fname_len, char *alias, int alias_len, int phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, php_stream *fp, char **error, int for_write TSRMLS_DC); int phar_parse_metadata(char **buffer, zval **metadata, int is_zip TSRMLS_DC); -void destroy_phar_manifest(void *pDest); +void destroy_phar_manifest_entry(void *pDest); /* tar functions in tar.c */ int phar_is_tar(char *buf); diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 52c8442e5b..41b51f11f7 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -559,20 +559,20 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, int retval; if ((resource = phar_open_url(wrapper, url, "r", flags TSRMLS_CC)) == NULL) { - return -1; + return FAILURE; } /* 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, flags TSRMLS_CC, "phar error: invalid url \"%s\"", url); - return -1; + return FAILURE; } if (strcasecmp("phar", resource->scheme)) { php_url_free(resource); php_stream_wrapper_log_error(wrapper, flags TSRMLS_CC, "phar error: not a phar url \"%s\"", url); - return -1; + return FAILURE; } host_len = strlen(resource->host); @@ -581,7 +581,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, spprintf(&internal_file, 0, "%s%s", plain_map, resource->path); retval = php_stream_stat_path_ex(internal_file, flags, ssb, context); if (retval == -1) { - php_stream_wrapper_log_error(wrapper, 0/* TODO:options */ TSRMLS_CC, "phar error: file \"%s\" extracted from \"%s\" could not be opened", internal_file, resource->host); + php_stream_wrapper_log_error(wrapper, 0/* TODO:options */ TSRMLS_CC, "phar error: file \"%s\" extracted from \"%s\" could not be stated", internal_file, resource->host); } php_url_free(resource); efree(internal_file); @@ -596,7 +596,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_wrapper_log_error(wrapper, flags TSRMLS_CC, error); efree(error); } - return 0; + return SUCCESS; } if (error) { efree(error); @@ -605,15 +605,17 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, /* root directory requested */ phar_dostat(phar, NULL, ssb, 1, phar->alias, phar->alias_len TSRMLS_CC); php_url_free(resource); - return 0; + return SUCCESS; } if (!phar->manifest.arBuckets) { php_url_free(resource); - return 0; + return SUCCESS; } /* search through the manifest of files, and if we have an exact match, it's a file */ if (SUCCESS == zend_hash_find(&phar->manifest, internal_file, strlen(internal_file), (void**)&entry)) { phar_dostat(phar, entry, ssb, 0, phar->alias, phar->alias_len TSRMLS_CC); + php_url_free(resource); + return SUCCESS; } else { /* search for directory (partial match of a file) */ zend_hash_internal_pointer_reset(&phar->manifest); @@ -625,7 +627,8 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, /* directory found, all dirs have the same stat */ if (key[strlen(internal_file)] == '/') { phar_dostat(phar, NULL, ssb, 1, phar->alias, phar->alias_len TSRMLS_CC); - break; + php_url_free(resource); + return SUCCESS; } } } @@ -636,7 +639,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, } php_url_free(resource); - return 0; + return FAILURE; } /* }}} */ diff --git a/ext/phar/tar.c b/ext/phar/tar.c index b8594a4e6d..d2249b22ea 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -170,7 +170,7 @@ int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, i myphar = (phar_archive_data *) ecalloc(1, sizeof(phar_archive_data)); zend_hash_init(&myphar->manifest, sizeof(phar_entry_info), - zend_get_hash_value, destroy_phar_manifest, 0); + zend_get_hash_value, destroy_phar_manifest_entry, 0); myphar->is_tar = 1; entry.is_tar = 1; diff --git a/ext/phar/tests/dir.phpt b/ext/phar/tests/dir.phpt index f642d6ddac..c5d9078d25 100644 --- a/ext/phar/tests/dir.phpt +++ b/ext/phar/tests/dir.phpt @@ -1,5 +1,5 @@ --TEST-- -Phar: mkdir test +Phar: mkdir/rmdir test --SKIPIF-- --INI-- @@ -9,17 +9,33 @@ phar.require_hash=0 isDir()); var_dump($phar['test/']->isDir()); +copy($fname, $fname2); mkdir($pname . '/another/dir/'); var_dump($phar['another/dir']->isDir()); +rmdir($pname . '/another/dir/'); +copy($fname, $fname3); +clearstatcache(); +var_dump(file_exists($pname . '/another/dir/')); +var_dump(file_exists($pname2 . '/test/')); +var_dump(file_exists($pname3 . '/another/dir/')); ?> --CLEAN-- + + --EXPECT-- bool(true) bool(true) bool(true) +bool(false) +bool(true) +bool(false) diff --git a/ext/phar/zip.c b/ext/phar/zip.c index a7e212c270..cc26e73140 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -113,7 +113,7 @@ int phar_open_zipfile(char *fname, int fname_len, char *alias, int alias_len, ph } /* set up our manifest */ zend_hash_init(&mydata->manifest, sizeof(phar_entry_info), - zend_get_hash_value, destroy_phar_manifest, 0); + zend_get_hash_value, destroy_phar_manifest_entry, 0); entry.phar = mydata; entry.is_zip = 1; /* prevent CRC checking */ -- 2.40.0