[Fix] Correct CoW logic and fix rm command fallout.
This commit is contained in:
parent
00e78cc2ba
commit
4b21d30567
@ -83,55 +83,57 @@ vfs_node* find_node_by_path(vfs_node* root, const std::string& path) {
|
||||
return current;
|
||||
}
|
||||
|
||||
/* Recursively set all nodes in a VFS tree to writeable. */
|
||||
void make_vfs_writable(vfs_node* node) {
|
||||
if(!node) return;
|
||||
node->read_only = false;
|
||||
for(auto const& [key, child] : node->children) {
|
||||
make_vfs_writable(child);
|
||||
}
|
||||
}
|
||||
|
||||
std::string CommandProcessor::_handle_vfs_action(sol::table action) {
|
||||
std::string action_name = action["action"].get_or<std::string>("");
|
||||
/* Make the CoW check universal for any write operation. */
|
||||
if(action_name == "rm" || action_name == "write_file") {
|
||||
if(_current_dir->read_only) {
|
||||
std::string remote_ip = "";
|
||||
/* Check if we are on a known remote system. */
|
||||
if(!_session_machine->is_vfs_a_copy) {
|
||||
if(!_session_machine->is_vfs_a_copy) {
|
||||
/* VFS is shared, a copy is required. */
|
||||
if(_session_machine == _home_machine) {
|
||||
/* We are modifying our own home machine. */
|
||||
fprintf(stderr, "CoW: Write attempt on player's home machine"
|
||||
"Creating persistant copy.\n");
|
||||
std::string original_path = get_full_path(_current_dir);
|
||||
|
||||
vfs_node* new_vfs_root = copy_vfs_node(_home_machine->vfs_root, nullptr);
|
||||
auto* new_machine = new Machine(_home_machine->id, _home_machine->hostname);
|
||||
new_machine->vfs_root = new_vfs_root;
|
||||
new_machine->services = _home_machine->services;
|
||||
new_machine->is_vfs_a_copy = true; /* Mark as copy. */
|
||||
|
||||
_home_machine = new_machine;
|
||||
_session_machine = new_machine;
|
||||
_current_dir = find_node_by_path(_session_machine->vfs_root, original_path);
|
||||
if(!_current_dir) { _current_dir = _session_machine->vfs_root; }
|
||||
} else {
|
||||
std::string remote_ip = "";
|
||||
/* Check if we are on a known remote system. */
|
||||
for(auto const& [ip, machine] : _world_machines) {
|
||||
if(machine == _session_machine) {
|
||||
remote_ip = ip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!remote_ip.empty()) {
|
||||
fprintf(stderr, "CoW: Write attempt on remote machine '%s'. "
|
||||
"Creating persistant copy.\n",
|
||||
remote_ip.c_str());
|
||||
std::string original_path = get_full_path(_current_dir);
|
||||
|
||||
if(!remote_ip.empty()) {
|
||||
/* This machine is using a shared VFS. Copy it! ;) */
|
||||
fprintf(stderr, "CoW: Write attempt on read-only remote system '%s'."
|
||||
"Creating persistant copy.\n", remote_ip.c_str());
|
||||
std::string original_path = get_full_path(_current_dir);
|
||||
/* Copy the sh.t out of the VFS. */
|
||||
vfs_node* new_vfs_root = copy_vfs_node(_session_machine->vfs_root, nullptr);
|
||||
make_vfs_writable(new_vfs_root);
|
||||
vfs_node* new_vfs_root = copy_vfs_node(_session_machine->vfs_root, nullptr);
|
||||
auto* new_machine = new Machine(_session_machine->id, _session_machine->hostname);
|
||||
new_machine->vfs_root = new_vfs_root;
|
||||
new_machine->services = _session_machine->services;
|
||||
new_machine->is_vfs_a_copy = true; /* Mark as copy. */
|
||||
|
||||
/* Create the new machine that will hold the copied VFS. */
|
||||
auto* new_machine = new Machine(_session_machine->id, _session_machine->hostname);
|
||||
new_machine->vfs_root = new_vfs_root;
|
||||
new_machine->services = _session_machine->services;
|
||||
new_machine->is_vfs_a_copy = true; /* Mark as copy. */
|
||||
_world_machines[remote_ip] = new_machine;
|
||||
_session_machine = new_machine;
|
||||
|
||||
/* Update the world map and the current session. */
|
||||
_world_machines[remote_ip] = new_machine;
|
||||
_session_machine = new_machine;
|
||||
|
||||
/* Update _current_dir to point to the equivalent dir in the new VFS. */
|
||||
_current_dir = find_node_by_path(_session_machine->vfs_root, original_path);
|
||||
if(!_current_dir) { _current_dir = _session_machine->vfs_root; }
|
||||
} else {
|
||||
return "Permission denied: Filesystem is read-only and not part of the world.";
|
||||
_current_dir = find_node_by_path(_session_machine->vfs_root, original_path);
|
||||
if(!_current_dir) { _current_dir = _session_machine->vfs_root; }
|
||||
} else {
|
||||
return "Permission denied: Filesystem is read-only and not part of the world.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -148,6 +150,7 @@ std::string CommandProcessor::_handle_vfs_action(sol::table action) {
|
||||
}
|
||||
_current_dir->children.erase(path);
|
||||
delete target_node;
|
||||
return ""; /* Success. */
|
||||
} else if(action_name == "write_file") {
|
||||
std::string filename = action["target"].get_or<std::string>("");
|
||||
std::string content = action["content"].get_or<std::string>("");
|
||||
@ -163,7 +166,7 @@ std::string CommandProcessor::_handle_vfs_action(sol::table action) {
|
||||
target_node->content = content;
|
||||
} else {
|
||||
vfs_node* new_file = new vfs_node {
|
||||
.name = filename, .type = FILE_NODE, .read_only = false, .content = content,
|
||||
.name = filename, .type = FILE_NODE, .content = content,
|
||||
.parent = _current_dir
|
||||
};
|
||||
_current_dir->children[filename] = new_file;
|
||||
|
||||
@ -12,7 +12,6 @@ LuaProcessor::LuaProcessor(void) {
|
||||
"name", &vfs_node::name,
|
||||
"type", &vfs_node::type,
|
||||
"children", &vfs_node::children,
|
||||
"read_only", &vfs_node::read_only,
|
||||
"content", &vfs_node::content); }
|
||||
|
||||
LuaProcessor::~LuaProcessor(void) {}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include "machine_manager.h"
|
||||
#include "machine.h"
|
||||
@ -13,7 +12,6 @@ vfs_node* new_node(std::string name, vfs_node_type type, vfs_node* parent) {
|
||||
node->name = name;
|
||||
node->type = type;
|
||||
node->parent = parent;
|
||||
node->read_only = false; /* Writable by default. */
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -24,7 +22,6 @@ vfs_node* copy_vfs_node(vfs_node* original, vfs_node* new_parent) {
|
||||
|
||||
/* Create the new node and copy its properties. */
|
||||
vfs_node* new_copy = new_node(original->name, original->type, new_parent);
|
||||
new_copy->read_only = original->read_only; /* Preserver read-only status. */
|
||||
new_copy->content = original->content;
|
||||
|
||||
/* Recursively copy all children. */
|
||||
@ -41,9 +38,6 @@ MachineManager::MachineManager(void) {
|
||||
vfs_node* bin = new_node("bin", DIR_NODE, _vfs_template_root);
|
||||
_vfs_template_root->children["bin"] = bin;
|
||||
|
||||
_vfs_template_root->read_only = true;
|
||||
bin->read_only = true;
|
||||
|
||||
/* Load all scripts from assets/scripts/bin into the VFS. */
|
||||
const std::string path = "assets/scripts/bin";
|
||||
for(const auto & entry : std::filesystem::directory_iterator(path)) {
|
||||
@ -62,7 +56,6 @@ MachineManager::MachineManager(void) {
|
||||
|
||||
MachineManager::~MachineManager(void) {
|
||||
/* TODO: Implement recursive deletion of all created VFS nodes.*/
|
||||
//delete _vfs_root;
|
||||
}
|
||||
|
||||
Machine* MachineManager::create_machine(uint32_t id, const std::string& hostname,
|
||||
|
||||
@ -16,7 +16,6 @@ enum vfs_node_type {
|
||||
struct vfs_node {
|
||||
std::string name;
|
||||
vfs_node_type type;
|
||||
bool read_only;
|
||||
|
||||
/* Files. */
|
||||
std::string content;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user