mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-23 13:51:49 +01:00
Split VFS implementations from API
This allows better validation and simplified default argument handling. Could also be useful in the future when we switch to proper VFS error reporting.
This commit is contained in:
parent
48acb6d369
commit
5f942e2dff
@ -10,6 +10,17 @@ namespace skyline::vfs {
|
|||||||
* @brief The Backing class provides abstract access to a storage device, all access can be done without using a specific backing
|
* @brief The Backing class provides abstract access to a storage device, all access can be done without using a specific backing
|
||||||
*/
|
*/
|
||||||
class Backing {
|
class Backing {
|
||||||
|
protected:
|
||||||
|
virtual size_t ReadImpl(span <u8> output, size_t offset) = 0;
|
||||||
|
|
||||||
|
virtual size_t WriteImpl(span <u8> input, size_t offset) {
|
||||||
|
throw exception("This backing does not support being written to");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void ResizeImpl(size_t pSize) {
|
||||||
|
throw exception("This backing does not support being resized");
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
union Mode {
|
union Mode {
|
||||||
struct {
|
struct {
|
||||||
@ -42,7 +53,15 @@ namespace skyline::vfs {
|
|||||||
* @param offset The offset to start reading from
|
* @param offset The offset to start reading from
|
||||||
* @return The amount of bytes read
|
* @return The amount of bytes read
|
||||||
*/
|
*/
|
||||||
virtual size_t Read(span <u8> output, size_t offset = 0) = 0;
|
size_t Read(span <u8> output, size_t offset = 0) {
|
||||||
|
if (!mode.read)
|
||||||
|
throw exception("Attempting to read a backing that is not readable");
|
||||||
|
|
||||||
|
if ((static_cast<ssize_t>(size) - offset) < output.size())
|
||||||
|
throw exception("Trying to read past the end of a backing: 0x{:X}/0x{:X} (Offset: 0x{:X})", output.size(), size, offset);
|
||||||
|
|
||||||
|
return ReadImpl(output, offset);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implicit casting for reading into spans of different types
|
* @brief Implicit casting for reading into spans of different types
|
||||||
@ -70,8 +89,18 @@ namespace skyline::vfs {
|
|||||||
* @param offset The offset where the input buffer should be written
|
* @param offset The offset where the input buffer should be written
|
||||||
* @return The amount of bytes written
|
* @return The amount of bytes written
|
||||||
*/
|
*/
|
||||||
virtual size_t Write(span <u8> input, size_t offset = 0) {
|
size_t Write(span <u8> input, size_t offset = 0) {
|
||||||
throw exception("This backing does not support being written to");
|
if (!mode.write)
|
||||||
|
throw exception("Attempting to write to a backing that is not writable");
|
||||||
|
|
||||||
|
if (input.size() > (static_cast<ssize_t>(size) - offset)) {
|
||||||
|
if (mode.append)
|
||||||
|
Resize(offset + input.size());
|
||||||
|
else
|
||||||
|
throw exception("Trying to write past the end of a non-appendable backing: 0x{:X}/0x{:X} (Offset: 0x{:X})", input.size(), size, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return WriteImpl(input, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -81,17 +110,17 @@ namespace skyline::vfs {
|
|||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void WriteObject(const T &object, size_t offset = 0) {
|
void WriteObject(const T &object, size_t offset = 0) {
|
||||||
size_t size;
|
size_t lSize;
|
||||||
if ((size = Write(span(reinterpret_cast<u8 *>(&object), sizeof(T)), offset)) != sizeof(T))
|
if ((lSize = Write(span(reinterpret_cast<u8 *>(&object), sizeof(T)), offset)) != sizeof(T))
|
||||||
throw exception("Object wasn't written fully into output backing: {}/{}", size, sizeof(T));
|
throw exception("Object wasn't written fully into output backing: {}/{}", lSize, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Resizes a backing to the given size
|
* @brief Resizes a backing to the given size
|
||||||
* @param size The new size for the backing
|
* @param pSize The new size for the backing
|
||||||
*/
|
*/
|
||||||
virtual void Resize(size_t size) {
|
void Resize(size_t pSize) {
|
||||||
throw exception("This backing does not support being resized");
|
ResizeImpl(pSize);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,10 @@
|
|||||||
namespace skyline::vfs {
|
namespace skyline::vfs {
|
||||||
constexpr size_t SectorSize{0x10};
|
constexpr size_t SectorSize{0x10};
|
||||||
|
|
||||||
CtrEncryptedBacking::CtrEncryptedBacking(crypto::KeyStore::Key128 ctr, crypto::KeyStore::Key128 key, std::shared_ptr<Backing> backing, size_t baseOffset) : Backing({true, false, false}), ctr(ctr), cipher(key, MBEDTLS_CIPHER_AES_128_CTR), backing(std::move(backing)), baseOffset(baseOffset) {}
|
CtrEncryptedBacking::CtrEncryptedBacking(crypto::KeyStore::Key128 ctr, crypto::KeyStore::Key128 key, std::shared_ptr<Backing> backing, size_t baseOffset) : Backing({true, false, false}), ctr(ctr), cipher(key, MBEDTLS_CIPHER_AES_128_CTR), backing(std::move(backing)), baseOffset(baseOffset) {
|
||||||
|
if (mode.write || mode.append)
|
||||||
|
throw exception("Cannot open a CtrEncryptedBacking as writable");
|
||||||
|
}
|
||||||
|
|
||||||
void CtrEncryptedBacking::UpdateCtr(u64 offset) {
|
void CtrEncryptedBacking::UpdateCtr(u64 offset) {
|
||||||
offset >>= 4;
|
offset >>= 4;
|
||||||
@ -15,7 +18,7 @@ namespace skyline::vfs {
|
|||||||
cipher.SetIV(ctr);
|
cipher.SetIV(ctr);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CtrEncryptedBacking::Read(span<u8> output, size_t offset) {
|
size_t CtrEncryptedBacking::ReadImpl(span<u8> output, size_t offset) {
|
||||||
size_t size{output.size()};
|
size_t size{output.size()};
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -24,9 +24,10 @@ namespace skyline::vfs {
|
|||||||
*/
|
*/
|
||||||
void UpdateCtr(u64 offset);
|
void UpdateCtr(u64 offset);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
size_t ReadImpl(span<u8> output, size_t offset) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CtrEncryptedBacking(crypto::KeyStore::Key128 ctr, crypto::KeyStore::Key128 key, std::shared_ptr<Backing> backing, size_t baseOffset);
|
CtrEncryptedBacking(crypto::KeyStore::Key128 ctr, crypto::KeyStore::Key128 key, std::shared_ptr<Backing> backing, size_t baseOffset);
|
||||||
|
|
||||||
size_t Read(span<u8> output, size_t offset = 0) override;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,23 @@ namespace skyline::vfs {
|
|||||||
* @brief The FileSystem class represents an abstract filesystem with child files and folders
|
* @brief The FileSystem class represents an abstract filesystem with child files and folders
|
||||||
*/
|
*/
|
||||||
class FileSystem {
|
class FileSystem {
|
||||||
|
protected:
|
||||||
|
virtual bool CreateFileImpl(const std::string &path, size_t size) {
|
||||||
|
throw exception("This filesystem does not support creating files");
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual bool CreateDirectoryImpl(const std::string &path, bool parents) {
|
||||||
|
throw exception("This filesystem does not support creating directories");
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual std::shared_ptr<Backing> OpenFileImpl(const std::string &path, Backing::Mode mode) = 0;
|
||||||
|
|
||||||
|
virtual std::optional<Directory::EntryType> GetEntryTypeImpl(const std::string &path) = 0;
|
||||||
|
|
||||||
|
virtual std::shared_ptr<Directory> OpenDirectoryImpl(const std::string &path, Directory::ListMode listMode) {
|
||||||
|
throw exception("This filesystem does not support opening directories");
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileSystem() = default;
|
FileSystem() = default;
|
||||||
|
|
||||||
@ -27,8 +44,8 @@ namespace skyline::vfs {
|
|||||||
* @param size The size of the file to create
|
* @param size The size of the file to create
|
||||||
* @return Whether creating the file succeeded
|
* @return Whether creating the file succeeded
|
||||||
*/
|
*/
|
||||||
virtual bool CreateFile(const std::string &path, size_t size) {
|
bool CreateFile(const std::string &path, size_t size) {
|
||||||
throw exception("This filesystem does not support creating files");
|
return CreateFileImpl(path, size);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,8 +54,8 @@ namespace skyline::vfs {
|
|||||||
* @param parents Whether all parent directories in the given path should be created
|
* @param parents Whether all parent directories in the given path should be created
|
||||||
* @return Whether creating the directory succeeded
|
* @return Whether creating the directory succeeded
|
||||||
*/
|
*/
|
||||||
virtual bool CreateDirectory(const std::string &path, bool parents) {
|
bool CreateDirectory(const std::string &path, bool parents) {
|
||||||
throw exception("This filesystem does not support creating directories");
|
return CreateDirectoryImpl(path, parents);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,14 +64,21 @@ namespace skyline::vfs {
|
|||||||
* @param mode The mode to open the file with
|
* @param mode The mode to open the file with
|
||||||
* @return A shared pointer to a Backing object of the file
|
* @return A shared pointer to a Backing object of the file
|
||||||
*/
|
*/
|
||||||
virtual std::shared_ptr<Backing> OpenFile(const std::string &path, Backing::Mode mode = {true, false, false}) = 0;
|
std::shared_ptr<Backing> OpenFile(const std::string &path, Backing::Mode mode = {true, false, false}) {
|
||||||
|
if (!mode.write && !mode.read)
|
||||||
|
throw exception("Cannot open a file with a mode that is neither readable nor writable");
|
||||||
|
|
||||||
|
return OpenFileImpl(path, mode);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Queries the type of the entry given by path
|
* @brief Queries the type of the entry given by path
|
||||||
* @param path The path to the entry
|
* @param path The path to the entry
|
||||||
* @return The type of the entry, if present
|
* @return The type of the entry, if present
|
||||||
*/
|
*/
|
||||||
virtual std::optional<Directory::EntryType> GetEntryType(const std::string &path) = 0;
|
std::optional<Directory::EntryType> GetEntryType(const std::string &path) {
|
||||||
|
return GetEntryTypeImpl(path);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks if a given file exists in a filesystem
|
* @brief Checks if a given file exists in a filesystem
|
||||||
@ -82,8 +106,11 @@ namespace skyline::vfs {
|
|||||||
* @param listMode The list mode for the directory
|
* @param listMode The list mode for the directory
|
||||||
* @return A shared pointer to a Directory object of the directory
|
* @return A shared pointer to a Directory object of the directory
|
||||||
*/
|
*/
|
||||||
virtual std::shared_ptr<Directory> OpenDirectory(const std::string &path, Directory::ListMode listMode) {
|
std::shared_ptr<Directory> OpenDirectory(const std::string &path, Directory::ListMode listMode = {true, true}) {
|
||||||
throw exception("This filesystem does not support opening directories");
|
if (!listMode.raw)
|
||||||
|
throw exception("Cannot open a directory with an empty listMode");
|
||||||
|
|
||||||
|
return OpenDirectoryImpl(path, listMode);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,7 @@ namespace skyline::vfs {
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t OsBacking::Read(span<u8> output, size_t offset) {
|
size_t OsBacking::ReadImpl(span<u8> output, size_t offset) {
|
||||||
if (!mode.read)
|
|
||||||
throw exception("Attempting to read a backing that is not readable");
|
|
||||||
|
|
||||||
auto ret{pread64(fd, output.data(), output.size(), offset)};
|
auto ret{pread64(fd, output.data(), output.size(), offset)};
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
throw exception("Failed to read from fd: {}", strerror(errno));
|
throw exception("Failed to read from fd: {}", strerror(errno));
|
||||||
@ -31,10 +28,7 @@ namespace skyline::vfs {
|
|||||||
return static_cast<size_t>(ret);
|
return static_cast<size_t>(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t OsBacking::Write(span<u8> input, size_t offset) {
|
size_t OsBacking::WriteImpl(span<u8> input, size_t offset) {
|
||||||
if (!mode.write)
|
|
||||||
throw exception("Attempting to write to a backing that is not writable");
|
|
||||||
|
|
||||||
auto ret{pwrite64(fd, input.data(), input.size(), offset)};
|
auto ret{pwrite64(fd, input.data(), input.size(), offset)};
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
throw exception("Failed to write to fd: {}", strerror(errno));
|
throw exception("Failed to write to fd: {}", strerror(errno));
|
||||||
@ -42,7 +36,7 @@ namespace skyline::vfs {
|
|||||||
return static_cast<size_t>(ret);
|
return static_cast<size_t>(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OsBacking::Resize(size_t pSize) {
|
void OsBacking::ResizeImpl(size_t pSize) {
|
||||||
int ret{ftruncate(fd, pSize)};
|
int ret{ftruncate(fd, pSize)};
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
throw exception("Failed to resize file: {}", strerror(errno));
|
throw exception("Failed to resize file: {}", strerror(errno));
|
||||||
|
@ -14,6 +14,13 @@ namespace skyline::vfs {
|
|||||||
int fd; //!< An FD to the backing
|
int fd; //!< An FD to the backing
|
||||||
bool closable; //!< Whether the FD can be closed when the backing is destroyed
|
bool closable; //!< Whether the FD can be closed when the backing is destroyed
|
||||||
|
|
||||||
|
protected:
|
||||||
|
size_t ReadImpl(span<u8> output, size_t offset) override;
|
||||||
|
|
||||||
|
size_t WriteImpl(span<u8> input, size_t offset) override;
|
||||||
|
|
||||||
|
void ResizeImpl(size_t size) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @param fd The file descriptor of the backing
|
* @param fd The file descriptor of the backing
|
||||||
@ -21,11 +28,5 @@ namespace skyline::vfs {
|
|||||||
OsBacking(int fd, bool closable = false, Mode = {true, false, false});
|
OsBacking(int fd, bool closable = false, Mode = {true, false, false});
|
||||||
|
|
||||||
~OsBacking();
|
~OsBacking();
|
||||||
|
|
||||||
size_t Read(span<u8> output, size_t offset = 0);
|
|
||||||
|
|
||||||
size_t Write(span<u8> input, size_t offset = 0);
|
|
||||||
|
|
||||||
void Resize(size_t size);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ namespace skyline::vfs {
|
|||||||
throw exception("Error creating the OS filesystem backing directory");
|
throw exception("Error creating the OS filesystem backing directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OsFileSystem::CreateFile(const std::string &path, size_t size) {
|
bool OsFileSystem::CreateFileImpl(const std::string &path, size_t size) {
|
||||||
auto fullPath{basePath + path};
|
auto fullPath{basePath + path};
|
||||||
|
|
||||||
// Create a directory that will hold the file
|
// Create a directory that will hold the file
|
||||||
@ -38,7 +38,7 @@ namespace skyline::vfs {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OsFileSystem::CreateDirectory(const std::string &path, bool parents) {
|
bool OsFileSystem::CreateDirectoryImpl(const std::string &path, bool parents) {
|
||||||
if (!parents) {
|
if (!parents) {
|
||||||
int ret{mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)};
|
int ret{mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)};
|
||||||
return ret == 0 || errno == EEXIST;
|
return ret == 0 || errno == EEXIST;
|
||||||
@ -58,10 +58,7 @@ namespace skyline::vfs {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Backing> OsFileSystem::OpenFile(const std::string &path, Backing::Mode mode) {
|
std::shared_ptr<Backing> OsFileSystem::OpenFileImpl(const std::string &path, Backing::Mode mode) {
|
||||||
if (!(mode.read || mode.write))
|
|
||||||
throw exception("Cannot open a file that is neither readable or writable");
|
|
||||||
|
|
||||||
int fd{open((basePath + path).c_str(), (mode.read && mode.write) ? O_RDWR : (mode.write ? O_WRONLY : O_RDONLY))};
|
int fd{open((basePath + path).c_str(), (mode.read && mode.write) ? O_RDWR : (mode.write ? O_WRONLY : O_RDONLY))};
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
throw exception("Failed to open file at '{}': {}", path, strerror(errno));
|
throw exception("Failed to open file at '{}': {}", path, strerror(errno));
|
||||||
@ -69,7 +66,7 @@ namespace skyline::vfs {
|
|||||||
return std::make_shared<OsBacking>(fd, true, mode);
|
return std::make_shared<OsBacking>(fd, true, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Directory::EntryType> OsFileSystem::GetEntryType(const std::string &path) {
|
std::optional<Directory::EntryType> OsFileSystem::GetEntryTypeImpl(const std::string &path) {
|
||||||
auto fullPath{basePath + path};
|
auto fullPath{basePath + path};
|
||||||
|
|
||||||
auto directory{opendir(fullPath.c_str())};
|
auto directory{opendir(fullPath.c_str())};
|
||||||
@ -84,7 +81,7 @@ namespace skyline::vfs {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Directory> OsFileSystem::OpenDirectory(const std::string &path, Directory::ListMode listMode) {
|
std::shared_ptr<Directory> OsFileSystem::OpenDirectoryImpl(const std::string &path, Directory::ListMode listMode) {
|
||||||
return std::make_shared<OsFileSystemDirectory>(basePath + path, listMode);
|
return std::make_shared<OsFileSystemDirectory>(basePath + path, listMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,18 +13,19 @@ namespace skyline::vfs {
|
|||||||
private:
|
private:
|
||||||
std::string basePath; //!< The base path for filesystem operations
|
std::string basePath; //!< The base path for filesystem operations
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool CreateFileImpl(const std::string &path, size_t size) override;
|
||||||
|
|
||||||
|
bool CreateDirectoryImpl(const std::string &path, bool parents) override;
|
||||||
|
|
||||||
|
std::shared_ptr<Backing> OpenFileImpl(const std::string &path, Backing::Mode mode) override;
|
||||||
|
|
||||||
|
std::optional<Directory::EntryType> GetEntryTypeImpl(const std::string &path) override;
|
||||||
|
|
||||||
|
std::shared_ptr<Directory> OpenDirectoryImpl(const std::string &path, Directory::ListMode listMode) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OsFileSystem(const std::string &basePath);
|
OsFileSystem(const std::string &basePath);
|
||||||
|
|
||||||
bool CreateFile(const std::string &path, size_t size);
|
|
||||||
|
|
||||||
bool CreateDirectory(const std::string &path, bool parents);
|
|
||||||
|
|
||||||
std::shared_ptr<Backing> OpenFile(const std::string &path, Backing::Mode mode = {true, false, false});
|
|
||||||
|
|
||||||
std::optional<Directory::EntryType> GetEntryType(const std::string &path);
|
|
||||||
|
|
||||||
std::shared_ptr<Directory> OpenDirectory(const std::string &path, Directory::ListMode listMode);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,7 +31,7 @@ namespace skyline::vfs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Backing> PartitionFileSystem::OpenFile(const std::string &path, Backing::Mode mode) {
|
std::shared_ptr<Backing> PartitionFileSystem::OpenFileImpl(const std::string &path, Backing::Mode mode) {
|
||||||
try {
|
try {
|
||||||
auto &entry{fileMap.at(path)};
|
auto &entry{fileMap.at(path)};
|
||||||
return std::make_shared<RegionBacking>(backing, fileDataOffset + entry.offset, entry.size, mode);
|
return std::make_shared<RegionBacking>(backing, fileDataOffset + entry.offset, entry.size, mode);
|
||||||
@ -40,16 +40,16 @@ namespace skyline::vfs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Directory::EntryType> PartitionFileSystem::GetEntryType(const std::string &path) {
|
std::optional<Directory::EntryType> PartitionFileSystem::GetEntryTypeImpl(const std::string &path) {
|
||||||
if (fileMap.count(path))
|
if (fileMap.count(path))
|
||||||
return Directory::EntryType::File;
|
return Directory::EntryType::File;
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Directory> PartitionFileSystem::OpenDirectory(const std::string &path, Directory::ListMode listMode) {
|
std::shared_ptr<Directory> PartitionFileSystem::OpenDirectoryImpl(const std::string &path, Directory::ListMode listMode) {
|
||||||
// PFS doesn't have directories
|
// PFS doesn't have directories
|
||||||
if (path != "")
|
if (!path.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
std::vector<Directory::Entry> fileList;
|
std::vector<Directory::Entry> fileList;
|
||||||
|
@ -39,14 +39,15 @@ namespace skyline::vfs {
|
|||||||
std::shared_ptr<Backing> backing; //!< The backing file of the filesystem
|
std::shared_ptr<Backing> backing; //!< The backing file of the filesystem
|
||||||
std::unordered_map<std::string, PartitionFileEntry> fileMap; //!< A map that maps file names to their corresponding entry
|
std::unordered_map<std::string, PartitionFileEntry> fileMap; //!< A map that maps file names to their corresponding entry
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<Backing> OpenFileImpl(const std::string &path, Backing::Mode mode) override;
|
||||||
|
|
||||||
|
std::optional<Directory::EntryType> GetEntryTypeImpl(const std::string &path) override;
|
||||||
|
|
||||||
|
std::shared_ptr<Directory> OpenDirectoryImpl(const std::string &path, Directory::ListMode listMode) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PartitionFileSystem(const std::shared_ptr<Backing> &backing);
|
PartitionFileSystem(const std::shared_ptr<Backing> &backing);
|
||||||
|
|
||||||
std::shared_ptr<Backing> OpenFile(const std::string &path, Backing::Mode mode = {true, false, false});
|
|
||||||
|
|
||||||
std::optional<Directory::EntryType> GetEntryType(const std::string &path);
|
|
||||||
|
|
||||||
std::shared_ptr<Directory> OpenDirectory(const std::string &path, Directory::ListMode listMode);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,20 +14,20 @@ namespace skyline::vfs {
|
|||||||
std::shared_ptr<vfs::Backing> backing; //!< The parent backing
|
std::shared_ptr<vfs::Backing> backing; //!< The parent backing
|
||||||
size_t baseOffset; //!< The offset of the region in the parent backing
|
size_t baseOffset; //!< The offset of the region in the parent backing
|
||||||
|
|
||||||
|
protected:
|
||||||
|
size_t ReadImpl(span <u8> output, size_t offset) override {
|
||||||
|
return backing->Read(output, baseOffset + offset);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @param file The backing to create the RegionBacking from
|
* @param file The backing to create the RegionBacking from
|
||||||
* @param offset The offset of the region start within the parent backing
|
* @param offset The offset of the region start within the parent backing
|
||||||
* @param size The size of the region in the parent backing
|
* @param size The size of the region in the parent backing
|
||||||
*/
|
*/
|
||||||
RegionBacking(const std::shared_ptr<vfs::Backing> &backing, size_t offset, size_t size, Mode mode = {true, false, false}) : Backing(mode, size), backing(backing), baseOffset(offset) {};
|
RegionBacking(const std::shared_ptr<vfs::Backing> &backing, size_t offset, size_t size, Mode mode = {true, false, false}) : Backing(mode, size), backing(backing), baseOffset(offset) {
|
||||||
|
if (mode.write || mode.append)
|
||||||
size_t Read(span <u8> output, size_t offset = 0) {
|
throw exception("Cannot open a RegionBacking as writable");
|
||||||
if (!mode.read)
|
};
|
||||||
throw exception("Attempting to read a backing that is not readable");
|
|
||||||
if (size - offset < output.size())
|
|
||||||
throw exception("Trying to read past the end of a region backing: 0x{:X}/0x{:X} (Offset: 0x{:X})", output.size(), size, offset);
|
|
||||||
return backing->Read(output, baseOffset + offset);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ namespace skyline::vfs {
|
|||||||
TraverseDirectory(entry.siblingOffset, path);
|
TraverseDirectory(entry.siblingOffset, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Backing> RomFileSystem::OpenFile(const std::string &path, Backing::Mode mode) {
|
std::shared_ptr<Backing> RomFileSystem::OpenFileImpl(const std::string &path, Backing::Mode mode) {
|
||||||
try {
|
try {
|
||||||
const auto &entry{fileMap.at(path)};
|
const auto &entry{fileMap.at(path)};
|
||||||
return std::make_shared<RegionBacking>(backing, header.dataOffset + entry.offset, entry.size, mode);
|
return std::make_shared<RegionBacking>(backing, header.dataOffset + entry.offset, entry.size, mode);
|
||||||
@ -58,7 +58,7 @@ namespace skyline::vfs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Directory::EntryType> RomFileSystem::GetEntryType(const std::string &path) {
|
std::optional<Directory::EntryType> RomFileSystem::GetEntryTypeImpl(const std::string &path) {
|
||||||
if (fileMap.count(path))
|
if (fileMap.count(path))
|
||||||
return Directory::EntryType::File;
|
return Directory::EntryType::File;
|
||||||
else if (directoryMap.count(path))
|
else if (directoryMap.count(path))
|
||||||
@ -67,7 +67,7 @@ namespace skyline::vfs {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Directory> RomFileSystem::OpenDirectory(const std::string &path, Directory::ListMode listMode) {
|
std::shared_ptr<Directory> RomFileSystem::OpenDirectoryImpl(const std::string &path, Directory::ListMode listMode) {
|
||||||
try {
|
try {
|
||||||
auto &entry{directoryMap.at(path)};
|
auto &entry{directoryMap.at(path)};
|
||||||
return std::make_shared<RomFileSystemDirectory>(backing, header, entry, listMode);
|
return std::make_shared<RomFileSystemDirectory>(backing, header, entry, listMode);
|
||||||
|
@ -32,6 +32,13 @@ namespace skyline {
|
|||||||
*/
|
*/
|
||||||
void TraverseDirectory(u32 offset, const std::string &path);
|
void TraverseDirectory(u32 offset, const std::string &path);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<Backing> OpenFileImpl(const std::string &path, Backing::Mode mode) override;
|
||||||
|
|
||||||
|
std::optional<Directory::EntryType> GetEntryTypeImpl(const std::string &path) override;
|
||||||
|
|
||||||
|
std::shared_ptr<Directory> OpenDirectoryImpl(const std::string &path, Directory::ListMode listMode) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct RomFsHeader {
|
struct RomFsHeader {
|
||||||
u64 headerSize; //!< The size of the header
|
u64 headerSize; //!< The size of the header
|
||||||
@ -69,12 +76,6 @@ namespace skyline {
|
|||||||
std::unordered_map<std::string, RomFsDirectoryEntry> directoryMap; //!< A map that maps directory names to their corresponding entry
|
std::unordered_map<std::string, RomFsDirectoryEntry> directoryMap; //!< A map that maps directory names to their corresponding entry
|
||||||
|
|
||||||
RomFileSystem(std::shared_ptr<Backing> backing);
|
RomFileSystem(std::shared_ptr<Backing> backing);
|
||||||
|
|
||||||
std::shared_ptr<Backing> OpenFile(const std::string &path, Backing::Mode mode = {true, false, false});
|
|
||||||
|
|
||||||
std::optional<Directory::EntryType> GetEntryType(const std::string &path);
|
|
||||||
|
|
||||||
std::shared_ptr<Directory> OpenDirectory(const std::string &path, Directory::ListMode listMode);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user