[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