| # portage_checksum.py -- core Portage functionality |
| # Copyright 1998-2004 Gentoo Foundation |
| # Distributed under the terms of the GNU General Public License v2 |
| # $Id: /var/cvsroot/gentoo-src/portage/pym/portage_checksum.py,v 1.10.2.2 2005/08/10 05:42:03 ferringb Exp $ |
| |
| |
| from portage_const import PRIVATE_PATH,PRELINK_BINARY |
| import os |
| import shutil |
| import stat |
| import portage_exec |
| import portage_util |
| import portage_locks |
| import commands |
| import sha |
| |
| prelink_capable = False |
| if os.path.exists(PRELINK_BINARY): |
| results = commands.getstatusoutput(PRELINK_BINARY+" --version > /dev/null 2>&1") |
| if (results[0] >> 8) == 0: |
| prelink_capable=1 |
| del results |
| |
| def perform_md5(x, calc_prelink=0): |
| return perform_checksum(x, md5hash, calc_prelink)[0] |
| |
| def perform_sha1(x, calc_prelink=0): |
| return perform_checksum(x, sha1hash, calc_prelink)[0] |
| |
| def perform_all(x, calc_prelink=0): |
| mydict = {} |
| mydict["SHA1"] = perform_sha1(x, calc_prelink) |
| mydict["MD5"] = perform_md5(x, calc_prelink) |
| return mydict |
| |
| def get_valid_checksum_keys(): |
| return ["SHA1", "MD5"] |
| |
| def verify_all(filename, mydict, calc_prelink=0, strict=0): |
| # Dict relates to single file only. |
| # returns: (passed,reason) |
| file_is_ok = True |
| reason = "Reason unknown" |
| try: |
| if mydict["size"] != os.stat(filename)[stat.ST_SIZE]: |
| return False,"Filesize does not match recorded size" |
| except OSError, e: |
| return False, str(e) |
| for x in mydict.keys(): |
| if x == "size": |
| continue |
| elif x == "SHA1": |
| if mydict[x] != perform_sha1(filename, calc_prelink=calc_prelink): |
| if strict: |
| raise portage_exception.DigestException, "Failed to verify '$(file)s' on checksum type '%(type)s'" % {"file":filename, "type":x} |
| else: |
| file_is_ok = False |
| reason = "Failed on %s verification" % (x,) |
| break |
| elif x == "MD5": |
| if mydict[x] != perform_md5(filename, calc_prelink=calc_prelink): |
| if strict: |
| raise portage_exception.DigestException, "Failed to verify '$(file)s' on checksum type '%(type)s'" % {"file":filename, "type":x} |
| else: |
| file_is_ok = False |
| reason = "Failed on %s verification" % (x,) |
| break |
| return file_is_ok,reason |
| |
| # We _try_ to load this module. If it fails we do the slow fallback. |
| try: |
| import fchksum |
| |
| def md5hash(filename): |
| return fchksum.fmd5t(filename) |
| |
| except ImportError: |
| import md5 |
| def md5hash(filename): |
| f = open(filename, 'rb') |
| blocksize=32768 |
| data = f.read(blocksize) |
| size = 0L |
| sum = md5.new() |
| while data: |
| sum.update(data) |
| size = size + len(data) |
| data = f.read(blocksize) |
| f.close() |
| |
| return (sum.hexdigest(),size) |
| |
| def sha1hash(filename): |
| f = open(filename, 'rb') |
| blocksize=32768 |
| data = f.read(blocksize) |
| size = 0L |
| sum = sha.new() |
| while data: |
| sum.update(data) |
| size = size + len(data) |
| data = f.read(blocksize) |
| f.close() |
| |
| return (sum.hexdigest(),size) |
| |
| def perform_checksum(filename, hash_function=md5hash, calc_prelink=0): |
| myfilename = filename[:] |
| prelink_tmpfile = PRIVATE_PATH+"/prelink-checksum.tmp."+str(os.getpid()) |
| mylock = None |
| |
| if calc_prelink and prelink_capable: |
| mylock = portage_locks.lockfile(prelink_tmpfile, wantnewlockfile=1) |
| # Create non-prelinked temporary file to checksum. |
| # Files rejected by prelink are summed in place. |
| retval=portage_exec.spawn([PRELINK_BINARY,"--undo","-o",prelink_tmpfile,filename],fd_pipes={}) |
| if retval==0: |
| #portage_util.writemsg(">>> prelink checksum '"+str(filename)+"'.\n") |
| myfilename=prelink_tmpfile |
| |
| myhash, mysize = hash_function(myfilename) |
| |
| if calc_prelink and prelink_capable: |
| if os.path.exists(prelink_tmpfile): |
| os.unlink(prelink_tmpfile) |
| portage_locks.unlockfile(mylock) |
| |
| return (myhash,mysize) |