pass.ret = return_value;
pass.fp = php_stream_fopen_tmpfile();
+ if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zval_ptr_dtor(&iteriter);
+ if (apply_reg) {
+ zval_ptr_dtor(®exiter);
+ }
+ php_stream_close(pass.fp);
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
+
if (SUCCESS == spl_iterator_apply((apply_reg ? regexiter : iteriter), (spl_iterator_apply_func_t) phar_build, (void *) &pass TSRMLS_CC)) {
zval_ptr_dtor(&iteriter);
} else {
zval_ptr_dtor(&iteriter);
+ if (apply_reg) {
+ zval_ptr_dtor(®exiter);
+ }
php_stream_close(pass.fp);
}
}
RETURN_FALSE;
}
+ if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
+
array_init(return_value);
pass.c = Z_OBJCE_P(obj);
RETURN_FALSE;
}
+ if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
if (zend_hash_exists(&phar_obj->arc.archive->manifest, fname, (uint) fname_len)) {
if (SUCCESS == zend_hash_find(&phar_obj->arc.archive->manifest, fname, (uint) fname_len, (void**)&entry)) {
if (entry->is_deleted) {
RETURN_FALSE;
}
valid_alias:
+ if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
if (phar_obj->arc.archive->alias_len && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), phar_obj->arc.archive->alias, phar_obj->arc.archive->alias_len, (void**)&fd_ptr)) {
zend_hash_del(&(PHAR_GLOBALS->phar_alias_map), phar_obj->arc.archive->alias, phar_obj->arc.archive->alias_len);
readd = 1;
} else {
len = -1;
}
+ if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
phar_flush(phar_obj->arc.archive, (char *) &zstub, len, 0, &error TSRMLS_CC);
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
"Cannot change stub, unable to read from input stream");
}
} else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &stub, &stub_len) == SUCCESS) {
+ if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
phar_flush(phar_obj->arc.archive, stub, stub_len, 0, &error TSRMLS_CC);
if (error) {
created_stub = 1;
}
+ if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
phar_flush(phar_obj->arc.archive, stub, stub_len, 1, &error TSRMLS_CC);
if (created_stub) {
case PHAR_SIG_MD5:
case PHAR_SIG_SHA1:
case PHAR_SIG_OPENSSL:
+ if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
phar_obj->arc.archive->sig_flags = algo;
phar_obj->arc.archive->is_modified = 1;
PHAR_G(openssl_privatekey) = key;
return;
}
+ if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
pharobj_set_compression(&phar_obj->arc.archive->manifest, flags TSRMLS_CC);
phar_obj->arc.archive->is_modified = 1;
phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
if (phar_obj->arc.archive->is_tar) {
RETURN_TRUE;
} else {
+ if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
pharobj_set_compression(&phar_obj->arc.archive->manifest, PHAR_ENT_COMPRESSED_NONE TSRMLS_CC);
}
RETURN_FALSE;
}
+ if (phar_obj->arc.archive->is_persistent) {
+ if (FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
+ /* re-populate with copied-on-write entry */
+ zend_hash_find(&phar_obj->arc.archive->manifest, oldfile, (uint) oldfile_len, (void**)&oldentry);
+ }
+
memcpy((void *) &newentry, oldentry, sizeof(phar_entry_info));
if (newentry.metadata) {
/* {{{ add a file within the phar archive from a string or resource
*/
-static void phar_add_file(phar_archive_data *phar, char *filename, int filename_len, char *cont_str, int cont_len, zval *zresource TSRMLS_DC)
+static void phar_add_file(phar_archive_data **pphar, char *filename, int filename_len, char *cont_str, int cont_len, zval *zresource TSRMLS_DC)
{
char *error;
long contents_len;
php_stream *contents_file;
if (filename_len >= sizeof(".phar")-1 && !memcmp(filename, ".phar", sizeof(".phar")-1)) {
- zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot create any files in magic \".phar\" directory", phar->fname);
+ zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot create any files in magic \".phar\" directory", (*pphar)->fname);
return;
}
- if (!(data = phar_get_or_create_entry_data(phar->fname, phar->fname_len, filename, filename_len, "w+b", 0, &error, 1 TSRMLS_CC))) {
+ if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, filename, filename_len, "w+b", 0, &error, 1 TSRMLS_CC))) {
if (error) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist and cannot be created: %s", filename, error);
efree(error);
data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len;
}
+ /* check for copy-on-write */
+ if (pphar[0] != data->phar) {
+ *pphar = data->phar;
+ }
phar_entry_delref(data TSRMLS_CC);
- phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
+ phar_flush(*pphar, 0, 0, 0, &error TSRMLS_CC);
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
/* {{{ create a directory within the phar archive
*/
-static void phar_mkdir(phar_archive_data *phar, char *dirname, int dirname_len TSRMLS_DC)
+static void phar_mkdir(phar_archive_data **pphar, char *dirname, int dirname_len TSRMLS_DC)
{
char *error;
phar_entry_data *data;
- if (!(data = phar_get_or_create_entry_data(phar->fname, phar->fname_len, dirname, dirname_len, "w+b", 2, &error, 1 TSRMLS_CC))) {
+ if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, dirname, dirname_len, "w+b", 2, &error, 1 TSRMLS_CC))) {
if (error) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Directory %s does not exist and cannot be created: %s", dirname, error);
efree(error);
efree(error);
}
+ /* check for copy on write */
+ if (data->phar != *pphar) {
+ *pphar = data->phar;
+ }
phar_entry_delref(data TSRMLS_CC);
- phar_flush(phar, 0, 0, 0, &error TSRMLS_CC);
+ phar_flush(*pphar, 0, 0, 0, &error TSRMLS_CC);
if (error) {
zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error);
return;
}
- phar_add_file(phar_obj->arc.archive, fname, fname_len, cont_str, cont_len, zresource TSRMLS_CC);
+ phar_add_file(&(phar_obj->arc.archive), fname, fname_len, cont_str, cont_len, zresource TSRMLS_CC);
}
/* }}} */
return;
}
+ if (phar_obj->arc.archive->is_persistent) {
+ if (FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
+ /* re-populate entry after copy on write */
+ zend_hash_find(&phar_obj->arc.archive->manifest, fname, (uint) fname_len, (void **)&entry);
+ }
entry->is_modified = 0;
entry->is_deleted = 1;
/* we need to "flush" the stream to save the newly deleted file on disk */
return;
}
- phar_mkdir(phar_obj->arc.archive, dirname, dirname_len TSRMLS_CC);
+ phar_mkdir(&phar_obj->arc.archive, dirname, dirname_len TSRMLS_CC);
}
/* }}} */
MAKE_STD_ZVAL(zresource);
php_stream_to_zval(resource, zresource);
- phar_add_file(phar_obj->arc.archive, fname, fname_len, NULL, 0, zresource TSRMLS_CC);
+ phar_add_file(&(phar_obj->arc.archive), fname, fname_len, NULL, 0, zresource TSRMLS_CC);
efree(zresource);
php_stream_close(resource);
}
return;
}
- phar_add_file(phar_obj->arc.archive, localname, localname_len, cont_str, cont_len, NULL TSRMLS_CC);
+ phar_add_file(&(phar_obj->arc.archive), localname, localname_len, cont_str, cont_len, NULL TSRMLS_CC);
}
/* }}} */
return;
}
+ if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
+ return;
+ }
if (phar_obj->arc.archive->metadata) {
zval_ptr_dtor(&phar_obj->arc.archive->metadata);
phar_obj->arc.archive->metadata = NULL;
return;
}
+ if (entry_obj->ent.entry->is_persistent) {
+ phar_archive_data *phar = entry_obj->ent.entry->phar;
+
+ if (FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
+ return;
+ }
+ /* re-populate after copy-on-write */
+ zend_hash_find(&phar->manifest, entry_obj->ent.entry->filename, entry_obj->ent.entry->filename_len, (void **)&entry_obj->ent.entry);
+ }
/* clear permissions */
entry_obj->ent.entry->flags &= ~PHAR_ENT_PERM_MASK;
perms &= 0777;
return;
}
+ if (entry_obj->ent.entry->is_persistent) {
+ phar_archive_data *phar = entry_obj->ent.entry->phar;
+
+ if (FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
+ return;
+ }
+ /* re-populate after copy-on-write */
+ zend_hash_find(&phar->manifest, entry_obj->ent.entry->filename, entry_obj->ent.entry->filename_len, (void **)&entry_obj->ent.entry);
+ }
if (entry_obj->ent.entry->metadata) {
zval_ptr_dtor(&entry_obj->ent.entry->metadata);
entry_obj->ent.entry->metadata = NULL;
}
if (entry_obj->ent.entry->metadata) {
+ if (entry_obj->ent.entry->is_persistent) {
+ phar_archive_data *phar = entry_obj->ent.entry->phar;
+
+ if (FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
+ return;
+ }
+ /* re-populate after copy-on-write */
+ zend_hash_find(&phar->manifest, entry_obj->ent.entry->filename, entry_obj->ent.entry->filename_len, (void **)&entry_obj->ent.entry);
+ }
zval_ptr_dtor(&entry_obj->ent.entry->metadata);
entry_obj->ent.entry->metadata = NULL;
entry_obj->ent.entry->is_modified = 1;
return;
}
+ if (entry_obj->ent.entry->is_persistent) {
+ phar_archive_data *phar = entry_obj->ent.entry->phar;
+
+ if (FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
+ return;
+ }
+ /* re-populate after copy-on-write */
+ zend_hash_find(&phar->manifest, entry_obj->ent.entry->filename, entry_obj->ent.entry->filename_len, (void **)&entry_obj->ent.entry);
+ }
switch (method) {
case PHAR_ENT_COMPRESSED_GZ:
if (entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ) {
return;
}
+ if (entry_obj->ent.entry->is_persistent) {
+ phar_archive_data *phar = entry_obj->ent.entry->phar;
+
+ if (FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
+ zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
+ return;
+ }
+ /* re-populate after copy-on-write */
+ zend_hash_find(&phar->manifest, entry_obj->ent.entry->filename, entry_obj->ent.entry->filename_len, (void **)&entry_obj->ent.entry);
+ }
if (!entry_obj->ent.entry->fp) {
if (FAILURE == phar_open_archive_fp(entry_obj->ent.entry->phar TSRMLS_CC)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot decompress entry \"%s\", phar error: Cannot open phar archive \"%s\" for reading", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);