mirror of
https://github.com/KrisKennaway/pyapple2disk.git
synced 2024-11-25 18:30:59 +00:00
Add some more file types
Fix some anomaly types Add anomalies for corrupted catalog metadata (pointing to out-of-bounds sector) Don't render the entire disk catalog in __str__, it's too verbose. Move it to a dedicated Catalog() method
This commit is contained in:
parent
67683829e4
commit
c57ee58def
@ -12,13 +12,18 @@ class FileType(object):
|
|||||||
self.long_type = long_type
|
self.long_type = long_type
|
||||||
self.parser = parser
|
self.parser = parser
|
||||||
|
|
||||||
|
# TODO: add handlers for parsing the rest
|
||||||
FILE_TYPES = {
|
FILE_TYPES = {
|
||||||
0x00: FileType('T', 'TEXT'),
|
0x00: FileType('T', 'TEXT'),
|
||||||
0x01: FileType('I', 'INTEGER BASIC'),
|
0x01: FileType('I', 'INTEGER BASIC'),
|
||||||
# TODO: add handler for parsing file content
|
|
||||||
0x02: FileType('A', 'APPLESOFT BASIC', applesoft.AppleSoft),
|
0x02: FileType('A', 'APPLESOFT BASIC', applesoft.AppleSoft),
|
||||||
0x04: FileType('B', 'BINARY'),
|
0x04: FileType('B', 'BINARY'),
|
||||||
# TODO: others
|
# TODO: add anomalies for these
|
||||||
|
0x08: FileType('S', 'Type S File'),
|
||||||
|
0x10: FileType('R', 'Relocatable object module file'),
|
||||||
|
0x20: FileType('a', 'Type a File'),
|
||||||
|
0x40: FileType('b', 'Type b File'),
|
||||||
|
# TODO: unknown file type
|
||||||
}
|
}
|
||||||
|
|
||||||
class VTOCSector(disklib.Sector):
|
class VTOCSector(disklib.Sector):
|
||||||
@ -47,7 +52,7 @@ class VTOCSector(disklib.Sector):
|
|||||||
if tracks_per_disk != disklib.TRACKS_PER_DISK:
|
if tracks_per_disk != disklib.TRACKS_PER_DISK:
|
||||||
self.anomalies.append(
|
self.anomalies.append(
|
||||||
anomaly.Anomaly(
|
anomaly.Anomaly(
|
||||||
self, anomaly.INTERESTING, 'Disk has %d tracks > %d' % (
|
self, anomaly.UNUSUAL, 'Disk has %d tracks > %d' % (
|
||||||
tracks_per_disk, disklib.TRACKS_PER_DISK)
|
tracks_per_disk, disklib.TRACKS_PER_DISK)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -58,7 +63,7 @@ class VTOCSector(disklib.Sector):
|
|||||||
if (catalog_track, catalog_sector) != (0x11, 0x0f):
|
if (catalog_track, catalog_sector) != (0x11, 0x0f):
|
||||||
self.anomalies.append(
|
self.anomalies.append(
|
||||||
anomaly.Anomaly(
|
anomaly.Anomaly(
|
||||||
self, anomaly.INTERESTING, 'Catalog begins in unusual place: T$%02X S$%02X' % (
|
self, anomaly.UNUSUAL, 'Catalog begins in unusual place: T$%02X S$%02X' % (
|
||||||
catalog_track, catalog_sector)
|
catalog_track, catalog_sector)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -82,7 +87,7 @@ class VTOCSector(disklib.Sector):
|
|||||||
self.anomalies.append(
|
self.anomalies.append(
|
||||||
anomaly.Anomaly(
|
anomaly.Anomaly(
|
||||||
self, anomaly.CORRUPTION,
|
self, anomaly.CORRUPTION,
|
||||||
'Freemap claims free sector in track 0: T$%02X S$%02X (cannot be allocated in DOS ' +
|
'Freemap claims free sector in track 0: T$%02X S$%02X (cannot be allocated in DOS '
|
||||||
'3.3)' % (track, sector)
|
'3.3)' % (track, sector)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -211,8 +216,9 @@ class Dos33Disk(disklib.Disk):
|
|||||||
# Maps stripped filename to File() object
|
# Maps stripped filename to File() object
|
||||||
self.files = {}
|
self.files = {}
|
||||||
for catalog_entry in self.catalog.itervalues():
|
for catalog_entry in self.catalog.itervalues():
|
||||||
|
newfile = self.ReadCatalogEntry(catalog_entry)
|
||||||
# TODO: last character has special meaning for deleted files and may legitimately be whitespace. Could collide with a non-deleted file of the same stripped name
|
# TODO: last character has special meaning for deleted files and may legitimately be whitespace. Could collide with a non-deleted file of the same stripped name
|
||||||
self.files[catalog_entry.FileName().rstrip()] = self.ReadCatalogEntry(catalog_entry)
|
self.files[catalog_entry.FileName().rstrip()] = newfile
|
||||||
|
|
||||||
def _ReadVTOC(self):
|
def _ReadVTOC(self):
|
||||||
return VTOCSector.fromSector(self.ReadSector(0x11, 0x0))
|
return VTOCSector.fromSector(self.ReadSector(0x11, 0x0))
|
||||||
@ -254,19 +260,26 @@ class Dos33Disk(disklib.Disk):
|
|||||||
# TODO: add sector type for this. What to do about sectors claimed by this file that are in use by another file? May discover this before or after this entry
|
# TODO: add sector type for this. What to do about sectors claimed by this file that are in use by another file? May discover this before or after this entry
|
||||||
print "Found deleted file %s" % entry.FileName()
|
print "Found deleted file %s" % entry.FileName()
|
||||||
break
|
break
|
||||||
fs = FileMetadataSector.fromSector(self.ReadSector(next_track, next_sector), entry.FileName())
|
try:
|
||||||
(next_track, next_sector) = (fs.next_track, fs.next_sector)
|
fs = FileMetadataSector.fromSector(self.ReadSector(next_track, next_sector), entry.FileName())
|
||||||
|
(next_track, next_sector) = (fs.next_track, fs.next_sector)
|
||||||
num_sectors = len(fs.data_track_sectors)
|
num_sectors = len(fs.data_track_sectors)
|
||||||
sector_list[fs.sector_offset:fs.sector_offset+num_sectors] = fs.data_track_sectors
|
sector_list[fs.sector_offset:fs.sector_offset + num_sectors] = fs.data_track_sectors
|
||||||
|
except disklib.IOError, e:
|
||||||
|
# TODO: add a flag indicating truncated file?
|
||||||
|
self.anomalies.append(
|
||||||
|
anomaly.Anomaly(
|
||||||
|
self, anomaly.CORRUPTION, 'File metadata sector out of bounds for file %s: %s' % (
|
||||||
|
entry.FileName(), e)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(next_track, next_sector) = (None, None)
|
||||||
|
|
||||||
# TODO: Assert we didn't have any holes. Or is this fine e.g. for a sparse text file?
|
# TODO: Assert we didn't have any holes. Or is this fine e.g. for a sparse text file?
|
||||||
|
|
||||||
#print track_sector_count
|
|
||||||
# We allocated space up-front for an unknown number of t/s list sectors, trim them from the end
|
# We allocated space up-front for an unknown number of t/s list sectors, trim them from the end
|
||||||
sector_list = sector_list[:entry.length - track_sector_count]
|
sector_list = sector_list[:entry.length - track_sector_count]
|
||||||
|
|
||||||
#print sector_list
|
|
||||||
contents = bitstring.BitString()
|
contents = bitstring.BitString()
|
||||||
for ts in sector_list:
|
for ts in sector_list:
|
||||||
if not ts:
|
if not ts:
|
||||||
@ -276,7 +289,12 @@ class Dos33Disk(disklib.Disk):
|
|||||||
try:
|
try:
|
||||||
fds = FileDataSector.fromSector(self.ReadSector(t, s), entry.FileName())
|
fds = FileDataSector.fromSector(self.ReadSector(t, s), entry.FileName())
|
||||||
except disklib.IOError, e:
|
except disklib.IOError, e:
|
||||||
print "%s: Failed to read File data sector: %s" % (entry, e)
|
self.anomalies.append(
|
||||||
|
anomaly.Anomaly(
|
||||||
|
self, anomaly.CORRUPTION, 'File data sector out of bounds for file %s: %s' % (
|
||||||
|
entry.FileName(), e)
|
||||||
|
)
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
contents.append(fds.data)
|
contents.append(fds.data)
|
||||||
|
|
||||||
@ -284,7 +302,7 @@ class Dos33Disk(disklib.Disk):
|
|||||||
self.AddChild(newfile)
|
self.AddChild(newfile)
|
||||||
return newfile
|
return newfile
|
||||||
|
|
||||||
def __str__(self):
|
def Catalog(self):
|
||||||
catalog = ['DISK VOLUME %d\n' % self.volume]
|
catalog = ['DISK VOLUME %d\n' % self.volume]
|
||||||
for filename in self.filenames:
|
for filename in self.filenames:
|
||||||
entry = self.catalog[filename]
|
entry = self.catalog[filename]
|
||||||
@ -298,6 +316,9 @@ class Dos33Disk(disklib.Disk):
|
|||||||
)
|
)
|
||||||
return '\n'.join(catalog)
|
return '\n'.join(catalog)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '%s (DOS 3.3 disk)' % (self.name)
|
||||||
|
|
||||||
|
|
||||||
class CatalogEntry(container.Container):
|
class CatalogEntry(container.Container):
|
||||||
def __init__(self, track, sector, file_type, file_name, length):
|
def __init__(self, track, sector, file_type, file_name, length):
|
||||||
|
@ -43,13 +43,13 @@ def main():
|
|||||||
print data
|
print data
|
||||||
|
|
||||||
|
|
||||||
# Group disks by hash of RWTS sector
|
# Group disks by hash of boot1 sector
|
||||||
rwts_hashes = {}
|
boot1_hashes = {}
|
||||||
for f, d in disks.iteritems():
|
for f, d in disks.iteritems():
|
||||||
rwts_hash = d.rwts.hash
|
boot1_hash = d.Boot1.hash
|
||||||
rwts_hashes.setdefault(rwts_hash, []).append(f)
|
boot1_hashes.setdefault(boot1_hash, []).append(f)
|
||||||
|
|
||||||
for h, disks in rwts_hashes.iteritems():
|
for h, disks in boot1_hashes.iteritems():
|
||||||
print h
|
print h
|
||||||
for d in sorted(disks):
|
for d in sorted(disks):
|
||||||
print " %s" % d
|
print " %s" % d
|
||||||
|
Loading…
Reference in New Issue
Block a user