diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index a1f7e2c2704..28895f20e6c 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -2094,6 +2094,28 @@ PHP_METHOD(Phar, isCompressed) } /* }}} */ +/* {{{ proto bool Phar::isWritable() + * Returns true if phar.readonly=0 or phar is a PharData AND the actual file is writable. + */ +PHP_METHOD(Phar, isWritable) +{ + php_stream_statbuf ssb; + PHAR_ARCHIVE_OBJECT(); + + if (!phar_obj->arc.archive->is_writeable) { + RETURN_FALSE; + } + if (SUCCESS != php_stream_stat_path(phar_obj->arc.archive->fname, &ssb)) { + if (phar_obj->arc.archive->is_brandnew) { + /* assume it works if the file doesn't exist yet */ + RETURN_TRUE; + } + RETURN_FALSE; + } + RETURN_BOOL((ssb.sb.st_mode & (S_IWOTH | S_IWGRP | S_IWUSR)) != 0); +} +/* }}} */ + /* {{{ proto bool Phar::delete(string entry) * Deletes a named file within the archive. */ @@ -3925,6 +3947,7 @@ zend_function_entry php_archive_methods[] = { PHP_ME(Phar, hasMetadata, NULL, ZEND_ACC_PUBLIC) PHP_ME(Phar, isBuffering, NULL, ZEND_ACC_PUBLIC) PHP_ME(Phar, isCompressed, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phar, isWritable, NULL, ZEND_ACC_PUBLIC) PHP_ME(Phar, isPhar, NULL, ZEND_ACC_PUBLIC) PHP_ME(Phar, isTar, NULL, ZEND_ACC_PUBLIC) PHP_ME(Phar, isZip, NULL, ZEND_ACC_PUBLIC) diff --git a/ext/phar/tests/phar_oo_iswriteable.phpt b/ext/phar/tests/phar_oo_iswriteable.phpt index 9957cea867f..89e977cd8d4 100644 --- a/ext/phar/tests/phar_oo_iswriteable.phpt +++ b/ext/phar/tests/phar_oo_iswriteable.phpt @@ -8,6 +8,7 @@ phar.require_hash=0 --FILE-- '; @@ -17,6 +18,9 @@ $files['dir/'] = ''; $hasdir = 1; include 'files/phar_test.inc'; $a = new Phar($fname); +$b = new PharData($fname2); +$b['test'] = 'hi'; + var_dump($a['a.php']->isWritable()); var_dump($a['a.php']->isReadable()); $a['a.php']->chmod(000); @@ -34,10 +38,26 @@ clearstatcache(); var_dump($a['a.php']->isWritable()); var_dump($a['a.php']->isReadable()); ?> +archive +isWritable()); +var_dump($b->isWritable()); +ini_set('phar.readonly',1); +clearstatcache(); +var_dump($a->isWritable()); +var_dump($b->isWritable()); +chmod($fname2, 000); +clearstatcache(); +var_dump($a->isWritable()); +var_dump($b->isWritable()); +?> ===DONE=== --CLEAN-- --EXPECT-- bool(true) @@ -50,4 +70,11 @@ bool(false) bool(true) bool(true) bool(true) +archive +bool(true) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) ===DONE===