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
This commit is contained in:
Billy Laws 2020-06-19 21:00:28 +01:00 committed by ◱ PixelyIon
parent 4d787c904e
commit 5c103ce9a6
5 changed files with 133 additions and 0 deletions

View File

@ -94,6 +94,7 @@ add_library(skyline SHARED
${source_DIR}/skyline/services/visrv/IManagerDisplayService.cpp ${source_DIR}/skyline/services/visrv/IManagerDisplayService.cpp
${source_DIR}/skyline/services/visrv/IManagerRootService.cpp ${source_DIR}/skyline/services/visrv/IManagerRootService.cpp
${source_DIR}/skyline/services/visrv/ISystemDisplayService.cpp ${source_DIR}/skyline/services/visrv/ISystemDisplayService.cpp
${source_DIR}/skyline/vfs/os_backing.cpp
) )
target_link_libraries(skyline vulkan android fmt tinyxml2 oboe) target_link_libraries(skyline vulkan android fmt tinyxml2 oboe)

View File

@ -0,0 +1,50 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <common.h>
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<typename T>
inline size_t Read(T *output, size_t offset = 0, size_t size = 0) {
return Read(reinterpret_cast<u8 *>(output), offset, size ? size : sizeof(T));
}
};
}

View File

@ -0,0 +1,27 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#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<size_t>(ret);
}
}

View File

@ -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);
};
}

View File

@ -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<vfs::Backing> 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<vfs::Backing> &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);
}
};
}