|
|
fa73ac |
From 054cd9db81af13b5cdc669067775ff71aa82625f Mon Sep 17 00:00:00 2001
|
|
|
fa73ac |
From: Matthew Almond <malmond@fb.com>
|
|
|
fa73ac |
Date: Tue, 9 Mar 2021 11:01:40 -0800
|
|
|
fa73ac |
Subject: [PATCH 1/2] Use libdnf.utils.checksum_{check,value}
|
|
|
fa73ac |
|
|
|
fa73ac |
libdnf has the canonical implementation of checksum handling. We aim to
|
|
|
fa73ac |
replace all use of dnf.yum.misc.checksum() with this. In doing so, this
|
|
|
fa73ac |
fixes installing previously downloaded and transcoded rpms to support
|
|
|
fa73ac |
|
|
|
fa73ac |
https://github.com/rpm-software-management/librepo/pull/222
|
|
|
fa73ac |
|
|
|
fa73ac |
This also has some minor performance benefits: librepo's checksum
|
|
|
fa73ac |
handling employs caching of previously downloaded files via extended
|
|
|
fa73ac |
attributes. This works for ordinary rpms in the dnf cache, but does not
|
|
|
fa73ac |
work (yet) for rpm paths specified on the command line due to
|
|
|
fa73ac |
https://github.com/rpm-software-management/librepo/issues/233. That
|
|
|
fa73ac |
issue is pretty minor, and the fix ends up in libdnf later.
|
|
|
fa73ac |
|
|
|
fa73ac |
The previous implementation maps all runtime errors to MiscError. We do
|
|
|
fa73ac |
this still by taking the libdnf.error.Error class (defined in SWIG) and
|
|
|
fa73ac |
map it directly back to the Python exception as before.
|
|
|
fa73ac |
---
|
|
|
fa73ac |
dnf/package.py | 18 ++++----
|
|
|
fa73ac |
dnf/yum/misc.py | 113 ------------------------------------------------
|
|
|
fa73ac |
2 files changed, 10 insertions(+), 121 deletions(-)
|
|
|
fa73ac |
|
|
|
fa73ac |
diff --git a/dnf/package.py b/dnf/package.py
|
|
|
fa73ac |
index b01e555eba..fc89cf98a8 100644
|
|
|
fa73ac |
--- a/dnf/package.py
|
|
|
fa73ac |
+++ b/dnf/package.py
|
|
|
fa73ac |
@@ -30,6 +30,8 @@
|
|
|
fa73ac |
import dnf.rpm
|
|
|
fa73ac |
import dnf.yum.misc
|
|
|
fa73ac |
import hawkey
|
|
|
fa73ac |
+import libdnf.error
|
|
|
fa73ac |
+import libdnf.utils
|
|
|
fa73ac |
import logging
|
|
|
fa73ac |
import os
|
|
|
fa73ac |
import rpm
|
|
|
fa73ac |
@@ -56,7 +58,10 @@ def _chksum(self):
|
|
|
fa73ac |
return self._priv_chksum
|
|
|
fa73ac |
if self._from_cmdline:
|
|
|
fa73ac |
chksum_type = dnf.yum.misc.get_default_chksum_type()
|
|
|
fa73ac |
- chksum_val = dnf.yum.misc.checksum(chksum_type, self.location)
|
|
|
fa73ac |
+ try:
|
|
|
fa73ac |
+ chksum_val = libdnf.utils.checksum_value(chksum_type, self.location)
|
|
|
fa73ac |
+ except libdnf.error.Error as e:
|
|
|
fa73ac |
+ raise dnf.exceptions.MiscError(str(e))
|
|
|
fa73ac |
return (hawkey.chksum_type(chksum_type),
|
|
|
fa73ac |
binascii.unhexlify(chksum_val))
|
|
|
fa73ac |
return super(Package, self).chksum
|
|
|
fa73ac |
@@ -330,10 +335,7 @@ def verifyLocalPkg(self):
|
|
|
fa73ac |
if self._from_cmdline:
|
|
|
fa73ac |
return True # local package always verifies against itself
|
|
|
fa73ac |
(chksum_type, chksum) = self.returnIdSum()
|
|
|
fa73ac |
- real_sum = dnf.yum.misc.checksum(chksum_type, self.localPkg(),
|
|
|
fa73ac |
- datasize=self._size)
|
|
|
fa73ac |
- if real_sum != chksum:
|
|
|
fa73ac |
- logger.debug(_('%s: %s check failed: %s vs %s'),
|
|
|
fa73ac |
- self, chksum_type, real_sum, chksum)
|
|
|
fa73ac |
- return False
|
|
|
fa73ac |
- return True
|
|
|
fa73ac |
+ try:
|
|
|
fa73ac |
+ return libdnf.utils.checksum_check(chksum_type, self.localPkg(), chksum)
|
|
|
fa73ac |
+ except libdnf.error.Error as e:
|
|
|
fa73ac |
+ raise dnf.exceptions.MiscError(str(e))
|
|
|
fa73ac |
diff --git a/dnf/yum/misc.py b/dnf/yum/misc.py
|
|
|
fa73ac |
index 3e3905feb8..af018a8a1b 100644
|
|
|
fa73ac |
--- a/dnf/yum/misc.py
|
|
|
fa73ac |
+++ b/dnf/yum/misc.py
|
|
|
fa73ac |
@@ -22,7 +22,6 @@
|
|
|
fa73ac |
|
|
|
fa73ac |
from __future__ import print_function, absolute_import
|
|
|
fa73ac |
from __future__ import unicode_literals
|
|
|
fa73ac |
-from dnf.exceptions import MiscError
|
|
|
fa73ac |
from dnf.pycomp import base64_decodebytes, basestring, unicode
|
|
|
fa73ac |
from stat import *
|
|
|
fa73ac |
import libdnf.utils
|
|
|
fa73ac |
@@ -32,7 +31,6 @@
|
|
|
fa73ac |
import dnf.i18n
|
|
|
fa73ac |
import errno
|
|
|
fa73ac |
import glob
|
|
|
fa73ac |
-import hashlib
|
|
|
fa73ac |
import io
|
|
|
fa73ac |
import os
|
|
|
fa73ac |
import os.path
|
|
|
fa73ac |
@@ -41,7 +39,6 @@
|
|
|
fa73ac |
import shutil
|
|
|
fa73ac |
import tempfile
|
|
|
fa73ac |
|
|
|
fa73ac |
-_available_checksums = set(['md5', 'sha1', 'sha256', 'sha384', 'sha512'])
|
|
|
fa73ac |
_default_checksums = ['sha256']
|
|
|
fa73ac |
|
|
|
fa73ac |
|
|
|
fa73ac |
@@ -68,119 +65,9 @@ def re_full_search_needed(s):
|
|
|
fa73ac |
return True
|
|
|
fa73ac |
return False
|
|
|
fa73ac |
|
|
|
fa73ac |
-
|
|
|
fa73ac |
-class Checksums(object):
|
|
|
fa73ac |
- """ Generate checksum(s), on given pieces of data. Producing the
|
|
|
fa73ac |
- Length and the result(s) when complete. """
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- def __init__(self, checksums=None, ignore_missing=False, ignore_none=False):
|
|
|
fa73ac |
- if checksums is None:
|
|
|
fa73ac |
- checksums = _default_checksums
|
|
|
fa73ac |
- self._sumalgos = []
|
|
|
fa73ac |
- self._sumtypes = []
|
|
|
fa73ac |
- self._len = 0
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- done = set()
|
|
|
fa73ac |
- for sumtype in checksums:
|
|
|
fa73ac |
- if sumtype == 'sha':
|
|
|
fa73ac |
- sumtype = 'sha1'
|
|
|
fa73ac |
- if sumtype in done:
|
|
|
fa73ac |
- continue
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- if sumtype in _available_checksums:
|
|
|
fa73ac |
- sumalgo = hashlib.new(sumtype)
|
|
|
fa73ac |
- elif ignore_missing:
|
|
|
fa73ac |
- continue
|
|
|
fa73ac |
- else:
|
|
|
fa73ac |
- raise MiscError('Error Checksumming, bad checksum type %s' %
|
|
|
fa73ac |
- sumtype)
|
|
|
fa73ac |
- done.add(sumtype)
|
|
|
fa73ac |
- self._sumtypes.append(sumtype)
|
|
|
fa73ac |
- self._sumalgos.append(sumalgo)
|
|
|
fa73ac |
- if not done and not ignore_none:
|
|
|
fa73ac |
- raise MiscError('Error Checksumming, no valid checksum type')
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- def __len__(self):
|
|
|
fa73ac |
- return self._len
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- # Note that len(x) is assert limited to INT_MAX, which is 2GB on i686.
|
|
|
fa73ac |
- length = property(fget=lambda self: self._len)
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- def update(self, data):
|
|
|
fa73ac |
- self._len += len(data)
|
|
|
fa73ac |
- for sumalgo in self._sumalgos:
|
|
|
fa73ac |
- data = data.encode('utf-8') if isinstance(data, unicode) else data
|
|
|
fa73ac |
- sumalgo.update(data)
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- def read(self, fo, size=2**16):
|
|
|
fa73ac |
- data = fo.read(size)
|
|
|
fa73ac |
- self.update(data)
|
|
|
fa73ac |
- return data
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- def hexdigests(self):
|
|
|
fa73ac |
- ret = {}
|
|
|
fa73ac |
- for sumtype, sumdata in zip(self._sumtypes, self._sumalgos):
|
|
|
fa73ac |
- ret[sumtype] = sumdata.hexdigest()
|
|
|
fa73ac |
- return ret
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- def hexdigest(self, checksum=None):
|
|
|
fa73ac |
- if checksum is None:
|
|
|
fa73ac |
- if not self._sumtypes:
|
|
|
fa73ac |
- return None
|
|
|
fa73ac |
- checksum = self._sumtypes[0]
|
|
|
fa73ac |
- if checksum == 'sha':
|
|
|
fa73ac |
- checksum = 'sha1'
|
|
|
fa73ac |
- return self.hexdigests()[checksum]
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- def digests(self):
|
|
|
fa73ac |
- ret = {}
|
|
|
fa73ac |
- for sumtype, sumdata in zip(self._sumtypes, self._sumalgos):
|
|
|
fa73ac |
- ret[sumtype] = sumdata.digest()
|
|
|
fa73ac |
- return ret
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- def digest(self, checksum=None):
|
|
|
fa73ac |
- if checksum is None:
|
|
|
fa73ac |
- if not self._sumtypes:
|
|
|
fa73ac |
- return None
|
|
|
fa73ac |
- checksum = self._sumtypes[0]
|
|
|
fa73ac |
- if checksum == 'sha':
|
|
|
fa73ac |
- checksum = 'sha1'
|
|
|
fa73ac |
- return self.digests()[checksum]
|
|
|
fa73ac |
-
|
|
|
fa73ac |
def get_default_chksum_type():
|
|
|
fa73ac |
return _default_checksums[0]
|
|
|
fa73ac |
|
|
|
fa73ac |
-def checksum(sumtype, file, CHUNK=2**16, datasize=None):
|
|
|
fa73ac |
- """takes filename, hand back Checksum of it
|
|
|
fa73ac |
- sumtype = md5 or sha/sha1/sha256/sha512 (note sha == sha1)
|
|
|
fa73ac |
- filename = /path/to/file
|
|
|
fa73ac |
- CHUNK=65536 by default"""
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- # chunking brazenly lifted from Ryan Tomayko
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- if isinstance(file, basestring):
|
|
|
fa73ac |
- try:
|
|
|
fa73ac |
- with open(file, 'rb', CHUNK) as fo:
|
|
|
fa73ac |
- return checksum(sumtype, fo, CHUNK, datasize)
|
|
|
fa73ac |
- except (IOError, OSError):
|
|
|
fa73ac |
- raise MiscError('Error opening file for checksum: %s' % file)
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- try:
|
|
|
fa73ac |
- # assumes file is a file-like-object
|
|
|
fa73ac |
- data = Checksums([sumtype])
|
|
|
fa73ac |
- while data.read(file, CHUNK):
|
|
|
fa73ac |
- if datasize is not None and data.length > datasize:
|
|
|
fa73ac |
- break
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- # This screws up the length, but that shouldn't matter. We only care
|
|
|
fa73ac |
- # if this checksum == what we expect.
|
|
|
fa73ac |
- if datasize is not None and datasize != data.length:
|
|
|
fa73ac |
- return '!%u!%s' % (datasize, data.hexdigest(sumtype))
|
|
|
fa73ac |
-
|
|
|
fa73ac |
- return data.hexdigest(sumtype)
|
|
|
fa73ac |
- except (IOError, OSError) as e:
|
|
|
fa73ac |
- raise MiscError('Error reading file for checksum: %s' % file)
|
|
|
fa73ac |
-
|
|
|
fa73ac |
class GenericHolder(object):
|
|
|
fa73ac |
"""Generic Holder class used to hold other objects of known types
|
|
|
fa73ac |
It exists purely to be able to do object.somestuff, object.someotherstuff
|
|
|
fa73ac |
|