#!/usr/bin/env python # # Usage: fileDiffer # # LUKS # quick regression test suite # Tests LUKS images for changes at certain disk offsets # # Does fast python code has to look ugly or is it just me? import sys class changes: pass def parseArgs(args): aFileName = args[1] bFileName = args[2] changelist = [] args[0:3] = [] for i in args: mychanges = changes(); if i.startswith('A'): mychanges.mode = 'ALLOWED' if i.startswith('R'): mychanges.mode = 'REQUIRED' mychanges.strictness = 'RANDOM' if i.startswith('S'): mychanges.mode = 'REQUIRED' mychanges.strictness = 'SEMANTIC' dashIndex = i.find('-') if dashIndex == -1: mychanges.starts = int(i[1:]) mychanges.ends = mychanges.starts else: mychanges.starts = int(i[1:dashIndex]) mychanges.ends = int(i[dashIndex+1:]) mychanges.miss = 0 changelist.append(mychanges) mychanges = changes(); mychanges.starts = 0 # mychanges.ends will be fixed later mychanges.mode = 'FORBIDDEN' changelist.append(mychanges) return [aFileName, bFileName, changelist] def mode(i): for c in changelist: if i >= c.starts and i<=c.ends: return c def cleanchanges(i): newchangelist=[] for c in changelist: if i <= c.starts or i <= c.ends: newchangelist.append(c) return newchangelist [aFileName, bFileName, changelist] = parseArgs(sys.argv) aFile = open(aFileName,'r') bFile = open(bFileName,'r') aString = aFile.read() bString = bFile.read() if len(aString) != len(bString): sys.exit("Mismatch different file sizes") fileLen = len(aString) fileLen10th = fileLen/10 # Create a catch all entry changelist[-1].ends = fileLen print "Changes list: (FORBIDDEN default)" print "start\tend\tmode\t\tstrictness" for i in changelist: if i.mode == 'REQUIRED': print "%d\t%d\t%s\t%s" % (i.starts, i.ends, i.mode, i.strictness) else: print "%d\t%d\t%s" % (i.starts, i.ends, i.mode) filepos = 0 fileLen10thC = 0 print "[..........]" sys.stdout.write("[") sys.stdout.flush() modeNotTrivial = 1 while filepos < fileLen: if modeNotTrivial == 1: c = mode(filepos) # print (filepos, c.mode) if c.mode == 'REQUIRED': if aString[filepos] == bString[filepos]: c.miss = c.miss + 1 else: if aString[filepos] != bString[filepos] and c.mode != 'ALLOWED': sys.exit("Mismatch at %d: change forbidden" % filepos) # Do some maintaince, print progress bar, and clean changelist # # Maintaining two counters appears to be faster than modulo operation if fileLen10thC == fileLen10th: fileLen10thC = 0 sys.stdout.write(".") sys.stdout.flush() changelist = cleanchanges(filepos) if len(changelist) == 1: modeNotTrivial = 0 filepos = filepos + 1 fileLen10thC = fileLen10thC + 1 for c in changelist: if c.mode == 'REQUIRED': if c.strictness == 'SEMANTIC' and c.miss == (c.ends-c.starts+1): sys.exit("Mismatch: not even a single change in region %d-%d." % (c.starts, c.ends)) # This is not correct. We should do a statistical test # of the sampled data against the hypothetical distribution # of collision. Chi-Square Test. if c.strictness == 'RANDOM' and c.miss == (c.ends-c.starts+1): sys.exit("Mismatch: not even a single change in region %d-%d." % (c.starts, c.ends)) print ".] - everything ok"