cellog Sun Jun 15 18:15:49 2008 UTC Modified files: (Branch: PHP_5_3) /php-src/ext/phar dirstream.c func_interceptors.c phar.c phar.phar phar_internal.h phar_object.c stream.c tar.c util.c zip.c Log: HUGE speed improvement, from 19 req/sec to 27 req/sec for phpMyAdmin - now speed with apc+phar.cache_list = on-disk speedcvs diff -u |less This is by generating a list of virtual directories and using those in stat calls instead of scanning the whole manifest hash table. on-disk phpMyAdmin = 28 req/sec
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/dirstream.c?r1=1.26.2.3&r2=1.26.2.4&diff_format=u Index: php-src/ext/phar/dirstream.c diff -u php-src/ext/phar/dirstream.c:1.26.2.3 php-src/ext/phar/dirstream.c:1.26.2.4 --- php-src/ext/phar/dirstream.c:1.26.2.3 Fri May 30 22:38:46 2008 +++ php-src/ext/phar/dirstream.c Sun Jun 15 18:15:48 2008 @@ -515,6 +515,7 @@ efree(error); return FAILURE; } + phar_add_virtual_dirs(phar, entry.filename, entry.filename_len TSRMLS_CC); return SUCCESS; } /* }}} */ @@ -589,12 +590,12 @@ 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 create directory \"%s\" in phar \"%s\", %s", entry->filename, phar->fname, error); - zend_hash_del(&phar->manifest, entry->filename, entry->filename_len); + 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; } + phar_delete_virtual_dirs(phar, resource->path + 1, strlen(resource->path) - 1 TSRMLS_CC); php_url_free(resource); return SUCCESS; } http://cvs.php.net/viewvc.cgi/php-src/ext/phar/func_interceptors.c?r1=1.20.2.3&r2=1.20.2.4&diff_format=u Index: php-src/ext/phar/func_interceptors.c diff -u php-src/ext/phar/func_interceptors.c:1.20.2.3 php-src/ext/phar/func_interceptors.c:1.20.2.4 --- php-src/ext/phar/func_interceptors.c:1.20.2.3 Thu Jun 12 18:46:58 2008 +++ php-src/ext/phar/func_interceptors.c Sun Jun 15 18:15:48 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: func_interceptors.c,v 1.20.2.3 2008/06/12 18:46:58 cellog Exp $ */ +/* $Id: func_interceptors.c,v 1.20.2.4 2008/06/15 18:15:48 cellog Exp $ */ #include "phar_internal.h" @@ -629,6 +629,26 @@ if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry, entry_len, (void **) &data)) { efree(entry); goto stat_entry; + } + if (SUCCESS == zend_hash_find(&((*pphar)->virtual_dirs), entry, entry_len, (void **) &data)) { + efree(entry); + efree(arch); + if (IS_EXISTS_CHECK(type)) { + RETURN_TRUE; + } + sb.st_size = 0; + sb.st_mode = 0777; + sb.st_mode |= S_IFDIR; /* regular directory */ +#ifdef NETWARE + sb.st_mtime.tv_sec = (*pphar)->max_timestamp; + sb.st_atime.tv_sec = (*pphar)->max_timestamp; + sb.st_ctime.tv_sec = (*pphar)->max_timestamp; +#else + sb.st_mtime = (*pphar)->max_timestamp; + sb.st_atime = (*pphar)->max_timestamp; + sb.st_ctime = (*pphar)->max_timestamp; +#endif + goto statme_baby; } else { char *save, *save2, *actual; int save_len, save2_len, actual_len; @@ -652,49 +672,36 @@ PHAR_G(cwd_len) = save_len; efree(entry); efree(save2); + if (IS_EXISTS_CHECK(type)) { + RETURN_TRUE; + } goto stat_entry; - } else { - phar_archive_data *phar = *pphar; - phar_zstr key; - char *str_key; - uint keylen; - ulong unused; - + } + if (SUCCESS == zend_hash_find(&((*pphar)->virtual_dirs), entry + 1, entry_len - 1, (void **) &data)) { PHAR_G(cwd) = save; PHAR_G(cwd_len) = save_len; - /* original not found either, this is possibly a directory relative to cwd */ - zend_hash_internal_pointer_reset(&phar->manifest); - while (FAILURE != zend_hash_has_more_elements(&phar->manifest)) { - if (HASH_KEY_NON_EXISTANT != - zend_hash_get_current_key_ex( - &phar->manifest, &key, &keylen, &unused, 0, NULL)) { - PHAR_STR(key, str_key); - if (!memcmp(actual, str_key, actual_len)) { - efree(save2); - efree(entry); - /* directory found, all dirs have the same stat */ - if (str_key[actual_len] == '/') { - sb.st_size = 0; - sb.st_mode = 0777; - sb.st_mode |= S_IFDIR; /* regular directory */ + efree(entry); + efree(save2); + efree(arch); + if (IS_EXISTS_CHECK(type)) { + RETURN_TRUE; + } + sb.st_size = 0; + sb.st_mode = 0777; + sb.st_mode |= S_IFDIR; /* regular directory */ #ifdef NETWARE - sb.st_mtime.tv_sec = phar->max_timestamp; - sb.st_atime.tv_sec = phar->max_timestamp; - sb.st_ctime.tv_sec = phar->max_timestamp; + sb.st_mtime.tv_sec = (*pphar)->max_timestamp; + sb.st_atime.tv_sec = (*pphar)->max_timestamp; + sb.st_ctime.tv_sec = (*pphar)->max_timestamp; #else - sb.st_mtime = phar->max_timestamp; - sb.st_atime = phar->max_timestamp; - sb.st_ctime = phar->max_timestamp; + sb.st_mtime = (*pphar)->max_timestamp; + sb.st_atime = (*pphar)->max_timestamp; + sb.st_ctime = (*pphar)->max_timestamp; #endif - goto statme_baby; - } - } - } - if (SUCCESS != zend_hash_move_forward(&phar->manifest)) { - break; - } - } + goto statme_baby; } + PHAR_G(cwd) = save; + PHAR_G(cwd_len) = save_len; efree(entry); efree(save2); efree(arch); http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar.c?r1=1.370.2.15&r2=1.370.2.16&diff_format=u Index: php-src/ext/phar/phar.c diff -u php-src/ext/phar/phar.c:1.370.2.15 php-src/ext/phar/phar.c:1.370.2.16 --- php-src/ext/phar/phar.c:1.370.2.15 Fri Jun 13 20:15:19 2008 +++ php-src/ext/phar/phar.c Sun Jun 15 18:15:48 2008 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: phar.c,v 1.370.2.15 2008/06/13 20:15:19 cellog Exp $ */ +/* $Id: phar.c,v 1.370.2.16 2008/06/15 18:15:48 cellog Exp $ */ #define PHAR_MAIN 1 #include "phar_internal.h" @@ -210,6 +210,10 @@ zend_hash_destroy(&phar->mounted_dirs); phar->mounted_dirs.arBuckets = NULL; } + if (phar->virtual_dirs.arBuckets) { + zend_hash_destroy(&phar->virtual_dirs); + phar->virtual_dirs.arBuckets = NULL; + } if (phar->metadata) { if (phar->is_persistent) { if (phar->metadata_len) { @@ -408,13 +412,16 @@ 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); } + if (!phar->donotflush) { phar_flush(phar, 0, 0, 0, error TSRMLS_CC); } @@ -959,6 +966,8 @@ zend_get_hash_value, destroy_phar_manifest_entry, mydata->is_persistent); zend_hash_init(&mydata->mounted_dirs, sizeof(char *), zend_get_hash_value, NULL, mydata->is_persistent); + zend_hash_init(&mydata->virtual_dirs, sizeof(char *), + zend_get_hash_value, NULL, mydata->is_persistent); offset = halt_offset + manifest_len + 4; memset(&entry, 0, sizeof(phar_entry_info)); entry.phar = mydata; @@ -981,6 +990,7 @@ } else { entry.is_dir = 0; } + phar_add_virtual_dirs(mydata, buffer, entry.filename_len TSRMLS_CC); entry.filename = pestrndup(buffer, entry.filename_len, entry.is_persistent); buffer += entry.filename_len; PHAR_GET_32(buffer, entry.uncompressed_filesize); @@ -1276,6 +1286,8 @@ zend_get_hash_value, destroy_phar_manifest_entry, 0); zend_hash_init(&mydata->mounted_dirs, sizeof(char *), zend_get_hash_value, NULL, 0); + zend_hash_init(&mydata->virtual_dirs, sizeof(char *), + zend_get_hash_value, NULL, mydata->is_persistent); mydata->fname_len = fname_len; snprintf(mydata->version, sizeof(mydata->version), "%s", PHP_PHAR_API_VERSION); mydata->is_temporary_alias = alias ? 0 : 1; @@ -3242,6 +3254,7 @@ } entry->metadata_str.c = 0; entry->filename = estrndup(entry->filename, entry->filename_len); + entry->is_persistent = 0; if (entry->metadata) { if (entry->metadata_len) { /* assume success, we would have failed before */ @@ -3385,7 +3398,7 @@ php_info_print_table_header(2, "Phar: PHP Archive support", "enabled"); php_info_print_table_row(2, "Phar EXT version", PHP_PHAR_VERSION); php_info_print_table_row(2, "Phar API version", PHP_PHAR_API_VERSION); - php_info_print_table_row(2, "CVS revision", "$Revision: 1.370.2.15 $"); + php_info_print_table_row(2, "CVS revision", "$Revision: 1.370.2.16 $"); php_info_print_table_row(2, "Phar-based phar archives", "enabled"); php_info_print_table_row(2, "Tar-based phar archives", "enabled"); php_info_print_table_row(2, "ZIP-based phar archives", "enabled"); http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar.phar?r1=1.7.2.14&r2=1.7.2.15&diff_format=u Index: php-src/ext/phar/phar.phar http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar_internal.h?r1=1.109.2.11&r2=1.109.2.12&diff_format=u Index: php-src/ext/phar/phar_internal.h diff -u php-src/ext/phar/phar_internal.h:1.109.2.11 php-src/ext/phar/phar_internal.h:1.109.2.12 --- php-src/ext/phar/phar_internal.h:1.109.2.11 Fri Jun 13 22:07:44 2008 +++ php-src/ext/phar/phar_internal.h Sun Jun 15 18:15:48 2008 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: phar_internal.h,v 1.109.2.11 2008/06/13 22:07:44 cellog Exp $ */ +/* $Id: phar_internal.h,v 1.109.2.12 2008/06/15 18:15:48 cellog Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -283,6 +283,8 @@ size_t internal_file_start; size_t halt_offset; HashTable manifest; + /* hash of virtual directories, as in path/to/file.txt has path/to and path as virtual directories */ + HashTable virtual_dirs; /* hash of mounted directory paths */ HashTable mounted_dirs; php_uint32 flags; @@ -428,6 +430,8 @@ 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); http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar_object.c?r1=1.266.2.19&r2=1.266.2.20&diff_format=u Index: php-src/ext/phar/phar_object.c diff -u php-src/ext/phar/phar_object.c:1.266.2.19 php-src/ext/phar/phar_object.c:1.266.2.20 --- php-src/ext/phar/phar_object.c:1.266.2.19 Fri Jun 13 22:07:44 2008 +++ php-src/ext/phar/phar_object.c Sun Jun 15 18:15:48 2008 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: phar_object.c,v 1.266.2.19 2008/06/13 22:07:44 cellog Exp $ */ +/* $Id: phar_object.c,v 1.266.2.20 2008/06/15 18:15:48 cellog Exp $ */ #include "phar_internal.h" #include "func_interceptors.h" @@ -2040,6 +2040,10 @@ zend_hash_init(&(phar->manifest), sizeof(phar_entry_info), zend_get_hash_value, destroy_phar_manifest_entry, 0); + zend_hash_init(&phar->mounted_dirs, sizeof(char *), + zend_get_hash_value, NULL, 0); + zend_hash_init(&phar->virtual_dirs, sizeof(char *), + zend_get_hash_value, NULL, 0); phar->fp = php_stream_fopen_tmpfile(); phar->fname = source->fname; @@ -2101,12 +2105,15 @@ newentry.phar = phar; newentry.old_flags = newentry.flags & ~PHAR_ENT_COMPRESSION_MASK; /* remove compression from old_flags */ zend_hash_add(&(phar->manifest), newentry.filename, newentry.filename_len, (void*)&newentry, sizeof(phar_entry_info), NULL); + phar_add_virtual_dirs(phar, newentry.filename, newentry.filename_len TSRMLS_CC); } if ((ret = phar_rename_archive(phar, ext, 0 TSRMLS_CC))) { return ret; } else { zend_hash_destroy(&(phar->manifest)); + zend_hash_destroy(&(phar->mounted_dirs)); + zend_hash_destroy(&(phar->virtual_dirs)); php_stream_close(phar->fp); efree(phar->fname); efree(phar); http://cvs.php.net/viewvc.cgi/php-src/ext/phar/stream.c?r1=1.27.2.3&r2=1.27.2.4&diff_format=u Index: php-src/ext/phar/stream.c diff -u php-src/ext/phar/stream.c:1.27.2.3 php-src/ext/phar/stream.c:1.27.2.4 --- php-src/ext/phar/stream.c:1.27.2.3 Fri May 30 22:38:46 2008 +++ php-src/ext/phar/stream.c Sun Jun 15 18:15:48 2008 @@ -842,6 +842,9 @@ 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); http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tar.c?r1=1.55.2.7&r2=1.55.2.8&diff_format=u Index: php-src/ext/phar/tar.c diff -u php-src/ext/phar/tar.c:1.55.2.7 php-src/ext/phar/tar.c:1.55.2.8 --- php-src/ext/phar/tar.c:1.55.2.7 Fri Jun 13 22:28:55 2008 +++ php-src/ext/phar/tar.c Sun Jun 15 18:15:48 2008 @@ -220,6 +220,8 @@ zend_get_hash_value, destroy_phar_manifest_entry, myphar->is_persistent); zend_hash_init(&myphar->mounted_dirs, sizeof(char *), zend_get_hash_value, NULL, myphar->is_persistent); + zend_hash_init(&myphar->virtual_dirs, sizeof(char *), + zend_get_hash_value, NULL, myphar->is_persistent); myphar->is_tar = 1; /* remember whether this entire phar was compressed with gz/bzip2 */ myphar->flags = compression; @@ -255,6 +257,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, myphar->is_persistent); return FAILURE; } @@ -296,6 +300,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, myphar->is_persistent); return FAILURE; } @@ -310,6 +316,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, myphar->is_persistent); return FAILURE; } @@ -348,6 +356,7 @@ entry.filename_len--; } } + phar_add_virtual_dirs(myphar, entry.filename, entry.filename_len TSRMLS_CC); if (sum1 != sum2) { if (error) { spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (checksum mismatch of file \"%s\")", fname, entry.filename); @@ -358,6 +367,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, myphar->is_persistent); return FAILURE; } @@ -393,6 +404,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, entry.is_persistent); return FAILURE; } @@ -411,6 +424,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, myphar->is_persistent); return FAILURE; } @@ -427,6 +442,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, myphar->is_persistent); return FAILURE; } @@ -448,6 +465,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, myphar->is_persistent); return FAILURE; } @@ -464,6 +483,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, myphar->is_persistent); return FAILURE; } @@ -481,6 +502,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, myphar->is_persistent); return FAILURE; } @@ -495,6 +518,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, myphar->is_persistent); return FAILURE; } @@ -507,6 +532,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, myphar->is_persistent); if (error) { spprintf(error, 0, "tar-based phar \"%s\" does not have a signature", fname); @@ -546,6 +573,8 @@ myphar->manifest.arBuckets = 0; zend_hash_destroy(&myphar->mounted_dirs); myphar->mounted_dirs.arBuckets = 0; + zend_hash_destroy(&myphar->virtual_dirs); + myphar->virtual_dirs.arBuckets = 0; pefree(myphar, myphar->is_persistent); return FAILURE; } http://cvs.php.net/viewvc.cgi/php-src/ext/phar/util.c?r1=1.55.2.8&r2=1.55.2.9&diff_format=u Index: php-src/ext/phar/util.c diff -u php-src/ext/phar/util.c:1.55.2.8 php-src/ext/phar/util.c:1.55.2.9 --- php-src/ext/phar/util.c:1.55.2.8 Fri Jun 13 22:07:44 2008 +++ php-src/ext/phar/util.c Sun Jun 15 18:15:48 2008 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: util.c,v 1.55.2.8 2008/06/13 22:07:44 cellog Exp $ */ +/* $Id: util.c,v 1.55.2.9 2008/06/15 18:15:48 cellog Exp $ */ #include "phar_internal.h" #ifdef PHAR_HAVE_OPENSSL @@ -689,6 +689,7 @@ } else { etemp.flags = etemp.old_flags = PHAR_ENT_PERM_DEF_FILE; } + phar_add_virtual_dirs(phar, path, path_len TSRMLS_CC); etemp.is_modified = 1; etemp.timestamp = time(0); etemp.is_crc_checked = 1; @@ -1217,7 +1218,20 @@ return NULL; } return entry; - } else if (phar->mounted_dirs.arBuckets && zend_hash_num_elements(&phar->mounted_dirs)) { + } + if (dir) { + if (SUCCESS == zend_hash_find(&phar->virtual_dirs, path, path_len, (void**)&entry)) { + /* a file or directory exists in a sub-directory of this path */ + entry = (phar_entry_info *) ecalloc(1, sizeof(phar_entry_info)); + /* this next line tells PharFileInfo->__destruct() to efree the filename */ + entry->is_temp_dir = entry->is_dir = 1; + entry->filename = (char *) estrndup(path, path_len + 1); + entry->filename_len = path_len; + entry->phar = phar; + return entry; + } + } + if (phar->mounted_dirs.arBuckets && zend_hash_num_elements(&phar->mounted_dirs)) { phar_zstr key; char *str_key; ulong unused; @@ -1290,50 +1304,6 @@ } } } - if (dir) { - /* try to find a directory */ - HashTable *manifest; - phar_zstr key; - char *str_key; - uint keylen; - ulong unused; - - if (!path_len) { - path = "/"; - } - manifest = &phar->manifest; - zend_hash_internal_pointer_reset(manifest); - while (FAILURE != zend_hash_has_more_elements(manifest)) { - if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(manifest, &key, &keylen, &unused, 0, NULL)) { - break; - } - - PHAR_STR(key, str_key); - - if (0 != memcmp(str_key, path, path_len)) { - /* entry in directory not found */ - if (SUCCESS != zend_hash_move_forward(manifest)) { - break; - } - continue; - } else { - if (str_key[path_len] != '/') { - if (SUCCESS != zend_hash_move_forward(manifest)) { - break; - } - continue; - } - /* found a file in this path */ - entry = (phar_entry_info *) ecalloc(1, sizeof(phar_entry_info)); - /* this next line tells PharFileInfo->__destruct() to efree the filename */ - entry->is_temp_dir = entry->is_dir = 1; - entry->filename = (char *) estrndup(path, path_len + 1); - entry->filename_len = path_len; - entry->phar = phar; - return entry; - } - } - } return NULL; } /* }}} */ @@ -1846,3 +1816,55 @@ return SUCCESS; } /* }}} */ + +/** + * 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) /* {{{ */ +{ + void *dummy = (void *) 1; + if (SUCCESS == zend_hash_find(ht, arKey, nKeyLength, (void **)&dummy)) { + dummy++; + } + + return zend_hash_update(ht, arKey, nKeyLength, &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); + } + } +} +/* }}} */ + +void phar_delete_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 == '/') { + void *dummy; + if (FAILURE == zend_hash_find(&phar->virtual_dirs, filename, s - filename, (void **)&dummy)) { + continue; + } + + if (!--dummy) { + zend_hash_del(&phar->virtual_dirs, filename, s - filename); + } else { + zend_hash_update(&phar->virtual_dirs, filename, s - filename, &dummy, sizeof(void *), NULL); + } + } + } +} +/* }}} */ http://cvs.php.net/viewvc.cgi/php-src/ext/phar/zip.c?r1=1.47.2.5&r2=1.47.2.6&diff_format=u Index: php-src/ext/phar/zip.c diff -u php-src/ext/phar/zip.c:1.47.2.5 php-src/ext/phar/zip.c:1.47.2.6 --- php-src/ext/phar/zip.c:1.47.2.5 Thu Jun 12 18:56:23 2008 +++ php-src/ext/phar/zip.c Sun Jun 15 18:15:48 2008 @@ -258,6 +258,8 @@ zend_get_hash_value, destroy_phar_manifest_entry, mydata->is_persistent); zend_hash_init(&mydata->mounted_dirs, sizeof(char *), zend_get_hash_value, NULL, mydata->is_persistent); + zend_hash_init(&mydata->virtual_dirs, sizeof(char *), + zend_get_hash_value, NULL, mydata->is_persistent); entry.phar = mydata; entry.is_zip = 1; entry.fp_type = PHAR_FP; @@ -267,6 +269,8 @@ mydata->manifest.arBuckets = 0; \ zend_hash_destroy(&mydata->mounted_dirs); \ mydata->mounted_dirs.arBuckets = 0; \ + zend_hash_destroy(&mydata->virtual_dirs); \ + mydata->virtual_dirs.arBuckets = 0; \ php_stream_close(fp); \ if (mydata->metadata) { \ zval_dtor(mydata->metadata); \ @@ -322,6 +326,7 @@ } else { entry.is_dir = 0; } + phar_add_virtual_dirs(mydata, entry.filename, entry.filename_len TSRMLS_CC); if (PHAR_GET_16(zipentry.extra_len)) { off_t loc = php_stream_tell(fp); if (FAILURE == phar_zip_process_extra(fp, &entry, PHAR_GET_16(zipentry.extra_len) TSRMLS_CC)) {
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php