fetcher: Check integrity of files before saving to disk.

Fetcher will check integrity of files using sha1sum file 
(and later with digital signatures) before saving them to 
their original locations.
This commit is contained in:
Bahadır Kandemir
2010-12-09 12:09:37 +00:00
parent 18732d09e2
commit 9bce9d24e7
4 changed files with 34 additions and 12 deletions
+1
View File
@@ -57,6 +57,7 @@ class Constants:
self.__c.xz_suffix = ".xz" self.__c.xz_suffix = ".xz"
self.__c.partial_suffix = ".part" self.__c.partial_suffix = ".part"
self.__c.temporary_suffix = ".tmp"
# suffix for auto generated debug packages # suffix for auto generated debug packages
self.__c.debug_name_suffix = "-dbginfo" self.__c.debug_name_suffix = "-dbginfo"
+9 -7
View File
@@ -105,19 +105,21 @@ class UIHandler:
class Fetcher: class Fetcher:
"""Fetcher can fetch a file from various sources using various """Fetcher can fetch a file from various sources using various
protocols.""" protocols."""
def __init__(self, url, destdir): def __init__(self, url, destdir, destfile=None):
if not isinstance(url, pisi.uri.URI): if not isinstance(url, pisi.uri.URI):
url = pisi.uri.URI(url) url = pisi.uri.URI(url)
if ctx.config.get_option("authinfo"): if ctx.config.get_option("authinfo"):
url.set_auth_info(ctx.config.get_option("authinfo")) url.set_auth_info(ctx.config.get_option("authinfo"))
self.url = url self.url = url
self.destdir = destdir self.destdir = destdir
self.archive_file = os.path.join(self.destdir, self.url.filename()) self.destfile = destfile
self.partial_file = self.archive_file + ctx.const.partial_suffix
self.progress = None self.progress = None
self.archive_file = os.path.join(destdir, destfile or url.filename())
self.partial_file = os.path.join(self.destdir, self.url.filename()) + ctx.const.partial_suffix
util.ensure_dirs(self.destdir) util.ensure_dirs(self.destdir)
def fetch (self): def fetch (self):
@@ -222,7 +224,7 @@ class Fetcher:
# helper function # helper function
def fetch_url(url, destdir, progress=None): def fetch_url(url, destdir, progress=None, destfile=None):
fetch = Fetcher(url, destdir) fetch = Fetcher(url, destdir, destfile)
fetch.progress = progress fetch.progress = progress
fetch.fetch() fetch.fetch()
+22 -4
View File
@@ -108,13 +108,17 @@ class File:
pisi.util.ensure_dirs(transfer_dir) pisi.util.ensure_dirs(transfer_dir)
# Check file integrity before saving?
check_integrity = sha1sum or sign
if sha1sum: if sha1sum:
sha1filename = File.download(pisi.uri.URI(uri.get_uri() + '.sha1sum'), transfer_dir) sha1filename = File.download(pisi.uri.URI(uri.get_uri() + '.sha1sum'), transfer_dir)
sha1f = file(sha1filename) sha1f = file(sha1filename)
newsha1 = sha1f.read().split("\n")[0] newsha1 = sha1f.read().split("\n")[0]
if uri.is_remote_file() or copylocal: if uri.is_remote_file() or copylocal:
localfile = pisi.util.join_path(transfer_dir, uri.filename()) tmpfile = check_integrity and uri.filename() + ctx.const.temporary_suffix
localfile = pisi.util.join_path(transfer_dir, tmpfile or uri.filename())
# TODO: code to use old .sha1sum file, is this a necessary optimization? # TODO: code to use old .sha1sum file, is this a necessary optimization?
#oldsha1fn = localfile + '.sha1sum' #oldsha1fn = localfile + '.sha1sum'
@@ -128,10 +132,9 @@ class File:
if uri.is_remote_file(): if uri.is_remote_file():
ctx.ui.info(_("Fetching %s") % uri.get_uri(), verbose=True) ctx.ui.info(_("Fetching %s") % uri.get_uri(), verbose=True)
pisi.fetcher.fetch_url(uri, transfer_dir, ctx.ui.Progress) pisi.fetcher.fetch_url(uri, transfer_dir, ctx.ui.Progress, tmpfile)
else: else:
# copy to transfer dir, # copy to transfer dir
localfile = pisi.util.join_path(transfer_dir, uri.filename())
ctx.ui.info(_("Copying %s to transfer dir") % uri.get_uri(), verbose=True) ctx.ui.info(_("Copying %s to transfer dir") % uri.get_uri(), verbose=True)
shutil.copy(uri.get_uri(), transfer_dir) shutil.copy(uri.get_uri(), transfer_dir)
else: else:
@@ -143,10 +146,25 @@ class File:
localfile = pisi.util.join_path(transfer_dir, os.path.basename(localfile)) localfile = pisi.util.join_path(transfer_dir, os.path.basename(localfile))
shutil.copy(oldfn, localfile) shutil.copy(oldfn, localfile)
def clean_temporary():
temp_files = [sha1filename]
if check_integrity:
temp_files.append(localfile)
for filename in temp_files:
try:
os.unlink(filename)
except OSError:
pass
if sha1sum: if sha1sum:
if (pisi.util.sha1_file(localfile) != newsha1): if (pisi.util.sha1_file(localfile) != newsha1):
clean_temporary()
raise Error(_("File integrity of %s compromised.") % uri) raise Error(_("File integrity of %s compromised.") % uri)
if check_integrity:
shutil.move(localfile, origfile)
localfile = origfile
localfile = File.decompress(localfile, compress) localfile = File.decompress(localfile, compress)
return localfile return localfile
+2 -1
View File
@@ -23,6 +23,7 @@ import pisi.context as ctx
import pisi.archive as archive import pisi.archive as archive
import pisi.uri import pisi.uri
import pisi.metadata import pisi.metadata
import pisi.file
import pisi.files import pisi.files
import pisi.util as util import pisi.util as util
import fetcher import fetcher
@@ -95,7 +96,7 @@ class Package:
if not os.path.exists(self.filepath): if not os.path.exists(self.filepath):
try: try:
fetcher.fetch_url(url, dest, ctx.ui.Progress) pisi.file.File.download(url, dest)
except pisi.fetcher.FetchError: except pisi.fetcher.FetchError:
# Bug 3465 # Bug 3465
if ctx.get_option('reinstall'): if ctx.get_option('reinstall'):