replaced my own vfs library by an external better vfs project
This commit is contained in:
parent
fa9d8b5d86
commit
a5b4723ac1
14 changed files with 23 additions and 274 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -7,3 +7,6 @@
|
|||
[submodule "external/wit"]
|
||||
path = external/wit
|
||||
url = https://git.faraphel.fr/Atlas/library-wit
|
||||
[submodule "external/vfspp"]
|
||||
path = external/vfspp
|
||||
url = https://github.com/nextgeniuspro/vfspp
|
||||
|
|
|
@ -2,19 +2,10 @@ cmake_minimum_required(VERSION 3.28)
|
|||
project(Atlas-Launcher LANGUAGES CXX)
|
||||
|
||||
|
||||
# set(CMAKE_AUTOMOC ON)
|
||||
# set(CMAKE_AUTOUIC ON)
|
||||
# set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
||||
# find_package(Qt6 REQUIRED COMPONENTS
|
||||
# Core
|
||||
# Gui
|
||||
# Widgets
|
||||
# )
|
||||
add_executable(Atlas-Launcher
|
||||
source/main.cpp
|
||||
|
||||
|
@ -31,17 +22,12 @@ target_include_directories(Atlas-Launcher PRIVATE
|
|||
target_link_libraries(Atlas-Launcher PRIVATE
|
||||
# Libraries
|
||||
angelscript
|
||||
vfspp
|
||||
|
||||
# Tools
|
||||
VFS
|
||||
SZS
|
||||
|
||||
# Qt Framework
|
||||
# Qt::Core
|
||||
# Qt::Gui
|
||||
# Qt::Widgets
|
||||
# SZS
|
||||
)
|
||||
|
||||
add_subdirectory(external/angelscript/angelscript/projects/cmake)
|
||||
add_subdirectory(external/vfs)
|
||||
add_subdirectory(external/szs)
|
||||
add_subdirectory(external/vfspp)
|
||||
# add_subdirectory(external/szs)
|
||||
|
|
|
@ -8,4 +8,6 @@ Mario Kart Wii mods launcher
|
|||
|
||||
AngelScript - The C/C++ like sandboxed script language allowing for the
|
||||
mods developer to write efficient and low-level code that can be trusted
|
||||
by a user.
|
||||
by a user.
|
||||
|
||||
vfspp - A C++ library that implement a virtual file system.
|
||||
|
|
18
external/vfs/CMakeLists.txt
vendored
18
external/vfs/CMakeLists.txt
vendored
|
@ -1,18 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.28)
|
||||
project(VFS LANGUAGES CXX)
|
||||
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
||||
add_library(VFS STATIC
|
||||
source/VirtualFileSystem.cpp
|
||||
source/exception/FileNotFoundException.cpp
|
||||
include/exception/FileNotFoundException.hpp
|
||||
)
|
||||
target_include_directories(VFS PUBLIC
|
||||
include/
|
||||
)
|
||||
|
||||
add_subdirectory(tests)
|
10
external/vfs/README.md
vendored
10
external/vfs/README.md
vendored
|
@ -1,10 +0,0 @@
|
|||
# Restricted Virtual File System
|
||||
This is a micro-library used to create a virtual file system to restrict access
|
||||
to the host file system while still being able to mount directories that can be accessed.
|
||||
|
||||
As of right now, this is an incredibly simple implementation of this system that
|
||||
work by mapping virtual directory path to a corresponding real directory path, replacing
|
||||
them while resolving the path and reject all others paths that have not been mounted
|
||||
to avoid access to other files.
|
||||
|
||||
It does not emulate a real file system nor allow control over permissions of the files.
|
49
external/vfs/include/VirtualFileSystem.hpp
vendored
49
external/vfs/include/VirtualFileSystem.hpp
vendored
|
@ -1,49 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
|
||||
namespace vfs {
|
||||
|
||||
/**
|
||||
* Represent a virtual file system.
|
||||
* Real directory can be mounted to safely interact with the real file system.
|
||||
*/
|
||||
class VirtualFileSystem {
|
||||
|
||||
public:
|
||||
explicit VirtualFileSystem();
|
||||
~VirtualFileSystem();
|
||||
|
||||
std::filesystem::path getWorkingDirectory() const;
|
||||
|
||||
void setWorkingDirectory(const std::filesystem::path& virtualPath);
|
||||
|
||||
/**
|
||||
* Mount a real directory into the virtual file system
|
||||
* @param sourcePath the path to the directory in the real file system
|
||||
* @param virtualDestinationPath the path to the directory in the virtual file system
|
||||
*/
|
||||
void mount(const std::filesystem::path& sourcePath, const std::filesystem::path& virtualDestinationPath) const;
|
||||
|
||||
/**
|
||||
* Unmount a directory from the virtual file system
|
||||
* @param virtualPath the path to the directory in the virtual file system
|
||||
*/
|
||||
void unmount(const std::filesystem::path& virtualPath) const;
|
||||
|
||||
/**
|
||||
* Get the real path on the host file system from its virtual path
|
||||
* @param virtualPath the virtual path
|
||||
* @return the real path
|
||||
*/
|
||||
std::filesystem::path resolve(const std::filesystem::path& virtualPath) const;
|
||||
|
||||
private:
|
||||
/// the internal temporary directory
|
||||
std::filesystem::path rootDirectoryPath;
|
||||
/// the virtual current working directory. Always relative.
|
||||
std::filesystem::path virtualWorkingDirectory;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
#include <filesystem>
|
||||
|
||||
|
||||
namespace vfs::exception {
|
||||
|
||||
class FileNotFoundException final : public std::runtime_error {
|
||||
public:
|
||||
explicit FileNotFoundException(const std::filesystem::path& path);
|
||||
};
|
||||
|
||||
}
|
88
external/vfs/source/VirtualFileSystem.cpp
vendored
88
external/vfs/source/VirtualFileSystem.cpp
vendored
|
@ -1,88 +0,0 @@
|
|||
#include "VirtualFileSystem.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "exception/FileNotFoundException.hpp"
|
||||
|
||||
|
||||
namespace vfs {
|
||||
|
||||
VirtualFileSystem::VirtualFileSystem() {
|
||||
// create the temporary directory
|
||||
char temporaryDirectoryPathTemplate[] = "/tmp/vfs-XXXXXX";
|
||||
const char* temporaryDirectoryPath = mkdtemp(temporaryDirectoryPathTemplate);
|
||||
// check for any issue while creating the directory
|
||||
if (temporaryDirectoryPath == nullptr)
|
||||
throw std::runtime_error("Could not create a temporary directory for the virtual file system.");
|
||||
|
||||
// store it as a standard path
|
||||
this->rootDirectoryPath = std::filesystem::path(temporaryDirectoryPath);
|
||||
|
||||
// set the virtual working directory at the root
|
||||
this->setWorkingDirectory("./");
|
||||
}
|
||||
|
||||
VirtualFileSystem::~VirtualFileSystem() {
|
||||
// delete everything in the temporary directory
|
||||
std::error_code error;
|
||||
remove_all(this->rootDirectoryPath, error);
|
||||
|
||||
// check for any error
|
||||
if (error)
|
||||
std::cerr << "Could not clean the VFS : " + error.message() << std::endl;
|
||||
}
|
||||
|
||||
std::filesystem::path VirtualFileSystem::getWorkingDirectory() const {
|
||||
return this->virtualWorkingDirectory;
|
||||
}
|
||||
|
||||
void VirtualFileSystem::setWorkingDirectory(const std::filesystem::path& virtualPath) {
|
||||
if (!virtualPath.is_relative())
|
||||
throw std::runtime_error("The working directory need to be a relative path (for the virtual file system root).");
|
||||
|
||||
// set the new working directory
|
||||
this->virtualWorkingDirectory = virtualPath;
|
||||
}
|
||||
|
||||
void VirtualFileSystem::mount(const std::filesystem::path& sourcePath, const std::filesystem::path& virtualDestinationPath) const {
|
||||
// create a symlink from the directory to our temporary directory
|
||||
const std::filesystem::path realDestinationPath = this->resolve(virtualDestinationPath);
|
||||
|
||||
// create a symlink to the directory to mount in our virtual file system directory
|
||||
std::error_code error;
|
||||
create_directory_symlink(absolute(sourcePath), realDestinationPath, error);
|
||||
// check for any error while creating the symlink
|
||||
if (error)
|
||||
throw std::runtime_error("Could not mount the directory in the virtual file system. Reason: " + error.message());
|
||||
}
|
||||
|
||||
void VirtualFileSystem::unmount(const std::filesystem::path& virtualPath) const {
|
||||
// get the real path of the given virtual path
|
||||
const std::filesystem::path realPath = this->resolve(virtualPath);
|
||||
|
||||
// check if it is a symbolic link
|
||||
if (!is_symlink(realPath))
|
||||
throw std::runtime_error("Not a mounted directory !");
|
||||
|
||||
// delete the symlink
|
||||
remove(realPath);
|
||||
}
|
||||
|
||||
std::filesystem::path VirtualFileSystem::resolve(const std::filesystem::path& virtualPath) const {
|
||||
// normalize the path by solving the special symbols first.
|
||||
std::filesystem::path normalizedVirtualPath = virtualPath.lexically_normal();
|
||||
|
||||
if (virtualPath.is_relative()) {
|
||||
// if the path is relative, prepend the working directory
|
||||
normalizedVirtualPath = this->virtualWorkingDirectory / normalizedVirtualPath;
|
||||
} else {
|
||||
// convert it into a relative path for the root
|
||||
normalizedVirtualPath = relative(normalizedVirtualPath.lexically_normal(), "/");
|
||||
}
|
||||
|
||||
// get the real path by prepending the real root directory path
|
||||
return this->rootDirectoryPath / normalizedVirtualPath;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#include "exception/FileNotFoundException.hpp"
|
||||
|
||||
|
||||
namespace vfs::exception {
|
||||
|
||||
FileNotFoundException::FileNotFoundException(const std::filesystem::path& path) :
|
||||
std::runtime_error("Could not find the file : " + path.string()) {}
|
||||
|
||||
}
|
25
external/vfs/tests/CMakeLists.txt
vendored
25
external/vfs/tests/CMakeLists.txt
vendored
|
@ -1,25 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.28)
|
||||
project(Test-VFS LANGUAGES CXX)
|
||||
|
||||
|
||||
enable_testing()
|
||||
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
||||
# Test executable
|
||||
add_executable(Test-VFS
|
||||
test-restriction.cpp
|
||||
)
|
||||
# Libraries
|
||||
target_link_libraries(Test-VFS PRIVATE
|
||||
# Code to test
|
||||
VFS
|
||||
)
|
||||
# Copy the assets to run the tests
|
||||
file(COPY _assets DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# Test
|
||||
add_test(NAME Test-VFS COMMAND Test-VFS)
|
1
external/vfs/tests/_assets/content.txt
vendored
1
external/vfs/tests/_assets/content.txt
vendored
|
@ -1 +0,0 @@
|
|||
This is a simple text file.
|
38
external/vfs/tests/test-restriction.cpp
vendored
38
external/vfs/tests/test-restriction.cpp
vendored
|
@ -1,38 +0,0 @@
|
|||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <VirtualFileSystem.hpp>
|
||||
|
||||
int main() {
|
||||
// TODO(Faraphel): use a real unit test framework ?
|
||||
|
||||
// create a basic virtual file system
|
||||
vfs::VirtualFileSystem fs;
|
||||
|
||||
// mount a directory into our system
|
||||
fs.mount("_assets", "/assets");
|
||||
|
||||
// TEST: check if a file outside of an allowed mounted directory can't be resolved
|
||||
try {
|
||||
const std::filesystem::path path = fs.resolve("/content.txt");
|
||||
throw std::runtime_error("[Test 1] - Impossible path should not be resolved !");
|
||||
} catch (const std::runtime_error& exception) {}
|
||||
|
||||
// TEST: check if a file in a mounted directory can be resolved
|
||||
try {
|
||||
const std::filesystem::path path = fs.resolve("/assets/content.txt");
|
||||
|
||||
// auto file = QFile(path);
|
||||
// file.open(QIODeviceBase::Text | QIODevice::ReadOnly);
|
||||
// std::cout << file.readAll().toStdString() << std::endl;
|
||||
|
||||
} catch (const std::runtime_error& exception) {
|
||||
throw std::runtime_error("[Test 2] - Path could not be accessed !");
|
||||
}
|
||||
|
||||
// TEST: cannot bypass security with the ".." parent directory syntax
|
||||
try {
|
||||
// const std::filesystem::path path = fs.resolve("/assets/../content.txt");
|
||||
// throw std::runtime_error("[Test 3] - Resolved impossible path");
|
||||
} catch (const std::runtime_error& exception) {
|
||||
}
|
||||
}
|
1
external/vfspp
vendored
Submodule
1
external/vfspp
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit f22a0b23827e0ff3faa8379dc0bad450db9ac17a
|
|
@ -1,9 +1,11 @@
|
|||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include "angelscript.h"
|
||||
#include "scriptstdstring/scriptstdstring.h"
|
||||
#include "scriptbuilder/scriptbuilder.h"
|
||||
#include <vfspp/VirtualFileSystem.hpp>
|
||||
#include <vfspp/MemoryFileSystem.hpp>
|
||||
#include <angelscript.h>
|
||||
#include <scriptstdstring/scriptstdstring.h>
|
||||
#include <scriptbuilder/scriptbuilder.h>
|
||||
|
||||
|
||||
void print(const std::string& in) {
|
||||
|
@ -14,6 +16,13 @@ void print(const std::string& in) {
|
|||
int main(int argc, char* argv[]) {
|
||||
int error;
|
||||
|
||||
// prepare a virtual file system
|
||||
auto fileSystem = std::make_unique<vfspp::VirtualFileSystem>();
|
||||
|
||||
auto fileSystemTmp = std::make_shared<vfspp::MemoryFileSystem>();
|
||||
fileSystemTmp->Initialize();
|
||||
fileSystem->AddFileSystem("/tmp", fileSystemTmp);
|
||||
|
||||
// engine
|
||||
asIScriptEngine* engine = asCreateScriptEngine();
|
||||
if (engine == nullptr)
|
||||
|
|
Loading…
Reference in a new issue