X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=daklib%2Futils.py;h=75845244270fc04e554675f831100a9c7b0123e8;hb=f612e250a402ae5e6a86f711d84c6b641a3d2b22;hp=ec82782fdaa593bf9a4c89e9ac2e44236bf15ce8;hpb=1d79ca7f4979f4b1d1b7741b4d2ab8af8db7c347;p=dak.git diff --git a/daklib/utils.py b/daklib/utils.py index ec82782f..75845244 100755 --- a/daklib/utils.py +++ b/daklib/utils.py @@ -22,7 +22,7 @@ ################################################################################ import codecs, commands, email.Header, os, pwd, re, select, socket, shutil, \ - sys, tempfile, traceback + sys, tempfile, traceback, stat import apt_pkg import database from dak_exceptions import * @@ -55,6 +55,10 @@ default_apt_config = "/etc/dak/apt.conf" alias_cache = None key_uid_email_cache = {} +# (hashname, function, earliest_changes_version) +known_hashes = [("sha1", apt_pkg.sha1sum, (1, 8)), + ("sha256", apt_pkg.sha256sum, (1, 8))] + ################################################################################ def open_file(filename, mode='r'): @@ -207,6 +211,116 @@ The rules for (signing_rules == 1)-mode are: ################################################################################ +def create_hash (lfiles, key, testfn, basedict = None): + rejmsg = [] + for f in lfiles.keys(): + try: + file_handle = open_file(f) + except CantOpenError: + rejmsg.append("Could not open file %s for checksumming" % (f)) + + # Check hash + if basedict and basedict.has_key(f): + basedict[f]['%ssum' % key] = testfn(file_handle) + file_handle.close() + + return rejmsg + +################################################################################ + +def check_hash (where, lfiles, key, testfn, basedict = None): + rejmsg = [] + if basedict: + for f in basedict.keys(): + if f not in lfiles: + rejmsg.append("%s: no %s checksum" % (f, key)) + + for f in lfiles.keys(): + if basedict and f not in basedict: + rejmsg.append("%s: extraneous entry in %s checksums" % (f, key)) + + try: + file_handle = open_file(f) + except CantOpenError: + continue + + # Check hash + if testfn(file_handle) != lfiles[f][key]: + rejmsg.append("%s: %s check failed." % (f, key)) + file_handle.close() + # Store the hashes for later use + if basedict: + basedict[f]['%ssum' % key] = lfiles[f][key] + # Check size + actual_size = os.stat(f)[stat.ST_SIZE] + size = int(lfiles[f]["size"]) + if size != actual_size: + rejmsg.append("%s: actual file size (%s) does not match size (%s) in %s" + % (f, actual_size, size, where)) + + return rejmsg + +################################################################################ + +def ensure_hashes(changes, dsc, files, dsc_files): + # Make sure we recognise the format of the Files: field + format = changes.get("format", "0.0").split(".",1) + if len(format) == 2: + format = int(format[0]), int(format[1]) + else: + format = int(float(format[0])), 0 + + rejmsg = [] + for x in changes: + if x.startswith("checksum-"): + h = x.split("-",1)[1] + if h not in dict(known_hashes): + rejmsg.append("Unsupported checksum field in .changes" % (h)) + + for x in dsc: + if x.startswith("checksum-"): + h = x.split("-",1)[1] + if h not in dict(known_hashes): + rejmsg.append("Unsupported checksum field in .dsc" % (h)) + + # We have to calculate the hash if we have an earlier changes version than + # the hash appears in rather than require it exist in the changes file + # I hate backwards compatibility + for h,f,v in known_hashes: + try: + if format < v: + for m in create_hash(files, h, f, files): + rejmsg.append(m) + else: + for m in check_hash(".changes %s" % (h), files, h, f, files): + rejmsg.append(m) + except NoFilesFieldError: + rejmsg.append("No Checksums-%s: field in .changes" % (h)) + except UnknownFormatError, format: + rejmsg.append("%s: unknown format of .changes" % (format)) + except ParseChangesError, line: + rejmsg.append("parse error for Checksums-%s in .changes, can't grok: %s." % (h, line)) + + if "source" not in changes["architecture"]: continue + + try: + if format < v: + for m in create_hash(dsc_files, h, f, dsc_files): + rejmsg.append(m) + else: + for m in check_hash(".dsc %s" % (h), dsc_files, h, f, dsc_files): + rejmsg.append(m) + except UnknownFormatError, format: + rejmsg.append("%s: unknown format of .dsc" % (format)) + except NoFilesFieldError: + rejmsg.append("No Checksums-%s: field in .dsc" % (h)) + except ParseChangesError, line: + rejmsg.append("parse error for Checksums-%s in .dsc, can't grok: %s." % (h, line)) + + return rejmsg + +################################################################################ + # Dropped support for 1.4 and ``buggy dchanges 3.4'' (?!) compared to di.pl def build_file_list(changes, is_a_dsc=0, field="files", hashname="md5sum"):