diff --git a/src/vfs.cc b/src/vfs.cc index 59a1f58..5e3d204 100644 --- a/src/vfs.cc +++ b/src/vfs.cc @@ -19,7 +19,8 @@ SetupState Container::setup(const std::wstring &filename) { if (!vd.validate()) { // Some "dual layer" ISO files will have both a video and game partition - constexpr static size_t sc_gamePartitionOffset = 2048 * 32 * 6192; + constexpr static size_t sc_gamePartitionOffset = + xdvdfs::SECTOR_SIZE * 32 * 6192; stream->m_offset = sc_gamePartitionOffset; @@ -82,7 +83,6 @@ Container::getFolderList(const std::filesystem::path &path) const { } void Container::build(xdvdfs::Stream &file, xdvdfs::FileEntry &dirent) { - // TODO consider std::filesystem::path::preferred_separator xdvdfs::FileEntry root("\\"); auto newHandle = registerFileEntry(root, sc_invalidHandle); @@ -96,17 +96,24 @@ void Container::buildFromTreeRecursive(xdvdfs::Stream &file, if (dirent.isDirectory()) { xdvdfs::FileEntry entry = dirent.getFirstEntry(file); - buildFromTreeRecursive(file, entry, newHandle); + if (entry.validate()) { + buildFromTreeRecursive(file, entry, newHandle); + } } if (dirent.hasLeftChild()) { xdvdfs::FileEntry entry = dirent.getLeftChild(file); - buildFromTreeRecursive(file, entry, parent); + + if (entry.validate()) { + buildFromTreeRecursive(file, entry, parent); + } } if (dirent.hasRightChild()) { xdvdfs::FileEntry entry = dirent.getRightChild(file); - buildFromTreeRecursive(file, entry, parent); + if (entry.validate()) { + buildFromTreeRecursive(file, entry, parent); + } } } diff --git a/src/xdvdfs.cc b/src/xdvdfs.cc index c1d21f2..d0fbce3 100644 --- a/src/xdvdfs.cc +++ b/src/xdvdfs.cc @@ -7,7 +7,28 @@ #include namespace xdvdfs { -bool VolumeDescriptor::validate() { +void VolumeDescriptor::readFromFile(Stream &file) { + std::vector buffer(SECTOR_SIZE); + + { + std::lock_guard lock(file.m_fileMutex); + + file.m_file.seekg(VOLUME_DESCRIPTOR_SECTOR * SECTOR_SIZE + file.m_offset, + std::ifstream::beg); + file.m_file.read(buffer.data(), buffer.size()); + } + + std::copy(buffer.begin(), buffer.begin() + 0x14, m_id1); + std::copy(buffer.begin() + 0x14, buffer.begin() + 0x18, + reinterpret_cast(&m_rootDirTableSector)); + std::copy(buffer.begin() + 0x18, buffer.begin() + 0x1C, + reinterpret_cast(&m_rootDirTableSize)); + std::copy(buffer.begin() + 0x1C, buffer.begin() + 0x24, + reinterpret_cast(&m_filetime)); + std::copy(buffer.begin() + 0x7EC, buffer.end(), m_id2); +} + +bool VolumeDescriptor::validate() const { if (std::memcmp(m_id1, MAGIC_ID, std::size(m_id1)) != 0) { return false; } @@ -23,48 +44,26 @@ bool VolumeDescriptor::validate() { return true; } -FileEntry::FileEntry(const FileEntry &other) - : m_leftSubTree(other.m_leftSubTree), m_rightSubTree(other.m_rightSubTree), - m_startSector(other.m_startSector), m_fileSize(other.m_fileSize), - m_attributes(other.m_attributes), m_filename(other.m_filename), - m_sectorNumber(other.m_sectorNumber) {} - -FileEntry::FileEntry(const std::string &name) - : m_leftSubTree(0), m_rightSubTree(0), m_startSector(0), m_fileSize(0), - m_attributes(FileEntry::FILE_DIRECTORY), m_filename(name), - m_sectorNumber(0) {} - -FileEntry VolumeDescriptor::getRootDirEntry(Stream &file) { +FileEntry VolumeDescriptor::getRootDirEntry(Stream &file) const { FileEntry dirent; dirent.readFromFile(file, m_rootDirTableSector, 0); return dirent; } +} // namespace xdvdfs -void VolumeDescriptor::readFromFile(Stream &file) { - std::vector buffer(SECTOR_SIZE); - - { - std::lock_guard lock(file.m_fileMutex); +namespace xdvdfs { - file.m_file.seekg(VOLUME_DESCRIPTOR_SECTOR * SECTOR_SIZE + file.m_offset, - std::ifstream::beg); - file.m_file.read(buffer.data(), buffer.size()); - } +FileEntry::FileEntry(const FileEntry &other) + : m_leftSubTree(other.m_leftSubTree), m_rightSubTree(other.m_rightSubTree), + m_startSector(other.m_startSector), m_fileSize(other.m_fileSize), + m_attributes(other.m_attributes), m_filename(other.m_filename), + m_sectorNumber(other.m_sectorNumber) {} - std::copy(buffer.begin(), buffer.begin() + 0x14, m_id1); - std::copy(buffer.begin() + 0x14, buffer.begin() + 0x18, - reinterpret_cast(&m_rootDirTableSector)); - std::copy(buffer.begin() + 0x18, buffer.begin() + 0x1C, - reinterpret_cast(&m_rootDirTableSize)); - std::copy(buffer.begin() + 0x1C, buffer.begin() + 0x24, - reinterpret_cast(&m_filetime)); - std::copy(buffer.begin() + 0x7EC, buffer.end(), m_id2); -} -} // namespace xdvdfs +FileEntry::FileEntry(const std::string &name) + : m_attributes(FileEntry::FILE_DIRECTORY), m_filename(name) {} -namespace xdvdfs { void FileEntry::readFromFile(Stream &file, std::streampos sector, std::streamoff offset) { std::vector buffer(SECTOR_SIZE); @@ -77,6 +76,8 @@ void FileEntry::readFromFile(Stream &file, std::streampos sector, file.m_file.read(buffer.data(), buffer.size()); } + m_sectorNumber = sector; + std::copy(buffer.begin(), buffer.begin() + 0x02, reinterpret_cast(&m_leftSubTree)); std::copy(buffer.begin() + 0x02, buffer.begin() + 0x04, @@ -88,10 +89,11 @@ void FileEntry::readFromFile(Stream &file, std::streampos sector, std::copy(buffer.begin() + 0x0C, buffer.begin() + 0x0D, reinterpret_cast(&m_attributes)); - size_t filenameLength = buffer[0x0D]; - m_filename = std::string(&buffer[0x0E], filenameLength); + if (validate()) { + size_t filenameLength{static_cast(buffer[0x0D])}; - m_sectorNumber = sector; + m_filename = std::string(&buffer[0x0E], filenameLength); + } } const std::string &FileEntry::getFilename() const { return m_filename; } @@ -128,6 +130,22 @@ uint32_t FileEntry::read(Stream &file, void *buffer, uint32_t bufferlength, return 0; } +bool FileEntry::validate() const { + if (m_leftSubTree == static_cast(-1)) { + return false; + } + + if (m_rightSubTree == static_cast(-1)) { + return false; + } + + if (m_startSector == static_cast(-1)) { + return false; + } + + return true; +} + bool FileEntry::isDirectory() const { return ((m_attributes & FileEntry::FILE_DIRECTORY) != 0); } diff --git a/src/xdvdfs.h b/src/xdvdfs.h index 69420e8..a6094f0 100644 --- a/src/xdvdfs.h +++ b/src/xdvdfs.h @@ -27,14 +27,17 @@ class FileEntry { FileEntry(const FileEntry &other); FileEntry(const std::string &name); - void readFromFile(Stream &file, std::streampos pos, std::streamoff offset); - const std::string &getFilename() const; - uint32_t getFileSize() const; + void readFromFile(Stream &file, std::streampos sector, std::streamoff offset); // matching dokany api for now uint32_t read(Stream &file, void *buffer, uint32_t bufferlength, int64_t offset) const; + bool validate() const; + + const std::string &getFilename() const; + uint32_t getFileSize() const; + uint8_t getAttributes() const { return m_attributes; } bool isDirectory() const; bool hasLeftChild() const; @@ -52,8 +55,8 @@ class FileEntry { static const uint8_t FILE_NORMAL = 0x80; private: - uint16_t m_leftSubTree{0}; - uint16_t m_rightSubTree{0}; + uint16_t m_leftSubTree{static_cast(-1)}; + uint16_t m_rightSubTree{static_cast(-1)}; uint32_t m_startSector{0}; uint32_t m_fileSize{0}; uint8_t m_attributes{0}; @@ -66,8 +69,9 @@ class VolumeDescriptor { public: void readFromFile(Stream &file); - bool validate(); - FileEntry getRootDirEntry(Stream &file); + bool validate() const; + + FileEntry getRootDirEntry(Stream &file) const; uint64_t getCreationTime() const { return m_filetime; } protected: