/* 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;
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);
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))) {
}
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));
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;
}
/* }}} */
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;
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);
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);
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;
}
/* }}} */
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);
}
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);
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;
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 */
phar_archive_data *phar, *pfrom, *pto;
phar_entry_info *entry;
uint host_len;
+ int is_dir = 0;
+ int is_modified = 0;
error = NULL;
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;
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
--- /dev/null
+--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)
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)
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
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)
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
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)
}
/* }}} */
-/**
- * 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;
}
}
}