Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#!/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
You can’t perform that action at this time.