From fcdfeb962a0643dca7f2e1a32f0a5e9f8ff5595d Mon Sep 17 00:00:00 2001 From: Martin Babinsky Date: Mon, 11 Jan 2016 16:22:40 +0100 Subject: [PATCH] use FFI call to rpmvercmp function for version comparison Stop using rpm-python to compare package versions since the implicit NSS initialization upon the module import breaks NSS handling in IPA code. Call rpm-libs C-API function via CFFI instead. Big thanks to Martin Kosek for sharing the code snippet that spurred this patch. https://fedorahosted.org/freeipa/ticket/5572 Reviewed-By: Jan Cholasta --- freeipa.spec.in | 2 +- ipaplatform/redhat/tasks.py | 44 ++++++++++++-------------------------------- 2 files changed, 13 insertions(+), 33 deletions(-) diff --git a/freeipa.spec.in b/freeipa.spec.in index 01d42bc621c83541af7517d6d91eb37fd5b5c5cc..cd26d4ce66e320f8b8bf6aaa3e738b4c11f89aa9 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -159,7 +159,7 @@ Requires: p11-kit Requires: systemd-python Requires: %{etc_systemd_dir} Requires: gzip -Requires: rpm-python +Requires: rpm-libs Conflicts: %{alt_name}-server Obsoletes: %{alt_name}-server < %{version} diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py index 2e894d776dcd5542e6c11cc0210add8ad9d90298..9be3ef664e6d15c31e53b7a8123de7b6bb2b81fe 100644 --- a/ipaplatform/redhat/tasks.py +++ b/ipaplatform/redhat/tasks.py @@ -30,7 +30,8 @@ import socket import sys import urllib import base64 -import rpm +from cffi import FFI +from ctypes.util import find_library from functools import total_ordering from subprocess import CalledProcessError @@ -47,35 +48,14 @@ from ipaplatform.paths import paths from ipaplatform.redhat.authconfig import RedHatAuthConfig from ipaplatform.base.tasks import BaseTaskNamespace +_ffi = FFI() +_ffi.cdef(""" +int rpmvercmp (const char *a, const char *b); +""") -# copied from rpmUtils/miscutils.py -def stringToVersion(verstring): - if verstring in [None, '']: - return (None, None, None) - i = verstring.find(':') - if i != -1: - try: - epoch = str(long(verstring[:i])) - except ValueError: - # look, garbage in the epoch field, how fun, kill it - epoch = '0' # this is our fallback, deal - else: - epoch = '0' - j = verstring.find('-') - if j != -1: - if verstring[i + 1:j] == '': - version = None - else: - version = verstring[i + 1:j] - release = verstring[j + 1:] - else: - if verstring[i + 1:] == '': - version = None - else: - version = verstring[i + 1:] - release = None - return (epoch, version, release) - +# use ctypes loader to get correct librpm.so library version according to +# https://cffi.readthedocs.org/en/latest/overview.html#id8 +_librpm = _ffi.dlopen(find_library("rpm")) log = log_mgr.get_logger(__name__) @@ -100,15 +80,15 @@ def selinux_enabled(): class IPAVersion(object): def __init__(self, version): - self.version_tuple = stringToVersion(version) + self.version = version def __eq__(self, other): assert isinstance(other, IPAVersion) - return rpm.labelCompare(self.version_tuple, other.version_tuple) == 0 + return _librpm.rpmvercmp(self.version, other.version) == 0 def __lt__(self, other): assert isinstance(other, IPAVersion) - return rpm.labelCompare(self.version_tuple, other.version_tuple) == -1 + return _librpm.rpmvercmp(self.version, other.version) < 0 class RedHatTaskNamespace(BaseTaskNamespace): -- 2.4.3