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"]
|
[submodule "external/wit"]
|
||||||
path = external/wit
|
path = external/wit
|
||||||
url = https://git.faraphel.fr/Atlas/library-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)
|
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 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
|
||||||
# find_package(Qt6 REQUIRED COMPONENTS
|
|
||||||
# Core
|
|
||||||
# Gui
|
|
||||||
# Widgets
|
|
||||||
# )
|
|
||||||
add_executable(Atlas-Launcher
|
add_executable(Atlas-Launcher
|
||||||
source/main.cpp
|
source/main.cpp
|
||||||
|
|
||||||
|
@ -31,17 +22,12 @@ target_include_directories(Atlas-Launcher PRIVATE
|
||||||
target_link_libraries(Atlas-Launcher PRIVATE
|
target_link_libraries(Atlas-Launcher PRIVATE
|
||||||
# Libraries
|
# Libraries
|
||||||
angelscript
|
angelscript
|
||||||
|
vfspp
|
||||||
|
|
||||||
# Tools
|
# Tools
|
||||||
VFS
|
# SZS
|
||||||
SZS
|
|
||||||
|
|
||||||
# Qt Framework
|
|
||||||
# Qt::Core
|
|
||||||
# Qt::Gui
|
|
||||||
# Qt::Widgets
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(external/angelscript/angelscript/projects/cmake)
|
add_subdirectory(external/angelscript/angelscript/projects/cmake)
|
||||||
add_subdirectory(external/vfs)
|
add_subdirectory(external/vfspp)
|
||||||
add_subdirectory(external/szs)
|
# add_subdirectory(external/szs)
|
||||||
|
|
|
@ -8,4 +8,6 @@ Mario Kart Wii mods launcher
|
||||||
|
|
||||||
AngelScript - The C/C++ like sandboxed script language allowing for the
|
AngelScript - The C/C++ like sandboxed script language allowing for the
|
||||||
mods developer to write efficient and low-level code that can be trusted
|
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 <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "angelscript.h"
|
#include <vfspp/VirtualFileSystem.hpp>
|
||||||
#include "scriptstdstring/scriptstdstring.h"
|
#include <vfspp/MemoryFileSystem.hpp>
|
||||||
#include "scriptbuilder/scriptbuilder.h"
|
#include <angelscript.h>
|
||||||
|
#include <scriptstdstring/scriptstdstring.h>
|
||||||
|
#include <scriptbuilder/scriptbuilder.h>
|
||||||
|
|
||||||
|
|
||||||
void print(const std::string& in) {
|
void print(const std::string& in) {
|
||||||
|
@ -14,6 +16,13 @@ void print(const std::string& in) {
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
int error;
|
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
|
// engine
|
||||||
asIScriptEngine* engine = asCreateScriptEngine();
|
asIScriptEngine* engine = asCreateScriptEngine();
|
||||||
if (engine == nullptr)
|
if (engine == nullptr)
|
||||||
|
|
Loading…
Reference in a new issue