From ff91d1101a224ca992466e4019d32edf2548ca32 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Sun, 25 Feb 2024 15:59:22 +0100 Subject: [PATCH] isofs: fix long directory listing Directory entries can't cross a sector boundary, so reading must continue on the next one. Add list() method --- core/imgread/isofs.cpp | 102 +++++++++++++++++++++++++++++------------ core/imgread/isofs.h | 16 ++++--- 2 files changed, 82 insertions(+), 36 deletions(-) diff --git a/core/imgread/isofs.cpp b/core/imgread/isofs.cpp index d22ac3aff7..31119dba21 100644 --- a/core/imgread/isofs.cpp +++ b/core/imgread/isofs.cpp @@ -61,41 +61,69 @@ IsoFs::Directory *IsoFs::getRoot() return root; } -IsoFs::Entry *IsoFs::Directory::getEntry(const std::string& name) +void IsoFs::Directory::reset() { - std::string isoname = name + ';'; - for (u32 i = 0; i < data.size(); ) + index = 0; + if (data.empty() && len != 0) + { + data.resize(len); + fs->disc->ReadSectors(startFad, len / 2048, data.data(), 2048); + } +} + +IsoFs::Entry *IsoFs::Directory::nextEntry() +{ + if (index >= data.size()) + return nullptr; + const iso9660_dir_t *dir = (const iso9660_dir_t *)&data[index]; + if (dir->length == 0) { - const iso9660_dir_t *dir = (const iso9660_dir_t *)&data[i]; + if ((index & 2047) == 0) + return nullptr; + index = ((index + 2047) / 2048) * 2048; + if (index >= data.size()) + return nullptr; + dir = (const iso9660_dir_t *)&data[index]; if (dir->length == 0) - break; + return nullptr; + } + std::string name(dir->filename.str + 1, dir->filename.str[0]); - if ((u8)dir->filename.str[0] > isoname.size() - && memcmp(dir->filename.str + 1, isoname.c_str(), isoname.size()) == 0) - { - DEBUG_LOG(GDROM, "Found %s at offset %X", name.c_str(), i); - u32 startFad = decode_iso733(dir->extent) + 150; - u32 len = decode_iso733(dir->size); - if ((dir->file_flags & ISO_DIRECTORY) == 0) - { - File *file = new File(fs); - file->startFad = startFad; - file->len = len; - - return file; - } - else - { - Directory *directory = new Directory(fs); - directory->data.resize(len); - fs->disc->ReadSectors(startFad, len / 2048, directory->data.data(), 2048); - - return directory; - } - } - i += dir->length; + u32 startFad = decode_iso733(dir->extent) + 150; + u32 len = decode_iso733(dir->size); + Entry *entry; + if ((dir->file_flags & ISO_DIRECTORY) == 0) + { + File *file = new File(fs); + entry = file; + } + else + { + Directory *directory = new Directory(fs); + len = ((len + 2047) / 2048) * 2048; + entry = directory; + } + entry->startFad = startFad; + entry->len = len; + entry->name = name; + index += dir->length; + + return entry; +} + +IsoFs::Entry *IsoFs::Directory::getEntry(const std::string& name) +{ + std::string isoname = name + ';'; + reset(); + while (true) + { + Entry *entry = nextEntry(); + if (entry == nullptr) + return nullptr; + if (entry->getName().substr(0, isoname.size()) == isoname) + return entry; + delete entry; } - return nullptr; } u32 IsoFs::File::read(u8 *buf, u32 size, u32 offset) const @@ -112,3 +140,17 @@ u32 IsoFs::File::read(u8 *buf, u32 size, u32 offset) const } return sectors * 2048 + size; } + +std::vector IsoFs::Directory::list() +{ + std::vector v; + reset(); + while (true) + { + Entry *entry = nextEntry(); + if (entry == nullptr) + break; + v.push_back(entry); + } + return v; +} diff --git a/core/imgread/isofs.h b/core/imgread/isofs.h index 4d2944900f..8399618725 100644 --- a/core/imgread/isofs.h +++ b/core/imgread/isofs.h @@ -27,24 +27,33 @@ class IsoFs public: virtual bool isDirectory() const = 0; virtual ~Entry() = default; + const std::string& getName() const { return name; } protected: Entry(IsoFs *fs) : fs(fs) {} IsoFs *fs; + std::string name; + u32 startFad = 0; + u32 len = 0; + + friend class IsoFs; }; class Directory final : public Entry { public: bool isDirectory() const override { return true; } - Entry *getEntry(const std::string& name); + std::vector list(); private: Directory(IsoFs *fs) : Entry(fs) {} + void reset(); + Entry *nextEntry(); std::vector data; + u32 index = 0; friend class IsoFs; }; @@ -53,17 +62,12 @@ class IsoFs { public: bool isDirectory() const override { return false; } - u32 getSize() const { return len; } - u32 read(u8 *buf, u32 size, u32 offset = 0) const; private: File(IsoFs *fs) : Entry(fs) {} - u32 startFad = 0; - u32 len = 0; - friend class IsoFs; };