--- /dev/null
+#!/usr/bin/python2.5
+import sys, os, re, gzip, bz2, hashlib
+
+package_file_map = {
+ 'Packages' : file,
+ 'Packages.gz' : gzip.GzipFile,
+ 'Packages.bz2' : bz2.BZ2File,
+ 'Sources' : file,
+ 'Sources.gz' : gzip.GzipFile,
+ 'Sources.bz2' : bz2.BZ2File,
+}
+
+def parse_packages_file(path):
+ try:
+ open_func = package_file_map[os.path.basename(path)]
+ file = open_func(path)
+ except IOError, e:
+ print "WARNING: failed to open %s: %s" % (path, e)
+ return {}
+ cur_dict = {}
+ key, value = None, ''
+ ret_list = []
+ while True:
+ try:
+ line = file.readline()
+ except IOError, e:
+ print "WARNING: failed to read %s: %s" % (path, e)
+ print "WARNING: %s" % e
+ return {}
+
+ # check if we are done with current value
+ if (line == '' or line[0] == '\n' or line[0] != ' ') and key != None:
+ cur_dict[key] = value
+
+ if line == '' or line == '\n': # done current block
+ if cur_dict != {}:
+ ret_list.append(cur_dict)
+ cur_dict = {}
+ key = None
+ if line == '': break
+ elif line[0] == ' ': # multi-line value
+ value += '\n' + line[1:-1]
+ else:
+ if line[-1] == '\n': line = line[:-1]
+ pos = line.find(':')
+ key = line[:pos]
+ if key == '': key = None
+ value = line[pos+2:]
+ return ret_list
+
+def find_packages_files(path):
+ files = []
+ for file in os.listdir(path):
+ file_path = "%s/%s" % (path, file)
+ if os.path.islink(file_path):
+ continue
+ elif os.path.isdir(file_path):
+ files += find_packages_files(file_path)
+ elif file in package_file_map:
+ files.append(file_path)
+ return files
+
+if len(sys.argv) != 2:
+ print "Usage: debian-check-md5sum.py base-dir"
+ sys.exit(1)
+base_dir = sys.argv[1]
+
+all = {}
+files_regex = re.compile('(\S+)\s+(\S+)\s+(\S+)')
+for file in find_packages_files(base_dir):
+ file_type = os.path.basename(file).split('.')[0]
+ a = parse_packages_file(file)
+ for package in parse_packages_file(file):
+ if file_type == 'Packages':
+ if 'Filename' in package:
+ all[package['Filename']] = package
+ elif file_type == 'Sources':
+ files = package['Files'].split('\n')
+ for file in files:
+ if file == '': continue
+ match = files_regex.match(file)
+ file_path = '%s/%s' % (package['Directory'], match.group(3))
+ all[file_path] = { 'MD5sum' : match.group(1) }
+print "NOTICE: need to check %d files" % len(all)
+
+ret_val = 0
+block_size = 65536
+for (file, package) in all.iteritems():
+ path = '%s/%s' % (base_dir, file)
+ try:
+ file = open(path, 'rb')
+ except IOError:
+ print "WARNING: missing %s" % path
+ continue
+ if 'SHA256' in package:
+ md = hashlib.sha256()
+ hash = package['SHA256']
+ elif 'SHA1' in package:
+ md = hashlib.sha1()
+ hash = package['SHA1']
+ elif 'MD5sum' in package:
+ md = hashlib.md5()
+ hash = package['MD5sum']
+ else:
+ print "WARNING: no hash found for %s" % path
+ print package
+ exit(1)
+ while True:
+ data = file.read(block_size)
+ if data == '': break
+ md.update(data)
+ hash_calc = md.hexdigest()
+ if hash == hash_calc:
+ print "NOTICE: hash ok for %s [hash = %s]" % (path, hash)
+ else:
+ print "ERROR: hash mismatch for %s [hash = %s, hash_calc = %s]" % \
+ (path, hash, hash_calc)
+ ret_val = 1
+exit(ret_val)