88 lines
3.2 KiB
C++
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;
|
|
}
|
|
|
|
|
|
}
|