add rename support

This commit is contained in:
Greg Beaver 2007-01-28 22:43:38 +00:00
parent 0bc1b90ec3
commit 744ec410ec
4 changed files with 183 additions and 4 deletions

View File

@ -26,7 +26,7 @@ Version 1.0.0
* always throw exceptions from the Phar object, and E_RECOVERABLE_ERROR from
streams interface
* Phar archive metadata
* support rename() in stream wrapper
X support rename() in stream wrapper [Greg]
Version 1.1.0

View File

@ -1248,7 +1248,7 @@ static php_stream_wrapper_ops phar_stream_wops = {
phar_wrapper_open_dir, /* opendir */
"phar",
phar_wrapper_unlink, /* unlink */
NULL, /* rename */
phar_wrapper_rename, /* rename */
NULL, /* create directory */
NULL, /* remove directory */
};
@ -2536,7 +2536,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
char *internal_file;
char *error;
phar_entry_data *idata;
resource = php_url_parse(url);
if (!resource && (resource = phar_open_url(wrapper, url, "rb", options TSRMLS_CC)) == NULL) {
@ -2561,7 +2561,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: write operations disabled by INI setting");
return FAILURE;
}
/* need to copy to strip leading "/", will get touched again */
internal_file = estrdup(resource->path + 1);
if (FAILURE == phar_get_entry_data(&idata, resource->host, strlen(resource->host), internal_file, strlen(internal_file), "r", &error TSRMLS_CC)) {
@ -2598,6 +2598,152 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
}
/* }}} */
static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC) /* {{{ */
{
php_url *resource_from, *resource_to;
char *from_file, *to_file;
char *error;
phar_entry_data *fromdata, *todata;
if (PHAR_G(readonly)) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: write operations disabled by INI setting");
return FAILURE;
}
resource_from = php_url_parse(url_from);
resource_to = php_url_parse(url_from);
if (!resource_from && (resource_from = phar_open_url(wrapper, url_from, "r+b", options TSRMLS_CC)) == NULL) {
return FAILURE;
}
if (!resource_to && (resource_to = phar_open_url(wrapper, url_to, "wb", options TSRMLS_CC)) == NULL) {
php_url_free(resource_from);
return FAILURE;
}
/* we must have at the very least phar://alias.phar/internalfile.php */
if (!resource_from->scheme || !resource_from->host || !resource_from->path) {
php_url_free(resource_from);
php_url_free(resource_to);
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: invalid url \"%s\"", url_from);
return FAILURE;
}
if (!resource_to->scheme || !resource_to->host || !resource_to->path) {
php_url_free(resource_from);
php_url_free(resource_to);
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: invalid url \"%s\"", url_to);
return FAILURE;
}
if (strcasecmp("phar", resource_from->scheme)) {
php_url_free(resource_from);
php_url_free(resource_to);
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: not a phar stream url \"%s\"", url_from);
return FAILURE;
}
if (strcasecmp("phar", resource_to->scheme)) {
php_url_free(resource_from);
php_url_free(resource_to);
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: not a phar stream url \"%s\"", url_to);
return FAILURE;
}
if (strcmp(resource_from->host, resource_to->host)) {
php_url_free(resource_from);
php_url_free(resource_to);
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: cannot rename \"%s\" to \"%s\", not within the same phar archive", url_from, url_to);
return FAILURE;
}
/* need to copy to strip leading "/", will get touched again */
from_file = estrdup(resource_from->path + 1);
to_file = estrdup(resource_to->path + 1);
if (FAILURE == phar_get_entry_data(&fromdata, resource_from->host, strlen(resource_from->host), from_file, strlen(from_file), "r", &error TSRMLS_CC)) {
/* constraints of fp refcount were not met */
if (error) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
efree(error);
}
efree(from_file);
efree(to_file);
php_url_free(resource_from);
php_url_free(resource_to);
return FAILURE;
}
if (error) {
efree(error);
}
if (!fromdata) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: \"%s\" is not a file in phar \"%s\", cannot rename", from_file, resource_from->host);
efree(from_file);
efree(to_file);
php_url_free(resource_from);
php_url_free(resource_to);
return FAILURE;
}
if (!(todata = phar_get_or_create_entry_data(resource_to->host, strlen(resource_to->host), to_file, strlen(to_file), "w", &error TSRMLS_CC))) {
/* constraints of fp refcount were not met */
if (error) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
efree(error);
}
efree(from_file);
efree(to_file);
php_url_free(resource_from);
php_url_free(resource_to);
return FAILURE;
}
if (error) {
efree(error);
}
if (fromdata->internal_file->fp_refcount > 1) {
/* more than just our fp resource is open for this file */
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: \"%s\" in phar \"%s\", has open file pointers, cannot rename", from_file, resource_from->host);
efree(from_file);
efree(to_file);
php_url_free(resource_from);
php_url_free(resource_to);
phar_entry_delref(fromdata TSRMLS_CC);
phar_entry_delref(todata TSRMLS_CC);
return FAILURE;
}
if (todata->internal_file->fp_refcount > 1) {
/* more than just our fp resource is open for this file */
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: \"%s\" in phar \"%s\", has open file pointers, cannot rename", to_file, resource_to->host);
efree(from_file);
efree(to_file);
php_url_free(resource_from);
php_url_free(resource_to);
phar_entry_delref(fromdata TSRMLS_CC);
phar_entry_delref(todata TSRMLS_CC);
return FAILURE;
}
php_stream_seek(fromdata->internal_file->fp, 0, SEEK_SET);
if (fromdata->internal_file->uncompressed_filesize != php_stream_copy_to_stream(fromdata->internal_file->fp, todata->internal_file->fp, PHP_STREAM_COPY_ALL)) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: rename failed \"%s\" to \"%s\"", url_from, url_to);
efree(from_file);
efree(to_file);
php_url_free(resource_from);
php_url_free(resource_to);
phar_entry_delref(fromdata TSRMLS_CC);
phar_entry_delref(todata TSRMLS_CC);
return FAILURE;
}
phar_entry_delref(fromdata TSRMLS_CC);
phar_entry_delref(todata TSRMLS_CC);
efree(from_file);
efree(to_file);
php_url_free(resource_from);
php_url_free(resource_to);
phar_wrapper_unlink(wrapper, url_from, 0, 0 TSRMLS_CC);
return SUCCESS;
}
/* }}} */
/**
* Open a directory handle within a phar archive
*/

View File

@ -225,6 +225,7 @@ static php_url* phar_open_url(php_stream_wrapper *wrapper, char *filename, char
static php_stream* phar_wrapper_open_url(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
static php_stream* phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC);
static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC);

View File

@ -0,0 +1,32 @@
--TEST--
Phar: rename test
--SKIPIF--
<?php if (!extension_loaded("phar")) print "skip"; ?>
--INI--
phar.readonly=0
phar.require_hash=0
--FILE--
<?php
$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
$pname = 'phar://' . $fname;
$file = "<?php
Phar::mapPhar('hio');
__HALT_COMPILER(); ?>";
$files = array();
$files['a'] = 'a';
include 'phar_test.inc';
include $fname;
echo file_get_contents($pname . '/a') . "\n";
rename($pname . '/a', $pname . '/b');
echo file_get_contents($pname . '/b') . "\n";
echo file_get_contents($pname . '/a') . "\n";
?>
--CLEAN--
<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?>
--EXPECTF--
a
a
Warning: file_get_contents(phar://%srename.phar.php/a): failed to open stream: phar error: "a" is not a file in phar "%srename.phar.php" in %srename.php on line %d