-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfindbadsectors.py
71 lines (61 loc) · 2.59 KB
/
findbadsectors.py
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
'''
Copy a file to new copy on same disk, replacing bad sectors (unreadable) with readable fillers
Helpful for example in large video files, to allow most of file to be played/read even with some broken sectors..
'''
import os
def sectorFix(name, dryrun=False):
badSectorReplacer = (b'badsector_' * 4096)[:4096]
outputFilename = '{}{}{}'.format(os.path.dirname(name), os.path.sep, 'fixed-' + os.path.basename(name))
with open(name, 'rb') as fid, (open("NUL", 'wb') if dryrun else open(outputFilename, 'wb')) as fidOut:
fid.seek(0, os.SEEK_END)
eof = fid.tell()
fid.seek(0)
fixedSectors = []
sectorCount = 0
pos = fid.tell()
while pos != eof:
sectorCount+= 1
try:
data = fid.read(4096)
if fidOut:
fidOut.write(data)
except Exception as e:
print('file {name} has bad sector at block {block}, tell:{tell}, exception:{ex}'.format(
name=name,block=pos/4096, tell=fid.tell(), ex=str(e)))
fixedSectors.append(pos)
fid.seek(pos + 4096)
if fidOut:
fidOut.write(badSectorReplacer)
pos = fid.tell()
return sectorCount, len(fixedSectors)
def search(path):
badFiles = []
totalFiles = 0
totalScannedSectors = 0
totalBadSectors = 0
for root, dirs, files in os.walk(path):
path = root.split(os.sep)
for filename in files:
totalFiles += 1
filePath = os.path.join(root, filename)
try:
fileSectors, fixedSectors = sectorFix(filePath, True)
except Exception as e:
print("couldn't scan file {}, exception: {}".format(filePath, str(e)))
continue
totalScannedSectors += fileSectors
totalBadSectors += fixedSectors
if fixedSectors:
badFiles.append(filePath)
print("\ncorrupted files:\n{}".format("\n".join(badFiles)))
print("\nsummary:\ntotal {} bad files out of {}".format(len(badFiles), totalFiles))
print("total {} bad sectors out of {}, ratio {}".format(
totalBadSectors, totalScannedSectors, (totalScannedSectors / totalBadSectors) if totalBadSectors else 0))
if __name__ == '__main__':
from sys import argv
if len(argv) == 2:
sectorFix(argv[1])
elif argv[1] == "--search":
search(argv[2])
else:
print("usage: {} [--search] path\n* Without search will fix bad sectors in a file, with search will recursively scan and report bad sectors in the path")