From e324e11452e1a7eafc2a8a2563fb7f78f9eb5f6c Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Wed, 8 Mar 2006 20:07:25 +0000 Subject: [PATCH] - Initial refcounting --- ext/phar/phar.c | 80 ++++++++++++++++++------------- ext/phar/tests/phar_oo_007.phpt | 84 +++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 33 deletions(-) create mode 100755 ext/phar/tests/phar_oo_007.phpt diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 3c11f57885..6e4de6ebb8 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -181,18 +181,31 @@ static void phar_destroy_phar_data(phar_archive_data *data TSRMLS_DC) /* {{{ */ php_stream_close(data->fp); } data->fp = 0; + efree(data); } /* }}}*/ static void destroy_phar_data(void *pDest) /* {{{ */ { - phar_archive_data *phar_data = (phar_archive_data *) pDest; + phar_archive_data *phar_data = *(phar_archive_data **) pDest; TSRMLS_FETCH(); - phar_destroy_phar_data(phar_data TSRMLS_CC); + if (--phar_data->refcount < 0) { + phar_destroy_phar_data(phar_data TSRMLS_CC); + } } /* }}}*/ +static void phar_spl_foreign_dtor(spl_filesystem_object *object TSRMLS_DC) /* {{{ */ +{ + phar_archive_data *phar_data = (phar_archive_data *) object->oth; + + if (--phar_data->refcount < 0) { + phar_destroy_phar_data(phar_data TSRMLS_CC); + } +} +/* }}} */ + static void destroy_phar_manifest(void *pDest) /* {{{ */ { phar_entry_info *entry = (phar_entry_info *)pDest; @@ -221,7 +234,8 @@ static phar_archive_data * phar_get_archive(char *fname, int fname_len, char *al } } if (fname && fname_len) { - if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void**)&fd)) { + if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void**)&fd_ptr)) { + fd = *fd_ptr; if (alias && alias_len) { zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&fd, sizeof(phar_archive_data*), NULL); } @@ -321,8 +335,7 @@ PHP_METHOD(Phar, canCompress) static int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, long halt_offset, phar_archive_data** pphar TSRMLS_DC) /* {{{ */ { char b32[4], *buffer, *endbuffer, *savebuf; - phar_archive_data mydata; - phar_archive_data *phar; + phar_archive_data *mydata; phar_entry_info entry; php_uint32 manifest_len, manifest_count, manifest_index, tmp_len; php_uint16 manifest_tag; @@ -334,17 +347,17 @@ static int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alia *pphar = NULL; } - if ((phar = phar_get_archive(fname, fname_len, alias, alias_len TSRMLS_CC)) != NULL) { + if ((mydata = phar_get_archive(fname, fname_len, alias, alias_len TSRMLS_CC)) != NULL) { /* Overloading or reloading an archive would only be possible if we */ /* refcount everything to be sure no stream for any file in the */ /* archive is open. */ - if (fname_len != phar->fname_len || strncmp(fname, phar->fname, fname_len)) { + if (fname_len != mydata->fname_len || strncmp(fname, mydata->fname, fname_len)) { php_stream_close(fp); - php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, phar->fname, fname); + php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, mydata->fname, fname); return FAILURE; } else { if (pphar) { - *pphar = phar; + *pphar = mydata; } php_stream_close(fp); return SUCCESS; @@ -459,11 +472,12 @@ static int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alia } /* set up our manifest */ - zend_hash_init(&mydata.manifest, sizeof(phar_entry_info), + mydata = emalloc(sizeof(phar_archive_data)); + zend_hash_init(&mydata->manifest, sizeof(phar_entry_info), zend_get_hash_value, destroy_phar_manifest, 0); offset = 0; - mydata.min_timestamp = 0; - mydata.max_timestamp = 0; + mydata->min_timestamp = 0; + mydata->max_timestamp = 0; for (manifest_index = 0; manifest_index < manifest_count; manifest_index++) { if (buffer + 4 > endbuffer) { MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)") @@ -480,13 +494,13 @@ static int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alia PHAR_GET_32(buffer, entry.uncompressed_filesize); PHAR_GET_32(buffer, entry.timestamp); if (offset == 0) { - mydata.min_timestamp = entry.timestamp; - mydata.max_timestamp = entry.timestamp; + mydata->min_timestamp = entry.timestamp; + mydata->max_timestamp = entry.timestamp; } else { - if (mydata.min_timestamp > entry.timestamp) { - mydata.min_timestamp = entry.timestamp; - } else if (mydata.max_timestamp < entry.timestamp) { - mydata.max_timestamp = entry.timestamp; + if (mydata->min_timestamp > entry.timestamp) { + mydata->min_timestamp = entry.timestamp; + } else if (mydata->max_timestamp < entry.timestamp) { + mydata->max_timestamp = entry.timestamp; } } PHAR_GET_32(buffer, entry.compressed_filesize); @@ -515,25 +529,26 @@ static int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alia } entry.crc_checked = 0; entry.fp = NULL; - zend_hash_add(&mydata.manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL); - } - - mydata.fname = estrndup(fname, fname_len); - mydata.fname_len = fname_len; - mydata.alias = alias ? estrndup(alias, alias_len) : mydata.fname; - mydata.alias_len = alias ? alias_len : fname_len; - snprintf(mydata.version, sizeof(mydata.version), "%u.%u.%u", manifest_tag >> 12, (manifest_tag >> 8) & 0xF, (manifest_tag >> 4) & 0xF); - mydata.internal_file_start = halt_offset + manifest_len + 4; - mydata.has_compressed_files = compressed; - mydata.fp = fp; - zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void*)&mydata, sizeof(phar_archive_data), (void**)&phar); + zend_hash_add(&mydata->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), NULL); + } + + mydata->fname = estrndup(fname, fname_len); + mydata->fname_len = fname_len; + mydata->alias = alias ? estrndup(alias, alias_len) : mydata->fname; + mydata->alias_len = alias ? alias_len : fname_len; + snprintf(mydata->version, sizeof(mydata->version), "%u.%u.%u", manifest_tag >> 12, (manifest_tag >> 8) & 0xF, (manifest_tag >> 4) & 0xF); + mydata->internal_file_start = halt_offset + manifest_len + 4; + mydata->has_compressed_files = compressed; + mydata->fp = fp; + mydata->refcount = 0; + zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void*)&mydata, sizeof(phar_archive_data), NULL); if (register_alias) { - zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&phar, sizeof(phar_archive_data*), NULL); + zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL); } efree(savebuf); if (pphar) { - *pphar = phar; + *pphar = mydata; } return SUCCESS; @@ -1818,7 +1833,6 @@ PHP_RINIT_FUNCTION(phar) /* {{{ */ PHP_RSHUTDOWN_FUNCTION(phar) /* {{{ */ { -/* zend_hash_apply(&(PHAR_GLOBALS->phar_fname_map), phar_apply_destroy TSRMLS_CC);*/ zend_hash_destroy(&(PHAR_GLOBALS->phar_alias_map)); zend_hash_destroy(&(PHAR_GLOBALS->phar_fname_map)); return SUCCESS; diff --git a/ext/phar/tests/phar_oo_007.phpt b/ext/phar/tests/phar_oo_007.phpt new file mode 100755 index 0000000000..6a2565220a --- /dev/null +++ b/ext/phar/tests/phar_oo_007.phpt @@ -0,0 +1,84 @@ +--TEST-- +Phar object: access through SplFileObject +--SKIPIF-- + +--FILE-- +setFileClass('MyFile'); + +$f = $phar['a.php']; + +$s = $f->fstat(); + +var_dump($s['atime']); +var_dump($s['ctime']); +var_dump($s['mtime']); + +var_dump($f->ftell()); +var_dump($f->eof()); +var_dump($f->fgets()); +var_dump($f->eof()); +var_dump($f->fseek(20)); +var_dump($f->ftell()); +var_dump($f->fgets()); +var_dump($f->rewind()); +var_dump($f->ftell()); +var_dump($f->fgets()); +var_dump($f->ftell()); + +?> +===AGAIN=== +ftell()); +var_dump($f->eof()); +var_dump($f->fgets()); +var_dump($f->eof()); + +//unset($f); without unset we check for working refcounting + +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +MyFile::__construct(phar://*/phar_oo_test.phar.php/a.php) +int(1141214400) +int(1141214400) +int(1141214400) +int(0) +bool(false) +string(32) "" +bool(true) +int(0) +int(20) +string(12) "a.php\n"; ?>" +NULL +int(0) +string(32) "" +int(32) +===AGAIN=== +MyFile::__construct(phar://*/phar_oo_test.phar.php/a.php) +int(0) +bool(false) +string(32) "" +bool(true) +===DONE=== -- 2.40.0