mirror of
https://github.com/robmcmullen/atrcopy.git
synced 2025-04-11 22:36:57 +00:00
Added check for magic values in media types
This commit is contained in:
parent
59ea74e182
commit
3897da6dc4
@ -92,9 +92,16 @@ class InvalidMediaSize(MediaError):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidAtrHeader(MediaError):
|
||||
class InvalidHeader(MediaError):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidCartHeader(MediaError):
|
||||
# Errors when trying to determine filesystem
|
||||
|
||||
class FilesystemError(AtrError):
|
||||
pass
|
||||
|
||||
|
||||
class IncompatibleMediaError(FilesystemError):
|
||||
pass
|
||||
|
||||
|
@ -31,6 +31,7 @@ class MediaType(Segment):
|
||||
if self.header is not None:
|
||||
self.check_header()
|
||||
self.check_media_size()
|
||||
self.check_magic()
|
||||
|
||||
#### initialization
|
||||
|
||||
@ -65,6 +66,16 @@ class MediaType(Segment):
|
||||
"""
|
||||
pass
|
||||
|
||||
def check_magic(self):
|
||||
"""Subclasses should override this method if there is some "magic"
|
||||
values that can identify (or rule out) this disk image class as a
|
||||
canditate.
|
||||
|
||||
Subclasses should raise the appropriate MediaError if the data is
|
||||
incompatible with this media type.
|
||||
"""
|
||||
pass
|
||||
|
||||
def find_filesystem(self):
|
||||
fs = filesystem.guess_filesystem(self)
|
||||
if fs:
|
||||
|
@ -104,7 +104,7 @@ def get_cart(cart_type):
|
||||
try:
|
||||
return known_cart_types[known_cart_type_map[cart_type]]
|
||||
except KeyError:
|
||||
raise errors.InvalidCartHeader("Unsupported cart type %d" % cart_type)
|
||||
raise errors.InvalidHeader("Unsupported cart type %d" % cart_type)
|
||||
|
||||
|
||||
class A8CartHeader:
|
||||
@ -120,12 +120,12 @@ class A8CartHeader:
|
||||
if len(data) == 16:
|
||||
header = data.view(dtype=self.format)[0]
|
||||
if header[0] != b'CART':
|
||||
raise errors.InvalidCartHeader
|
||||
raise errors.InvalidHeader
|
||||
self.cart_type = int(header[1])
|
||||
self.crc = int(header[2])
|
||||
self.set_type(self.cart_type)
|
||||
else:
|
||||
raise errors.InvalidCartHeader
|
||||
raise errors.InvalidHeader
|
||||
|
||||
def __str__(self):
|
||||
return "%s Cartridge (atari800 type=%d size=%d, %d banks, crc=%d)" % (self.cart_name, self.cart_type, self.cart_size, self.bank_size, self.crc)
|
||||
@ -150,7 +150,7 @@ class A8CartHeader:
|
||||
def check_media(self, media):
|
||||
media_size = len(media) - 16
|
||||
if self.cart_size != media_size:
|
||||
raise errors.InvalidCartHeader("Invalid cart size: {media_size}, expected {self.cart_size} for {self.cart_name}")
|
||||
raise errors.InvalidHeader("Invalid cart size: {media_size}, expected {self.cart_size} for {self.cart_name}")
|
||||
|
||||
|
||||
class Atari8bitCart(CartImage):
|
||||
|
@ -27,14 +27,14 @@ class AtrHeader(Segment):
|
||||
if len(header) == 16:
|
||||
values = header.view(dtype=self.format)[0]
|
||||
if values[0] != 0x296:
|
||||
raise errors.InvalidAtrHeader("no ATR header magic value")
|
||||
raise errors.InvalidHeader("no ATR header magic value")
|
||||
self.image_size = (int(values[3]) * 256 * 256 + int(values[1])) * 16
|
||||
self.sector_size = int(values[2])
|
||||
self.crc = int(values[4])
|
||||
self.unused = int(values[5])
|
||||
self.flags = int(values[6])
|
||||
else:
|
||||
raise errors.InvalidAtrHeader("incorrect AHC header size of %d" % len(bytes))
|
||||
raise errors.InvalidHeader("incorrect AHC header size of %d" % len(bytes))
|
||||
|
||||
def encode(self, raw):
|
||||
values = raw.view(dtype=self.format)[0]
|
||||
@ -51,10 +51,10 @@ class AtrHeader(Segment):
|
||||
|
||||
def check_media(self, media):
|
||||
if self.sector_size != media.sector_size:
|
||||
raise errors.InvalidAtrHeader("ExpectedMismatch between sector sizes: header claims {self.sector_size}, expected {media.sector_size} for {media.pretty_name}")
|
||||
raise errors.InvalidHeader("ExpectedMismatch between sector sizes: header claims {self.sector_size}, expected {media.sector_size} for {media.pretty_name}")
|
||||
media_size = len(media) - 16
|
||||
if self.image_size != media_size:
|
||||
raise errors.InvalidAtrHeader("Invalid media size: header claims {self.image_size}, expected {media_size} for {media.pretty_name}")
|
||||
raise errors.InvalidHeader("Invalid media size: header claims {self.image_size}, expected {media_size} for {media.pretty_name}")
|
||||
|
||||
|
||||
class AtariSingleDensity(DiskImage):
|
||||
@ -71,10 +71,10 @@ class AtariSingleDensity(DiskImage):
|
||||
if len(header_data) == 16:
|
||||
try:
|
||||
header = AtrHeader(container)
|
||||
except errors.InvalidAtrHeader:
|
||||
except errors.InvalidHeader:
|
||||
header = None
|
||||
else:
|
||||
raise errors.InvalidAtrHeader(f"file size {len(data)} small to be {self.pretty_name}")
|
||||
raise errors.InvalidHeader(f"file size {len(data)} small to be {self.pretty_name}")
|
||||
return header
|
||||
|
||||
|
||||
@ -86,6 +86,14 @@ class AtariSingleDensityShortImage(AtariSingleDensity):
|
||||
if size >= self.expected_size:
|
||||
raise errors.InvalidMediaSize(f"{self.pretty_name} must be less than size {self.expected_size}")
|
||||
|
||||
def check_magic(self):
|
||||
# Must have an ATR header for this to be a disk image
|
||||
if self.header is None:
|
||||
raise errors.InvalidHeader("Must have an ATR header for a non-standard image size")
|
||||
flag = self[0:2].view(dtype='<u2')
|
||||
if flag == 0xffff:
|
||||
raise errors.InvalidHeader("Appears to be an executable")
|
||||
|
||||
|
||||
class AtariEnhancedDensity(AtariSingleDensity):
|
||||
pretty_name = "Atari ED (130K) Floppy Disk Image"
|
||||
|
@ -29,23 +29,20 @@ class TestMediaTypesInTestDataDir:
|
||||
base_path = None
|
||||
expected_mime = ""
|
||||
|
||||
def test_test_data_dir(self):
|
||||
for pathname in sorted(glob.glob(os.path.join(os.path.dirname(__file__), "../test_data/", "*"))):
|
||||
wrapped, ext = os.path.splitext(pathname)
|
||||
if ext not in ext_to_valid_types:
|
||||
# skip for now until recognize bare files
|
||||
continue
|
||||
print(f"checking {pathname}")
|
||||
sample_data = np.fromfile(pathname, dtype=np.uint8)
|
||||
container = guess_container(sample_data)
|
||||
if container.compression_algorithm != "no compression":
|
||||
_, ext = os.path.splitext(wrapped)
|
||||
container.guess_media_type()
|
||||
print(ext, ext_to_valid_types)
|
||||
if ext in ext_to_valid_types:
|
||||
assert container.media.__class__ in ext_to_valid_types[ext]
|
||||
else:
|
||||
assert container.media.__class__ == MediaType
|
||||
@pytest.mark.parametrize("pathname", sorted(glob.glob(os.path.join(os.path.dirname(__file__), "../test_data/", "*"))))
|
||||
def test_test_data_dir(self, pathname):
|
||||
wrapped, ext = os.path.splitext(pathname)
|
||||
print(f"checking {pathname}")
|
||||
sample_data = np.fromfile(pathname, dtype=np.uint8)
|
||||
container = guess_container(sample_data)
|
||||
if container.compression_algorithm != "no compression":
|
||||
_, ext = os.path.splitext(wrapped)
|
||||
container.guess_media_type()
|
||||
print(ext, ext_to_valid_types)
|
||||
if ext in ext_to_valid_types:
|
||||
assert container.media.__class__ in ext_to_valid_types[ext]
|
||||
else:
|
||||
assert container.media.__class__ == MediaType
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
Loading…
x
Reference in New Issue
Block a user