1#!/usr/bin/env python 2 3# 4# Usage: fileDiffer <afile> <bfile> <list of disk changes> 5# 6 7# LUKS 8# quick regression test suite 9# Tests LUKS images for changes at certain disk offsets 10# 11# Does fast python code has to look ugly or is it just me? 12 13import sys 14 15class changes: 16 pass 17 18def parseArgs(args): 19 aFileName = args[1] 20 bFileName = args[2] 21 changelist = [] 22 args[0:3] = [] 23 for i in args: 24 mychanges = changes(); 25 if i.startswith('A'): 26 mychanges.mode = 'ALLOWED' 27 if i.startswith('R'): 28 mychanges.mode = 'REQUIRED' 29 mychanges.strictness = 'RANDOM' 30 if i.startswith('S'): 31 mychanges.mode = 'REQUIRED' 32 mychanges.strictness = 'SEMANTIC' 33 34 dashIndex = i.find('-') 35 if dashIndex == -1: 36 mychanges.starts = int(i[1:]) 37 mychanges.ends = mychanges.starts 38 else: 39 mychanges.starts = int(i[1:dashIndex]) 40 mychanges.ends = int(i[dashIndex+1:]) 41 mychanges.miss = 0 42 changelist.append(mychanges) 43 mychanges = changes(); 44 mychanges.starts = 0 45# mychanges.ends will be fixed later 46 mychanges.mode = 'FORBIDDEN' 47 changelist.append(mychanges) 48 return [aFileName, bFileName, changelist] 49 50def mode(i): 51 for c in changelist: 52 if i >= c.starts and i<=c.ends: 53 return c 54def cleanchanges(i): 55 newchangelist=[] 56 for c in changelist: 57 if i <= c.starts or i <= c.ends: 58 newchangelist.append(c) 59 return newchangelist 60 61[aFileName, bFileName, changelist] = parseArgs(sys.argv) 62 63aFile = open(aFileName,'r') 64bFile = open(bFileName,'r') 65 66aString = aFile.read() 67bString = bFile.read() 68 69if len(aString) != len(bString): 70 sys.exit("Mismatch different file sizes") 71 72fileLen = len(aString) 73fileLen10th = fileLen/10 74 75# Create a catch all entry 76changelist[-1].ends = fileLen 77 78print "Changes list: (FORBIDDEN default)" 79print "start\tend\tmode\t\tstrictness" 80for i in changelist: 81 if i.mode == 'REQUIRED': 82 print "%d\t%d\t%s\t%s" % (i.starts, i.ends, i.mode, i.strictness) 83 else: 84 print "%d\t%d\t%s" % (i.starts, i.ends, i.mode) 85 86 87filepos = 0 88fileLen10thC = 0 89print "[..........]" 90sys.stdout.write("[") 91sys.stdout.flush() 92 93modeNotTrivial = 1 94while filepos < fileLen: 95 96 if modeNotTrivial == 1: 97 c = mode(filepos) 98# print (filepos, c.mode) 99 if c.mode == 'REQUIRED': 100 if aString[filepos] == bString[filepos]: 101 c.miss = c.miss + 1 102 else: 103 if aString[filepos] != bString[filepos] and c.mode != 'ALLOWED': 104 sys.exit("Mismatch at %d: change forbidden" % filepos) 105 106 # Do some maintaince, print progress bar, and clean changelist 107 # 108 # Maintaining two counters appears to be faster than modulo operation 109 if fileLen10thC == fileLen10th: 110 fileLen10thC = 0 111 sys.stdout.write(".") 112 sys.stdout.flush() 113 changelist = cleanchanges(filepos) 114 if len(changelist) == 1: 115 modeNotTrivial = 0 116 filepos = filepos + 1 117 fileLen10thC = fileLen10thC + 1 118 119for c in changelist: 120 if c.mode == 'REQUIRED': 121 if c.strictness == 'SEMANTIC' and c.miss == (c.ends-c.starts+1): 122 sys.exit("Mismatch: not even a single change in region %d-%d." % (c.starts, c.ends)) 123 # This is not correct. We should do a statistical test 124 # of the sampled data against the hypothetical distribution 125 # of collision. Chi-Square Test. 126 if c.strictness == 'RANDOM' and c.miss == (c.ends-c.starts+1): 127 sys.exit("Mismatch: not even a single change in region %d-%d." % (c.starts, c.ends)) 128 129print ".] - everything ok" 130