Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Control Computer Program
- local modem = peripheral.find("modem") or error("No modem found")
- modem.open(1) -- Open channel 1 for communication
- local nodes = {}
- local fileMap = {}
- -- Function to save the file map
- local function saveFileMap()
- local file = io.open("/fragment.txt", "w")
- file:write(textutils.serialize(fileMap))
- file:close()
- end
- -- Function to load the file map
- local function loadFileMap()
- local file = io.open("/fragment.txt", "r")
- if file then
- fileMap = textutils.unserialize(file:read("*all"))
- file:close()
- end
- end
- -- Function to discover storage nodes
- local function discoverNodes()
- print("Discovering storage nodes...")
- modem.transmit(1, 1, {type = "discovery"})
- local timer = os.startTimer(5)
- local discoveredNodes = {}
- while true do
- local event, param1, param2, param3, param4, param5 = os.pullEvent()
- if event == "modem_message" and param4.type == "discovery_response" then
- table.insert(discoveredNodes, param4.id)
- print("Discovered node: " .. param4.id)
- elseif event == "timer" and param1 == timer then
- break
- end
- end
- return discoveredNodes
- end
- -- Function to send a request to a node
- local function sendRequest(nodeId, request)
- modem.transmit(1, 1, request)
- local timer = os.startTimer(5)
- while true do
- local event, param1, param2, param3, param4, param5 = os.pullEvent()
- if event == "modem_message" and param4.id == request.id then
- return param4.response
- elseif event == "timer" and param1 == timer then
- error("Request timed out for node: " .. nodeId)
- end
- end
- end
- -- Function to distribute a file across nodes
- local function distributeFile(path, content)
- local chunkSize = math.ceil(#content / #nodes)
- local chunks = {}
- for i, nodeId in ipairs(nodes) do
- local start = (i - 1) * chunkSize + 1
- local chunk = content:sub(start, math.min(start + chunkSize - 1, #content))
- chunks[i] = chunk
- local response = sendRequest(nodeId, {
- id = os.getComputerID() .. "_" .. os.clock(),
- action = "write",
- path = path .. "_chunk_" .. i,
- content = chunk
- })
- if not response.success then
- error("Failed to write chunk " .. i .. " to node " .. nodeId)
- end
- end
- fileMap[path] = {chunks = #nodes, size = #content, nodeMap = nodes}
- saveFileMap()
- end
- -- Function to read a file from nodes
- local function readFile(path)
- if not fileMap[path] then
- error("File not found: " .. path)
- end
- local content = ""
- for i, nodeId in ipairs(fileMap[path].nodeMap) do
- local response = sendRequest(nodeId, {
- id = os.getComputerID() .. "_" .. os.clock(),
- action = "read",
- path = path .. "_chunk_" .. i
- })
- if response.success then
- content = content .. response.content
- else
- error("Failed to read chunk " .. i .. " from node " .. nodeId)
- end
- end
- return content
- end
- -- Function to delete a file from nodes
- local function deleteFile(path)
- if not fileMap[path] then
- error("File not found: " .. path)
- end
- for i, nodeId in ipairs(fileMap[path].nodeMap) do
- local response = sendRequest(nodeId, {
- id = os.getComputerID() .. "_" .. os.clock(),
- action = "delete",
- path = path .. "_chunk_" .. i
- })
- if not response.success then
- error("Failed to delete chunk " .. i .. " from node " .. nodeId)
- end
- end
- fileMap[path] = nil
- saveFileMap()
- end
- -- Function to list files in a directory
- local function listFiles(path)
- local files = {}
- for file, _ in pairs(fileMap) do
- if file:sub(1, #path) == path then
- local name = file:sub(#path + 1)
- local firstSlash = name:find("/")
- if firstSlash then
- name = name:sub(1, firstSlash - 1)
- end
- if not files[name] then
- files[name] = true
- end
- end
- end
- return keys(files)
- end
- -- Discover storage nodes
- nodes = discoverNodes()
- if #nodes == 0 then
- error("No storage nodes found. Make sure the storage nodes are running and connected.")
- end
- print("Found " .. #nodes .. " storage node(s)")
- loadFileMap()
- -- Override the entire fs API
- local oldFS = fs
- fs = {}
- function fs.list(path)
- print("DEBUG: Listing directory: " .. path)
- return listFiles(path)
- end
- function fs.exists(path)
- print("DEBUG: Checking if exists: " .. path)
- return fileMap[path] ~= nil
- end
- function fs.isDir(path)
- print("DEBUG: Checking if directory: " .. path)
- return #listFiles(path) > 0
- end
- function fs.isReadOnly(path)
- print("DEBUG: Checking if read-only: " .. path)
- return false
- end
- function fs.getSize(path)
- print("DEBUG: Getting size of: " .. path)
- return fileMap[path] and fileMap[path].size or 0
- end
- function fs.getFreeSpace(path)
- print("DEBUG: Getting free space")
- return math.huge
- end
- function fs.makeDir(path)
- print("DEBUG: Making directory: " .. path)
- -- Directories are implicit, so we don't need to do anything
- end
- function fs.move(fromPath, toPath)
- print("DEBUG: Moving from " .. fromPath .. " to " .. toPath)
- if fileMap[fromPath] then
- fileMap[toPath] = fileMap[fromPath]
- fileMap[fromPath] = nil
- saveFileMap()
- else
- error("Source file does not exist")
- end
- end
- function fs.copy(fromPath, toPath)
- print("DEBUG: Copying from " .. fromPath .. " to " .. toPath)
- if fileMap[fromPath] then
- local content = readFile(fromPath)
- distributeFile(toPath, content)
- else
- error("Source file does not exist")
- end
- end
- function fs.delete(path)
- print("DEBUG: Deleting: " .. path)
- deleteFile(path)
- end
- function fs.open(path, mode)
- print("DEBUG: Opening file: " .. path .. " with mode: " .. mode)
- if mode == "r" then
- local content = readFile(path)
- local position = 1
- return {
- read = function()
- if position > #content then return nil end
- local char = content:sub(position, position)
- position = position + 1
- return char:byte()
- end,
- readLine = function()
- local line = ""
- while position <= #content do
- local char = content:sub(position, position)
- position = position + 1
- if char == "\n" then break end
- line = line .. char
- end
- return #line > 0 and line or nil
- end,
- readAll = function() return content end,
- close = function() end
- }
- elseif mode == "w" or mode == "a" then
- local buffer = ""
- return {
- write = function(str) buffer = buffer .. str end,
- writeLine = function(str) buffer = buffer .. str .. "\n" end,
- flush = function() distributeFile(path, buffer) end,
- close = function() distributeFile(path, buffer) end
- }
- end
- end
- -- Override io functions
- local oldIO = io
- io = {}
- function io.open(path, mode)
- print("DEBUG: IO Opening file: " .. path .. " with mode: " .. mode)
- return fs.open(path, mode)
- end
- -- Create a sandbox environment
- local sandbox = setmetatable({}, {__index = _G})
- sandbox.fs = fs
- sandbox.io = io
- -- Override shell commands
- local oldShell = shell
- sandbox.shell = setmetatable({}, {__index = oldShell})
- function sandbox.shell.run(...)
- local args = {...}
- print("DEBUG: Running command: " .. table.concat(args, " "))
- return oldShell.run(...)
- end
- -- Set up the new environment
- setfenv(1, sandbox)
- -- Run the shell with the overridden APIs
- shell.run("rom/programs/shell")
Advertisement
Add Comment
Please, Sign In to add comment