Atlas-Launcher/external/vfs/source/VirtualFileSystem.cpp

88 lines
3.2 KiB
C++

#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;
}
}