add file.mount(...) and file.unmount(...)

This commit is contained in:
MihailRis 2025-03-17 23:01:44 +03:00
parent 6286096b57
commit e8153f3393
4 changed files with 68 additions and 10 deletions

View File

@ -10,9 +10,24 @@
#include <utility>
#include "io/devices/StdfsDevice.hpp"
#include "io/devices/ZipFileDevice.hpp"
#include "world/files/WorldFiles.hpp"
#include "debug/Logger.hpp"
#include <chrono>
#include "maths/util.hpp"
template<int n>
static std::string generate_random_base64() {
auto now = std::chrono::high_resolution_clock::now();
auto seed = now.time_since_epoch().count();
util::PseudoRandom random(seed); // fixme: replace with safe random
ubyte bytes[n];
random.rand(bytes, n);
return util::base64_urlsafe_encode(bytes, n);
}
namespace fs = std::filesystem;
static debug::Logger logger("engine-paths");
@ -150,8 +165,32 @@ void EnginePaths::setCurrentWorldFolder(io::path folder) {
io::create_subdevice("world", "user", currentWorldFolder);
}
#include <chrono>
#include "maths/util.hpp"
std::string EnginePaths::mount(const io::path& file) {
if (file.extension() == ".zip") {
auto stream = io::read(file);
auto device = std::make_unique<io::ZipFileDevice>(
std::move(stream), [file]() { return io::read(file); }
);
std::string name;
do {
name = std::string("M.") + generate_random_base64<6>();
} while (std::find(mounted.begin(), mounted.end(), name) != mounted.end());
io::set_device(name, std::move(device));
mounted.push_back(name);
return name;
}
throw std::runtime_error("unable to mount " + file.string());
}
void EnginePaths::unmount(const std::string& name) {
const auto& found = std::find(mounted.begin(), mounted.end(), name);
if (found == mounted.end()) {
throw std::runtime_error(name + " is not mounted");
}
io::remove_device(name);
mounted.erase(found);
}
std::string EnginePaths::createWriteablePackDevice(const std::string& name) {
const auto& found = writeablePacks.find(name);
@ -168,14 +207,7 @@ std::string EnginePaths::createWriteablePackDevice(const std::string& name) {
if (folder.emptyOrInvalid()) {
throw std::runtime_error("pack not found");
}
auto now = std::chrono::high_resolution_clock::now();
auto seed = now.time_since_epoch().count();
util::PseudoRandom random(seed); // fixme: replace with safe random
auto number = random.rand64();
auto entryPoint = std::string("W.") + util::base64_urlsafe_encode(reinterpret_cast<ubyte*>(&number), 6);
auto entryPoint = std::string("W.") + generate_random_base64<6>();
io::create_subdevice(entryPoint, folder.entryPoint(), folder.pathPart());
writeablePacks[name] = entryPoint;
return entryPoint;
@ -189,6 +221,9 @@ void EnginePaths::setContentPacks(std::vector<ContentPack>* contentPacks) {
for (const auto& [_, entryPoint] : writeablePacks) {
io::remove_device(entryPoint);
}
for (const auto& entryPoint : mounted) {
io::remove_device(entryPoint);
}
contentEntryPoints.clear();
this->contentPacks = contentPacks;
// Create content devices

View File

@ -34,6 +34,9 @@ public:
io::path getControlsFile() const;
io::path getSettingsFile() const;
std::string mount(const io::path& file);
void unmount(const std::string& name);
std::string createWriteablePackDevice(const std::string& name);
void setContentPacks(std::vector<ContentPack>* contentPacks);
@ -51,6 +54,7 @@ private:
std::vector<ContentPack>* contentPacks = nullptr;
std::vector<std::string> contentEntryPoints;
std::unordered_map<std::string, std::string> writeablePacks;
std::vector<std::string> mounted;
};
struct PathsRoot {

View File

@ -238,6 +238,17 @@ static int l_is_writeable(lua::State* L) {
return lua::pushboolean(L, is_writeable(entryPoint));
}
static int l_mount(lua::State* L) {
auto& paths = engine->getPaths();
return lua::pushstring(L, paths.mount(lua::require_string(L, 1)));
}
static int l_unmount(lua::State* L) {
auto& paths = engine->getPaths();
paths.unmount(lua::require_string(L, 1));
return 0;
}
const luaL_Reg filelib[] = {
{"exists", lua::wrap<l_exists>},
{"find", lua::wrap<l_find>},
@ -259,5 +270,7 @@ const luaL_Reg filelib[] = {
{"read_combined_list", lua::wrap<l_read_combined_list>},
{"read_combined_object", lua::wrap<l_read_combined_object>},
{"is_writeable", lua::wrap<l_is_writeable>},
{"mount", lua::wrap<l_mount>},
{"unmount", lua::wrap<l_unmount>},
{NULL, NULL}
};

View File

@ -37,6 +37,12 @@ namespace util {
return static_cast<int>(seed);
}
void rand(unsigned char* dst, size_t n) {
for (size_t i = 0; i < n; i++) {
dst[i] = rand();
}
}
int32_t rand32() {
return (rand() << 16) | rand();
}