diff --git a/lib/vfs/acorndfs.cc b/lib/vfs/acorndfs.cc index 1f6b4af8..7ea03d0d 100644 --- a/lib/vfs/acorndfs.cc +++ b/lib/vfs/acorndfs.cc @@ -1,9 +1,7 @@ #include "lib/globals.h" #include "lib/vfs/vfs.h" -#include "lib/sector.h" -#include "lib/image.h" -#include "lib/sectorinterface.h" #include "lib/config.pb.h" +#include class AcornDfsDirent : public Dirent { @@ -38,13 +36,11 @@ class AcornDfsFilesystem : public Filesystem public: AcornDfsFilesystem( const AcornDfsProto& config, std::shared_ptr sectors): - _config(config), - _sectors(sectors) + Filesystem(sectors), + _config(config) { } - void create() {} - FilesystemStatus check() { return FS_OK; @@ -83,8 +79,8 @@ private: std::vector> findAllFiles() { std::vector> result; - auto sector0 = getSector(0); - auto sector1 = getSector(1); + auto sector0 = getLogicalSector(0); + auto sector1 = getLogicalSector(1); if (sector1[5] & 7) throw BadFilesystemException(); @@ -115,23 +111,8 @@ private: throw FileNotFoundException(); } - Bytes getSector(uint32_t block) - { - uint32_t track = block / _config.sectors_per_track(); - uint32_t sector = block % _config.sectors_per_track(); - return _sectors->get(track, 0, sector)->data; - } - - void putSector(uint32_t block, const Bytes& bytes) - { - uint32_t track = block / _config.sectors_per_track(); - uint32_t sector = block % _config.sectors_per_track(); - _sectors->put(track, 0, sector)->data = bytes; - } - private: const AcornDfsProto& _config; - std::shared_ptr _sectors; }; std::unique_ptr Filesystem::createAcornDfsFilesystem( diff --git a/lib/vfs/brother120fs.cc b/lib/vfs/brother120fs.cc index f0813ed6..68108629 100644 --- a/lib/vfs/brother120fs.cc +++ b/lib/vfs/brother120fs.cc @@ -1,9 +1,7 @@ #include "lib/globals.h" #include "lib/vfs/vfs.h" -#include "lib/sector.h" -#include "lib/image.h" -#include "lib/sectorinterface.h" #include "lib/config.pb.h" +#include /* Number of sectors on a 120kB disk. */ static constexpr int SECTOR_COUNT = 468; @@ -47,13 +45,11 @@ class Brother120Filesystem : public Filesystem public: Brother120Filesystem( const Brother120FsProto& config, std::shared_ptr sectors): - _config(config), - _sectors(sectors) + Filesystem(sectors), + _config(config) { } - void create() {} - FilesystemStatus check() { return FS_OK; @@ -93,7 +89,7 @@ private: int inode = 0; for (int block = 0; block < DIRECTORY_SECTORS; block++) { - auto bytes = getSector(block); + auto bytes = getLogicalSector(block); for (int d = 0; d < SECTOR_SIZE/16; d++, inode++) { Bytes buffer = bytes.slice(d*16, 16); @@ -108,7 +104,6 @@ private: return result; } - std::unique_ptr findFile(const Path& path) { if (path.size() != 1) @@ -123,23 +118,8 @@ private: throw FileNotFoundException(); } - Bytes getSector(uint32_t block) - { - uint32_t track = block / 12; - uint32_t sector = block % 12; - return _sectors->get(track, 0, sector)->data; - } - - void putSector(uint32_t block, const Bytes& bytes) - { - uint32_t track = block / 12; - uint32_t sector = block % 12; - _sectors->put(track, 0, sector)->data = bytes; - } - private: const Brother120FsProto& _config; - std::shared_ptr _sectors; }; std::unique_ptr Filesystem::createBrother120Filesystem( diff --git a/lib/vfs/vfs.cc b/lib/vfs/vfs.cc index 84e84090..f618fcb2 100644 --- a/lib/vfs/vfs.cc +++ b/lib/vfs/vfs.cc @@ -1,5 +1,11 @@ #include "globals.h" #include "vfs.h" +#include "lib/proto.h" +#include "lib/layout.pb.h" +#include "lib/imginputoutpututils.h" +#include "lib/image.h" +#include "lib/sector.h" +#include "lib/sectorinterface.h" #include "lib/config.pb.h" Path::Path(const std::string& path) @@ -21,6 +27,30 @@ Path::Path(const std::string& path) } } +Filesystem::Filesystem(std::shared_ptr sectors): + _sectors(sectors) +{ + auto& layout = config.layout(); + + if (!layout.has_tracks() || !layout.has_sides()) + Error() << "filesystem support cannot be used without concrete layout information"; + + unsigned block = 0; + for (const auto& p : getTrackOrdering(layout, layout.tracks(), layout.sides())) + { + int track = p.first; + int side = p.second; + + auto trackdata = getTrackFormat(layout, track, side); + auto sectors = getTrackSectors(trackdata); + if (sectors.empty()) + Error() << "filesystem support cannot be used without concrete layout information"; + + for (int sectorId : sectors) + _locations.push_back(std::make_tuple(track, side, sectorId)); + } +} + std::unique_ptr Filesystem::createFilesystem( const FilesystemProto& config, std::shared_ptr image) { @@ -38,3 +68,21 @@ std::unique_ptr Filesystem::createFilesystem( } } +Bytes Filesystem::getLogicalSector(uint32_t number) +{ + if (number >= _locations.size()) + throw BadFilesystemException(); + + auto& i = _locations[number]; + return _sectors->get(std::get<0>(i), std::get<1>(i), std::get<2>(i))->data; +} + +void Filesystem::putLogicalSector(uint32_t number, const Bytes& data) +{ + if (number >= _locations.size()) + throw BadFilesystemException(); + + auto& i = _locations[number]; + _sectors->put(std::get<0>(i), std::get<1>(i), std::get<2>(i))->data = data; +} + diff --git a/lib/vfs/vfs.h b/lib/vfs/vfs.h index 0d2594d5..8e9fc87e 100644 --- a/lib/vfs/vfs.h +++ b/lib/vfs/vfs.h @@ -32,7 +32,7 @@ enum FilesystemStatus FS_BAD }; -class FilesystemException {}; +class FilesystemException : public ErrorException {}; class BadPathException : public FilesystemException {}; class FileNotFoundException : public FilesystemException {}; class BadFilesystemException : public FilesystemException {}; @@ -70,6 +70,17 @@ public: virtual void setMetadata(const Path& path, const std::map& metadata) { throw UnimplementedFilesystemException(); } +protected: + Filesystem(std::shared_ptr sectors); + + Bytes getLogicalSector(uint32_t number); + void putLogicalSector(uint32_t number, const Bytes& data); + +private: + typedef std::tuple location_t; + std::vector _locations; + std::shared_ptr _sectors; + public: static std::unique_ptr createBrother120Filesystem( const FilesystemProto& config, std::shared_ptr image); diff --git a/lib/vfs/vfs.proto b/lib/vfs/vfs.proto index b6b53fe1..4c327588 100644 --- a/lib/vfs/vfs.proto +++ b/lib/vfs/vfs.proto @@ -9,7 +9,6 @@ message AcornDfsProto { } optional Flavour flavour = 1 [default = ACORN_DFS, (help) = "which flavour of DFS to implement"]; - optional int32 sectors_per_track = 2 [default = 10, (help) = "number of sectors per filesystem track"]; } message Brother120FsProto {