mirror of https://github.com/brouhaha/sosar.git
New SOSAllocationBitmap class.
This commit is contained in:
parent
3111409cd9
commit
7263000c0b
12
sosar.py
12
sosar.py
|
@ -71,15 +71,17 @@ else:
|
|||
print('must specify image file format', file = sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
file_mode = { 'mkfs': 'w',
|
||||
'ls': 'r' } [args.cmd] + 'b'
|
||||
|
||||
image = open(args.image, file_mode)
|
||||
|
||||
if args.cmd == 'mkfs':
|
||||
image = open(args.image, 'wb')
|
||||
disk = SOSDisk(image, fmt, new = True, size = args.size)
|
||||
disk = SOSDisk(image, fmt, new = True, volume_block_count = args.size)
|
||||
else:
|
||||
image = open(args.image, 'rb')
|
||||
disk = SOSDisk(image, fmt)
|
||||
|
||||
args.cmd_fn(args, disk)
|
||||
|
||||
image.close()
|
||||
|
||||
disk.close()
|
||||
|
||||
|
|
81
sosdisk.py
81
sosdisk.py
|
@ -1,5 +1,6 @@
|
|||
import datetime
|
||||
from enum import Enum, IntEnum, IntFlag
|
||||
import math
|
||||
import string
|
||||
import struct
|
||||
import sys
|
||||
|
@ -144,6 +145,52 @@ def u32_to_sos_timestamp(b):
|
|||
return datetime.datetime(year, month, day, hour, minute)
|
||||
|
||||
|
||||
class SOSAllocationBitmap:
|
||||
def __init__(self, disk, start_block, bitmap_block_count, create = False, volume_block_count = None):
|
||||
self.disk = disk
|
||||
self.start_block = start_block
|
||||
self.bitmap_block_count = bitmap_block_count
|
||||
self.data = self.disk.get_blocks(self.start_block, self.bitmap_block_count)
|
||||
if create:
|
||||
self.__create_new(volume_block_count)
|
||||
|
||||
def __create_new(self, volume_block_count):
|
||||
print('creating bitmap')
|
||||
print(volume_block_count)
|
||||
self.bitmap_block_count = math.ceil(volume_block_count / (8 * self.disk.block_size))
|
||||
# mark all blocks as free
|
||||
print(self.bitmap_block_count, self.disk.block_size)
|
||||
self.data[:] = bytes(self.bitmap_block_count * self.disk.block_size)
|
||||
print(len(self.data))
|
||||
# mark blocks occupied by boot blocks, volume directory, and
|
||||
# volume allocation bitmap as in use
|
||||
self[0:self.start_block+self.bitmap_block_count] = [1] * (self.start_block+self.bitmap_block_count)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if isinstance(key, slice):
|
||||
result = [self.__getitem__(i) for i in range(*key.indices(len(self.data)))]
|
||||
else:
|
||||
# XXX is bit numbering little-endian or big-endian?
|
||||
return bool((self.data[key >> 3] >> (key & 7)) & 1)
|
||||
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
print('setitem(', key, ', ', value, ')')
|
||||
if isinstance(key, slice):
|
||||
print('slice')
|
||||
print(key.indices(len(self.data)))
|
||||
for k, v in zip(range(*key.indices(len(self.data))), value):
|
||||
print(k, v)
|
||||
self.__setitem__(k, v)
|
||||
print(self.data)
|
||||
else:
|
||||
# XXX is bit numbering little-endian or big-endian?
|
||||
if value:
|
||||
self.data[key >> 3] |= (1 << (key & 7))
|
||||
else:
|
||||
self.data[key >> 3] &= ~ (1 << (key & 7))
|
||||
|
||||
|
||||
class SOSStorage:
|
||||
@classmethod
|
||||
def create(cls, disk, storage_type, key_pointer):
|
||||
|
@ -169,7 +216,6 @@ class SOSStorage:
|
|||
class SOSSeedling(SOSStorage):
|
||||
def __init__(self, disk, key_pointer):
|
||||
super().__init__(disk, key_pointer)
|
||||
self.disk.mark_used(key_pointer)
|
||||
self.index[0] = key_pointer
|
||||
self.data_blocks += 1
|
||||
|
||||
|
@ -182,7 +228,6 @@ class SOSSapling(SOSStorage):
|
|||
b = index_data[j] + (index_data[j + 256] << 8)
|
||||
if b != 0:
|
||||
self.index[j] = b
|
||||
self.disk.mark_used(b)
|
||||
self.data_blocks += 1
|
||||
self.last_block_index = j
|
||||
|
||||
|
@ -200,7 +245,6 @@ class SOSTree(SOSStorage):
|
|||
b = index_data[j] + (index_data[j + 256] << 8)
|
||||
if b != 0:
|
||||
self.index[j * 256 + i] = b
|
||||
self.disk.mark_used(b)
|
||||
self.data_blocks += 1
|
||||
self.last_block_index = j
|
||||
|
||||
|
@ -415,50 +459,40 @@ class SOSDisk:
|
|||
sys.exit(2)
|
||||
self.dirty = False
|
||||
self.block_count = len(self.data) // self.block_size
|
||||
self.used = [False] * self.block_count
|
||||
if self.image_file_fmt != 'po':
|
||||
if len(self.data) != (35 * 8 * self.block_size):
|
||||
print('Images other than 16-sector floppy must be in SOS/ProDOS sector order', file = sys.stderr)
|
||||
sys.exit(2)
|
||||
self.data = reinterleave(self.data, interleave_tables[self.image_file_fmt], interleave_tables['po'])
|
||||
self.mark_used(0, 2) # boot blocks
|
||||
self.volume_directory = SOSDirectory(self, 2, new = False)
|
||||
self.bitmap_block_count = (self.volume_directory.header.total_blocks + 1) // (self.block_size * 8)
|
||||
self.bitmap_start_block = self.volume_directory.header.bitmap_pointer
|
||||
self.mark_used(self.volume_directory.header.bitmap_pointer, self.bitmap_block_count)
|
||||
|
||||
def __create_new(volume_block_count = 280, volume_directory_block_count = 4):
|
||||
self.data = bytearray(size * self.block_size)
|
||||
self.mark_used(0, 2) # boot blocks
|
||||
self.allocation_bitmap = SOSAllocationBitmap(self, self.bitmap_start_block, self.bitmap_block_count)
|
||||
|
||||
def __create_new(self, volume_block_count = 280, volume_directory_block_count = 4):
|
||||
print('create new')
|
||||
self.dirty = True
|
||||
self.block_count = volume_block_count;
|
||||
self.data = bytearray(self.block_count * self.block_size)
|
||||
self.bitmap_block_count = (volume_block_count + 1) // (self.block_size * 8)
|
||||
self.bitmap_start_block = 2 + volume_directory_block_count
|
||||
self.mark_used(self.bitmap_start_block, self.bitmap_block_count) # allocation bitmap
|
||||
self.allocation_bitmap = SOSAllocationBitmap(self, self.bitmap_start_block, self.bitmap_block_count, create = True, volume_block_count = self.block_count)
|
||||
self.volume_directory = SOSDirectory(self, 2, new = True, block_count = volume_directory_block_count)
|
||||
|
||||
|
||||
def close(self):
|
||||
if self.dirty:
|
||||
print('dirty')
|
||||
self.image_file.seek(0)
|
||||
self.image_file.write(reinterleave(self.data, interleave_tables['po'], interleave_tables[self.image_file_fmt]))
|
||||
self.data = None
|
||||
self.image_file.close()
|
||||
|
||||
def mark_used(self, first_block, count = 1):
|
||||
for block in range(first_block, first_block + count):
|
||||
if self.used[block]:
|
||||
print('block %d multiply used' % block)
|
||||
self.used[block] = True
|
||||
|
||||
def get_blocks(self, first_block, count = 1):
|
||||
self.mark_used(first_block, count)
|
||||
offset = first_block * 512
|
||||
length = count * 512
|
||||
return memoryview(self.data[offset:offset+length])
|
||||
|
||||
def alloc_block(self):
|
||||
pass
|
||||
|
||||
def print_directory(self,
|
||||
recursive = False,
|
||||
long = False,
|
||||
|
@ -507,3 +541,8 @@ class SOSDisk:
|
|||
# 35-36 2 bit map pointer 2 parent pointer
|
||||
# 37-38 2 total blocks 1 parent_entry_num 2 header_pointer
|
||||
# 1 parent_entry_length = $27
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
with open('foo.po', 'w') as f:
|
||||
disk = SOSDisk(f, new = True)
|
||||
|
|
Loading…
Reference in New Issue