From a180fcc9bc928993221e4a6e3347951b8cbaf4d0 Mon Sep 17 00:00:00 2001 From: Greg Beaver Date: Sat, 3 May 2008 02:04:24 +0000 Subject: [PATCH] add Phar::unlinkArchive() to allow complete removal of a parsed phar archive from memory and disk --- ext/phar/phar_object.c | 46 +++++++++++++ ext/phar/tests/phar_convert_zip.phpt | 1 - ext/phar/tests/phar_unlinkarchive.phpt | 95 ++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 ext/phar/tests/phar_unlinkarchive.phpt diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 1f199041fb..5cd40fab1a 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1279,6 +1279,46 @@ PHP_METHOD(Phar, getSupportedCompression) } /* }}} */ +/* {{{ proto array Phar::unlinkArchive(string archive) + * Completely remove a phar archive from memory and disk + */ +PHP_METHOD(Phar, unlinkArchive) +{ + char *fname, *error; + int fname_len; + phar_archive_data *phar; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) { + RETURN_FALSE; + } + + if (!fname_len) { + zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Unknown phar archive \"\""); + return; + } + + if (FAILURE == phar_open_filename(fname, fname_len, NULL, 0, REPORT_ERRORS, &phar, &error TSRMLS_CC)) { + if (error) { + zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Unknown phar archive \"%s\": %s", fname, error); + efree(error); + } else { + zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Unknown phar archive \"%s\"", fname); + } + return; + } + + if (phar->refcount) { + zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar archive \"%s\" has open file handles or objects. fclose() all file handles, and unset() all objects prior to calling unlinkArchive()", fname); + return; + } + fname = estrndup(phar->fname, phar->fname_len); + phar_archive_delref(phar TSRMLS_CC); + unlink(fname); + efree(fname); + RETURN_TRUE; +} +/* }}} */ + #if HAVE_SPL #define PHAR_ARCHIVE_OBJECT() \ @@ -4297,6 +4337,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_running, 0, 0, 1) ZEND_ARG_INFO(0, retphar) ZEND_END_ARG_INFO(); +static +ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_ua, 0, 0, 1) + ZEND_ARG_INFO(0, archive) +ZEND_END_ARG_INFO(); + #if HAVE_SPL static @@ -4473,6 +4518,7 @@ zend_function_entry php_archive_methods[] = { PHP_ME(Phar, running, arginfo_phar_running, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) PHP_ME(Phar, mount, arginfo_phar_mount, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) PHP_ME(Phar, mungServer, arginfo_phar_mungServer, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) + PHP_ME(Phar, unlinkArchive, arginfo_phar_ua, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) PHP_ME(Phar, webPhar, arginfo_phar_webPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) {NULL, NULL, NULL} }; diff --git a/ext/phar/tests/phar_convert_zip.phpt b/ext/phar/tests/phar_convert_zip.phpt index b5e1de06f6..734551ee9c 100644 --- a/ext/phar/tests/phar_convert_zip.phpt +++ b/ext/phar/tests/phar_convert_zip.phpt @@ -35,7 +35,6 @@ copy($fname2, $fname3); $phar = new Phar($fname3); var_dump($phar->isFileFormat(Phar::ZIP)); var_dump($phar->getStub()); - ?> ===DONE=== --CLEAN-- diff --git a/ext/phar/tests/phar_unlinkarchive.phpt b/ext/phar/tests/phar_unlinkarchive.phpt new file mode 100644 index 0000000000..a239d54afb --- /dev/null +++ b/ext/phar/tests/phar_unlinkarchive.phpt @@ -0,0 +1,95 @@ +--TEST-- +Phar::unlinkArchive() +--SKIPIF-- + +--INI-- +phar.require_hash=0 +phar.readonly=0 +--FILE-- +getMessage(),"\n"; +} + +$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar'; +$pdname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.tar'; + +try { +Phar::unlinkArchive($fname); +} catch (Exception $e) { +echo $e->getMessage(),"\n"; +} +file_put_contents($pdname, 'blahblah'); +try { +Phar::unlinkArchive($pdname); +} catch (Exception $e) { +echo $e->getMessage(),"\n"; +} +Phar::unlinkArchive(array()); + +$pname = 'phar://' . $fname; +$fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.zip'; +$fname3 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.2.phar.zip'; +$stub = ''; +$file = $stub; + +$files = array(); +$files['a'] = 'a'; +$files['b'] = 'b'; +$files['c'] = 'c'; + +include 'files/phar_test.inc'; + +$phar = new Phar($fname); +var_dump($phar->isFileFormat(Phar::ZIP)); +var_dump($phar->getStub()); +try { +Phar::unlinkArchive($fname); +} catch (Exception $e) { +echo $e->getMessage(),"\n"; +} +$phar = $phar->convertToExecutable(Phar::ZIP); +var_dump($phar->isFileFormat(Phar::ZIP)); +var_dump($phar->getStub()); + +copy($fname2, $fname3); + +$phar = new Phar($fname3); +var_dump($phar->isFileFormat(Phar::ZIP)); +var_dump($phar->getStub()); + +Phar::unlinkArchive($fname); +var_dump(file_exists($fname)); +$phar = new Phar($fname); +var_dump(count($phar)); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +Unknown phar archive "" +Unknown phar archive "%sphar_unlinkarchive.phar" +Unknown phar archive "%sphar_unlinkarchive.phar.tar": internal corruption of phar "%sphar_unlinkarchive.phar.tar" (truncated entry) + +Warning: Phar::unlinkArchive() expects parameter 1 to be string, array given in %sphar_unlinkarchive.php on line %d +bool(false) +string(48) "" +phar archive "%sphar_unlinkarchive.phar" has open file handles or objects. fclose() all file handles, and unset() all objects prior to calling unlinkArchive() +bool(true) +string(60) "