From 5c103ce9a639c0e42c1c85585861fa5ecbcadef3 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Fri, 19 Jun 2020 21:00:28 +0100 Subject: [PATCH] Introduce basic VFS backing system together with two implementations - The backing system provides a flexible way to access a a region of abstract memory. - It is currently barebones and only has support for reading data but this will be expanded as necessary. The current implementations are: - OsBacking - A backing that abstracts a linux file descriptor - RegionBacking - A backing that creates a region from a portion of an existing one --- app/CMakeLists.txt | 1 + app/src/main/cpp/skyline/vfs/backing.h | 50 +++++++++++++++++++ app/src/main/cpp/skyline/vfs/os_backing.cpp | 27 ++++++++++ app/src/main/cpp/skyline/vfs/os_backing.h | 24 +++++++++ app/src/main/cpp/skyline/vfs/region_backing.h | 31 ++++++++++++ 5 files changed, 133 insertions(+) create mode 100644 app/src/main/cpp/skyline/vfs/backing.h create mode 100644 app/src/main/cpp/skyline/vfs/os_backing.cpp create mode 100644 app/src/main/cpp/skyline/vfs/os_backing.h create mode 100644 app/src/main/cpp/skyline/vfs/region_backing.h diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 280fb6a7..5f23c7bc 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -94,6 +94,7 @@ add_library(skyline SHARED ${source_DIR}/skyline/services/visrv/IManagerDisplayService.cpp ${source_DIR}/skyline/services/visrv/IManagerRootService.cpp ${source_DIR}/skyline/services/visrv/ISystemDisplayService.cpp + ${source_DIR}/skyline/vfs/os_backing.cpp ) target_link_libraries(skyline vulkan android fmt tinyxml2 oboe) diff --git a/app/src/main/cpp/skyline/vfs/backing.h b/app/src/main/cpp/skyline/vfs/backing.h new file mode 100644 index 00000000..1a96fa67 --- /dev/null +++ b/app/src/main/cpp/skyline/vfs/backing.h @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include + +namespace skyline::vfs { + /** + * @brief The Backing class represents an abstract region of memory + */ + class Backing { + public: + size_t size; //!< The size of the backing in bytes + + /** + * @param size The initial size of the backing + */ + Backing(size_t size = 0) : size(size) {} + + /* Delete the move constructor to prevent multiple instances of the same backing */ + Backing(const Backing &) = delete; + + Backing &operator=(const Backing &) = delete; + + virtual ~Backing() = default; + + /** + * @brief Read bytes from the backing at a particular offset to a buffer + * @param output The object to write to + * @param offset The offset to start reading from + * @param size The amount to read in bytes + * @return The amount of bytes read + */ + virtual size_t Read(u8 *output, size_t offset, size_t size) = 0; + + /** + * @brief Read bytes from the backing at a particular offset to a buffer (template version) + * @tparam T The type of object to write to + * @param output The object to write to + * @param offset The offset to start reading from + * @param size The amount to read in bytes + * @return The amount of bytes read + */ + template + inline size_t Read(T *output, size_t offset = 0, size_t size = 0) { + return Read(reinterpret_cast(output), offset, size ? size : sizeof(T)); + } + }; +} diff --git a/app/src/main/cpp/skyline/vfs/os_backing.cpp b/app/src/main/cpp/skyline/vfs/os_backing.cpp new file mode 100644 index 00000000..55a74e26 --- /dev/null +++ b/app/src/main/cpp/skyline/vfs/os_backing.cpp @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#include +#include +#include +#include "os_backing.h" + +namespace skyline::vfs { + OsBacking::OsBacking(int fd) : fd(fd) { + struct stat fileInfo; + + if (fstat(fd, &fileInfo)) + throw exception("Failed to stat fd: {}", strerror(errno)); + + size = fileInfo.st_size; + } + + size_t OsBacking::Read(u8 *output, size_t offset, size_t size) { + auto ret = pread64(fd, output, size, offset); + + if (ret < 0) + throw exception("Failed to read from fd: {}", strerror(errno)); + + return static_cast(ret); + } +} \ No newline at end of file diff --git a/app/src/main/cpp/skyline/vfs/os_backing.h b/app/src/main/cpp/skyline/vfs/os_backing.h new file mode 100644 index 00000000..7592bf82 --- /dev/null +++ b/app/src/main/cpp/skyline/vfs/os_backing.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include "backing.h" + +namespace skyline::vfs { + /** + * @brief The OsBacking class provides the backing abstractions for a physical linux file + */ + class OsBacking : public Backing { + private: + int fd; //!< An FD to the backing + + public: + /** + * @param fd The file descriptor of the backing + */ + OsBacking(int fd); + + size_t Read(u8 *output, size_t offset, size_t size); + }; +} \ No newline at end of file diff --git a/app/src/main/cpp/skyline/vfs/region_backing.h b/app/src/main/cpp/skyline/vfs/region_backing.h new file mode 100644 index 00000000..8e8c25c1 --- /dev/null +++ b/app/src/main/cpp/skyline/vfs/region_backing.h @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include "backing.h" + +namespace skyline::vfs { + /** + * @brief The RegionBacking class provides a way to create a new, smaller backing from a region of an existing backing + */ + class RegionBacking : public Backing { + private: + std::shared_ptr backing; //!< The parent backing + size_t offset; //!< The offset of the region in the parent backing + + public: + /** + * @param file The backing to create the RegionBacking from + * @param offset The offset of the region start within the parent backing + * @param size The size of the region in the parent backing + */ + RegionBacking(const std::shared_ptr &backing, size_t offset, size_t size) : Backing(size), backing(backing), offset(offset) {}; + + inline size_t Read(u8 *output, size_t offset, size_t size) { + size = std::min(offset + size, this->size) - offset; + + return backing->Read(output, this->offset + offset, size); + } + }; +} \ No newline at end of file