#!/usr/bin/env python3 | |
# (c) Maxim Suhanov | |
# 2020 | |
import sys | |
if len(sys.argv) != 4: | |
print('Usage: extract_unallocated.py <bitmap file> <flat image> <cluster size (in bytes)') | |
sys.exit(0) | |
with open(sys.argv[1], 'rb') as bitmap: | |
bitmap_buffer = bitmap.read() | |
volume = open(sys.argv[2], 'rb') | |
cluster_size = int(sys.argv[3]) | |
if cluster_size <= 0 or cluster_size % 512 != 0: | |
raise ValueError('Invalid cluster size') | |
sector_size = 512 | |
sectors_per_cluster = cluster_size // sector_size | |
empty_sector = b'EMPTY ' * 32 | |
original_sector = b'ORIGINAL ' * 32 | |
null_sector = b'\x00' * 512 | |
cnt_empty = 0 | |
cnt_original = 0 | |
cnt_valid = 0 | |
cnt_null = 0 | |
bit_index = 0 | |
while True: | |
try: | |
current_bitmap_byte = bitmap_buffer[bit_index // 8] | |
except IndexError: | |
break | |
current_bitmap_bit = (current_bitmap_byte >> (bit_index % 8)) & 1 | |
if current_bitmap_bit == 0: | |
volume.seek(bit_index * cluster_size) | |
for __ in range(sectors_per_cluster): | |
unallocated_sector = volume.read(sector_size) | |
truncated_read = len(unallocated_sector) != sector_size | |
if unallocated_sector == empty_sector: | |
cnt_empty += 1 | |
elif unallocated_sector == original_sector: | |
cnt_original += 1 | |
else: | |
cnt_valid += 1 | |
sys.stdout.buffer.write(unallocated_sector) | |
if unallocated_sector == null_sector: | |
cnt_null += 1 | |
if truncated_read: | |
break | |
if truncated_read: | |
break | |
bit_index += 1 | |
volume.close() | |
print('Empty (null) sectors: {}, original sectors: {}, valid unallocated sectors: {}, valid sectors with nulls: {}\n'.format(cnt_empty, cnt_original, cnt_valid, cnt_null), file = sys.stderr) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment