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(&central, 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

Reply via email to