diff options
-rw-r--r-- | .gitignore | 54 | ||||
-rw-r--r-- | CREDITS | 2 | ||||
-rw-r--r-- | EXPERIMENTAL | 0 | ||||
-rw-r--r-- | LICENSE | 68 | ||||
-rw-r--r-- | README.md | 36 | ||||
-rw-r--r-- | config.m4 | 30 | ||||
-rw-r--r-- | examples/repomanage.php | 74 | ||||
-rw-r--r-- | php_rpminfo.h | 60 | ||||
-rw-r--r-- | rpminfo.c | 178 | ||||
-rw-r--r-- | tests/001.phpt | 10 | ||||
-rw-r--r-- | tests/002.phpt | 29 |
11 files changed, 541 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7c022dd --- /dev/null +++ b/.gitignore @@ -0,0 +1,54 @@ +# Object files +*.o +*.lo + +# Libraries +*.lib +*.a +*.la + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app + + +# autotools +.deps +.libs +config.cache +config.guess +config.h +config.h.in +config.log +config.nice +config.status +config.sub +configure +configure.in +conftest +conftest.c +Makefile +Makefile.fragments +Makefile.global +Makefile.objects +acinclude.m4 +aclocal.m4 +autom4te.cache +build +install-sh +libtool +ltmain.sh +ltmain.sh.backup +missing +mkinstalldirs +modules +run-tests.php +run-tests.log +tmp-php.ini @@ -0,0 +1,2 @@ +rpminfo +Remi Collet diff --git a/EXPERIMENTAL b/EXPERIMENTAL new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/EXPERIMENTAL @@ -0,0 +1,68 @@ +-------------------------------------------------------------------- + The PHP License, version 3.01 +Copyright (c) 1999 - 2017 The PHP Group. All rights reserved. +-------------------------------------------------------------------- + +Redistribution and use in source and binary forms, with or without +modification, is permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. The name "PHP" must not be used to endorse or promote products + derived from this software without prior written permission. For + written permission, please contact group@php.net. + + 4. Products derived from this software may not be called "PHP", nor + may "PHP" appear in their name, without prior written permission + from group@php.net. You may indicate that your software works in + conjunction with PHP by saying "Foo for PHP" instead of calling + it "PHP Foo" or "phpfoo" + + 5. The PHP Group may publish revised and/or new versions of the + license from time to time. Each version will be given a + distinguishing version number. + Once covered code has been published under a particular version + of the license, you may always continue to use it under the terms + of that version. You may also choose to use such covered code + under the terms of any subsequent version of the license + published by the PHP Group. No one other than the PHP Group has + the right to modify the terms applicable to covered code created + under this License. + + 6. Redistributions of any form whatsoever must retain the following + acknowledgment: + "This product includes PHP software, freely available from + <http://www.php.net/software/>". + +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------- + +This software consists of voluntary contributions made by many +individuals on behalf of the PHP Group. + +The PHP Group can be contacted via Email at group@php.net. + +For more information on the PHP Group and the PHP project, +please see <http://www.php.net>. + +PHP includes the Zend Engine, freely available at +<http://www.zend.com>. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e3c75aa --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +rpminfo +======= + +Experimental wrapper for librpm + +For now, only expose + + int rpmvercmp(string evr1, string evr2); + + +Mostly a PoC build for fun because of + +https://bugzilla.redhat.com/1537981 +performance issue: dnf repomanage is really slow + + +Some benchmark results (find 15 old RPMs among 5000) + +# DNF on Fedora + + $ time dnf repomanage --old --keep 5 . + ... + real 0m15,971s + +# YUM on RHEL / CentOS + + $ time repomanage --old --keep 5 . + ... + real 0m5.519s + +# PHP script + + $ time php repomanage.php --old --keep 5 . + ... + real 0m0,634s + diff --git a/config.m4 b/config.m4 new file mode 100644 index 0000000..8d117a9 --- /dev/null +++ b/config.m4 @@ -0,0 +1,30 @@ +dnl config.m4 for extension rpminfo + +PHP_ARG_ENABLE(rpminfo, whether to enable rpminfo support, + [ --enable-rpminfo Enable rpminfo support]) + +if test "$PHP_RPMINFO" != "no"; then + dnl Write more examples of tests here... + + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + + AC_MSG_CHECKING(for librpm) + if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists rpm; then + if $PKG_CONFIG rpm --atleast-version 4; then + LIBRPM_CFLAGS=`$PKG_CONFIG rpm --cflags` + LIBRPM_LIBDIR=`$PKG_CONFIG rpm --libs` + LIBRPM_VERSON=`$PKG_CONFIG rpm --modversion` + AC_MSG_RESULT(from pkgconfig: version $LIBRPM_VERSON) + else + AC_MSG_ERROR(system librpm is too old) + fi + else + AC_MSG_ERROR(pkg-config not found) + fi + PHP_EVAL_LIBLINE($LIBRPM_LIBDIR, RPMINFO_SHARED_LIBADD) + PHP_EVAL_INCLINE($LIBRPM_CFLAGS) + + PHP_SUBST(RPMINFO_SHARED_LIBADD) + + PHP_NEW_EXTENSION(rpminfo, rpminfo.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) +fi diff --git a/examples/repomanage.php b/examples/repomanage.php new file mode 100644 index 0000000..8428118 --- /dev/null +++ b/examples/repomanage.php @@ -0,0 +1,74 @@ +#!/usr/bin/php +<?php + +extension_loaded("rpminfo") or die("rpminfo extension missing"); + +for ($i=1 ; $i<$_SERVER['argc'] ; $i++) { + switch($_SERVER['argv'][$i]) { + case '-o': + case '--old': + if (isset($old)) { + die("--old option incompatible with --new\n"); + } + $old = true; + break; + case '-n': + case '--new': + if (isset($new)) { + die("--new option incompatible with --old\n"); + } + case '-k': + case '--keep': + if (!isset($_SERVER['argv'][$i+1])) { + die("Missing argument for --keep option\n"); + } + $keep = (int)$_SERVER['argv'][$i+1]; + $i++; + break; + default: + $rpms = $_SERVER['argv'][$i]; + } +} +if (!isset($old)) { + die("Missing --old or --new option\n"); +} +if (!isset($keep)) { + $keep = 1; +} +if (!isset($rpms)) { + die("Missing rpm directory argument\n"); +} +if (is_dir($rpms)) { +} else { + die("$rpms is not a directory\n"); +} + +$tree = []; +$handle = popen('rpm -qp --qf "%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH} %{NEVR}\n" ' . $rpms . "/*.rpm", "r"); +while ($line = fgets($handle)) { + $tab = explode(' ', trim($line)); + if (count($tab) == 6) { + $tree[$tab[4]][$tab[0]][] = [ + 'name' => $tab[0], + 'path' => $tab[5], + 'evr' => "${tab[1]}:${tab[2]}-${tab[3]}", + ]; + } else { + echo "Ignore $line\n"; + } +} +foreach($tree as $arch => $subtree) { + foreach ($subtree as $name => $versions) { + if (count($versions) > $keep) { + if ($old) { + usort($versions, function($a, $b) { return -rpmvercmp($a['evr'], $b['evr']);} ); + } else { + usort($versions, function($a, $b) { return rpmvercmp($a['evr'], $b['evr']);} ); + } + for ($i = $keep ; $i < count($versions) ; $i++) { + echo $versions[$i]['path'] . "\n"; + } + } + } +} + diff --git a/php_rpminfo.h b/php_rpminfo.h new file mode 100644 index 0000000..9c8319c --- /dev/null +++ b/php_rpminfo.h @@ -0,0 +1,60 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 2018 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> | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHP_RPMINFO_H +#define PHP_RPMINFO_H + +extern zend_module_entry rpminfo_module_entry; +#define phpext_rpminfo_ptr &rpminfo_module_entry + +#define PHP_RPMINFO_VERSION "0.1.0" /* Replace with version number for your extension */ + +#ifdef PHP_WIN32 +# define PHP_RPMINFO_API __declspec(dllexport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +# define PHP_RPMINFO_API __attribute__ ((visibility("default"))) +#else +# define PHP_RPMINFO_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +/* + Declare any global variables you may need between the BEGIN + and END macros here: + +ZEND_BEGIN_MODULE_GLOBALS(rpminfo) + zend_long global_value; + char *global_string; +ZEND_END_MODULE_GLOBALS(rpminfo) +*/ + +/* Always refer to the globals in your function as RPMINFO_G(variable). + You are encouraged to rename these macros something shorter, see + examples in any other php module directory. +*/ +#define RPMINFO_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(rpminfo, v) + +#if defined(ZTS) && defined(COMPILE_DL_RPMINFO) +ZEND_TSRMLS_CACHE_EXTERN() +#endif + +#endif /* PHP_RPMINFO_H */ + diff --git a/rpminfo.c b/rpminfo.c new file mode 100644 index 0000000..b08e05b --- /dev/null +++ b/rpminfo.c @@ -0,0 +1,178 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 2018 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 "php_rpminfo.h" + +#include <rpm/rpmlib.h> + +/* If you declare any globals in php_rpminfo.h uncomment this: +ZEND_DECLARE_MODULE_GLOBALS(rpminfo) +*/ + +/* True global resources - no need for thread safety here */ +static int le_rpminfo; + +/* {{{ PHP_INI + */ +/* Remove comments and fill if you need to have entries in php.ini +PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("rpminfo.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_rpminfo_globals, rpminfo_globals) + STD_PHP_INI_ENTRY("rpminfo.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_rpminfo_globals, rpminfo_globals) +PHP_INI_END() +*/ +/* }}} */ + + +ZEND_BEGIN_ARG_INFO_EX(arginfo_rpmvercmp, 0, 0, 2) + ZEND_ARG_INFO(0, evr1) + ZEND_ARG_INFO(0, evr2) +ZEND_END_ARG_INFO() + +/* Every user-visible function in PHP should document itself in the source */ +/* {{{ proto string rpmcmpver(string evr1, string evr2) + Return a string to confirm that the module is compiled in */ +PHP_FUNCTION(rpmvercmp) +{ + char *evr1, *evr2; + size_t len1, len2; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &evr1, &len1, &evr2, &len2) == FAILURE) { + return; + } + + RETURN_LONG(rpmvercmp(evr1, evr2)); +} + +/* {{{ php_rpminfo_init_globals + */ +/* Uncomment this function if you have INI entries +static void php_rpminfo_init_globals(zend_rpminfo_globals *rpminfo_globals) +{ + rpminfo_globals->global_value = 0; + rpminfo_globals->global_string = NULL; +} +*/ +/* }}} */ + +/* {{{ PHP_MINIT_FUNCTION + */ +PHP_MINIT_FUNCTION(rpminfo) +{ + /* If you have INI entries, uncomment these lines + REGISTER_INI_ENTRIES(); + */ + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MSHUTDOWN_FUNCTION + */ +PHP_MSHUTDOWN_FUNCTION(rpminfo) +{ + /* uncomment this line if you have INI entries + UNREGISTER_INI_ENTRIES(); + */ + return SUCCESS; +} +/* }}} */ + +/* Remove if there's nothing to do at request start */ +/* {{{ PHP_RINIT_FUNCTION + */ +PHP_RINIT_FUNCTION(rpminfo) +{ +#if defined(COMPILE_DL_RPMINFO) && defined(ZTS) + ZEND_TSRMLS_CACHE_UPDATE(); +#endif + return SUCCESS; +} +/* }}} */ + +/* Remove if there's nothing to do at request end */ +/* {{{ PHP_RSHUTDOWN_FUNCTION + */ +PHP_RSHUTDOWN_FUNCTION(rpminfo) +{ + 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, "RPM library version", RPMVERSION); + php_info_print_table_end(); + + /* Remove comments if you have entries in php.ini + DISPLAY_INI_ENTRIES(); + */ +} +/* }}} */ + +/* {{{ rpminfo_functions[] + * + * Every user visible function must have an entry in rpminfo_functions[]. + */ +const zend_function_entry rpminfo_functions[] = { + PHP_FE(rpmvercmp, arginfo_rpmvercmp) + PHP_FE_END +}; +/* }}} */ + +/* {{{ rpminfo_module_entry + */ +zend_module_entry rpminfo_module_entry = { + STANDARD_MODULE_HEADER, + "rpminfo", + rpminfo_functions, + PHP_MINIT(rpminfo), + PHP_MSHUTDOWN(rpminfo), + PHP_RINIT(rpminfo), /* Replace with NULL if there's nothing to do at request start */ + PHP_RSHUTDOWN(rpminfo), /* Replace with NULL if there's nothing to do at request end */ + PHP_MINFO(rpminfo), + PHP_RPMINFO_VERSION, + STANDARD_MODULE_PROPERTIES +}; +/* }}} */ + +#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 + */ diff --git a/tests/001.phpt b/tests/001.phpt new file mode 100644 index 0000000..69f6aff --- /dev/null +++ b/tests/001.phpt @@ -0,0 +1,10 @@ +--TEST-- +Check for rpminfo presence +--SKIPIF-- +<?php if (!extension_loaded("rpminfo")) print "skip"; ?> +--FILE-- +<?php +echo "rpminfo extension is available"; +?> +--EXPECT-- +rpminfo extension is available diff --git a/tests/002.phpt b/tests/002.phpt new file mode 100644 index 0000000..513339c --- /dev/null +++ b/tests/002.phpt @@ -0,0 +1,29 @@ +--TEST-- +Check for rpmvercmp function +--SKIPIF-- +<?php if (!extension_loaded("rpminfo")) print "skip"; ?> +--FILE-- +<?php +var_dump(rpmvercmp("1.0", "1.1")); +var_dump(rpmvercmp("1.1", "1.0")); +var_dump(rpmvercmp("1.0", "1.0")); +// Errors +var_dump(rpmvercmp()); +var_dump(rpmvercmp("a")); +var_dump(rpmvercmp("a", "b", "c")); +?> +Done +--EXPECT-- +int(-1) +int(1) +int(0) + +Warning: rpmvercmp() expects exactly 2 parameters, 0 given in /work/GIT/php-rpminfo/tests/002.php on line 6 +NULL + +Warning: rpmvercmp() expects exactly 2 parameters, 1 given in /work/GIT/php-rpminfo/tests/002.php on line 7 +NULL + +Warning: rpmvercmp() expects exactly 2 parameters, 3 given in /work/GIT/php-rpminfo/tests/002.php on line 8 +NULL +Done |