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