summaryrefslogtreecommitdiffstats
path: root/rpminfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'rpminfo.c')
-rw-r--r--rpminfo.c413
1 files changed, 363 insertions, 50 deletions
diff --git a/rpminfo.c b/rpminfo.c
index 53b9c6c..e3fc4f5 100644
--- a/rpminfo.c
+++ b/rpminfo.c
@@ -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,17 +33,20 @@
#include "php_rpminfo.h"
-/* For PHP < 8.0 */
-#ifndef ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE
-#define ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, type_hint, allow_null, default_value) \
- ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null)
-#endif
+#include "rpminfo_arginfo.h"
-#ifndef RETURN_THROWS
-#define RETURN_THROWS() return
-#endif
+#ifdef HAVE_ARCHIVE
+struct php_rpm_stream_data_t {
+ FD_t gzdi;
+ Header h;
+ rpmfiles files;
+ rpmfi fi;
+ php_stream *stream;
+};
-#include "rpminfo_arginfo.h"
+#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)
@@ -231,6 +235,9 @@ PHP_FUNCTION(rpminfo)
zval_dtor(error);
ZVAL_NULL(error);
}
+ if (php_check_open_basedir(path)) {
+ RETURN_NULL();
+ }
f = Fopen(path, "r");
if (f) {
@@ -287,7 +294,7 @@ PHP_FUNCTION(rpmdbinfo)
db = rpminfo_getdb();
di = rpmdbInitIterator(db, RPMDBI_LABEL, name, len);
if (!di) {
- // Not found
+ /* Not found */
RETURN_NULL();
}
@@ -312,7 +319,7 @@ static unsigned char nibble(char c) {
if (c >= 'A' && c <= 'F') {
return (c - 'A') + 10;
}
- return 0;
+ return 0;
}
static int hex2bin(const char *hex, char *bin, int len) {
@@ -376,49 +383,29 @@ PHP_FUNCTION(rpmdbsearch)
RETURN_THROWS();
}
if (rpmTagGetType(crit) == RPM_NULL_TYPE) {
-#if PHP_VERSION_ID < 80000
- php_error_docref(NULL, E_WARNING, "Unkown rpmtag");
- RETURN_NULL();
-#else
zend_argument_value_error(2, "Unkown rpmtag");
RETURN_THROWS();
-#endif
}
if (mode != RPMMIRE_DEFAULT &&
mode != RPMMIRE_STRCMP &&
mode != RPMMIRE_REGEX &&
mode != RPMMIRE_GLOB &&
mode != -1) {
-#if PHP_VERSION_ID < 80000
- php_error_docref(NULL, E_WARNING, "Unkown rpmmire");
- RETURN_NULL();
-#else
zend_argument_value_error(3, "Unkown rpmmire");
RETURN_THROWS();
-#endif
}
if (crit == RPMTAG_PKGID) {
if (len != 32) {
-#if PHP_VERSION_ID < 80000
- php_error_docref(NULL, E_WARNING, "Bad length for PKGID, 32 expected");
- RETURN_NULL();
-#else
zend_argument_value_error(1, "Bad length for PKGID, 32 expected");
RETURN_THROWS();
-#endif
}
len = hex2bin(name, MD5, len);
name = MD5;
} else if (crit == RPMTAG_HDRID) {
if (len != 40) {
-#if PHP_VERSION_ID < 80000
- php_error_docref(NULL, E_WARNING, "Bad length for HDRID, 40 expected");
- RETURN_NULL();
-#else
zend_argument_value_error(1, "Bad length for HDRID, 40 expected");
RETURN_THROWS();
-#endif
}
} else if (crit == RPMTAG_INSTALLTID) {
tid = atol(name);
@@ -447,7 +434,7 @@ PHP_FUNCTION(rpmdbsearch)
}
}
if (!di) {
- // Not found
+ /* Not found */
RETURN_NULL();
}
@@ -469,16 +456,17 @@ PHP_FUNCTION(rpmvercmp)
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;
+ size_t len1, len2, oplen;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &in_evr1, &len1, &in_evr2, &len2) == FAILURE) {
+ 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
+ /* Epoch */
p = strchr(evr1, ':');
if (p) {
v1 = p+1;
@@ -498,11 +486,11 @@ PHP_FUNCTION(rpmvercmp)
e2 = 0;
}
if (e1 < e2) {
- RETVAL_LONG(-1);
+ r = -1;
} else if (e1 > e2) {
- RETVAL_LONG(1);
+ r = 1;
} else {
- // Version
+ /* Version */
p = strchr(v1, '-');
if (p) {
r1 = p+1;
@@ -518,16 +506,39 @@ PHP_FUNCTION(rpmvercmp)
r2 = empty;
}
r = rpmvercmp(v1, v2);
- if (r) {
- RETVAL_LONG(r);
- } else {
- // Release
+ if (!r) {
+ /* Release*/
r = rpmvercmp(r1, r2);
- RETVAL_LONG(r);
}
}
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();
}
/* }}} */
@@ -543,13 +554,8 @@ PHP_FUNCTION(rpmaddtag)
}
if (rpmTagGetType(tag) == RPM_NULL_TYPE) {
-#if PHP_VERSION_ID < 80000
- php_error_docref(NULL, E_WARNING, "Unkown rpmtag");
- RETURN_BOOL(0);
-#else
zend_argument_value_error(1, "Unkown rpmtag");
RETURN_THROWS();
-#endif
}
if (RPMINFO_G(tags)) {
@@ -572,12 +578,308 @@ PHP_FUNCTION(rpmaddtag)
}
/* }}} */
+#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 (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();
+ }
+
+ 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;
+ const char *tagname;
+ rpmtd names;
REGISTER_STRING_CONSTANT("RPMVERSION", (char *)RPMVERSION, CONST_CS | CONST_PERSISTENT);
@@ -617,6 +919,10 @@ PHP_MINIT_FUNCTION(rpminfo)
}
rpmtdFree(names);
+#ifdef HAVE_ARCHIVE
+ php_register_url_stream_wrapper("rpm", &php_stream_rpm_wrapper);
+#endif
+
return SUCCESS;
}
/* }}} */
@@ -668,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