diff options
author | Mike Frysinger <vapier@chromium.org> | 2017-10-06 01:23:28 -0400 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-10-06 15:51:10 -0700 |
commit | 3ba7a0819210d3e7d016f771c298865cae19efd4 (patch) | |
tree | b7c28b4d6a98c0e8ec66466dc286b5637fed23a3 /scripts/blockdiff.py | |
parent | acd7be816579a0c13ac6f746a2555b7c73f95a3b (diff) |
scripts: import blockdiff
This was added to dev/host/ for debug helping with paycheck.py,
so move it here so it's alongside that script.
BUG=None
TEST=None
Change-Id: I63ae858464cc13344335613093907673052a9859
Reviewed-on: https://chromium-review.googlesource.com/704200
Commit-Ready: Mike Frysinger <vapier@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
Diffstat (limited to 'scripts/blockdiff.py')
-rwxr-xr-x | scripts/blockdiff.py | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/scripts/blockdiff.py b/scripts/blockdiff.py new file mode 100755 index 00000000..feb5bd91 --- /dev/null +++ b/scripts/blockdiff.py @@ -0,0 +1,113 @@ +#!/usr/bin/python +# +# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Block diff utility.""" + +import optparse +import sys + + +class BlockDiffError(Exception): + pass + + +def BlockDiff(block_size, file1, file2, name1, name2, max_length=-1): + """Performs a binary diff of two files by blocks. + + Args: + block_size: the size of a block to diff by + file1: first file object + file2: second file object + name1: name of first file (for error reporting) + name2: name of second file (for error reporting) + max_length: the maximum length to read/diff in bytes (optional) + Returns: + A list of (start, length) pairs representing block extents that differ + between the two files. + Raises: + BlockDiffError if there were errors while diffing. + + """ + if max_length < 0: + max_length = sys.maxint + diff_list = [] + num_blocks = extent_start = extent_length = 0 + while max_length or extent_length: + read_length = min(max_length, block_size) + data1 = file1.read(read_length) + data2 = file2.read(read_length) + if len(data1) != len(data2): + raise BlockDiffError('read %d bytes from %s but %d bytes from %s' % + (len(data1), name1, len(data2), name2)) + + if data1 != data2: + # Data is different, mark it down. + if extent_length: + # Stretch the current diff extent. + extent_length += 1 + else: + # Start a new diff extent. + extent_start = num_blocks + extent_length = 1 + elif extent_length: + # Record the previous extent. + diff_list.append((extent_start, extent_length)) + extent_length = 0 + + # Are we done reading? + if not data1: + break + + max_length -= len(data1) + num_blocks += 1 + + return diff_list + + +def main(argv): + # Parse command-line arguments. + parser = optparse.OptionParser( + usage='Usage: %prog FILE1 FILE2', + description='Compare FILE1 and FILE2 by blocks.') + + parser.add_option('-b', '--block-size', metavar='NUM', type=int, default=4096, + help='the block size to use (default: %default)') + parser.add_option('-m', '--max-length', metavar='NUM', type=int, default=-1, + help='maximum number of bytes to compared') + + opts, args = parser.parse_args(argv[1:]) + + try: + name1, name2 = args + except ValueError: + parser.error('unexpected number of arguments') + + # Perform the block diff. + try: + with open(name1) as file1: + with open(name2) as file2: + diff_list = BlockDiff(opts.block_size, file1, file2, name1, name2, + opts.max_length) + except BlockDiffError as e: + print >> sys.stderr, 'Error:', e + return 2 + + # Print the diff, if such was found. + if diff_list: + total_diff_blocks = 0 + for extent_start, extent_length in diff_list: + total_diff_blocks += extent_length + print('%d->%d (%d)' % + (extent_start, extent_start + extent_length, extent_length)) + + print 'total diff: %d blocks' % total_diff_blocks + return 1 + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) |