at startup. This caches the manifest, so that on first access to a phar archive, no file manifest parsing occurs.
This could use further tweaking. For instance, the full copy of the manifest into the current process may be unnecessary if refcounting could be external
to the manifest. This would be another significant gain. With APC, I measure a slight perf increase to 19 req/sec up from 16 req/sec, without it approaches
regular PHP at 3.8 req/sec (regular is 4 req/sec). This is benching phpMyAdmin
#ifndef PHAR_HAVE_OPENSSL
static int phar_call_openssl_signverify(int is_sign, php_stream *fp, off_t end, char *key, int key_len, char **signature, int *signature_len TSRMLS_DC);
#endif
+static void destroy_phar_data(void *pDest);
ZEND_DECLARE_MODULE_GLOBALS(phar)
#if PHP_VERSION_ID >= 50300
}
/* }}}*/
+/* this global stores the global cached pre-parsed manifests */
+static HashTable cached_phars;
+static HashTable cached_alias;
+
+static void phar_split_cache_list(TSRMLS_D)
+{
+ char *tmp;
+ char *key, *lasts, *end;
+ char ds[1];
+ phar_archive_data *phar;
+
+ if (!PHAR_GLOBALS->cache_list || !(PHAR_GLOBALS->cache_list[0])) {
+ return;
+ }
+
+ ds[0] = DEFAULT_DIR_SEPARATOR;
+ zend_init_rsrc_list(TSRMLS_C);
+ tmp = estrdup(PHAR_GLOBALS->cache_list);
+
+ /* fake request startup */
+ PHAR_GLOBALS->request_init = 1;
+ PHAR_G(has_bz2) = zend_hash_exists(&module_registry, "bz2", sizeof("bz2"));
+ PHAR_G(has_zlib) = zend_hash_exists(&module_registry, "zlib", sizeof("zlib"));
+ zend_hash_init(&(PHAR_GLOBALS->phar_fname_map), sizeof(phar_archive_data*), zend_get_hash_value, destroy_phar_data, 1);
+ zend_hash_init(&(PHAR_GLOBALS->phar_alias_map), sizeof(phar_archive_data*), zend_get_hash_value, NULL, 1);
+ PHAR_GLOBALS->manifest_cached = 1;
+ PHAR_GLOBALS->persist = 1;
+
+ for (key = php_strtok_r(tmp, ds, &lasts);
+ key;
+ key = php_strtok_r(NULL, ds, &lasts))
+ {
+ end = strchr(key, DEFAULT_DIR_SEPARATOR);
+ if (end) {
+ if (SUCCESS == phar_open_from_filename(key, end - key, NULL, 0, 0, &phar, NULL TSRMLS_CC)) {
+finish_up:
+ php_stream_close(phar->fp);
+ phar->fp = NULL;
+ } else {
+finish_error:
+ PHAR_GLOBALS->persist = 0;
+ PHAR_GLOBALS->manifest_cached = 0;
+ zend_destroy_rsrc_list(&EG(regular_list) TSRMLS_CC);
+ efree(tmp);
+ zend_hash_destroy(&(PHAR_G(phar_fname_map)));
+ PHAR_GLOBALS->phar_fname_map.arBuckets = 0;
+ zend_hash_destroy(&(PHAR_G(phar_alias_map)));
+ PHAR_GLOBALS->phar_alias_map.arBuckets = 0;
+ /* free cached manifests */
+ PHAR_GLOBALS->request_init = 0;
+ return;
+ }
+ } else {
+ if (SUCCESS == phar_open_from_filename(key, strlen(key), NULL, 0, 0, &phar, NULL TSRMLS_CC)) {
+ goto finish_up;
+ } else {
+ goto finish_error;
+ }
+ }
+ }
+ PHAR_GLOBALS->persist = 0;
+ PHAR_GLOBALS->request_init = 0;
+ cached_phars = PHAR_GLOBALS->phar_fname_map;
+ cached_alias = PHAR_GLOBALS->phar_alias_map;
+ PHAR_GLOBALS->phar_fname_map.arBuckets = 0;
+ PHAR_GLOBALS->phar_alias_map.arBuckets = 0;
+
+ zend_destroy_rsrc_list(&EG(regular_list) TSRMLS_CC);
+ efree(tmp);
+}
+/* }}} */
+
+ZEND_INI_MH(phar_ini_cache_list) /* {{{ */
+{
+ PHAR_G(cache_list) = new_value;
+
+ if (stage == ZEND_INI_STAGE_STARTUP) {
+ phar_split_cache_list(TSRMLS_C);
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
PHP_INI_BEGIN()
STD_PHP_INI_BOOLEAN( "phar.readonly", "1", PHP_INI_ALL, phar_ini_modify_handler, readonly, zend_phar_globals, phar_globals)
STD_PHP_INI_BOOLEAN( "phar.require_hash", "1", PHP_INI_ALL, phar_ini_modify_handler, require_hash, zend_phar_globals, phar_globals)
+ STD_PHP_INI_ENTRY("phar.cache_list", "", PHP_INI_SYSTEM, phar_ini_cache_list, cache_list, zend_phar_globals, phar_globals)
PHP_INI_END()
/**
void phar_destroy_phar_data(phar_archive_data *phar TSRMLS_DC) /* {{{ */
{
if (phar->alias && phar->alias != phar->fname) {
- efree(phar->alias);
+ pefree(phar->alias, phar->is_persistent);
phar->alias = NULL;
}
if (phar->fname) {
- efree(phar->fname);
+ pefree(phar->fname, phar->is_persistent);
phar->fname = NULL;
}
if (phar->signature) {
- efree(phar->signature);
+ pefree(phar->signature, phar->is_persistent);
phar->signature = NULL;
}
if (phar->manifest.arBuckets) {
phar->mounted_dirs.arBuckets = NULL;
}
if (phar->metadata) {
- zval_ptr_dtor(&phar->metadata);
+ if (phar->is_persistent) {
+ if (phar->metadata_len) {
+ /* for zip comments that are strings */
+ free(phar->metadata);
+ } else {
+ zval_internal_ptr_dtor(&phar->metadata);
+ }
+ } else {
+ zval_ptr_dtor(&phar->metadata);
+ }
+ phar->metadata_len = 0;
phar->metadata = 0;
}
if (phar->fp) {
php_stream_close(phar->ufp);
phar->fp = 0;
}
- efree(phar);
+ pefree(phar, phar->is_persistent);
}
/* }}}*/
entry->fp = 0;
}
if (entry->metadata) {
- zval_ptr_dtor(&entry->metadata);
+ if (entry->is_persistent) {
+ if (entry->metadata_len) {
+ /* for zip comments that are strings */
+ free(entry->metadata);
+ } else {
+ zval_internal_ptr_dtor(&entry->metadata);
+ }
+ } else {
+ zval_ptr_dtor(&entry->metadata);
+ }
+ entry->metadata_len = 0;
entry->metadata = 0;
}
if (entry->metadata_str.c) {
smart_str_free(&entry->metadata_str);
entry->metadata_str.c = 0;
}
- efree(entry->filename);
+ pefree(entry->filename, entry->is_persistent);
if (entry->link) {
- efree(entry->link);
+ pefree(entry->link, entry->is_persistent);
entry->link = 0;
}
if (entry->tmp) {
- efree(entry->tmp);
+ pefree(entry->tmp, entry->is_persistent);
entry->tmp = 0;
}
}
phar_destroy_phar_data(mydata TSRMLS_CC);\
}\
if (signature) {\
- efree(signature);\
+ pefree(signature, mydata->is_persistent);\
}\
MAPPHAR_ALLOC_FAIL(msg)
} else {
buf_len = zip_metadata_len;
}
-
+
if (buf_len) {
- ALLOC_INIT_ZVAL(*metadata);
+ ALLOC_ZVAL(*metadata);
+ INIT_ZVAL(**metadata);
p = (const unsigned char*) *buffer;
PHP_VAR_UNSERIALIZE_INIT(var_hash);
if (!php_var_unserialize(metadata, &p, p + buf_len, &var_hash TSRMLS_CC)) {
return FAILURE;
}
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+ if (PHAR_G(persist)) {
+ /* lazy init metadata */
+ zval_ptr_dtor(metadata);
+ *metadata = (zval *) pemalloc(buf_len, 1);
+ memcpy(*metadata, *buffer, buf_len);
+ if (!zip_metadata_len) {
+ *buffer += buf_len;
+ }
+ return SUCCESS;
+ }
} else {
*metadata = NULL;
}
int pos = -1;
size_t len = 0;
- *signature = (char*)safe_emalloc(digest_len, 2, 1);
+ *signature = (char*)safe_pemalloc(digest_len, 2, 1, PHAR_G(persist));
for (; len < digest_len; ++len) {
(*signature)[++pos] = hexChars[((const unsigned char *)digest)[len] >> 4];
* This is used by phar_open_from_filename to process the manifest, but can be called
* directly.
*/
-int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, long halt_offset, phar_archive_data** pphar, php_uint32 compression, char **error TSRMLS_DC) /* {{{ */
+static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, long halt_offset, phar_archive_data** pphar, php_uint32 compression, char **error TSRMLS_DC) /* {{{ */
{
char b32[4], *buffer, *endbuffer, *savebuf;
phar_archive_data *mydata = NULL;
MAPPHAR_FAIL("internal corruption of phar \"%s\" (too many manifest entries for size of manifest)")
}
- mydata = ecalloc(sizeof(phar_archive_data), 1);
+ mydata = pecalloc(sizeof(phar_archive_data), 1, PHAR_G(persist));
+ mydata->is_persistent = PHAR_G(persist);
/* check whether we have meta data, zero check works regardless of byte order */
- if (phar_parse_metadata(&buffer, &mydata->metadata, 0 TSRMLS_CC) == FAILURE) {
- MAPPHAR_FAIL("unable to read phar metadata in .phar file \"%s\"");
+ 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\"");
+ }
+ } else {
+ if (phar_parse_metadata(&buffer, &mydata->metadata, 0 TSRMLS_CC) == FAILURE) {
+ MAPPHAR_FAIL("unable to read phar metadata in .phar file \"%s\"");
+ }
}
/* set up our manifest */
zend_hash_init(&mydata->manifest, sizeof(phar_entry_info),
- zend_get_hash_value, destroy_phar_manifest_entry, 0);
+ zend_get_hash_value, destroy_phar_manifest_entry, mydata->is_persistent);
zend_hash_init(&mydata->mounted_dirs, sizeof(char *),
- zend_get_hash_value, NULL, 0);
+ zend_get_hash_value, NULL, mydata->is_persistent);
offset = halt_offset + manifest_len + 4;
memset(&entry, 0, sizeof(phar_entry_info));
entry.phar = mydata;
entry.fp_type = PHAR_FP;
+ entry.is_persistent = mydata->is_persistent;
for (manifest_index = 0; manifest_index < manifest_count; ++manifest_index) {
if (buffer + 4 > endbuffer) {
} else {
entry.is_dir = 0;
}
- entry.filename = estrndup(buffer, entry.filename_len);
+ entry.filename = pestrndup(buffer, entry.filename_len, entry.is_persistent);
buffer += entry.filename_len;
PHAR_GET_32(buffer, entry.uncompressed_filesize);
PHAR_GET_32(buffer, entry.timestamp);
entry.filename_len--;
entry.flags |= PHAR_ENT_PERM_DEF_DIR;
}
- if (phar_parse_metadata(&buffer, &entry.metadata, 0 TSRMLS_CC) == FAILURE) {
- efree(entry.filename);
- MAPPHAR_FAIL("unable to read file metadata in .phar file \"%s\"");
+ if (entry.is_persistent) {
+ PHAR_GET_32(buffer, entry.metadata_len);
+ if (phar_parse_metadata(&buffer, &entry.metadata, entry.metadata_len TSRMLS_CC) == FAILURE) {
+ pefree(entry.filename, entry.is_persistent);
+ MAPPHAR_FAIL("unable to read file metadata in .phar file \"%s\"");
+ }
+ } else {
+ if (phar_parse_metadata(&buffer, &entry.metadata, 0 TSRMLS_CC) == FAILURE) {
+ pefree(entry.filename, entry.is_persistent);
+ MAPPHAR_FAIL("unable to read file metadata in .phar file \"%s\"");
+ }
}
entry.offset = entry.offset_abs = offset;
offset += entry.compressed_filesize;
case PHAR_ENT_COMPRESSED_GZ:
if (!PHAR_G(has_zlib)) {
if (entry.metadata) {
- zval_ptr_dtor(&entry.metadata);
+ if (entry.is_persistent) {
+ free(entry.metadata);
+ } else {
+ zval_ptr_dtor(&entry.metadata);
+ }
}
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
MAPPHAR_FAIL("zlib extension is required for gz compressed .phar file \"%s\"");
}
break;
case PHAR_ENT_COMPRESSED_BZ2:
if (!PHAR_G(has_bz2)) {
if (entry.metadata) {
- zval_ptr_dtor(&entry.metadata);
+ if (entry.is_persistent) {
+ free(entry.metadata);
+ } else {
+ zval_ptr_dtor(&entry.metadata);
+ }
}
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
MAPPHAR_FAIL("bz2 extension is required for bzip2 compressed .phar file \"%s\"");
}
break;
default:
if (entry.uncompressed_filesize != entry.compressed_filesize) {
if (entry.metadata) {
- zval_ptr_dtor(&entry.metadata);
+ if (entry.is_persistent) {
+ free(entry.metadata);
+ } else {
+ zval_ptr_dtor(&entry.metadata);
+ }
}
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
MAPPHAR_FAIL("internal corruption of phar \"%s\" (compressed and uncompressed size does not match for uncompressed entry)");
}
break;
mydata->halt_offset = halt_offset;
mydata->flags = manifest_flags;
mydata->fp = fp;
- mydata->fname = estrndup(fname, fname_len);
+ mydata->fname = pestrndup(fname, fname_len, mydata->is_persistent);
#ifdef PHP_WIN32
phar_unixify_path_separators(mydata->fname, fname_len);
#endif
mydata->ext_len = (mydata->fname + mydata->fname_len) - mydata->ext;
}
}
- mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len);
+ mydata->alias = alias ?
+ pestrndup(alias, alias_len, mydata->is_persistent) :
+ pestrndup(mydata->fname, fname_len, mydata->is_persistent);
mydata->alias_len = alias ? alias_len : fname_len;
mydata->sig_flags = sig_flags;
mydata->sig_len = sig_len;
zend_stream_open_function = phar_orig_zend_open;
}
#endif
+ if (PHAR_G(manifest_cached)) {
+ zend_hash_destroy(&(cached_phars));
+ zend_hash_destroy(&(cached_alias));
+ }
+}
+/* }}} */
+
+static void phar_update_cached_entry(void *data, void *argument) /* {{{ */
+{
+ phar_entry_info *entry = (phar_entry_info *)data;
+ TSRMLS_FETCH();
+
+ entry->phar = (phar_archive_data *)argument;
+ if (entry->link) {
+ entry->link = estrdup(entry->link);
+ }
+ if (entry->tmp) {
+ entry->tmp = estrdup(entry->tmp);
+ }
+ entry->metadata_str.c = 0;
+ entry->filename = estrndup(entry->filename, entry->filename_len);
+ if (entry->metadata) {
+ if (entry->metadata_len) {
+ /* assume success, we would have failed before */
+ phar_parse_metadata((char **) &entry->metadata, &entry->metadata, entry->metadata_len TSRMLS_CC);
+ } else {
+ zval *t;
+
+ t = entry->metadata;
+ ALLOC_ZVAL(entry->metadata);
+ *entry->metadata = *t;
+ zval_copy_ctor(entry->metadata);
+#if PHP_VERSION_ID < 50300
+ entry->metadata->refcount = 1;
+#else
+ Z_SET_REFCOUNT_P(entry->metadata, 1);
+#endif
+
+ entry->metadata_str.c = NULL;
+ entry->metadata_str.len = 0;
+ }
+ }
+}
+
+static void phar_copy_cached_phar(void *data) /* {{{ */
+{
+ phar_archive_data *phar, **pphar = (phar_archive_data **)data;
+ HashTable newmanifest;
+ char *fname;
+ TSRMLS_FETCH();
+
+ phar = (phar_archive_data *) emalloc(sizeof(phar_archive_data));
+ *phar = **pphar;
+ phar->is_persistent = 0;
+ fname = phar->fname;
+ phar->fname = estrndup(phar->fname, phar->fname_len);
+ phar->ext = phar->fname + (phar->ext - fname);
+ if (phar->alias) {
+ phar->alias = estrndup(phar->alias, phar->alias_len);
+ }
+ if (phar->signature) {
+ phar->signature = estrdup(phar->signature);
+ }
+ 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);
+ } else {
+ zval *t;
+
+ t = phar->metadata;
+ ALLOC_ZVAL(phar->metadata);
+ *phar->metadata = *t;
+ zval_copy_ctor(phar->metadata);
+#if PHP_VERSION_ID < 50300
+ phar->metadata->refcount = 1;
+#else
+ Z_SET_REFCOUNT_P(phar->metadata, 1);
+#endif
+ }
+ }
+ zend_hash_init(&newmanifest, sizeof(phar_entry_info),
+ zend_get_hash_value, destroy_phar_manifest_entry, 0);
+ zend_hash_copy(&newmanifest, &(*pphar)->manifest, NULL, NULL, sizeof(phar_entry_info));
+ zend_hash_apply_with_argument(&newmanifest, (apply_func_arg_t) phar_update_cached_entry, (void *)phar TSRMLS_CC);
+ phar->manifest = newmanifest;
+ zend_hash_init(&phar->mounted_dirs, sizeof(char *),
+ zend_get_hash_value, NULL, 0);
+ *pphar = phar;
+}
+/* }}} */
+
+static int phar_update_alias_map(void *data) /* {{{ */
+{
+ phar_archive_data **pphar, **old = (phar_archive_data **)data;
+ TSRMLS_FETCH();
+
+ zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), (*old)->fname, (*old)->fname_len, (void **) &pphar);
+ if (pphar) {
+ *old = *pphar;
+ }
+ return ZEND_HASH_APPLY_KEEP;
}
/* }}} */
PHAR_GLOBALS->request_done = 0;
zend_hash_init(&(PHAR_GLOBALS->phar_fname_map), sizeof(phar_archive_data*), zend_get_hash_value, destroy_phar_data, 0);
zend_hash_init(&(PHAR_GLOBALS->phar_alias_map), sizeof(phar_archive_data*), zend_get_hash_value, NULL, 0);
+ if (PHAR_G(manifest_cached)) {
+ zend_hash_copy(&(PHAR_GLOBALS->phar_fname_map), &cached_phars, phar_copy_cached_phar, NULL, sizeof(phar_archive_data *));
+ zend_hash_copy(&(PHAR_GLOBALS->phar_alias_map), &cached_alias, NULL, NULL, sizeof(phar_archive_data *));
+ zend_hash_apply(&(PHAR_GLOBALS->phar_alias_map), (apply_func_t) phar_update_alias_map TSRMLS_CC);
+ }
zend_hash_init(&(PHAR_GLOBALS->phar_SERVER_mung_list), sizeof(const char *), zend_get_hash_value, NULL, 0);
PHAR_G(cwd) = NULL;
PHAR_G(cwd_len) = 0;
PHAR_G(cwd_init) = 0;
- phar_intercept_functions(TSRMLS_C);
+ if (!PHAR_G(orig_fopen)) {
+ phar_intercept_functions(TSRMLS_C);
+ }
}
}
/* }}} */
static zend_module_dep phar_deps[] = {
ZEND_MOD_OPTIONAL("apc")
ZEND_MOD_OPTIONAL("openssl")
+ ZEND_MOD_OPTIONAL("zlib")
+ ZEND_MOD_OPTIONAL("bz2")
#if HAVE_SPL
ZEND_MOD_REQUIRED("spl")
#endif
HashTable phar_alias_map;
HashTable phar_SERVER_mung_list;
int readonly;
+ char* cache_list;
+ int manifest_cached;
+ int persist;
int has_zlib;
int has_bz2;
zend_bool readonly_orig;
/* when changing compression, save old flags in case fp is NULL */
php_uint32 old_flags;
zval *metadata;
+ int metadata_len; /* only used for cached manifests */
php_uint32 filename_len;
char *filename;
enum phar_fp_type fp_type;
char tar_type;
/* zip-based phar file stuff */
int is_zip:1;
+ /* for cached phar entries */
+ int is_persistent:1;
} phar_entry_info;
/* information about a phar file (the archive itself) */
int sig_len;
char *signature;
zval *metadata;
+ int metadata_len; /* only used for cached manifests */
/* if 1, then this alias was manually specified by the user and is not a permanent alias */
int is_temporary_alias:1;
int is_modified:1;
int is_tar:1;
/* PharData variables */
int is_data:1;
+ /* for cached phar manifests */
+ int is_persistent:1;
};
#define PHAR_MIME_PHP '\0'
hdr = (tar_header*)buf;
old = (memcmp(hdr->magic, "ustar", sizeof("ustar")-1) != 0);
- myphar = (phar_archive_data *) ecalloc(1, sizeof(phar_archive_data));
+ myphar = (phar_archive_data *) pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
+ myphar->is_persistent = PHAR_G(persist);
zend_hash_init(&myphar->manifest, sizeof(phar_entry_info),
- zend_get_hash_value, destroy_phar_manifest_entry, 0);
+ zend_get_hash_value, destroy_phar_manifest_entry, myphar->is_persistent);
zend_hash_init(&myphar->mounted_dirs, sizeof(char *),
- zend_get_hash_value, NULL, 0);
+ 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;
/* some tar programs store directories with trailing slash */
entry.filename_len--;
}
- entry.filename = estrndup(name, entry.filename_len);
+ entry.filename = pestrndup(name, entry.filename_len, myphar->is_persistent);
} else {
- entry.filename = estrdup(hdr->name);
+ entry.filename = pestrdup(hdr->name, myphar->is_persistent);
entry.filename_len = strlen(entry.filename);
if (entry.filename[entry.filename_len - 1] == '/') {
/* some tar programs store directories with trailing slash */
if (error) {
spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (checksum mismatch of file \"%s\")", fname, entry.filename);
}
- efree(entry.filename);
+ pefree(entry.filename, myphar->is_persistent);
php_stream_close(fp);
zend_hash_destroy(&myphar->manifest);
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
- efree(myphar);
+ pefree(myphar, myphar->is_persistent);
return FAILURE;
}
entry.fp_type = PHAR_FP;
entry.flags = phar_tar_number(hdr->mode, sizeof(hdr->mode)) & PHAR_ENT_PERM_MASK;
entry.timestamp = phar_tar_number(hdr->mtime, sizeof(hdr->mtime));
+ entry.is_persistent = myphar->is_persistent;
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
if (error) {
spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file - hard link to non-existent file \"%s\"", fname, hdr->linkname);
}
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
php_stream_close(fp);
zend_hash_destroy(&myphar->manifest);
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
- efree(myphar);
+ pefree(myphar, entry.is_persistent);
return FAILURE;
}
entry.link = estrdup(hdr->linkname);
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
- efree(myphar);
+ pefree(myphar, myphar->is_persistent);
return FAILURE;
}
}
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
- efree(myphar);
+ pefree(myphar, myphar->is_persistent);
return FAILURE;
}
read = php_stream_read(fp, buf, size);
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
- efree(myphar);
+ pefree(myphar, myphar->is_persistent);
return FAILURE;
}
- actual_alias = estrndup(buf, size);
+ actual_alias = pestrndup(buf, size, myphar->is_persistent);
myphar->alias = actual_alias;
myphar->alias_len = size;
php_stream_seek(fp, pos, SEEK_SET);
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
- efree(myphar);
+ pefree(myphar, myphar->is_persistent);
return FAILURE;
}
}
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
- efree(myphar);
+ pefree(myphar, myphar->is_persistent);
return FAILURE;
}
}
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
- efree(myphar);
+ pefree(myphar, myphar->is_persistent);
return FAILURE;
}
} while (read != 0);
- myphar->fname = estrndup(fname, fname_len);
+ myphar->fname = pestrndup(fname, fname_len, myphar->is_persistent);
#ifdef PHP_WIN32
phar_unixify_path_separators(myphar->fname, fname_len);
#endif
myphar->manifest.arBuckets = 0;
zend_hash_destroy(&myphar->mounted_dirs);
myphar->mounted_dirs.arBuckets = 0;
- efree(myphar);
+ pefree(myphar, myphar->is_persistent);
return FAILURE;
}
myphar = *actual;
}
}
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
- myphar->alias = estrndup(alias, alias_len);
+ myphar->alias = pestrndup(alias, alias_len, myphar->is_persistent);
myphar->alias_len = alias_len;
} else {
- myphar->alias = estrndup(myphar->fname, fname_len);
+ myphar->alias = pestrndup(myphar->fname, fname_len, myphar->is_persistent);
myphar->alias_len = fname_len;
}
myphar->is_temporary_alias = 1;
--INI--
phar.readonly=0
phar.require_hash=0
+phar.cache_list=
--FILE--
<?php
phpinfo(INFO_MODULES);
Phar fully realized by Gregory Beaver and Marcus Boerger.
Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.
Directive => Local Value => Master Value
+phar.cache_list => no value => no value
phar.readonly => Off => Off
phar.require_hash => Off => Off
%a
Phar fully realized by Gregory Beaver and Marcus Boerger.
Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.
Directive => Local Value => Master Value
+phar.cache_list => no value => no value
phar.readonly => On => Off
phar.require_hash => On => Off
%a
--INI--
phar.readonly=1
phar.require_hash=1
+phar.cache_list=
--FILE--
<?php
phpinfo(INFO_MODULES);
Phar fully realized by Gregory Beaver and Marcus Boerger.
Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.
Directive => Local Value => Master Value
+phar.cache_list => no value => no value
phar.readonly => On => On
phar.require_hash => On => On
%a
--INI--
phar.readonly=1
phar.require_hash=1
+phar.cache_list=
--FILE--
<?php
phpinfo(INFO_MODULES);
Phar fully realized by Gregory Beaver and Marcus Boerger.
Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.
Directive => Local Value => Master Value
+phar.cache_list => no value => no value
phar.readonly => On => On
phar.require_hash => On => On
%a
--INI--
phar.readonly=0
phar.require_hash=0
+phar.cache_list=
--POST--
a=b
--FILE--
</table><br />
<table border="0" cellpadding="3" width="600">
<tr class="h"><th>Directive</th><th>Local Value</th><th>Master Value</th></tr>
+<tr><td class="e">phar.cache_list</td><td class="v"><i>no value</i></td><td class="v"><i>no value</i></td></tr>
<tr><td class="e">phar.readonly</td><td class="v">Off</td><td class="v">Off</td></tr>
<tr><td class="e">phar.require_hash</td><td class="v">Off</td><td class="v">Off</td></tr>
</table><br />
</table><br />
<table border="0" cellpadding="3" width="600">
<tr class="h"><th>Directive</th><th>Local Value</th><th>Master Value</th></tr>
+<tr><td class="e">phar.cache_list</td><td class="v"><i>no value</i></td><td class="v"><i>no value</i></td></tr>
<tr><td class="e">phar.readonly</td><td class="v">On</td><td class="v">Off</td></tr>
<tr><td class="e">phar.require_hash</td><td class="v">On</td><td class="v">Off</td></tr>
</table><br />
php_stream_close(fp);
return FAILURE;
}
- mydata = ecalloc(sizeof(phar_archive_data), 1);
+ mydata = pecalloc(sizeof(phar_archive_data), 1, PHAR_G(persist));
+ mydata->is_persistent = PHAR_G(persist);
/* read in archive comment, if any */
if (locator.comment_len) {
spprintf(error, 4096, "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname);
}
php_stream_close(fp);
- efree(mydata);
+ pefree(mydata, mydata->is_persistent);
return FAILURE;
}
+ mydata->metadata_len = PHAR_GET_16(locator.comment_len);
if (phar_parse_metadata(&metadata, &mydata->metadata, PHAR_GET_16(locator.comment_len) TSRMLS_CC) == FAILURE) {
+ mydata->metadata_len = 0;
/* if not valid serialized data, it is a regular string */
- ALLOC_INIT_ZVAL(mydata->metadata);
- ZVAL_STRINGL(mydata->metadata, metadata, PHAR_GET_16(locator.comment_len), 1);
+ if (entry.is_persistent) {
+ ALLOC_PERMANENT_ZVAL(mydata->metadata);
+ } else {
+ ALLOC_ZVAL(mydata->metadata);
+ }
+ INIT_ZVAL(*mydata->metadata);
+ metadata = pestrndup(metadata, PHAR_GET_16(locator.comment_len), mydata->is_persistent);
+ ZVAL_STRINGL(mydata->metadata, metadata, PHAR_GET_16(locator.comment_len), 0);
}
} else {
mydata->metadata = NULL;
}
return FAILURE;
foundit:
- mydata->fname = estrndup(fname, fname_len);
+ mydata->fname = pestrndup(fname, fname_len, mydata->is_persistent);
#ifdef PHP_WIN32
phar_unixify_path_separators(mydata->fname, fname_len);
#endif
php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET);
/* read in central directory */
zend_hash_init(&mydata->manifest, sizeof(phar_entry_info),
- zend_get_hash_value, destroy_phar_manifest_entry, 0);
+ zend_get_hash_value, destroy_phar_manifest_entry, mydata->is_persistent);
zend_hash_init(&mydata->mounted_dirs, sizeof(char *),
- zend_get_hash_value, NULL, 0);
+ zend_get_hash_value, NULL, mydata->is_persistent);
entry.phar = mydata;
entry.is_zip = 1;
entry.fp_type = PHAR_FP;
+ entry.is_persistent = mydata->is_persistent;
#define PHAR_ZIP_FAIL(errmsg) \
zend_hash_destroy(&mydata->manifest); \
mydata->manifest.arBuckets = 0; \
if (error) { \
spprintf(error, 4096, "phar error: %s in zip-based phar \"%s\"", errmsg, mydata->fname); \
} \
- efree(mydata->fname); \
+ pefree(mydata->fname, mydata->is_persistent); \
if (mydata->alias) { \
- efree(mydata->alias); \
+ pefree(mydata->alias, mydata->is_persistent); \
} \
- efree(mydata); \
+ pefree(mydata, mydata->is_persistent); \
return FAILURE;
/* add each central directory item to the manifest */
PHAR_ZIP_FAIL("Cannot process zips created from stdin (zero-length filename)");
}
entry.filename_len = PHAR_GET_16(zipentry.filename_len);
- entry.filename = (char *) emalloc(entry.filename_len + 1);
+ entry.filename = (char *) pemalloc(entry.filename_len + 1, entry.is_persistent);
if (entry.filename_len != php_stream_read(fp, entry.filename, entry.filename_len)) {
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unable to read in filename from central directory, truncated");
}
entry.filename[entry.filename_len] = '\0';
}
break;
case 1 :
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unsupported compression method (Shrunk) used in this zip");
case 2 :
case 3 :
case 4 :
case 5 :
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unsupported compression method (Reduce) used in this zip");
case 6 :
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unsupported compression method (Implode) used in this zip");
case 7 :
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unsupported compression method (Tokenize) used in this zip");
case 9 :
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unsupported compression method (Deflate64) used in this zip");
case 10 :
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unsupported compression method (PKWare Implode/old IBM TERSE) used in this zip");
case 14 :
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unsupported compression method (LZMA) used in this zip");
case 18 :
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unsupported compression method (IBM TERSE) used in this zip");
case 19 :
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unsupported compression method (IBM LZ77) used in this zip");
case 97 :
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unsupported compression method (WavPack) used in this zip");
case 98 :
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unsupported compression method (PPMd) used in this zip");
default :
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unsupported compression method (unknown) used in this zip");
}
/* get file metadata */
if (zipentry.comment_len) {
if (PHAR_GET_16(zipentry.comment_len) != php_stream_read(fp, buf, PHAR_GET_16(zipentry.comment_len))) {
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unable to read in file comment, truncated");
}
p = buf;
+ entry.metadata_len = zipentry.comment_len;
if (phar_parse_metadata(&p, &(entry.metadata), PHAR_GET_16(zipentry.comment_len) TSRMLS_CC) == FAILURE) {
+ entry.metadata_len = 0;
/* if not valid serialized data, it is a regular string */
- ALLOC_INIT_ZVAL(entry.metadata);
- ZVAL_STRINGL(entry.metadata, buf, PHAR_GET_16(zipentry.comment_len), 1);
+ if (entry.is_persistent) {
+ ALLOC_PERMANENT_ZVAL(entry.metadata);
+ } else {
+ ALLOC_ZVAL(entry.metadata);
+ }
+ INIT_ZVAL(*entry.metadata);
+ ZVAL_STRINGL(entry.metadata, pestrndup(buf, PHAR_GET_16(zipentry.comment_len), entry.is_persistent), PHAR_GET_16(zipentry.comment_len), 0);
}
} else {
entry.metadata = NULL;
if (entry.flags & PHAR_ENT_COMPRESSED_GZ) {
filter = php_stream_filter_create("zlib.inflate", NULL, php_stream_is_persistent(fp) TSRMLS_CC);
if (!filter) {
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unable to decompress alias, zlib filter creation failed");
}
php_stream_filter_append(&fp->readfilters, filter);
if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unable to read in alias, truncated");
}
php_stream_filter_flush(filter, 1);
php_stream_filter *filter;
filter = php_stream_filter_create("bzip2.decompress", NULL, php_stream_is_persistent(fp) TSRMLS_CC);
if (!filter) {
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unable to read in alias, bzip2 filter creation failed");
}
php_stream_filter_append(&fp->readfilters, filter);
php_stream_filter_append(&fp->readfilters, filter);
if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unable to read in alias, truncated");
}
php_stream_filter_flush(filter, 1);
php_stream_filter_remove(filter, 1 TSRMLS_CC);
} else {
if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
- efree(entry.filename);
+ pefree(entry.filename, entry.is_persistent);
PHAR_ZIP_FAIL("unable to read in alias, truncated");
}
}
return FAILURE;
}
}
- mydata->alias = actual_alias;
+ mydata->alias = entry.is_persistent ? pestrndup(actual_alias, mydata->alias_len, 1) : actual_alias;
+ if (entry.is_persistent) {
+ efree(actual_alias);
+ }
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, mydata->alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
} else {
phar_archive_data **fd_ptr;
}
}
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, mydata->alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
- mydata->alias = estrndup(alias, alias_len);
+ mydata->alias = pestrndup(alias, alias_len, mydata->is_persistent);
mydata->alias_len = alias_len;
} else {
- mydata->alias = estrndup(mydata->fname, fname_len);
+ mydata->alias = pestrndup(mydata->fname, fname_len, mydata->is_persistent);
mydata->alias_len = fname_len;
}
mydata->is_temporary_alias = 1;