forked from cnvogelg/amitools
-
Notifications
You must be signed in to change notification settings - Fork 1
/
xdfscan
executable file
·171 lines (150 loc) · 4.31 KB
/
xdfscan
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#!/usr/bin/env python2.7
# xdfscan
# quickly scan large sets of Amiga disk image files
import sys
import argparse
import os.path
import time
from amitools.fs.blkdev.BlkDevFactory import BlkDevFactory
from amitools.fs.validate.Validator import Validator
from amitools.fs.validate.Progress import Progress
# ----- logging -----
class MyProgress(Progress):
def __init__(self):
Progress.__init__(self)
self.clk = int(time.clock() * 1000)
def begin(self, msg):
Progress.begin(self, msg)
def add(self):
Progress.add(self)
clk = int(time.clock() * 1000)
delta = clk - self.clk
# update display every 250ms
if delta > 250:
self.clk = clk
print("%s: %d\r" % (self.msg, self.num)),
sys.stdout.flush()
def pre_log_path(path, msg):
print("%20s %s \r" % (msg, path)),
sys.stdout.flush()
def log_path(path, msg):
print("%20s %s " % (msg, path))
def print_block(percent):
print("%3.1f%%\r" % (percent / 10.0)),
sys.stdout.flush()
# ----- scanner -----
factory = BlkDevFactory()
def scan(path, args):
if not os.path.exists(path):
log_path(path, "DOES NOT EXIST")
return 1
if os.path.isdir(path):
return scan_dir(path, args)
elif os.path.isfile(path):
return scan_file(path, args)
def scan_dir(path, args):
for name in sorted(os.listdir(path)):
epath = os.path.join(path, name)
result = scan(epath, args)
if result != 0:
return result
return 0
def check_extension(path, args):
ext = []
if not args.skip_disks:
ext += ['.adf','.adz','.adf.gz']
if not args.skip_hds:
ext += ['.hdf']
for a in ext:
if path.endswith(a):
return True
return False
def scan_file(path, args):
if not check_extension(path, args):
return 0
try:
pre_log_path(path,"scan")
ret_code = 0
ret_str = ""
stay = True
# create a block device for image file
blkdev = factory.open(path, read_only=True)
# create validator
progress = MyProgress()
v = Validator(blkdev, min_level=args.level, debug=args.debug, progress=progress)
# 1. check boot block
res = []
boot_dos, bootable = v.scan_boot()
if boot_dos:
# 2. check root block
root = v.scan_root()
if not root:
# disk is bootable
if bootable:
res.append("boot")
else:
res.append(" ")
# invalid root
res.append("nofs")
else:
# 3. scan tree
v.scan_dir_tree()
# 4. scan files
v.scan_files()
# 5. scan_bitmap
v.scan_bitmap()
# summary
e, w = v.get_summary()
if w > 0:
res.append("w%03d" % w)
if e > 0:
res.append("E%03d" % e)
else:
res.append(" ")
# disk is bootable
if bootable:
res.append("boot")
else:
res.append(" ")
if e == 0 and w == 0:
res.append(" ok ")
else:
res.append("NOK ")
else:
# boot block is not dos
res.append("NDOS")
# report result
if len(res) == 0:
res.append("done")
log_path(path," ".join(res))
# summary
if args.verbose:
v.log.dump()
return ret_code
except IOError,e:
log_path(path,"BLKDEV?")
if args.verbose:
print e
return 0
# ----- main -----
def main():
parser = argparse.ArgumentParser()
parser.add_argument('input', nargs='+', help="input image file or directory (to scan tree)")
parser.add_argument('-v', '--verbose', action='store_true', default=False, help="be more verbos")
parser.add_argument('-d', '--debug', action='store_true', default=False, help="show debug info")
parser.add_argument('-q', '--quick', action='store_true', default=False, help="quick mode. faster: skip image if root is invalid")
parser.add_argument('-l', '--level', default=2, help="show only level or above (0=debug, 1=info, 2=warn, 3=error)", type=int)
parser.add_argument('-D', '--skip-disks', action='store_true', default=False, help="do not scan disk images")
parser.add_argument('-H', '--skip-hds', action='store_true', default=False, help="do not scan hard disk images")
args = parser.parse_args()
# main scan loop
ret = 0
for i in args.input:
ret = scan(i, args)
if ret != 0:
break
sys.exit(ret)
try:
main()
except KeyboardInterrupt, e:
print "aborting..."