summaryrefslogtreecommitdiff
path: root/linearizeDisk.py
blob: bd7a69ca9e80e808aafb2dca9fdb3f394dd8b0be (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
#!/usr/bin/env python3

"""
For some reason blocks in the bitsavers images are not in linear order, but
shuffled. Not sure why and if other disks are affected as well, but this script
reorders them.
"""

import os, logging
from itertools import chain

def linearBlocks (fd):
    fd.seek (0, os.SEEK_END)
    size = fd.tell ()
    logging.debug ('File size is {} bytes'.format (size))

    blockSize = 512
    blocksPerChunk = 15
    if size == 1228800:
        # 1.2m
        blocksPerChunk = 15
    elif size in (368640, 737280):
        # 360k or 720k
        blocksPerChunk = 9
    elif size == 819200:
        # 800k
        blocksPerChunk = 10
    else:
        logging.warning ('Cannot determine blocks per chunk from filesize')
    chunkSize = blockSize*blocksPerChunk
    chunks = size//chunkSize
    skip = 1
    if size%chunkSize != 0:
        logging.warning ('File size {} is not multiple of chunk size {}'.format (size, chunkSize))

    # first even then odd chunks
    for j in chain (range (0, chunks, 2), range (1, chunks, 2)):
        pos = j*chunkSize
        logging.debug ('Seeking to {} for chunk {} and reading {} blocks @ {} bytes'.format (pos, j, blocksPerChunk, blockSize))
        fd.seek (pos, os.SEEK_SET)
        for i in range (blocksPerChunk):
            yield fd.read (blockSize)

if __name__ == '__main__':
    import argparse, sys
    
    parser = argparse.ArgumentParser(description='Reorder EUMEL archive disk’s blocks.')
    parser.add_argument ('-v', '--verbose', help='Enable debugging messages', action='store_true')
    parser.add_argument ('input', help='Input file')
    parser.add_argument ('output', help='Out file')
    args = parser.parse_args ()
    if args.verbose:
        logging.basicConfig (level=logging.DEBUG)
    else:
        logging.basicConfig (level=logging.WARNING)

    with open (args.input, 'rb') as infd, open (args.output, 'wb') as outfd:
        for b in linearBlocks (infd):
            outfd.write (b)