From b412ee5342b1ed43278ef87d75dfd9701a6fba7c Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 8 Feb 2018 13:24:38 +0100 Subject: new function: array rpmdbinfo(string name [, bool full]); --- README.md | 22 ++++++- REFLECTION | 11 +++- package.xml | 4 +- rpminfo.c | 148 +++++++++++++++++++++++++++++++---------------- tests/007-rpmdbinfo.phpt | 26 +++++++++ 5 files changed, 156 insertions(+), 55 deletions(-) create mode 100644 tests/007-rpmdbinfo.phpt diff --git a/README.md b/README.md index a53d7e4..9461c22 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,10 @@ Allow to compare 2 EVR (epoch:version-release) strings. The return value is < 0 ## rpminfo - array rpminfo(string path [, bool full ]); + array rpminfo(string path [, bool full [, string &error]]); Retrieve information from a rpm file, reading its metadata. +If given `error` will be used to store error message instead of raising a warning. The return value is a hash table, or false if it fails. $ php -a @@ -82,6 +83,25 @@ The return value is a hash table, or false if it fails. php > echo $error; Can't open 'missing.rpm': No such file or directory +## rpmdbinfo + + array rpmdbinfo(string path [, bool full ]); + +Retrieve information from rpm database about an installed package. +The return value is an array of hash tables, or false if it fails. + + $ php -a + php > print_r(rpmdbinfo("php")); + Array + ( + [0] => Array + ( + [Name] => php + [Version] => 7.2.2 + [Release] => 1.fc27.remi + [Arch] => x86_64 + ) + ) ---- diff --git a/REFLECTION b/REFLECTION index 0c99556..5e105d2 100644 --- a/REFLECTION +++ b/REFLECTION @@ -1,10 +1,17 @@ -Extension [ extension #15 rpminfo version 0.1.2-dev ] { +Extension [ extension #15 rpminfo version 0.1.3-dev ] { - Constants [1] { - Constant [ string RPMVERSION ] { 4.14.0 } + Constant [ string RPMVERSION ] { 4.14.1 } } - Functions { + Function [ function rpmdbinfo ] { + + - Parameters [2] { + Parameter #0 [ $name ] + Parameter #1 [ $full ] + } + } Function [ function rpminfo ] { - Parameters [3] { diff --git a/package.xml b/package.xml index 6ee0aca..4f2d3a6 100644 --- a/package.xml +++ b/package.xml @@ -21,7 +21,8 @@ PHP 3.01 -- +- new function: + array rpmdbinfo(string name [, bool full]); @@ -45,6 +46,7 @@ + diff --git a/rpminfo.c b/rpminfo.c index 9749198..2eb0cdc 100644 --- a/rpminfo.c +++ b/rpminfo.c @@ -24,6 +24,8 @@ #include "php_ini.h" #include "ext/standard/info.h" +#include +#include #include #include #include @@ -34,6 +36,7 @@ ZEND_DECLARE_MODULE_GLOBALS(rpminfo) static rpmts rpminfo_getts(rpmVSFlags flags) { if (!RPMINFO_G(ts)) { + rpmReadConfigFiles(NULL, NULL); RPMINFO_G(ts) = rpmtsCreate(); } if (RPMINFO_G(ts)) { @@ -42,6 +45,61 @@ static rpmts rpminfo_getts(rpmVSFlags flags) { return RPMINFO_G(ts); } +static void rpm_header_to_zval(zval *return_value, Header h, zend_bool full) +{ + HeaderIterator hi; + rpmTagVal tag; + rpmTagType type; + const char *val; + + array_init(return_value); + hi = headerInitIterator(h); + while ((tag=headerNextTag(hi)) != RPMTAG_NOT_FOUND) { + switch (tag) { + case RPMTAG_NAME: + case RPMTAG_VERSION: + case RPMTAG_RELEASE: + case RPMTAG_EPOCH: + case RPMTAG_ARCH: + break; + default: + if (!full) { + continue; + } + } + + type = rpmTagGetTagType(tag); + switch (type) { + case RPM_STRING_TYPE: + case RPM_I18NSTRING_TYPE: + val = headerGetString(h, tag); + if (val) { + add_assoc_string(return_value, rpmTagGetName(tag), headerGetAsString(h, tag)); + } else { + add_assoc_null(return_value, rpmTagGetName(tag)); + } + break; + case RPM_CHAR_TYPE: + case RPM_INT8_TYPE: + case RPM_INT16_TYPE: + case RPM_INT32_TYPE: + case RPM_INT64_TYPE: + add_assoc_long(return_value, rpmTagGetName(tag), (zend_long)headerGetNumber(h, tag)); + break; + default: + val = headerGetAsString(h, tag); + if (val) { + add_assoc_string(return_value, rpmTagGetName(tag), headerGetAsString(h, tag)); + } else { + add_assoc_null(return_value, rpmTagGetName(tag)); + } + } + } + if (full) { + add_assoc_bool(return_value, "IsSource", headerIsSource(h)); + } +} + ZEND_BEGIN_ARG_INFO_EX(arginfo_rpminfo, 0, 0, 1) ZEND_ARG_INFO(0, path) ZEND_ARG_INFO(0, full) @@ -53,15 +111,11 @@ ZEND_END_ARG_INFO() PHP_FUNCTION(rpminfo) { char *path, *e_msg; - const char *val; size_t len, e_len=0; zend_bool full = 0; zval *error = NULL; FD_t f; Header h; - HeaderIterator hi; - rpmTagVal tag; - rpmTagType type; rpmts ts = rpminfo_getts(_RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES | RPMVSF_NOHDRCHK); if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|bz", &path, &len, &full, &error) == FAILURE) { @@ -79,53 +133,7 @@ PHP_FUNCTION(rpminfo) rc = rpmReadPackageFile(ts, f, "rpminfo", &h); if (rc == RPMRC_OK || rc == RPMRC_NOKEY || rc == RPMRC_NOTTRUSTED) { - - array_init(return_value); - hi = headerInitIterator(h); - while ((tag=headerNextTag(hi)) != RPMTAG_NOT_FOUND) { - switch (tag) { - case RPMTAG_NAME: - case RPMTAG_VERSION: - case RPMTAG_RELEASE: - case RPMTAG_EPOCH: - case RPMTAG_ARCH: - break; - default: - if (!full) { - continue; - } - } - - type = rpmTagGetTagType(tag); - switch (type) { - case RPM_STRING_TYPE: - case RPM_I18NSTRING_TYPE: - val = headerGetString(h, tag); - if (val) { - add_assoc_string(return_value, rpmTagGetName(tag), headerGetAsString(h, tag)); - } else { - add_assoc_null(return_value, rpmTagGetName(tag)); - } - break; - case RPM_CHAR_TYPE: - case RPM_INT8_TYPE: - case RPM_INT16_TYPE: - case RPM_INT32_TYPE: - case RPM_INT64_TYPE: - add_assoc_long(return_value, rpmTagGetName(tag), (zend_long)headerGetNumber(h, tag)); - break; - default: - val = headerGetAsString(h, tag); - if (val) { - add_assoc_string(return_value, rpmTagGetName(tag), headerGetAsString(h, tag)); - } else { - add_assoc_null(return_value, rpmTagGetName(tag)); - } - } - } - if (full) { - add_assoc_bool(return_value, "IsSource", headerIsSource(h)); - } + rpm_header_to_zval(return_value, h, full); if (h) { headerFree(h); } @@ -156,6 +164,43 @@ PHP_FUNCTION(rpminfo) } /* }}} */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_rpmdbinfo, 0, 0, 1) + ZEND_ARG_INFO(0, name) + ZEND_ARG_INFO(0, full) +ZEND_END_ARG_INFO() + +/* {{{ proto array rpmdbinfo(string name [, bool full [, string &$error]) + Retrieve information from a RPM file */ +PHP_FUNCTION(rpmdbinfo) +{ + char *name; + size_t len; + zend_bool full = 0; + Header h; + rpmdb db; + rpmdbMatchIterator di; + rpmts ts = rpminfo_getts(_RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES | RPMVSF_NOHDRCHK); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|b", &name, &len, &full) == FAILURE) { + return; + } + + rpmtsOpenDB(ts, O_RDONLY); + db = rpmtsGetRdb(ts); + di = rpmdbInitIterator(db, RPMTAG_NAME, name, len); + if (!di) { + RETURN_FALSE; + } + + array_init(return_value); + while ((h = rpmdbNextIterator(di)) != NULL) { + zval tmp; + rpm_header_to_zval(&tmp, h, full); + add_next_index_zval(return_value, &tmp); + } +} +/* }}} */ + ZEND_BEGIN_ARG_INFO_EX(arginfo_rpmvercmp, 0, 0, 2) ZEND_ARG_INFO(0, evr1) ZEND_ARG_INFO(0, evr2) @@ -240,6 +285,7 @@ PHP_GSHUTDOWN_FUNCTION(rpminfo) * Every user visible function must have an entry in rpminfo_functions[]. */ const zend_function_entry rpminfo_functions[] = { + PHP_FE(rpmdbinfo, arginfo_rpmdbinfo) PHP_FE(rpminfo, arginfo_rpminfo) PHP_FE(rpmvercmp, arginfo_rpmvercmp) PHP_FE_END diff --git a/tests/007-rpmdbinfo.phpt b/tests/007-rpmdbinfo.phpt new file mode 100644 index 0000000..6ef5aa1 --- /dev/null +++ b/tests/007-rpmdbinfo.phpt @@ -0,0 +1,26 @@ +--TEST-- +Check for rpmdbinfo function +--SKIPIF-- + +--FILE-- + +Done +--EXPECTF-- +bool(false) +array(1) { + [0]=> + array(4) { + ["Name"]=> + string(4) "bash" + ["Version"]=> + string(%d) "%s" + ["Release"]=> + string(%d) "%s" + ["Arch"]=> + string(%d) "%s" + } +} +Done -- cgit