cellog Sun Oct 12 19:40:30 2008 UTC
Modified files:
/php-src/ext/phar dirstream.c phar.c phar_internal.h phar_object.c
tar.c util.c zip.c
/php-src/ext/phar/tests/cache_list copyonwrite2.phar.phpt
copyonwrite3.phar.phpt
/php-src/ext/phar/tests/cache_list/files write2.phar write3.phar
Log:
MFB: add tests for copy-on-write support
- fix metadata handling with cached phars
- fix virtual_dirs with rmdir
- ensure that after copy-on-write, all existing Phar objects link to the
newly copied phar data
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/dirstream.c?r1=1.33&r2=1.34&diff_format=u
Index: php-src/ext/phar/dirstream.c
diff -u php-src/ext/phar/dirstream.c:1.33 php-src/ext/phar/dirstream.c:1.34
--- php-src/ext/phar/dirstream.c:1.33 Sat Sep 13 22:31:18 2008
+++ php-src/ext/phar/dirstream.c Sun Oct 12 19:40:29 2008
@@ -507,12 +507,6 @@
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 0;
- }
-
memset((void *) &entry, 0, sizeof(phar_entry_info));
/* strip leading "/" */
@@ -631,50 +625,43 @@
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 0;
- }
-
- for (zend_hash_internal_pointer_reset(&phar->manifest);
+ if (!entry->is_deleted) {
+ for (zend_hash_internal_pointer_reset(&phar->manifest);
HASH_KEY_NON_EXISTANT !=
zend_hash_get_current_key_ex(&phar->manifest, &key, &key_len, &unused, 0, NULL);
zend_hash_move_forward(&phar->manifest)) {
- PHAR_STR(key, str_key);
+ PHAR_STR(key, str_key);
- if (!entry->is_deleted &&
- key_len > path_len &&
- memcmp(str_key, resource->path+1, path_len) == 0 &&
- IS_SLASH(str_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);
+ if (key_len > path_len &&
+ memcmp(str_key, resource->path+1, path_len) ==
0 &&
+ IS_SLASH(str_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;
}
- php_url_free(resource);
- return 0;
}
- }
- for (zend_hash_internal_pointer_reset(&phar->virtual_dirs);
- HASH_KEY_NON_EXISTANT !=
zend_hash_get_current_key_ex(&phar->virtual_dirs, &key, &key_len, &unused, 0,
NULL);
- zend_hash_move_forward(&phar->virtual_dirs)) {
-
- PHAR_STR(key, str_key);
-
- if (!entry->is_deleted &&
- key_len > path_len &&
- memcmp(str_key, resource->path+1, path_len) == 0 &&
- IS_SLASH(str_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);
+ for (zend_hash_internal_pointer_reset(&phar->virtual_dirs);
+ HASH_KEY_NON_EXISTANT !=
zend_hash_get_current_key_ex(&phar->virtual_dirs, &key, &key_len, &unused, 0,
NULL);
+ zend_hash_move_forward(&phar->virtual_dirs)) {
+
+ PHAR_STR(key, str_key);
+
+ if (key_len > path_len &&
+ memcmp(str_key, resource->path+1, path_len) ==
0 &&
+ IS_SLASH(str_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;
}
- php_url_free(resource);
- return 0;
}
}
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar.c?r1=1.388&r2=1.389&diff_format=u
Index: php-src/ext/phar/phar.c
diff -u php-src/ext/phar/phar.c:1.388 php-src/ext/phar/phar.c:1.389
--- php-src/ext/phar/phar.c:1.388 Thu Oct 9 00:51:27 2008
+++ php-src/ext/phar/phar.c Sun Oct 12 19:40:29 2008
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: phar.c,v 1.388 2008/10/09 00:51:27 cellog Exp $ */
+/* $Id: phar.c,v 1.389 2008/10/12 19:40:29 cellog Exp $ */
#define PHAR_MAIN 1
#include "phar_internal.h"
@@ -637,9 +637,7 @@
zval_ptr_dtor(metadata);
*metadata = (zval *) pemalloc(buf_len, 1);
memcpy(*metadata, *buffer, buf_len);
- if (!zip_metadata_len) {
- *buffer += buf_len;
- }
+ *buffer += buf_len;
return SUCCESS;
}
} else {
@@ -1036,9 +1034,7 @@
/* check whether we have meta data, zero check works regardless of byte
order */
if (mydata->is_persistent) {
- char *mysave = buffer;
PHAR_GET_32(buffer, mydata->metadata_len);
- buffer = mysave;
if (phar_parse_metadata(&buffer, &mydata->metadata,
mydata->metadata_len TSRMLS_CC) == FAILURE) {
MAPPHAR_FAIL("unable to read phar metadata in .phar
file \"%s\"");
}
@@ -2562,6 +2558,8 @@
return EOF;
}
+ zend_hash_clean(&phar->virtual_dirs);
+
if (phar->is_zip) {
return phar_zip_flush(phar, user_stub, len, convert, error
TSRMLS_CC);
}
@@ -2739,6 +2737,7 @@
}
/* after excluding deleted files, calculate manifest size in
bytes and number of entries */
++new_manifest_count;
+ phar_add_virtual_dirs(phar, entry->filename,
entry->filename_len);
if (entry->is_dir) {
/* we use this to calculate API version, 1.1.1 is used
for phars with directories */
@@ -3545,6 +3544,7 @@
PHAR_GLOBALS->request_ends = 0;
PHAR_GLOBALS->request_done = 0;
zend_hash_init(&(PHAR_GLOBALS->phar_fname_map), 5,
zend_get_hash_value, destroy_phar_data, 0);
+ zend_hash_init(&(PHAR_GLOBALS->phar_persist_map), 5,
zend_get_hash_value, NULL, 0);
zend_hash_init(&(PHAR_GLOBALS->phar_alias_map), 5,
zend_get_hash_value, NULL, 0);
if (PHAR_G(manifest_cached)) {
@@ -3581,6 +3581,8 @@
PHAR_GLOBALS->phar_alias_map.arBuckets = NULL;
zend_hash_destroy(&(PHAR_GLOBALS->phar_fname_map));
PHAR_GLOBALS->phar_fname_map.arBuckets = NULL;
+ zend_hash_destroy(&(PHAR_GLOBALS->phar_persist_map));
+ PHAR_GLOBALS->phar_persist_map.arBuckets = NULL;
PHAR_GLOBALS->phar_SERVER_mung_list = 0;
if (PHAR_GLOBALS->cached_fp) {
@@ -3620,7 +3622,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.388 $");
+ php_info_print_table_row(2, "CVS revision", "$Revision: 1.389 $");
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_internal.h?r1=1.119&r2=1.120&diff_format=u
Index: php-src/ext/phar/phar_internal.h
diff -u php-src/ext/phar/phar_internal.h:1.119
php-src/ext/phar/phar_internal.h:1.120
--- php-src/ext/phar/phar_internal.h:1.119 Thu Oct 9 00:51:27 2008
+++ php-src/ext/phar/phar_internal.h Sun Oct 12 19:40:29 2008
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: phar_internal.h,v 1.119 2008/10/09 00:51:27 cellog Exp $ */
+/* $Id: phar_internal.h,v 1.120 2008/10/12 19:40:29 cellog Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -150,6 +150,9 @@
typedef struct _phar_archive_data phar_archive_data;
ZEND_BEGIN_MODULE_GLOBALS(phar)
+ /* a list of phar_archive_data objects that reference a cached phar, so
+ that if copy-on-write is performed, we can swap them out for the new
value */
+ HashTable phar_persist_map;
HashTable phar_fname_map;
/* for cached phars, this is a per-process store of fp/ufp */
phar_entry_fp *cached_fp;
@@ -593,6 +596,7 @@
char *phar_decompress_filter(phar_entry_info * entry, int return_unknown);
char *phar_compress_filter(phar_entry_info * entry, int return_unknown);
+void phar_remove_virtual_dirs(phar_archive_data *phar, char *filename, int
filename_len TSRMLS_DC);
void phar_add_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);
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar_object.c?r1=1.286&r2=1.287&diff_format=u
Index: php-src/ext/phar/phar_object.c
diff -u php-src/ext/phar/phar_object.c:1.286
php-src/ext/phar/phar_object.c:1.287
--- php-src/ext/phar/phar_object.c:1.286 Sun Oct 12 06:53:51 2008
+++ php-src/ext/phar/phar_object.c Sun Oct 12 19:40:29 2008
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: phar_object.c,v 1.286 2008/10/12 06:53:51 cellog Exp $ */
+/* $Id: phar_object.c,v 1.287 2008/10/12 19:40:29 cellog Exp $ */
#include "phar_internal.h"
#include "func_interceptors.h"
@@ -1254,6 +1254,9 @@
if (!phar_data->is_persistent) {
phar_obj->arc.archive->is_data = is_data;
+ } else if (!EG(exception)) {
+ /* register this guy so we can modify if necessary */
+ zend_hash_add(&PHAR_GLOBALS->phar_persist_map, (const char *)
phar_obj->arc.archive, sizeof(phar_obj->arc.archive), (void *) &phar_obj,
sizeof(phar_archive_object **), NULL);
}
phar_obj->spl.info_class = phar_ce_entry;
@@ -1378,6 +1381,19 @@
return; \
}
+/* {{{ proto void Phar::__destruct()
+ * if persistent, remove from the cache
+ */
+PHP_METHOD(Phar, __destruct)
+{
+ phar_archive_object *phar_obj =
(phar_archive_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (phar_obj->arc.archive && phar_obj->arc.archive->is_persistent) {
+ zend_hash_del(&PHAR_GLOBALS->phar_persist_map, (const char *)
&(phar_obj->arc.archive), sizeof(&(phar_obj->arc.archive)));
+ }
+}
+/* }}} */
+
struct _phar_t {
phar_archive_object *p;
zend_class_entry *c;
@@ -3923,6 +3939,15 @@
PHAR_ARCHIVE_OBJECT();
if (phar_obj->arc.archive->metadata) {
+ if (phar_obj->arc.archive->is_persistent) {
+ zval *ret;
+ char *buf = estrndup((char *)
phar_obj->arc.archive->metadata, phar_obj->arc.archive->metadata_len);
+ /* assume success, we would have failed before */
+ phar_parse_metadata(&buf, &ret,
phar_obj->arc.archive->metadata_len TSRMLS_CC);
+ efree(buf);
+ RETURN_ZVAL(ret, 0, 1);
+ return;
+ }
RETURN_ZVAL(phar_obj->arc.archive->metadata, 1, 0);
}
}
@@ -5098,6 +5123,7 @@
PHP_ME(Phar, __construct, arginfo_phar___construct,
ZEND_ACC_PRIVATE)
#else
PHP_ME(Phar, __construct, arginfo_phar___construct,
ZEND_ACC_PUBLIC)
+ PHP_ME(Phar, __destruct, NULL,
ZEND_ACC_PUBLIC)
PHP_ME(Phar, addEmptyDir, arginfo_phar_emptydir,
ZEND_ACC_PUBLIC)
PHP_ME(Phar, addFile, arginfo_phar_addfile,
ZEND_ACC_PUBLIC)
PHP_ME(Phar, addFromString, arginfo_phar_fromstring,
ZEND_ACC_PUBLIC)
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tar.c?r1=1.62&r2=1.63&diff_format=u
Index: php-src/ext/phar/tar.c
diff -u php-src/ext/phar/tar.c:1.62 php-src/ext/phar/tar.c:1.63
--- php-src/ext/phar/tar.c:1.62 Sat Sep 13 22:31:18 2008
+++ php-src/ext/phar/tar.c Sun Oct 12 19:40:29 2008
@@ -620,6 +620,7 @@
}
}
+ phar_add_virtual_dirs(entry->phar, entry->filename,
entry->filename_len);
memset((char *) &header, 0, sizeof(header));
if (entry->filename_len > 100) {
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/util.c?r1=1.67&r2=1.68&diff_format=u
Index: php-src/ext/phar/util.c
diff -u php-src/ext/phar/util.c:1.67 php-src/ext/phar/util.c:1.68
--- php-src/ext/phar/util.c:1.67 Sat Oct 11 22:12:18 2008
+++ php-src/ext/phar/util.c Sun Oct 12 19:40:29 2008
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: util.c,v 1.67 2008/10/11 22:12:18 cellog Exp $ */
+/* $Id: util.c,v 1.68 2008/10/12 19:40:29 cellog Exp $ */
#include "phar_internal.h"
@@ -2219,8 +2219,10 @@
if (entry->metadata) {
if (entry->metadata_len) {
+ char *buf = estrndup((char *) entry->metadata,
entry->metadata_len);
/* assume success, we would have failed before */
phar_parse_metadata((char **) &entry->metadata,
&entry->metadata, entry->metadata_len TSRMLS_CC);
+ efree(buf);
} else {
zval *t;
@@ -2245,6 +2247,7 @@
phar_archive_data *phar;
HashTable newmanifest;
char *fname;
+ phar_archive_object **objphar;
phar = (phar_archive_data *) emalloc(sizeof(phar_archive_data));
*phar = **pphar;
@@ -2264,7 +2267,9 @@
if (phar->metadata) {
/* assume success, we would have failed before */
if (phar->metadata_len) {
- phar_parse_metadata((char **) &phar->metadata,
&phar->metadata, phar->metadata_len TSRMLS_CC);
+ char *buf = estrndup((char *) phar->metadata,
phar->metadata_len);
+ phar_parse_metadata(&buf, &phar->metadata,
phar->metadata_len TSRMLS_CC);
+ efree(buf);
} else {
zval *t;
@@ -2291,6 +2296,15 @@
zend_get_hash_value, NULL, 0);
zend_hash_copy(&phar->virtual_dirs, &(*pphar)->virtual_dirs, NULL,
NULL, sizeof(void *));
*pphar = phar;
+
+ /* now, scan the list of persistent Phar objects referencing this phar
and update the pointers */
+ for (zend_hash_internal_pointer_reset(&PHAR_GLOBALS->phar_persist_map);
+ SUCCESS == zend_hash_get_current_data(&PHAR_GLOBALS->phar_persist_map,
(void **) &objphar);
+ zend_hash_move_forward(&PHAR_GLOBALS->phar_persist_map)) {
+ if (objphar[0]->arc.archive->fname_len == phar->fname_len &&
!memcmp(objphar[0]->arc.archive->fname, phar->fname, phar->fname_len)) {
+ objphar[0]->arc.archive = phar;
+ }
+ }
}
/* }}} */
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/zip.c?r1=1.57&r2=1.58&diff_format=u
Index: php-src/ext/phar/zip.c
diff -u php-src/ext/phar/zip.c:1.57 php-src/ext/phar/zip.c:1.58
--- php-src/ext/phar/zip.c:1.57 Sat Oct 11 21:23:13 2008
+++ php-src/ext/phar/zip.c Sun Oct 12 19:40:29 2008
@@ -704,6 +704,7 @@
}
}
+ phar_add_virtual_dirs(entry->phar, entry->filename,
entry->filename_len);
memset(&local, 0, sizeof(local));
memset(¢ral, 0, sizeof(central));
memset(&perms, 0, sizeof(perms));
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/cache_list/copyonwrite2.phar.phpt?r1=1.1&r2=1.2&diff_format=u
Index: php-src/ext/phar/tests/cache_list/copyonwrite2.phar.phpt
diff -u /dev/null php-src/ext/phar/tests/cache_list/copyonwrite2.phar.phpt:1.2
--- /dev/null Sun Oct 12 19:40:30 2008
+++ php-src/ext/phar/tests/cache_list/copyonwrite2.phar.phpt Sun Oct 12
19:40:30 2008
@@ -0,0 +1,17 @@
+--TEST--
+Phar: copy-on-write test 2 [cache_list]
+--INI--
+default_charset=UTF-8
+phar.cache_list={PWD}/copyonwrite2.phar.php
+phar.readonly=0
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--FILE_EXTERNAL--
+files/write2.phar
+--EXPECT--
+string(2) "hi"
+bool(true)
+string(2) "hi"
+bool(true)
+bool(true)
+ok
\ No newline at end of file
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/cache_list/copyonwrite3.phar.phpt?r1=1.1&r2=1.2&diff_format=u
Index: php-src/ext/phar/tests/cache_list/copyonwrite3.phar.phpt
diff -u /dev/null php-src/ext/phar/tests/cache_list/copyonwrite3.phar.phpt:1.2
--- /dev/null Sun Oct 12 19:40:30 2008
+++ php-src/ext/phar/tests/cache_list/copyonwrite3.phar.phpt Sun Oct 12
19:40:30 2008
@@ -0,0 +1,16 @@
+--TEST--
+Phar: copy-on-write test 3 [cache_list]
+--INI--
+default_charset=UTF-8
+phar.cache_list={PWD}/copyonwrite3.phar.php
+phar.readonly=0
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--FILE_EXTERNAL--
+files/write3.phar
+--EXPECT--
+bool(true)
+bool(true)
+bool(false)
+bool(false)
+ok
\ No newline at end of file
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/cache_list/files/write2.phar?r1=1.1&r2=1.2&diff_format=u
Index: php-src/ext/phar/tests/cache_list/files/write2.phar
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/cache_list/files/write3.phar?r1=1.1&r2=1.2&diff_format=u
Index: php-src/ext/phar/tests/cache_list/files/write3.phar
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php