diff options
| -rw-r--r-- | .github/workflows/ci.yaml | 43 | ||||
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | CHANGELOG.md | 114 | ||||
| -rw-r--r-- | README.md | 59 | ||||
| -rw-r--r-- | composer.json | 14 | ||||
| -rw-r--r-- | package.xml | 27 | ||||
| -rw-r--r-- | php_rpminfo.h | 2 | ||||
| -rw-r--r-- | rpminfo.c | 90 | ||||
| -rw-r--r-- | rpminfo.stub.php | 7 | ||||
| -rw-r--r-- | rpminfo_arginfo.h | 20 | ||||
| -rw-r--r-- | tests/004-constants.phpt | 2 | ||||
| -rw-r--r-- | tests/008-rpmdbsearch.phpt | 11 | ||||
| -rw-r--r-- | tests/015-rpmmacro.phpt | 25 |
13 files changed, 386 insertions, 29 deletions
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b0bc6f8..792341d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -11,7 +11,7 @@ jobs: matrix: distro: ['rockylinux'] el: [8] - php: ['8.0', '8.2', 'remi-8.0', 'remi-8.1', 'remi-8.2', 'remi-8.3'] + php: ['8.0', '8.2', 'remi-8.0', 'remi-8.1', 'remi-8.2', 'remi-8.3', 'remi-8.4', 'remi-8.5'] container: image: ${{ matrix.distro }}:${{ matrix.el }} steps: @@ -43,7 +43,7 @@ jobs: matrix: distro: ['rockylinux'] el: [9] - php: [0, '8.1', '8.2', 'remi-8.0', 'remi-8.1', 'remi-8.2', 'remi-8.3'] + php: [0, '8.2', '8.3', 'remi-8.0', 'remi-8.1', 'remi-8.2', 'remi-8.3', 'remi-8.4', 'remi-8.5'] container: image: ${{ matrix.distro }}:${{ matrix.el }} steps: @@ -69,12 +69,47 @@ jobs: TEST_PHP_ARGS: '-q --show-diff' run: | make test + Linux_EL10: + runs-on: ubuntu-latest + strategy: + matrix: + distro: ['almalinux'] + el: [10] + php: [0, 'remi-8.0', 'remi-8.1', 'remi-8.2', 'remi-8.3', 'remi-8.4', 'remi-8.5'] + container: + image: ${{ matrix.distro }}:${{ matrix.el }} + steps: + - name: Install gzip + run: | + dnf install -y "gzip" + - name: Checkout + uses: actions/checkout@v4 + - name: Setup PHP module + if: ${{ matrix.php }} + run: | + dnf install -y "https://rpms.remirepo.net/enterprise/remi-release-${{ matrix.el }}.rpm" + dnf module enable -y "php:${{ matrix.php }}" + - name: Install PHP + run: | + dnf install -y "php" "php-devel" "rpm-devel" + - name: Show PHP version + run: php -v + - name: Make php-rpminfo + run: | + phpize + ./configure + make -j"$(nproc)" + - name: Test php-rpminfo + env: + TEST_PHP_ARGS: '-q --show-diff' + run: | + make test Linux_Fedora: runs-on: ubuntu-latest strategy: matrix: - fedora: [39, 40, 41] - php: [0, 'remi-8.0', 'remi-8.1', 'remi-8.2', 'remi-8.3'] + fedora: [42, 43] + php: [0, 'remi-8.0', 'remi-8.1', 'remi-8.2', 'remi-8.3', 'remi-8.4', 'remi-8.5'] container: image: fedora:${{ matrix.fedora }} steps: @@ -55,6 +55,7 @@ modules run-tests.php run-tests.log tmp-php.ini +sendpackagist # Archives rpminfo-*.tgz diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..676cb3d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,114 @@ +# Unreleased + +- + +# Version 1.2.1 - 2025-09-25 + +- use `RPMTAG_SIGMD5` instead of `RPMTAG_PKGID` removed in RPM 6 +- use `RPMTAG_SHA1HEADER` instead of `RPMTAG_HDRID` removed in RPM 6 + +# Version 1.2.0 - 2024-12-19 + +- add `rpmexpand`, `rpmexpandnumeric` to retrieve rpm macro value +- add `rpmdefine` to set rpm macro value + +# Version 1.1.1 - 2024-09-03 + +- display author and license in phpinfo +- drop support for librpm < 4.13 + +# Version 1.1.0 - 2023-11-10 + +- check open_basedir restriction +- new function: `rpmgetsymlink(string $path, string $name): ?string` + +# Version 1.0.1 - 2023-10-13 + +- fix stack smashing on 32-bit +- allow retrieval of hardlink content + +# Version 1.0.0 - 2023-10-12 + +- implement rpm stream wrapper with librpm >= 4.13 + +# Version 0.7.0 - 2023-09-26 + +- add optional operator to `rpmcmpver` for consistency with version_compare +- drop support for PHP 7 + +# Version 0.6.0 - 2021-06-18 + +- generate arginfo from stub and add missing default values +- raise dependency on PHP 7.2 +- raise exception on bad parameter value with PHP 8 + +# Version 0.5.1 - 2020-09-23 + +- split tests for PHP 7/8 +- improve librpm example + +# Version 0.5.0 - 2020-04-07 + +- add `rpmaddtag()` function + +# Version 0.4.2 - 2020-03-25 + +- improve reflection with better parameter names +- speed optimization: open DB only once per request + +# Version 0.4.1 - 2020-03-18 + +- fix build with RPM 4.12 (Fedora 21-22 only) +- add type hinting in reflection +- return `NULL` instead of `FALSE` on failure + +# Version 0.4.0 - 2020-03-13 + +- improve search logic, use index when exists and no search mode +- add 'full' parameter to `rpmdbsearch` +- allow `rpmdbinfo` to search on NEVR (instead of name only) +- first "stable" release + +# Version 0.3.1 - 2020-03-12 + +- allow search by Pkgid, Hdrid, Installtid with specific input +- fix search with various other tags (Version, ...) + +# Version 0.3.0 - 2020-03-12 + +- add `rpmdbsearch` function to search packages using + name, installed files, requires, provides... + +# Version 0.2.3 - 2020-03-11 + +- fix gh#2 free allocated iterators to avoid "DB2053 Freeing read locks..." messages + +# Version 0.2.2 - 2020-03-11 + +- Fix gh#1 `rpmvercmp()` incorrect comparison result + +# Version 0.2.1 - 2018-02-12 + +- add summary in minimal information set +- retrieve array from metadata +- add `RPMSENSE_*` macros + +# Version 0.2.0 - 2018-02-08 + +- new function: + `array rpmdbinfo(string name [, bool full]);` + +# Version 0.1.3 - 2018-02-08 + +- first pecl release +- `rpminfo()`: add option to retrieve error message instead of raising a warning + +# Version 0.1.1 - 2018-01-26 + +- fix segfault in ZTS mode +- define `RPMVERSION` constant + +# Version 0.1.0 - 2018-01-26 +- first release with 2 functions: + `int rpmvercmp(string evr1, string evr2);` + `array rpminfo(string path [, bool full]);` @@ -1,3 +1,5 @@ +[](https://github.com/remicollet/rpminfo/actions/workflows/ci.yaml) + # RPM information extension for PHP Retrieve RPM information from PHP code using librpm. @@ -23,6 +25,15 @@ From the sources tree $ make $ make test +From https://pecl.php.net/ using pecl command + + $ pecl install rpminfo + +From https://packagist.org/ using PHP Installer for Extensions + + $ pie install remi/rpminfo + + ---- # Usage @@ -42,7 +53,7 @@ Allow to compare 2 EVR (epoch:version-release) strings. The return value is < 0 ## rpminfo - array rpminfo(string path [, bool full [, string &error]]); + rpminfo(string path [, bool full [, string &error]]): array; Retrieve information from a rpm file, reading its metadata. If given `error` will be used to store error message instead of raising a warning. @@ -86,7 +97,7 @@ The return value is a hash table, or false if it fails. ## rpmdbinfo - array rpmdbinfo(string path [, bool full ]); + rpmdbinfo(string path [, bool full ]): array; Retrieve information from rpm database about an installed package. The return value is an array of hash tables, or false if it fails. @@ -182,6 +193,50 @@ The return value is an array of hash tables, or false if it fails. ) ) +## rpmexpand + + rpmexpand($text): string + +Retrieve expanded value of a RPM macro + + $ php -a + php > var_dump(rpmexpand("%{?fedora:Fedora %{fedora}}%{?rhel:Enterprise Linux %{rhel}}")); + string(9) "Fedora 41" + +## rpmexpandnumeric + + rpmexpandnumeric($text): int + +Retrieve numerical value of a RPM macro + + $ php -a + php > var_dump(rpmexpandnumeric("%__isa_bits")); + int(64) + +## rpmdefine + + rpmdefine($text): bool + +Define or change a RPM macro value. + +For example, can be used to set the Database path and backend + + $ mock -r almalinux-8-x86_64 init + ... + $ mock -r fedora-41-x86_64 init + ... + $ php -a + php > // use an old database (bdb) from an EL-8 chroot + php > rpmdefine("_dbpath /var/lib/mock/almalinux-8-x86_64/root/var/lib/rpm"); + php > rpmdefine("_db_backend bdb_ro"); + php > var_dump(rpmdbinfo("almalinux-release")[0]["Summary"]); + string(22) "AlmaLinux release file" + php > // use a new database (sqlite) from a Fedora-41 chroot + php > rpmdefine("_dbpath /var/lib/mock/fedora-41-x86_64/root/usr/lib/sysimage/rpm"); + php > rpmdefine("_db_backend sqlite"); + php > var_dump(rpmdbinfo("fedora-release")[0]["Summary"]); + string(20) "Fedora release files" + ---- # LICENSE diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..e7e64cc --- /dev/null +++ b/composer.json @@ -0,0 +1,14 @@ +{ + "name": "remi/rpminfo", + "type": "php-ext", + "license": "PHP-3.01", + "description": "RPM information", + "require": { + "php": ">= 8.0.0" + }, + "php-ext": { + "extension-name": "rpminfo", + "os-families": "linux", + "configure-options": [] + } +} diff --git a/package.xml b/package.xml index 9f29bbe..58b197e 100644 --- a/package.xml +++ b/package.xml @@ -13,10 +13,10 @@ Documentation: https://www.php.net/rpminfo <email>remi@php.net</email> <active>yes</active> </lead> - <date>2024-09-03</date> + <date>2025-09-25</date> <version> - <release>1.1.2dev</release> - <api>1.1.0</api> + <release>1.2.1</release> + <api>1.2.0</api> </version> <stability> <release>stable</release> @@ -24,7 +24,8 @@ Documentation: https://www.php.net/rpminfo </stability> <license uri="https://www.php.net/license/3_01.txt" filesource="LICENSE">PHP-3.01</license> <notes><![CDATA[ -- +- use RPMTAG_SIGMD5 instead of RPMTAG_PKGID removed in RPM 6 +- use RPMTAG_SHA1HEADER instead of RPMTAG_HDRID removed in RPM 6 ]]></notes> <contents> <dir name="/"> @@ -38,6 +39,7 @@ Documentation: https://www.php.net/rpminfo <file name="CREDITS" role="doc"/> <file name="LICENSE" role="doc"/> <file name="README.md" role="doc"/> + <file name="CHANGELOG.md" role="doc"/> <dir name ="examples"> <file name="repomanage.php" role="doc"/> <file name="rpmvercmp.php" role="doc"/> @@ -57,6 +59,7 @@ Documentation: https://www.php.net/rpminfo <file name="012-rpmaddtag.phpt" role="test"/> <file name="013-rpmdbsearch-error.phpt" role="test"/> <file name="014-stream.phpt" role="test"/> + <file name="015-rpmmacro.phpt" role="test"/> <file name="bidon.rpm" role="test"/> <file name="bidon-src.rpm" role="test"/> </dir> @@ -76,6 +79,22 @@ Documentation: https://www.php.net/rpminfo <extsrcrelease/> <changelog> <release> + <date>2024-12-19</date> + <version> + <release>1.2.0</release> + <api>1.2.0</api> + </version> + <stability> + <release>stable</release> + <api>stable</api> + </stability> + <license uri="https://www.php.net/license/3_01.txt" filesource="LICENSE">PHP-3.01</license> + <notes><![CDATA[ +- add rpmexpand, rpmexpandnumeric to retrieve rpm macro value +- add rpmdefine to set rpm macro value + ]]></notes> + </release> + <release> <date>2024-09-03</date> <version> <release>1.1.1</release> diff --git a/php_rpminfo.h b/php_rpminfo.h index 6f54208..68a8694 100644 --- a/php_rpminfo.h +++ b/php_rpminfo.h @@ -22,7 +22,7 @@ extern zend_module_entry rpminfo_module_entry; #define phpext_rpminfo_ptr &rpminfo_module_entry -#define PHP_RPMINFO_VERSION "1.1.2-dev" +#define PHP_RPMINFO_VERSION "1.2.1" #define PHP_RPMINFO_AUTHOR "Remi Collet" #define PHP_RPMINFO_LICENSE "PHP-3.01" @@ -30,6 +30,7 @@ #include <rpm/rpmio.h> #include <rpm/rpmlib.h> #include <rpm/rpmts.h> +#include <rpm/rpmmacro.h> #include "php_rpminfo.h" @@ -69,6 +70,13 @@ static rpmdb rpminfo_getdb(void) { return RPMINFO_G(db); } +static void rpminfo_closedb(void) { + if (RPMINFO_G(db)) { + rpmtsCloseDB(RPMINFO_G(ts)); + RPMINFO_G(db) = NULL; + } +} + static void rpm_header_to_zval(zval *return_value, Header h, zend_bool full) { HeaderIterator hi; @@ -391,22 +399,22 @@ PHP_FUNCTION(rpmdbsearch) RETURN_THROWS(); } - if (crit == RPMTAG_PKGID) { + if (crit == RPMTAG_INSTALLTID) { + tid = atol(name); + name = (char *)&tid; + len = sizeof(tid); + } else if (crit == RPMTAG_SIGMD5) { if (len != 32) { - zend_argument_value_error(1, "Bad length for PKGID, 32 expected"); + zend_argument_value_error(1, "Bad length for PKGID/SIGMD5, 32 expected"); RETURN_THROWS(); } len = hex2bin(name, MD5, len); name = MD5; - } else if (crit == RPMTAG_HDRID) { + } else if (crit == RPMTAG_SHA1HEADER) { if (len != 40) { - zend_argument_value_error(1, "Bad length for HDRID, 40 expected"); + zend_argument_value_error(1, "Bad length for HDRID/SHA1HEADER, 40 expected"); RETURN_THROWS(); } - } else if (crit == RPMTAG_INSTALLTID) { - tid = atol(name); - name = (char *)&tid; - len = sizeof(tid); } else if (crit == RPMTAG_INSTFILENAMES) { /* use input parameters */ } else { @@ -867,6 +875,66 @@ PHP_FUNCTION(rpmgetsymlink) } /* }}} */ +/* {{{ proto array rpmexpand(string $text): string + Expand macro in text */ +PHP_FUNCTION(rpmexpand) +{ + char *text, *result; + size_t len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &text, &len) == FAILURE) { + RETURN_THROWS(); + } + + (void)rpminfo_getts(); /* read config files */ + + result = rpmExpand(text, NULL); + RETVAL_STRING(result); + free(result); +} +/* }}} */ + +/* {{{ proto array rpmexpandnumeric(string $text): int + Expand macro in text */ +PHP_FUNCTION(rpmexpandnumeric) +{ + char *text; + size_t len; + int result; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &text, &len) == FAILURE) { + RETURN_THROWS(); + } + + (void)rpminfo_getts(); /* read config files */ + + result = rpmExpandNumeric(text); + + RETURN_LONG(result); +} +/* }}} */ + +/* {{{ proto array rpmdefine(string $macro): bool + Define a new macro */ +PHP_FUNCTION(rpmdefine) +{ + char *macro; + size_t len; + int result; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", ¯o, &len) == FAILURE) { + RETURN_THROWS(); + } + + (void)rpminfo_getts(); /* read config files */ + + rpminfo_closedb(); /* Close the DB to allow path change */ + + result = rpmDefineMacro(NULL, macro, RMIL_GLOBAL); + + RETURN_BOOL(result == 0); +} +/* }}} */ /* {{{ PHP_MINIT_FUNCTION */ @@ -940,10 +1008,8 @@ PHP_RINIT_FUNCTION(rpminfo) PHP_RSHUTDOWN_FUNCTION(rpminfo) { if (RPMINFO_G(ts)) { - if (RPMINFO_G(db)) { - rpmtsCloseDB(RPMINFO_G(ts)); - RPMINFO_G(db) = NULL; - } + rpminfo_closedb(); + rpmtsFree(RPMINFO_G(ts)); RPMINFO_G(ts) = NULL; } diff --git a/rpminfo.stub.php b/rpminfo.stub.php index aa87215..026df4b 100644 --- a/rpminfo.stub.php +++ b/rpminfo.stub.php @@ -13,3 +13,10 @@ function rpminfo(string $path, bool $full = false, ?string &$error = null): Arra function rpmvercmp(string $evr1, string $evr2, ?string $operator = null): int|bool {} function rpmgetsymlink(string $path, string $name): string|null {} + +function rpmexpand(string $text): string {} + +function rpmexpandnumeric(string $text): int {} + +function rpmdefine(string $macro): bool {} + diff --git a/rpminfo_arginfo.h b/rpminfo_arginfo.h index 0764f6f..6db4fed 100644 --- a/rpminfo_arginfo.h +++ b/rpminfo_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 6b129e53b21eb21027683874775c2cdb7d1d485d */ + * Stub hash: dc980a56084190700162f5a8c70b54fcdbc30ced */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_rpmaddtag, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, rpmtag, IS_LONG, 0) @@ -34,6 +34,18 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_rpmgetsymlink, 0, 2, IS_STRING, ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_rpmexpand, 0, 1, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, text, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_rpmexpandnumeric, 0, 1, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, text, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_rpmdefine, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, macro, IS_STRING, 0) +ZEND_END_ARG_INFO() + ZEND_FUNCTION(rpmaddtag); ZEND_FUNCTION(rpmdbinfo); @@ -41,6 +53,9 @@ ZEND_FUNCTION(rpmdbsearch); ZEND_FUNCTION(rpminfo); ZEND_FUNCTION(rpmvercmp); ZEND_FUNCTION(rpmgetsymlink); +ZEND_FUNCTION(rpmexpand); +ZEND_FUNCTION(rpmexpandnumeric); +ZEND_FUNCTION(rpmdefine); static const zend_function_entry ext_functions[] = { @@ -50,5 +65,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(rpminfo, arginfo_rpminfo) ZEND_FE(rpmvercmp, arginfo_rpmvercmp) ZEND_FE(rpmgetsymlink, arginfo_rpmgetsymlink) + ZEND_FE(rpmexpand, arginfo_rpmexpand) + ZEND_FE(rpmexpandnumeric, arginfo_rpmexpandnumeric) + ZEND_FE(rpmdefine, arginfo_rpmdefine) ZEND_FE_END }; diff --git a/tests/004-constants.phpt b/tests/004-constants.phpt index 397c97f..18104cc 100644 --- a/tests/004-constants.phpt +++ b/tests/004-constants.phpt @@ -8,5 +8,5 @@ var_dump(RPMVERSION); ?> Done --EXPECTF-- -string(%d) "4.%s" +string(%d) "%s" Done diff --git a/tests/008-rpmdbsearch.phpt b/tests/008-rpmdbsearch.phpt index f348b92..6e0e402 100644 --- a/tests/008-rpmdbsearch.phpt +++ b/tests/008-rpmdbsearch.phpt @@ -1,7 +1,10 @@ --TEST-- Check for rpmdbinfo function --SKIPIF-- -<?php if (!extension_loaded("rpminfo")) print "skip"; ?> +<?php +if (!extension_loaded("rpminfo")) print "skip"; +?> + --FILE-- <?php echo "Name / glob\n"; @@ -20,16 +23,16 @@ $phprpm = $a[0]['Name']; $p = rpmdbinfo($phprpm, 1); echo "Pkgid\n"; -$a = rpmdbsearch($p[0]['Sigmd5'], RPMTAG_PKGID); +$a = rpmdbsearch($p[0]['Sigmd5'], RPMTAG_SIGMD5); var_dump($a[0]['Name'] == $phprpm); echo "Hdrid\n"; -$a = rpmdbsearch($p[0]['Sha1header'], RPMTAG_HDRID); +$a = rpmdbsearch($p[0]['Sha1header'], RPMTAG_SHA1HEADER); var_dump($a[0]['Name'] == $phprpm); var_dump(count($a[0]) < 10); echo "Hdrid (full)\n"; -$a = rpmdbsearch($p[0]['Sha1header'], RPMTAG_HDRID, -1, true); +$a = rpmdbsearch($p[0]['Sha1header'], RPMTAG_SHA1HEADER, -1, true); var_dump($a[0]['Name'] == $phprpm); var_dump($a[0]['Sha1header'] == $p[0]['Sha1header']); var_dump(count($a[0]) > 20); diff --git a/tests/015-rpmmacro.phpt b/tests/015-rpmmacro.phpt new file mode 100644 index 0000000..794cabf --- /dev/null +++ b/tests/015-rpmmacro.phpt @@ -0,0 +1,25 @@ +--TEST-- +Check for rpmdefine, rpmexpand, rpmexpandnumeric +--SKIPIF-- +<?php if (!extension_loaded("rpminfo")) print "skip"; ?> +--FILE-- +<?php +var_dump(is_dir(rpmexpand("%{_dbpath}"))); + +var_dump(rpmexpandnumeric("%__isa_bits") === PHP_INT_SIZE * 8); +var_dump(is_int(rpmexpandnumeric("0%{?fedora}%{?rhel}"))); + +$name = "_my_test_macro_for_rpminfo_"; +$val = __FILE__; +var_dump(rpmexpand("%$name") === "%$name" ); +var_dump(rpmdefine("$name $val")); +var_dump(rpmexpand("%$name") === __FILE__); +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) + |
