def _file_conflict_is_permitted_rpm411(self, left, right, filename): # In rpm 4.12+ the rpmfilesCompare() function is exposed nicely as the # rpm.files.matches Python method. In earlier rpm versions there is # nothing equivalent in the Python bindings, although we can use ctypes # to poke around and call the older rpmfiCompare() C API directly... librpm = ctypes.CDLL('librpm.so.3') _rpm = ctypes.CDLL( os.path.join(os.path.dirname(rpm.__file__), '_rpm.so')) class rpmfi_s(ctypes.Structure): pass librpm.rpmfiCompare.argtypes = [ ctypes.POINTER(rpmfi_s), ctypes.POINTER(rpmfi_s) ] librpm.rpmfiCompare.restype = ctypes.c_int _rpm.fiFromFi.argtypes = [ctypes.py_object] _rpm.fiFromFi.restype = ctypes.POINTER(rpmfi_s) ts = rpm.TransactionSet() ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES) left_hdr = ts.hdrFromFdno(open(left.lookup_location()[0], 'rb')) right_hdr = ts.hdrFromFdno(open(self.download_package(right), 'rb')) left_fi = rpm.fi(left_hdr) try: while left_fi.FN() != filename: left_fi.next() except StopIteration: raise KeyError('Entry %s not found in %s' % (filename, left)) right_fi = rpm.fi(right_hdr) try: while right_fi.FN() != filename: right_fi.next() except StopIteration: raise KeyError('Entry %s not found in %s' % (filename, right)) if librpm.rpmfiCompare(_rpm.fiFromFi(left_fi), _rpm.fiFromFi(right_fi)) == 0: logger.debug( 'Conflict on %s between %s and %s permitted because files match', filename, left, right) return True if left_fi.FColor() != right_fi.FColor(): logger.debug( 'Conflict on %s between %s and %s permitted because colors differ', filename, left, right) return True return False
def execute(self, _context, _self_node, _input_node, output_parent): NSMAP = { None: SWID_XMLNS, 'sha256': 'http://www.w3.org/2001/04/xmlenc#sha256', 'md5': 'http://www.w3.org/2001/04/xmldsig-more#md5', 'n8060': 'http://csrc.nist.gov/ns/swid/2015-extensions/1.0', 'payload-generated-42': XMLNS, } output = [] last_dir = None for f in fi(self.rpm_header): append_to = None name = f[0] location = None m = re.search(r'^(.*/)(.+)$', name) if m is not None: location = m.group(1) name = m.group(2) while location is not None and last_dir is not None: last_dir_path = last_dir.get('fullname') + '/' if location.startswith(last_dir_path): location = location[len(last_dir_path):] append_to = last_dir break last_dir = last_dir.getparent() if S_ISDIR(f[2]): e = etree.Element("Directory", nsmap=NSMAP) last_dir = e else: e = etree.Element("File", size=str(f[1]), nsmap=NSMAP) e.set("fullname", f[0]) e.set("name", name) if location: location = re.sub(r'^(.+)/$', r'\g<1>', location) e.set("location", location) if f[12]: if len(f[12]) == 64 and f[12] != "0" * 64: e.set("{%s}hash" % NSMAP['sha256'], f[12]) if len(f[12]) == 32 and f[12] != "0" * 32: e.set("{%s}hash" % NSMAP['md5'], f[12]) if not S_ISDIR(f[2]): if (f[4] & (RPMFILE_CONFIG | RPMFILE_GHOST)) \ or (f[9] & RPMVERIFY_FILEDIGEST) == 0 \ or (f[9] & RPMVERIFY_FILESIZE) == 0: e.set("{%s}mutable" % NSMAP['n8060'], "true") if not (f[4] & (RPMFILE_DOC | RPMFILE_MISSINGOK | RPMFILE_GHOST | RPMFILE_LICENSE | RPMFILE_README)): e.set("key", "true") if append_to is None: append_to = output append_to.append(e) self._cleanup_fullname(output) for e in output: output_parent.append(e)
def test_conflict_is_ignored_if_file_colors_are_different(request, dir_server): # This is part of RPM's multilib support. If two packages own the same file # but the file color is different in each, the preferred color wins (and # there is no conflict). This lets both .i386 and .x86_64 packages own # /bin/bash while installing only the .x86_64 version. p2 = rpmfluff.SimpleRpmBuild('a', '0.1', '1', ['i386', 'x86_64']) p2.add_simple_compilation(installPath='usr/bin/thing') baserepo = rpmfluff.YumRepoBuild([p2]) baserepo.make('i386', 'x86_64') dir_server.basepath = baserepo.repoDir p1 = rpmfluff.SimpleRpmBuild('a', '0.2', '1', ['i386', 'x86_64']) p1.add_simple_compilation(installPath='usr/bin/thing') p1.make() def cleanUp(): shutil.rmtree(baserepo.repoDir) shutil.rmtree(p2.get_base_dir()) shutil.rmtree(p1.get_base_dir()) request.addfinalizer(cleanUp) # Make sure we really have different files with different colors # (this was surprisingly hard to get right) rpmheader_32 = p1.get_built_rpm_header('i386') rpmheader_64 = p1.get_built_rpm_header('x86_64') if hasattr(rpm, 'files'): # rpm 4.12+ assert 1 == rpm.files(rpmheader_32)['/usr/bin/thing'].color assert 2 == rpm.files(rpmheader_64)['/usr/bin/thing'].color else: # sad old rpm < 4.12 fi_32 = rpm.fi(rpmheader_32) while fi_32.FN() != '/usr/bin/thing': fi_32.next() assert fi_32.FColor() == 1 fi_64 = rpm.fi(rpmheader_64) while fi_64.FN() != '/usr/bin/thing': fi_64.next() assert fi_64.FColor() == 2 exitcode, out, err = run_rpmdeplint([ 'rpmdeplint', 'check-conflicts', '--repo=base,{}'.format(dir_server.url), p1.get_built_rpm('i386') ]) assert exitcode == 0
def test_conflict_is_ignored_if_file_colors_are_different(request, dir_server): # This is part of RPM's multilib support. If two packages own the same file # but the file color is different in each, the preferred color wins (and # there is no conflict). This lets both .i386 and .x86_64 packages own # /bin/bash while installing only the .x86_64 version. p2 = rpmfluff.SimpleRpmBuild('a', '0.1', '1', ['i386', 'x86_64']) p2.add_simple_compilation(installPath='usr/bin/thing') baserepo = rpmfluff.YumRepoBuild([p2]) baserepo.make('i386', 'x86_64') dir_server.basepath = baserepo.repoDir p1 = rpmfluff.SimpleRpmBuild('a', '0.2', '1', ['i386', 'x86_64']) p1.add_simple_compilation(installPath='usr/bin/thing') p1.make() def cleanUp(): shutil.rmtree(baserepo.repoDir) shutil.rmtree(p2.get_base_dir()) shutil.rmtree(p1.get_base_dir()) request.addfinalizer(cleanUp) # Make sure we really have different files with different colors # (this was surprisingly hard to get right) rpmheader_32 = p1.get_built_rpm_header('i386') rpmheader_64 = p1.get_built_rpm_header('x86_64') if hasattr(rpm, 'files'): # rpm 4.12+ assert 1 == rpm.files(rpmheader_32)['/usr/bin/thing'].color assert 2 == rpm.files(rpmheader_64)['/usr/bin/thing'].color else: # sad old rpm < 4.12 fi_32 = rpm.fi(rpmheader_32) while fi_32.FN() != '/usr/bin/thing': fi_32.next() assert fi_32.FColor() == 1 fi_64 = rpm.fi(rpmheader_64) while fi_64.FN() != '/usr/bin/thing': fi_64.next() assert fi_64.FColor() == 2 exitcode, out, err = run_rpmdeplint(['rpmdeplint', 'check-conflicts', '--repo=base,{}'.format(dir_server.url), p1.get_built_rpm('i386')]) assert exitcode == 0
def package_files(self, pkg_name): """ Returns list of files provided by package See also: http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch04s02s03.html """ if self._is_installed(pkg_name): ts = rpm.TransactionSet() mi = ts.dbMatch("name", pkg_name) fi = rpm.fi(next(mi)) return [f[0] for f in fi] # Tracer will not find uninstalled applications return []
def _file_conflict_is_permitted_rpm411(self, left, right, filename): # In rpm 4.12+ the rpmfilesCompare() function is exposed nicely as the # rpm.files.matches Python method. In earlier rpm versions there is # nothing equivalent in the Python bindings, although we can use ctypes # to poke around and call the older rpmfiCompare() C API directly... librpm = ctypes.CDLL('librpm.so.3') _rpm = ctypes.CDLL(os.path.join(os.path.dirname(rpm.__file__), '_rpm.so')) class rpmfi_s(ctypes.Structure): pass librpm.rpmfiCompare.argtypes = [ctypes.POINTER(rpmfi_s), ctypes.POINTER(rpmfi_s)] librpm.rpmfiCompare.restype = ctypes.c_int _rpm.fiFromFi.argtypes = [ctypes.py_object] _rpm.fiFromFi.restype = ctypes.POINTER(rpmfi_s) ts = rpm.TransactionSet() ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES) left_hdr = ts.hdrFromFdno(open(left.lookup_location()[0], 'rb')) right_hdr = ts.hdrFromFdno(open(self.download_package(right), 'rb')) left_fi = rpm.fi(left_hdr) try: while left_fi.FN() != filename: left_fi.next() except StopIteration: raise KeyError('Entry %s not found in %s' % (filename, left)) right_fi = rpm.fi(right_hdr) try: while right_fi.FN() != filename: right_fi.next() except StopIteration: raise KeyError('Entry %s not found in %s' % (filename, right)) if librpm.rpmfiCompare(_rpm.fiFromFi(left_fi), _rpm.fiFromFi(right_fi)) == 0: logger.debug('Conflict on %s between %s and %s permitted because files match', filename, left, right) return True if left_fi.FColor() != right_fi.FColor(): logger.debug('Conflict on %s between %s and %s permitted because colors differ', filename, left, right) return True return False
def get_list_of_config(package): """Get all files marked as config in package :param package: RPM Header of package :type package: rpm.hdr :return: Strings list of files marked as config in package :rtype: list """ files = rpm.fi(package) # pylint: disable=no-member result = [] for rpm_file in files: if rpm_file[4] & rpm.RPMFILE_CONFIG: # pylint: disable=no-member result.append(rpm_file[0]) return result
def get_list_of_config(self, package): """Get all files marked as config in package :param package: RPM Header of package :type package: rpm.hdr :return: Strings list of files marked as config in package :rtype: list """ files = rpm.fi(package) # pylint: disable=no-member result = [] for rpm_file in files: if rpm_file[4] & rpm.RPMFILE_CONFIG: # pylint: disable=no-member file_name = rpm_file[0] if self.root: file_name = os.path.normpath(self.root + file_name) result.append(file_name) return result