freeipa

FreeIPA is an integrated Identity and Authentication solution for Linux/UNIX networked environments.  |  http://www.freeipa.org/

Commit 6b6a11f use FFI call to rpmvercmp function for version comparison

2 files Authored by mbabinsk 2 years ago , Committed by jcholast 2 years ago ,
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 <mkosek@redhat.com> for sharing the code snippet
that spurred this patch.

https://fedorahosted.org/freeipa/ticket/5572

Reviewed-By: Jan Cholasta <jcholast@redhat.com>

    
1 @@ -214,7 +214,7 @@
2   Requires: dbus-python
3   Requires: python-dns >= 1.11.1
4   Requires: python-kdcproxy >= 0.3
5 - Requires: rpm-python
6 + Requires: rpm-libs
7   
8   %description -n python2-ipaserver
9   IPA is an integrated solution to provide centrally managed Identity (users,
 1 @@ -30,13 +30,14 @@
 2   import socket
 3   import sys
 4   import base64
 5 + from cffi import FFI
 6 + from ctypes.util import find_library
 7   from functools import total_ordering
 8   
 9   from subprocess import CalledProcessError
10   from nss.error import NSPRError
11   from pyasn1.error import PyAsn1Error
12   from six.moves import urllib
13 - import rpm
14   
15   from ipapython.ipa_log_manager import root_logger, log_mgr
16   from ipapython import ipautil
17 @@ -48,35 +49,14 @@
18   from ipaplatform.redhat.authconfig import RedHatAuthConfig
19   from ipaplatform.base.tasks import BaseTaskNamespace
20   
21 + _ffi = FFI()
22 + _ffi.cdef("""
23 + int rpmvercmp (const char *a, const char *b);
24 + """)
25   
26 - # copied from rpmUtils/miscutils.py
27 - def stringToVersion(verstring):
28 -     if verstring in [None, '']:
29 -         return (None, None, None)
30 -     i = verstring.find(':')
31 -     if i != -1:
32 -         try:
33 -             epoch = str(long(verstring[:i]))
34 -         except ValueError:
35 -             # look, garbage in the epoch field, how fun, kill it
36 -             epoch = '0' # this is our fallback, deal
37 -     else:
38 -         epoch = '0'
39 -     j = verstring.find('-')
40 -     if j != -1:
41 -         if verstring[i + 1:j] == '':
42 -             version = None
43 -         else:
44 -             version = verstring[i + 1:j]
45 -         release = verstring[j + 1:]
46 -     else:
47 -         if verstring[i + 1:] == '':
48 -             version = None
49 -         else:
50 -             version = verstring[i + 1:]
51 -         release = None
52 -     return (epoch, version, release)
53 - 
54 + # use ctypes loader to get correct librpm.so library version according to
55 + # https://cffi.readthedocs.org/en/latest/overview.html#id8
56 + _librpm = _ffi.dlopen(find_library("rpm"))
57   
58   log = log_mgr.get_logger(__name__)
59   
60 @@ -101,15 +81,15 @@
61   class IPAVersion(object):
62   
63       def __init__(self, version):
64 -         self.version_tuple = stringToVersion(version)
65 +         self.version = version
66   
67       def __eq__(self, other):
68           assert isinstance(other, IPAVersion)
69 -         return rpm.labelCompare(self.version_tuple, other.version_tuple) == 0
70 +         return _librpm.rpmvercmp(self.version, other.version) == 0
71   
72       def __lt__(self, other):
73           assert isinstance(other, IPAVersion)
74 -         return rpm.labelCompare(self.version_tuple, other.version_tuple) == -1
75 +         return _librpm.rpmvercmp(self.version, other.version) < 0
76   
77   
78   class RedHatTaskNamespace(BaseTaskNamespace):