/* +----------------------------------------------------------------------+ | rpminfo extension for PHP | +----------------------------------------------------------------------+ | 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 | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Remi Collet <remi@php.net> | +----------------------------------------------------------------------+ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #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> #include <rpm/rpmio.h> #include <rpm/rpmlib.h> #include <rpm/rpmts.h> #include "php_rpminfo.h" #include "rpminfo_arginfo.h" 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; ZEND_DECLARE_MODULE_GLOBALS(rpminfo) 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), _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) { 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; } } } 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: add_assoc_long(return_value, rpmTagGetName(tag), (zend_long)headerGetNumber(h, tag)); break; case RPM_INT16_TYPE: if (rpmTagGetReturnType(tag) == RPM_ARRAY_RETURN_TYPE) { struct rpmtd_s keys; if (headerGet(h, tag, &keys, HEADERGET_MINMEM)) { uint16_t *key; zval tmp; array_init(&tmp); rpmtdInit(&keys); while (rpmtdNext(&keys)>=0) { key = rpmtdGetUint16(&keys); add_next_index_long(&tmp, (zend_long)*key); } add_assoc_zval(return_value, rpmTagGetName(tag), &tmp); } else { add_assoc_null(return_value, rpmTagGetName(tag)); } } else { add_assoc_long(return_value, rpmTagGetName(tag), (zend_long)headerGetNumber(h, tag)); } break; case RPM_INT32_TYPE: if (rpmTagGetReturnType(tag) == RPM_ARRAY_RETURN_TYPE) { struct rpmtd_s keys; if (headerGet(h, tag, &keys, HEADERGET_MINMEM)) { uint32_t *key; zval tmp; array_init(&tmp); rpmtdInit(&keys); while (rpmtdNext(&keys)>=0) { key = rpmtdGetUint32(&keys); add_next_index_long(&tmp, (zend_long)*key); } add_assoc_zval(return_value, rpmTagGetName(tag), &tmp); } else { add_assoc_null(return_value, rpmTagGetName(tag)); } } else { add_assoc_long(return_value, rpmTagGetName(tag), (zend_long)headerGetNumber(h, tag)); } break; case RPM_INT64_TYPE: if (rpmTagGetReturnType(tag) == RPM_ARRAY_RETURN_TYPE) { struct rpmtd_s keys; if (headerGet(h, tag, &keys, HEADERGET_MINMEM)) { uint64_t *key; zval tmp; array_init(&tmp); rpmtdInit(&keys); while (rpmtdNext(&keys)>=0) { key = rpmtdGetUint64(&keys); add_next_index_long(&tmp, (zend_long)*key); } add_assoc_zval(return_value, rpmTagGetName(tag), &tmp); } else { add_assoc_null(return_value, rpmTagGetName(tag)); } } else { add_assoc_long(return_value, rpmTagGetName(tag), (zend_long)headerGetNumber(h, tag)); } break; case RPM_STRING_ARRAY_TYPE: { struct rpmtd_s keys; if (headerGet(h, tag, &keys, HEADERGET_MINMEM)) { const char *key; zval tmp; array_init(&tmp); while ((key = rpmtdNextString(&keys))) { add_next_index_string(&tmp, key); } add_assoc_zval(return_value, rpmTagGetName(tag), &tmp); } else { add_assoc_null(return_value, rpmTagGetName(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)); } } } headerFreeIterator(hi); if (full) { add_assoc_bool(return_value, "IsSource", headerIsSource(h)); } } /* {{{ proto array rpminfo(string path [, bool full [, string &$error]) Retrieve information from a RPM file */ PHP_FUNCTION(rpminfo) { char *path, *e_msg; size_t len, e_len=0; zend_bool full = 0; zval *error = NULL; FD_t f; Header h; rpmts ts = rpminfo_getts(); if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|bz", &path, &len, &full, &error) == FAILURE) { 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) { int rc; rc = rpmReadPackageFile(ts, f, "rpminfo", &h); if (rc == RPMRC_OK || rc == RPMRC_NOKEY || rc == RPMRC_NOTTRUSTED) { rpm_header_to_zval(return_value, h, full); if (h) { headerFree(h); } Fclose(f); return; } else if (rc == RPMRC_NOTFOUND) { e_len = spprintf(&e_msg, 0, "Can't read '%s': Argument is not a RPM file", path); } else if (rc == RPMRC_NOTFOUND) { e_len = spprintf(&e_msg, 0, "Can't read '%s': Error reading header from package", path); } else { e_len = spprintf(&e_msg, 0, "Can't read '%s': Unkown error", path); } Fclose(f); } else { e_len = spprintf(&e_msg, 0, "Can't open '%s': %s", path, Fstrerror(f)); } if (e_len) { if (error) { ZVAL_STRINGL(error, e_msg, e_len); } else { php_error_docref(NULL, E_WARNING, "%s", e_msg); } efree(e_msg); } RETURN_NULL(); } /* }}} */ /* {{{ proto array rpmdbinfo(string nevr [, bool full]) Retrieve information from an installed RPM */ PHP_FUNCTION(rpmdbinfo) { char *name; size_t len; zend_bool full = 0; Header h; rpmdb db; rpmdbMatchIterator di; if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|b", &name, &len, &full) == FAILURE) { RETURN_THROWS(); } db = rpminfo_getdb(); di = rpmdbInitIterator(db, RPMDBI_LABEL, name, len); if (!di) { /* Not found */ RETURN_NULL(); } 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); } rpmdbFreeIterator(di); } /* }}} */ 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 || tag == RPMDBI_FILETRIGGERNAME || tag == RPMDBI_TRANSFILETRIGGERNAME || tag == RPMDBI_RECOMMENDNAME || tag == RPMDBI_SUGGESTNAME || tag == RPMDBI_SUPPLEMENTNAME || tag == RPMDBI_ENHANCENAME || 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 EVRs (epoch:version-release) strings */ 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, 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); } /* }}} */ 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); } /* }}} */ /* {{{ 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); REGISTER_LONG_CONSTANT("RPMSENSE_LESS", RPMSENSE_LESS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_GREATER", RPMSENSE_GREATER, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_EQUAL", RPMSENSE_EQUAL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_POSTTRANS", RPMSENSE_POSTTRANS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_PREREQ", RPMSENSE_PREREQ, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_PRETRANS", RPMSENSE_PRETRANS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_INTERP", RPMSENSE_INTERP, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_SCRIPT_PRE", RPMSENSE_SCRIPT_PRE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_SCRIPT_POST", RPMSENSE_SCRIPT_POST, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_SCRIPT_PREUN", RPMSENSE_SCRIPT_PREUN, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_SCRIPT_POSTUN", RPMSENSE_SCRIPT_POSTUN, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_SCRIPT_VERIFY", RPMSENSE_SCRIPT_VERIFY, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_FIND_REQUIRES", RPMSENSE_FIND_REQUIRES, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_FIND_PROVIDES", RPMSENSE_FIND_PROVIDES, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_TRIGGERIN", RPMSENSE_TRIGGERIN, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_TRIGGERUN", RPMSENSE_TRIGGERUN, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_TRIGGERPOSTUN", RPMSENSE_TRIGGERPOSTUN, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_MISSINGOK", RPMSENSE_MISSINGOK, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_RPMLIB", RPMSENSE_RPMLIB, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("RPMSENSE_TRIGGERPREIN", RPMSENSE_TRIGGERPREIN, CONST_CS | CONST_PERSISTENT); 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); php_register_url_stream_wrapper("rpm", &php_stream_rpm_wrapper); return SUCCESS; } /* }}} */ /* {{{ PHP_RINIT_FUNCTION */ 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; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ 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); php_info_print_table_row(2, "RPM stream wrapper", "yes"); php_info_print_table_end(); /* Remove comments if you have entries in php.ini DISPLAY_INI_ENTRIES(); */ } /* }}} */ /* {{{ PHP_GINIT_FUNCTION */ static PHP_GINIT_FUNCTION(rpminfo) /* {{{ */ { #if defined(COMPILE_DL_SESSION) && defined(ZTS) ZEND_TSRMLS_CACHE_UPDATE(); #endif rpminfo_globals->ts = NULL; rpminfo_globals->db = NULL; } /* }}} */ /* {{{ rpminfo_module_entry */ zend_module_entry rpminfo_module_entry = { STANDARD_MODULE_HEADER_EX, NULL, NULL, "rpminfo", ext_functions, PHP_MINIT(rpminfo), NULL, PHP_RINIT(rpminfo), PHP_RSHUTDOWN(rpminfo), PHP_MINFO(rpminfo), PHP_RPMINFO_VERSION, PHP_MODULE_GLOBALS(rpminfo), PHP_GINIT(rpminfo), NULL, NULL, STANDARD_MODULE_PROPERTIES_EX }; /* }}} */ #ifdef COMPILE_DL_RPMINFO #ifdef ZTS ZEND_TSRMLS_CACHE_DEFINE() #endif ZEND_GET_MODULE(rpminfo) #endif /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */