From 3c98331cf690a33859aa172a634d0554263a4583 Mon Sep 17 00:00:00 2001 From: Rob McMullen Date: Mon, 25 Mar 2019 16:32:54 -0700 Subject: [PATCH] Added file parsing in atari dos dirent --- atrcopy/filesystem.py | 6 ++++++ atrcopy/filesystems/atari_dos2.py | 32 ++++++++++++++++++++++++++++--- atrcopy/segment.py | 17 ++++++++-------- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/atrcopy/filesystem.py b/atrcopy/filesystem.py index 7722be3..e8fb6b6 100644 --- a/atrcopy/filesystem.py +++ b/atrcopy/filesystem.py @@ -91,6 +91,12 @@ class Filesystem: #### + @property + def max_file_size(self): + return len(self.media) + + #### + def iter_segments(self): if self.boot is not None: yield self.boot diff --git a/atrcopy/filesystems/atari_dos2.py b/atrcopy/filesystems/atari_dos2.py index 390ae92..f309a61 100644 --- a/atrcopy/filesystems/atari_dos2.py +++ b/atrcopy/filesystems/atari_dos2.py @@ -110,6 +110,7 @@ class AtariDosDirent(Dirent): ]) def __init__(self, filesystem, parent, file_num, start): + self.file_num = file_num Dirent.__init__(self, filesystem, parent, file_num, start, 16) self.flag = 0 self.opened_output = False @@ -124,10 +125,8 @@ class AtariDosDirent(Dirent): self.basename = b'' self.ext = b'' self.is_sane = True - self.current_sector = 0 - self.current_read = 0 - self.sectors_seen = None self.parse_raw_dirent() + self.get_file() def __str__(self): return "File #%-2d (%s) %03d %-8s%-3s %03d" % (self.file_num, self.summary, self.starting_sector, self.basename.decode("latin1"), self.ext.decode("latin1"), self.num_sectors) @@ -202,6 +201,33 @@ class AtariDosDirent(Dirent): self.deleted = True self._in_use = False + def get_file(self): + media = self.filesystem.media + offsets = np.empty(self.filesystem.max_file_size, dtype=np.uint32) + length = 0 + next_sector = self.starting_sector + sectors_seen = set() + + while next_sector > 0: + index, size = media.get_index_of_sector(next_sector) + num_bytes = media[index + size - 1] + file_num = media[index + size - 3] >> 2 + if file_num != self.file_num: + raise errors.FileNumberMismatchError164(f"Expecting file {self.file_num}, found {file_num}") + sectors_seen.add(next_sector) + + offsets[length:length + num_bytes] = np.arange(index, index+num_bytes) + length += num_bytes + + next_sector = ((media[index + size - 3] & 0x3) << 8) + media[index + size - 2] + if next_sector in sectors_seen: + raise errors.InvalidFile(f"Bad sector pointer data: attempting to reread sector {next_sector}") + + offsets = np.copy(offsets[0:length]) + file_segment = Segment(media, offsets, name=self.filename) + self.segments = [file_segment] + return file_segment + def update_sector_info(self, sector_list): self.num_sectors = sector_list.num_sectors self.starting_sector = sector_list.first_sector diff --git a/atrcopy/segment.py b/atrcopy/segment.py index 300d097..9f621d8 100644 --- a/atrcopy/segment.py +++ b/atrcopy/segment.py @@ -202,14 +202,13 @@ class Segment: @property def verbose_info(self): + lines = [] name = self.verbose_name or self.name - if self.rawdata.is_indexed: - s = "%s ($%04x bytes) non-contiguous file; file index of first byte: $%04x" % (name, len(self), self.rawdata.order[0]) - else: - s = "%s ($%04x bytes)" % (name, len(self)) - if self.error: - s += " error='%s'" % self.error - return s + lines.append(f"{name}: {len(self)} bytes") + for s in self.segments: + v = s.segment_info(" ") + lines.extend(v) + return "\n".join(lines) def segment_info(self, indent=""): lines = [] @@ -423,8 +422,8 @@ class Segment: return comments def set_comment_at(self, index, text): - rawindex = self.get_raw_index(index) - self.rawdata.extra.comments[rawindex] = text + rawindex = self.container_offset[index] + self.container.comments[rawindex] = text def set_comment(self, ranges, text): self.set_style_ranges(ranges, comment=True)