summaryrefslogtreecommitdiffstats
path: root/make/df-verify.py
blob: 51cbf5bdbb9e67256ec61e10e3ad8143a9eac067 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
###############################################################################
##
## Coded for minimum version of Python 2.7 .
##
## Python3 is incompatible.
##
## Authors: konablend
##
###############################################################################

import hashlib
import os
import signal
import sys

sys.dont_write_bytecode = True
sys.path.insert(0, os.path.join(sys.path[0], 'lib'))
import hb_distfile

###############################################################################

def signal_handler(signal, frame):
    sys.stderr.write('^C')
    sys.exit(1)

signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

###############################################################################

## simple structure object
class Struct(object):
    pass

###############################################################################

class Tool(hb_distfile.Tool):
    def __init__(self):
        super(Tool, self).__init__()
        self.parser.prog = self.name
        self.parser.usage = '%prog [OPTIONS] FILE'
        self.parser.description = 'Verify distfile data integrity.'
        self.parser.add_option('--disable', default=False, action='store_true', help='do nothing and exit without error')
        self.parser.add_option('--md5', default=None, action='store', metavar='HASH', help='verify MD5 HASH against data')
        self._parse()

    def _load_config2(self, parser, data):
        parser.values.disable = data['disable-verify']

    def _scan(self, filename):
        self.verbosef('scanning %s\n' % filename)
        hasher = hashlib.md5()
        with open(filename, 'r') as o:
            data_total = 0
            while True:
                data = o.read(65536)
                if not data:
                    break
                hasher.update(data)
                data_total += len(data)
        self.verbosef('scanned %d bytes\n' % data_total)
        r = Struct()
        r.md5 = hasher.hexdigest()
        r.size = data_total
        return r

    def _verify(self, filename):
        r = Struct()
        r.scan = self._scan(filename)
        r.status = self.options.md5 == r.scan.md5
        return r

    def _run(self, error):
        if self.options.disable:
            self.infof('%s failure; administratively disabled.\n' % self.name)
            sys.exit(0)
        if len(self.args) != 1:
            raise error('no file specified')
        filename = self.args[0]
        if self.options.md5:
            error.op = 'verify'
            r = self._verify(filename)
            self.infof('MD5 (%s) = %s (%s)\n', filename, r.scan.md5, 'pass' if r.status else 'fail; expecting %s' % self.options.md5)
        else:
            error.op = 'scan'
            r = self._scan(filename)
            self.infof('MD5 (%s) = %s (%d bytes)\n', filename, r.md5, r.size)

    def run(self):
        error = hb_distfile.ToolError(self.name)
        try:
            self._run(error)
        except Exception, x:
            self.debug_exception()
            self.errln('%s failure; %s' % (error.op,x), exit=1)

###############################################################################

tool = Tool()
tool.run()