summaryrefslogtreecommitdiffstats
path: root/rpminfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'rpminfo.c')
-rw-r--r--rpminfo.c757
1 files changed, 682 insertions, 75 deletions
diff --git a/rpminfo.c b/rpminfo.c
index 263270a..e3fc4f5 100644
--- a/rpminfo.c
+++ b/rpminfo.c
@@ -1,8 +1,8 @@
/*
+----------------------------------------------------------------------+
- | PHP Version 7 |
+ | rpminfo extension for PHP |
+----------------------------------------------------------------------+
- | Copyright (c) 2018 The PHP Group |
+ | Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -23,6 +23,7 @@
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
+#include "ext/standard/php_string.h"
#include <fcntl.h>
#include <rpm/rpmdb.h>
@@ -32,44 +33,78 @@
#include "php_rpminfo.h"
+#include "rpminfo_arginfo.h"
+
+#ifdef HAVE_ARCHIVE
+struct php_rpm_stream_data_t {
+ FD_t gzdi;
+ Header h;
+ rpmfiles files;
+ rpmfi fi;
+ php_stream *stream;
+};
+
+#define STREAM_DATA_FROM_STREAM() \
+ struct php_rpm_stream_data_t *self = (struct php_rpm_stream_data_t *) stream->abstract;
+#endif
+
ZEND_DECLARE_MODULE_GLOBALS(rpminfo)
-static rpmts rpminfo_getts(rpmVSFlags flags) {
+static rpmts rpminfo_getts(void) {
if (!RPMINFO_G(ts)) {
rpmReadConfigFiles(NULL, NULL);
RPMINFO_G(ts) = rpmtsCreate();
}
if (RPMINFO_G(ts)) {
- (void)rpmtsSetVSFlags(RPMINFO_G(ts), flags);
+ (void)rpmtsSetVSFlags(RPMINFO_G(ts), _RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES | RPMVSF_NOHDRCHK);
}
return RPMINFO_G(ts);
}
+static rpmdb rpminfo_getdb(void) {
+ if (!RPMINFO_G(db)) {
+ rpmts ts = rpminfo_getts();
+
+ rpmtsOpenDB(ts, O_RDONLY);
+ RPMINFO_G(db) = rpmtsGetRdb(ts);
+ }
+ return RPMINFO_G(db);
+}
+
static void rpm_header_to_zval(zval *return_value, Header h, zend_bool full)
{
HeaderIterator hi;
rpmTagVal tag;
rpmTagType type;
const char *val;
+ int i;
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:
- case RPMTAG_SUMMARY:
- break;
- default:
- if (!full) {
- continue;
- }
+ if (!full) {
+ switch (tag) {
+ case RPMTAG_NAME:
+ case RPMTAG_VERSION:
+ case RPMTAG_RELEASE:
+ case RPMTAG_EPOCH:
+ case RPMTAG_ARCH:
+ case RPMTAG_SUMMARY:
+ /* Always present tags */
+ break;
+ default:
+ /* Additional tags */
+ for (i=0 ; i<RPMINFO_G(nb_tags) ; i++) {
+ if (tag == RPMINFO_G(tags)[i]) {
+ break;
+ }
+ }
+ if (i==RPMINFO_G(nb_tags)) {
+ continue;
+ }
+ }
}
- //printf("Tag: %-30s Type: %8lx - %8lx - %8lx\n", rpmTagGetName(tag), (long)rpmTagGetTagType(tag), (long)rpmTagGetType(tag), (long)rpmTagGetReturnType(tag));
type = rpmTagGetTagType(tag);
switch (type) {
case RPM_STRING_TYPE:
@@ -174,17 +209,12 @@ static void rpm_header_to_zval(zval *return_value, Header h, zend_bool full)
}
}
}
+ headerFreeIterator(hi);
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)
- ZEND_ARG_INFO(1, error)
-ZEND_END_ARG_INFO()
-
/* {{{ proto array rpminfo(string path [, bool full [, string &$error])
Retrieve information from a RPM file */
PHP_FUNCTION(rpminfo)
@@ -195,16 +225,19 @@ PHP_FUNCTION(rpminfo)
zval *error = NULL;
FD_t f;
Header h;
- rpmts ts = rpminfo_getts(_RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES | RPMVSF_NOHDRCHK);
+ rpmts ts = rpminfo_getts();
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|bz", &path, &len, &full, &error) == FAILURE) {
- return;
+ RETURN_THROWS();
}
if (error) {
ZVAL_DEREF(error);
zval_dtor(error);
ZVAL_NULL(error);
}
+ if (php_check_open_basedir(path)) {
+ RETURN_NULL();
+ }
f = Fopen(path, "r");
if (f) {
@@ -239,17 +272,12 @@ PHP_FUNCTION(rpminfo)
}
efree(e_msg);
}
- RETURN_FALSE;
+ RETURN_NULL();
}
/* }}} */
-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 */
+/* {{{ proto array rpmdbinfo(string nevr [, bool full])
+ Retrieve information from an installed RPM */
PHP_FUNCTION(rpmdbinfo)
{
char *name;
@@ -258,17 +286,16 @@ PHP_FUNCTION(rpmdbinfo)
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;
+ RETURN_THROWS();
}
- rpmtsOpenDB(ts, O_RDONLY);
- db = rpmtsGetRdb(ts);
- di = rpmdbInitIterator(db, RPMTAG_NAME, name, len);
+ db = rpminfo_getdb();
+ di = rpmdbInitIterator(db, RPMDBI_LABEL, name, len);
if (!di) {
- RETURN_FALSE;
+ /* Not found */
+ RETURN_NULL();
}
array_init(return_value);
@@ -277,33 +304,583 @@ PHP_FUNCTION(rpmdbinfo)
rpm_header_to_zval(&tmp, h, full);
add_next_index_zval(return_value, &tmp);
}
+
+ rpmdbFreeIterator(di);
}
/* }}} */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_rpmvercmp, 0, 0, 2)
- ZEND_ARG_INFO(0, evr1)
- ZEND_ARG_INFO(0, evr2)
-ZEND_END_ARG_INFO()
+static unsigned char nibble(char c) {
+ if (c >= '0' && c <= '9') {
+ return (c - '0');
+ }
+ if (c >= 'a' && c <= 'f') {
+ return (c - 'a') + 10;
+ }
+ if (c >= 'A' && c <= 'F') {
+ return (c - 'A') + 10;
+ }
+ return 0;
+}
+
+static int hex2bin(const char *hex, char *bin, int len) {
+ int i;
+
+ for (i=0 ; (i+1)<len ; i+=2, hex+=2, bin++) {
+ *bin = nibble(hex[0]) << 4 | nibble(hex[1]);
+ }
+
+ return i/2;
+}
+
+static int haveIndex(zend_long tag) {
+ /*
+ All DB indexes
+ excepted RPMDBI_PACKAGES and RPMDBI_LABEL doesn't match any tag
+ */
+ if (tag == RPMDBI_NAME ||
+ tag == RPMDBI_BASENAMES ||
+ tag == RPMDBI_GROUP ||
+ tag == RPMDBI_REQUIRENAME ||
+ tag == RPMDBI_PROVIDENAME ||
+ tag == RPMDBI_CONFLICTNAME ||
+ tag == RPMDBI_OBSOLETENAME ||
+ tag == RPMDBI_TRIGGERNAME ||
+ tag == RPMDBI_DIRNAMES ||
+ tag == RPMDBI_INSTALLTID ||
+ tag == RPMDBI_SIGMD5 ||
+ tag == RPMDBI_SHA1HEADER ||
+#ifdef HAVE_WEAKDEP
+ tag == RPMDBI_FILETRIGGERNAME ||
+ tag == RPMDBI_TRANSFILETRIGGERNAME ||
+ tag == RPMDBI_RECOMMENDNAME ||
+ tag == RPMDBI_SUGGESTNAME ||
+ tag == RPMDBI_SUPPLEMENTNAME ||
+ tag == RPMDBI_ENHANCENAME ||
+#endif
+ tag == RPMDBI_INSTFILENAMES) {
+ return 1;
+ }
+ return 0;
+}
+
+/* {{{ proto array rpmdbsearch(string pattern [, integer tag_name = RPMTAG_NAME [, integer mode = -1 [, bool full = 0]]])
+ Search information from installed RPMs */
+PHP_FUNCTION(rpmdbsearch)
+{
+ char MD5[16];
+ rpm_tid_t tid;
+ char *name;
+ size_t len;
+ zend_long crit = RPMTAG_NAME;
+ zend_long mode = -1;
+ zend_bool full = 0;
+ Header h;
+ rpmdb db;
+ rpmdbMatchIterator di;
+ int useIndex = 1;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|llb", &name, &len, &crit, &mode, &full) == FAILURE) {
+ RETURN_THROWS();
+ }
+ if (rpmTagGetType(crit) == RPM_NULL_TYPE) {
+ zend_argument_value_error(2, "Unkown rpmtag");
+ RETURN_THROWS();
+ }
+ if (mode != RPMMIRE_DEFAULT &&
+ mode != RPMMIRE_STRCMP &&
+ mode != RPMMIRE_REGEX &&
+ mode != RPMMIRE_GLOB &&
+ mode != -1) {
+ zend_argument_value_error(3, "Unkown rpmmire");
+ RETURN_THROWS();
+ }
+
+ if (crit == RPMTAG_PKGID) {
+ if (len != 32) {
+ zend_argument_value_error(1, "Bad length for PKGID, 32 expected");
+ RETURN_THROWS();
+ }
+ len = hex2bin(name, MD5, len);
+ name = MD5;
+ } else if (crit == RPMTAG_HDRID) {
+ if (len != 40) {
+ zend_argument_value_error(1, "Bad length for HDRID, 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 {
+ /* Faster mode if index exists and name is not a pattern */
+ useIndex = haveIndex(crit) && mode < 0;
+ }
+
+ db = rpminfo_getdb();
+ if (useIndex) {
+ /* Simple criterion using index */
+ di = rpmdbInitIterator(db, crit, name, len);
+ } else {
+ /* query all packages */
+ di = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0);
+ /* add criterion */
+ if (di) {
+ if (rpmdbSetIteratorRE(di, crit, (mode<0 ? RPMMIRE_DEFAULT : mode), name)) {
+ php_error_docref(NULL, E_WARNING, "Can't set filter");
+ RETURN_NULL();
+ }
+ }
+ }
+ if (!di) {
+ /* Not found */
+ RETURN_NULL();
+ }
+
+ array_init_size(return_value, rpmdbGetIteratorCount(di));
+ while ((h = rpmdbNextIterator(di)) != NULL) {
+ zval tmp;
+ rpm_header_to_zval(&tmp, h, full);
+ add_next_index_zval(return_value, &tmp);
+ }
+
+ rpmdbFreeIterator(di);
+}
+/* }}} */
/* {{{ proto int rpmcmpver(string evr1, string evr2)
- Compare 2 RPM evr (epoch:version-release) strings */
+ Compare 2 RPM EVRs (epoch:version-release) strings */
PHP_FUNCTION(rpmvercmp)
{
- char *evr1, *evr2;
- size_t len1, len2;
+ char *in_evr1, *evr1, *v1, *r1;
+ char *in_evr2, *evr2, *v2, *r2;
+ char *p, empty[] = "";
+ char *op = NULL;
+ long e1, e2, r;
+ size_t len1, len2, oplen;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|s", &in_evr1, &len1, &in_evr2, &len2, &op, &oplen) == FAILURE) {
+ RETURN_THROWS();
+ }
+ evr1 = estrdup(in_evr1);
+ evr2 = estrdup(in_evr2);
+
+ /* Epoch */
+ p = strchr(evr1, ':');
+ if (p) {
+ v1 = p+1;
+ *p=0;
+ e1 = atol(evr1);
+ } else {
+ v1 = evr1;
+ e1 = 0;
+ }
+ p = strchr(evr2, ':');
+ if (p) {
+ v2 = p+1;
+ *p=0;
+ e2 = atol(evr2);
+ } else {
+ v2 = evr2;
+ e2 = 0;
+ }
+ if (e1 < e2) {
+ r = -1;
+ } else if (e1 > e2) {
+ r = 1;
+ } else {
+ /* Version */
+ p = strchr(v1, '-');
+ if (p) {
+ r1 = p+1;
+ *p = 0;
+ } else {
+ r1 = empty;
+ }
+ p = strchr(v2, '-');
+ if (p) {
+ r2 = p+1;
+ *p = 0;
+ } else {
+ r2 = empty;
+ }
+ r = rpmvercmp(v1, v2);
+ if (!r) {
+ /* Release*/
+ r = rpmvercmp(r1, r2);
+ }
+ }
+ efree(evr1);
+ efree(evr2);
+
+ if (!op) {
+ RETURN_LONG(r);
+ }
+
+ if (!strcmp(op, "<") || !strcmp(op, "lt")) {
+ RETURN_BOOL(r < 0);
+ }
+ if (!strcmp(op, "<=") || !strcmp(op, "le")) {
+ RETURN_BOOL(r <= 0);
+ }
+ if (!strcmp(op, ">") || !strcmp(op, "gt")) {
+ RETURN_BOOL(r > 0);
+ }
+ if (!strcmp(op, ">=") || !strcmp(op, "ge")) {
+ RETURN_BOOL(r >= 0);
+ }
+ if (!strcmp(op, "==") || !strcmp(op, "=") || !strcmp(op, "eq")) {
+ RETURN_BOOL(r == 0);
+ }
+ if (!strcmp(op, "!=") || !strcmp(op, "<>") || !strcmp(op, "ne")) {
+ RETURN_BOOL(r != 0);
+ }
+
+ zend_argument_value_error(3, "must be a valid comparison operator");
+ RETURN_THROWS();
+}
+/* }}} */
+
+/* {{{ proto int rpmaddtag(int tag)
+ add a tag in the default set */
+PHP_FUNCTION(rpmaddtag)
+{
+ int i;
+ zend_long tag;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &tag) == FAILURE) {
+ RETURN_THROWS();
+ }
+
+ if (rpmTagGetType(tag) == RPM_NULL_TYPE) {
+ zend_argument_value_error(1, "Unkown rpmtag");
+ RETURN_THROWS();
+ }
+
+ if (RPMINFO_G(tags)) {
+ for (i=0 ; i<RPMINFO_G(nb_tags) ; i++) {
+ if (RPMINFO_G(tags)[i] == tag) {
+ RETURN_BOOL(0);
+ }
+ }
+ if (RPMINFO_G(nb_tags) == RPMINFO_G(max_tags)) {
+ RPMINFO_G(max_tags) += 16;
+ RPMINFO_G(tags) = erealloc(RPMINFO_G(tags), RPMINFO_G(max_tags) * sizeof(rpmTagVal));
+ }
+ } else {
+ RPMINFO_G(max_tags) = 16;
+ RPMINFO_G(tags) = emalloc(RPMINFO_G(max_tags) * sizeof(rpmTagVal));
+ }
+ RPMINFO_G(tags)[RPMINFO_G(nb_tags)++] = tag;
+
+ RETURN_BOOL(1);
+}
+/* }}} */
+
+#ifdef HAVE_ARCHIVE
+static ssize_t php_rpm_ops_read(php_stream *stream, char *buf, size_t count)
+{
+ ssize_t n = -1;
+ STREAM_DATA_FROM_STREAM();
+
+ if (self) {
+ n = rpmfiArchiveRead(self->fi, buf, count);
+ if (n == 0 || n < (ssize_t)count) {
+ stream->eof = 1;
+ }
+ }
+ return n;
+}
+
+static void php_rpm_ops_free(struct php_rpm_stream_data_t *self, int close_handle)
+{
+ if (self) {
+ if (close_handle) {
+ Fclose(self->gzdi);
+ rpmfilesFree(self->files);
+ rpmfiFree(self->fi);
+ headerFree(self->h);
+ }
+ efree(self);
+ }
+}
+
+static int php_rpm_ops_close(php_stream *stream, int close_handle)
+{
+ STREAM_DATA_FROM_STREAM();
+
+ php_rpm_ops_free(self, close_handle);
+ stream->abstract = NULL;
+
+ return EOF;
+}
+
+static int php_zip_ops_stat(php_stream *stream, php_stream_statbuf *ssb)
+{
+ STREAM_DATA_FROM_STREAM();
+
+ if (self) {
+ struct stat s[2]; /* librpm may use different size (32-bit) */
+ int rc;
+ rc = rpmfiStat(self->fi, 0, s);
+ memcpy(&ssb->sb, s, sizeof(ssb->sb));
+ return rc;
+ }
+ return -1;
+}
+
+const php_stream_ops php_stream_rpmio_ops = {
+ NULL, /* write */
+ php_rpm_ops_read,
+ php_rpm_ops_close,
+ NULL, /* flush */
+ "rpm",
+ NULL, /* seek */
+ NULL, /* cast */
+ php_zip_ops_stat,
+ NULL /* set_option */
+};
+
+static struct php_rpm_stream_data_t *php_stream_rpm_finder(const char *path, int want_content)
+{
+ size_t path_len;
+ zend_string *file_basename;
+ char file_dirname[MAXPATHLEN];
+ char *fragment;
+ size_t fragment_len;
+ struct php_rpm_stream_data_t *self = NULL;
+ FD_t fdi;
+ FD_t gzdi;
+ int rc;
+ Header h;
+ char rpmio_flags[80];
+ const char *compr;
+ rpmfiles files;
+ rpmfi fi;
+ rpmts ts = rpminfo_getts();
+
+ fragment = strchr(path, '#');
+ if (!fragment) {
+ return NULL;
+ }
+ if (strncasecmp("rpm://", path, 6) == 0) {
+ path += 6;
+ }
+ fragment_len = strlen(fragment);
+ if (fragment_len < 1) {
+ return NULL;
+ }
+ path_len = strlen(path);
+ if (path_len >= MAXPATHLEN) {
+ return NULL;
+ }
+ memcpy(file_dirname, path, path_len - fragment_len);
+ file_dirname[path_len - fragment_len] = '\0';
+ file_basename = php_basename(path, path_len - fragment_len, NULL, 0);
+ fragment++;
+ if (php_check_open_basedir(file_dirname)) {
+ zend_string_release_ex(file_basename, 0);
+ return NULL;
+ }
+ fdi = Fopen(file_dirname, "r.ufdio");
+ if (Ferror(fdi)) {
+ zend_string_release_ex(file_basename, 0);
+ return NULL;
+ }
+ rc = rpmReadPackageFile(ts, fdi, "rpm2cpio", &h);
+ if (rc != RPMRC_OK && rc != RPMRC_NOKEY && rc != RPMRC_NOTTRUSTED) {
+ zend_string_release_ex(file_basename, 0);
+ Fclose(fdi);
+ return NULL;
+ }
+
+ compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
+ snprintf(rpmio_flags, sizeof(rpmio_flags), "r.%s", compr ? compr : "gzip");
+ gzdi = Fdopen(fdi, rpmio_flags);
+ if (gzdi == NULL) {
+ headerFree(h);
+ Fclose(fdi);
+ zend_string_release_ex(file_basename, 0);
+ return NULL;
+ }
+
+ files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
+ fi = rpmfiNewArchiveReader(gzdi, files, RPMFI_ITER_READ_ARCHIVE);
+
+ while((rc = rpmfiNext(fi)) >=0) {
+ const char *fn = rpmfiFN(fi);
+ /*
+ printf("Name=%s, Size=%d, N=%d, mode=%d, reg=%d, content=%d, rdev=%d, inode=%d link=%s\n", fn,
+ (int)rpmfiFSize(fi), (int)rpmfiFNlink(fi), (int)rpmfiFMode(fi),
+ (int)S_ISREG(rpmfiFMode(fi)), (int)rpmfiArchiveHasContent(fi),
+ (int)rpmfiFRdev(fi), (int)rpmfiFInode(fi), rpmfiFLink(fi));
+ */
+ if (!strcmp(fn, fragment)) {
+ if (want_content && S_ISREG(rpmfiFMode(fi)) && !rpmfiArchiveHasContent(fi)) {
+ rpm_rdev_t rdev = rpmfiFRdev(fi);
+ rpm_ino_t inode = rpmfiFInode(fi);
+ while((rc = rpmfiNext(fi)) >=0) {
+ if (rdev == rpmfiFRdev(fi) && inode == rpmfiFInode(fi) && rpmfiArchiveHasContent(fi)) {
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+ if (rc == RPMERR_ITER_END) {
+ Fclose(gzdi);
+ rpmfilesFree(files);
+ rpmfiFree(fi);
+ headerFree(h);
+ } else {
+ self = emalloc(sizeof(*self));
+ self->gzdi = gzdi;
+ self->files = files;
+ self->fi = fi;
+ self->h = h;
+ }
+ zend_string_release_ex(file_basename, 0);
+
+ return self;
+}
+
+php_stream *php_stream_rpm_opener(php_stream_wrapper *wrapper,
+ const char *path,
+ const char *mode,
+ int options,
+ zend_string **opened_path,
+ php_stream_context *context STREAMS_DC)
+{
+ struct php_rpm_stream_data_t *self;
+
+ if (mode[0] != 'r') {
+ return NULL;
+ }
+ self = php_stream_rpm_finder(path, 1);
+ if (self) {
+ if (opened_path) {
+ *opened_path = zend_string_init(path, strlen(path), 0);
+ }
+ if (!S_ISREG(rpmfiFMode(self->fi)) || !rpmfiArchiveHasContent(self->fi)) {
+ php_rpm_ops_free(self, 1);
+ } else {
+ return php_stream_alloc(&php_stream_rpmio_ops, self, NULL, mode);
+ }
+ }
+
+ return NULL;
+}
+
+static int php_stream_rpm_stat(php_stream_wrapper *wrapper, const char *url, int flags,
+ php_stream_statbuf *ssb, php_stream_context *context)
+{
+ struct php_rpm_stream_data_t *self;
+ int rc = -1;
+
+ self = php_stream_rpm_finder(url, 0);
+ if (self) {
+ struct stat s[2]; /* librpm may use different size (32-bit) */
+ rc = rpmfiStat(self->fi, 0, s);
+ memcpy(&ssb->sb, s, sizeof(ssb->sb));
+ php_rpm_ops_free(self, 1);
+ }
+
+ return rc;
+}
+
+static const php_stream_wrapper_ops rpm_stream_wops = {
+ php_stream_rpm_opener,
+ NULL, /* close */
+ NULL, /* fstat */
+ php_stream_rpm_stat,
+ NULL, /* opendir */
+ "RPM wrapper",
+ NULL, /* unlink */
+ NULL, /* rename */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL /* metadata */
+};
+
+const php_stream_wrapper php_stream_rpm_wrapper = {
+ &rpm_stream_wops,
+ NULL,
+ 0 /* is_url */
+};
+
+/* {{{ proto array rpmgetsymlink(string path , string name)
+ Retrieve soft link target of en entry */
+PHP_FUNCTION(rpmgetsymlink)
+{
+ char *path, *name;
+ const char *link;
+ size_t plen, nlen;
+ FD_t fdi;
+ FD_t gzdi;
+ int rc;
+ Header h;
+ char rpmio_flags[80];
+ const char *compr;
+ rpmfiles files;
+ rpmfi fi;
+ rpmts ts = rpminfo_getts();
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &path, &plen, &name, &nlen) == FAILURE) {
+ RETURN_THROWS();
+ }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &evr1, &len1, &evr2, &len2) == FAILURE) {
- return;
+ if (php_check_open_basedir(path)) {
+ RETURN_NULL();
+ }
+ fdi = Fopen(path, "r.ufdio");
+ if (Ferror(fdi)) {
+ RETURN_NULL();
+ }
+ rc = rpmReadPackageFile(ts, fdi, "rpm2cpio", &h);
+ if (rc != RPMRC_OK && rc != RPMRC_NOKEY && rc != RPMRC_NOTTRUSTED) {
+ Fclose(fdi);
+ RETURN_NULL();
}
- RETURN_LONG(rpmvercmp(evr1, evr2));
+ compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
+ snprintf(rpmio_flags, sizeof(rpmio_flags), "r.%s", compr ? compr : "gzip");
+ gzdi = Fdopen(fdi, rpmio_flags);
+ if (gzdi == NULL) {
+ headerFree(h);
+ Fclose(fdi);
+ RETURN_NULL();
+ }
+
+ files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
+ fi = rpmfiNewArchiveReader(gzdi, files, RPMFI_ITER_READ_ARCHIVE);
+
+ rc = rpmfiFindFN(fi, name);
+ rpmfiSetFX(fi, rc); /* return value have change in 4.18 (from previous to new) */
+ if (rc < 0
+ || rpmfiFX(fi) != rc
+ || (link = rpmfiFLink(fi)) == NULL) {
+ RETVAL_NULL();
+ } else {
+ RETVAL_STRING(link);
+ }
+ rpmfiFree(fi);
+ rpmfilesFree(files);
+ headerFree(h);
+ Fclose(gzdi);
}
/* }}} */
+#endif /* HAVE_ARCHIVE */
+
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(rpminfo)
{
+ const char *tagname;
+ rpmtd names;
+
REGISTER_STRING_CONSTANT("RPMVERSION", (char *)RPMVERSION, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RPMSENSE_ANY", RPMSENSE_ANY, CONST_CS | CONST_PERSISTENT);
@@ -330,6 +907,22 @@ PHP_MINIT_FUNCTION(rpminfo)
REGISTER_LONG_CONSTANT("RPMSENSE_KEYRING", RPMSENSE_KEYRING, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RPMSENSE_CONFIG", RPMSENSE_CONFIG, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("RPMMIRE_DEFAULT", RPMMIRE_DEFAULT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("RPMMIRE_STRCMP", RPMMIRE_STRCMP, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("RPMMIRE_REGEX", RPMMIRE_REGEX, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("RPMMIRE_GLOB", RPMMIRE_GLOB, CONST_CS | CONST_PERSISTENT);
+
+ names = rpmtdNew();
+ rpmTagGetNames(names, 1);
+ while ((tagname = rpmtdNextString(names))) {
+ zend_register_long_constant(tagname, strlen(tagname), rpmTagGetValue(tagname+7), CONST_CS | CONST_PERSISTENT, module_number);
+ }
+ rpmtdFree(names);
+
+#ifdef HAVE_ARCHIVE
+ php_register_url_stream_wrapper("rpm", &php_stream_rpm_wrapper);
+#endif
+
return SUCCESS;
}
/* }}} */
@@ -341,6 +934,35 @@ PHP_RINIT_FUNCTION(rpminfo)
#if defined(COMPILE_DL_RPMINFO) && defined(ZTS)
ZEND_TSRMLS_CACHE_UPDATE();
#endif
+
+ RPMINFO_G(nb_tags) = 0;
+ RPMINFO_G(max_tags) = 0;
+ RPMINFO_G(tags) = NULL;
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_RSHUTDOWN_FUNCTION
+ */
+PHP_RSHUTDOWN_FUNCTION(rpminfo)
+{
+ if (RPMINFO_G(ts)) {
+ if (RPMINFO_G(db)) {
+ rpmtsCloseDB(RPMINFO_G(ts));
+ RPMINFO_G(db) = NULL;
+ }
+ rpmtsFree(RPMINFO_G(ts));
+ RPMINFO_G(ts) = NULL;
+ }
+
+ if (RPMINFO_G(tags)) {
+ efree(RPMINFO_G(tags));
+ RPMINFO_G(nb_tags) = 0;
+ RPMINFO_G(max_tags) = 0;
+ RPMINFO_G(tags) = NULL;
+ }
+
return SUCCESS;
}
/* }}} */
@@ -352,7 +974,14 @@ PHP_MINFO_FUNCTION(rpminfo)
php_info_print_table_start();
php_info_print_table_header(2, "rpminfo support", "enabled");
php_info_print_table_row(2, "Extension version", PHP_RPMINFO_VERSION);
+ php_info_print_table_row(2, "Author", PHP_RPMINFO_AUTHOR);
+ php_info_print_table_row(2, "License", PHP_RPMINFO_LICENSE);
php_info_print_table_row(2, "RPM library version", RPMVERSION);
+#ifdef HAVE_ARCHIVE
+ php_info_print_table_row(2, "RPM stream wrapper", "yes");
+#else
+ php_info_print_table_row(2, "RPM stream wrapper", "no");
+#endif
php_info_print_table_end();
/* Remove comments if you have entries in php.ini
@@ -369,32 +998,10 @@ static PHP_GINIT_FUNCTION(rpminfo) /* {{{ */
ZEND_TSRMLS_CACHE_UPDATE();
#endif
rpminfo_globals->ts = NULL;
+ rpminfo_globals->db = NULL;
}
/* }}} */
-/* {{{ PHP_GSHUTDOWN_FUNCTION
-*/
-PHP_GSHUTDOWN_FUNCTION(rpminfo)
-{
- if (rpminfo_globals->ts) {
- rpmtsFree(rpminfo_globals->ts);
- rpminfo_globals->ts = NULL;
- }
-}
-/* }}} */
-
-/* {{{ rpminfo_functions[]
- *
- * 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
-};
-/* }}} */
-
/* {{{ rpminfo_module_entry
*/
zend_module_entry rpminfo_module_entry = {
@@ -402,16 +1009,16 @@ zend_module_entry rpminfo_module_entry = {
NULL,
NULL,
"rpminfo",
- rpminfo_functions,
+ ext_functions,
PHP_MINIT(rpminfo),
NULL,
PHP_RINIT(rpminfo),
- NULL,
+ PHP_RSHUTDOWN(rpminfo),
PHP_MINFO(rpminfo),
PHP_RPMINFO_VERSION,
PHP_MODULE_GLOBALS(rpminfo),
PHP_GINIT(rpminfo),
- PHP_GSHUTDOWN(rpminfo),
+ NULL,
NULL,
STANDARD_MODULE_PROPERTIES_EX
};