Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- os.pullEvent = os.pullEventRaw
- os.loadAPI("/md5")
- local args = {...}
- local cfgfile = "/rfs-sv.cfg"
- local prefix
- local senders = {}
- local function loadConfig()
- local f = fs.open(cfgfile, "r")
- if f == nil then return end
- f.readLine() -- unused
- f.readLine() -- unused
- prefix = f.readLine()
- f.close()
- if fs.exists("/idlist") then
- local fn = assert(loadfile("/idlist"))
- senders = {}
- setfenv(fn, senders)
- fn()
- if prefix then
- fs.delete(prefix.."/ids")
- fs.copy("/idlist", prefix.."/ids")
- end
- end
- return prefix ~= nil
- end
- local function prompt(str)
- write(str)
- return read()
- end
- local function newConfig()
- prefix = prefix or prompt("Prefix: ")
- local f = fs.open(cfgfile, "w")
- f.writeLine("")
- f.writeLine("")
- f.writeLine(prefix)
- f.close()
- end
- if #args >= 1 then
- local mode = args[1]
- if mode == "config" or mode == "reconfig" then
- if mode == "config" then
- loadConfig()
- end
- newConfig()
- return
- end
- end
- if not loadConfig() then
- print("Server not fully configured (config file "..cfgfile..")")
- print("To configure, use")
- print(" "..shell.getRunningProgram().." config")
- print("To configure from scratch, erasing any existing settings, use")
- print(" "..shell.getRunningProgram().." reconfig")
- return
- end
- for _,v in ipairs(redstone.getSides()) do
- if peripheral.getType(v) == "modem" then
- rednet.open(v)
- end
- end
- local nextHandle = 0
- local handles = {}
- local handleAuth = {}
- -- verify path, return fixed path or raise error
- local function path(p)
- if type(p) ~= "string" then error("expected string, got "..tostring(p)) end
- p = p:gsub("\\","/")
- if p:sub(1,1) ~= "/" then error("path must start with slash") end
- if (p.."/"):find("/%.%./") then error("path may not use ..") end
- return p
- end
- local function allowsType(granted, requested)
- if granted == "rw" then
- return requested == "ro" or requested == "rw"
- elseif granted == "ro" then
- return requested == "ro"
- else
- return false
- end
- end
- local function checkAuth(sender, path, type)
- do return true end -- Disable authentication
- sender = "_" .. sender
- if not senders[sender] then
- return false
- end
- local matches = senders[sender].rfs2 or {}
- matches["/"] = senders[sender].rfs
- local longest, longestLength = nil, 0
- for k,v in pairs(matches) do
- if path:sub(1, k:len()) == k and k:len() > longestLength then
- longest = k
- longestLength = k:len()
- end
- end
- return allowsType(matches[longest], type)
- end
- local function assertAuth(sender, path, type)
- if not checkAuth(sender, path, type) then
- if type == "rw" and checkAuth(sender, path, "ro") then error("Read-only filesystem", 0) end
- error("Acccess denied.", 0)
- end
- end
- local function process(sender, t)
- local level = senders["_"..sender] and senders["_"..sender].rfs -- or getMatchLevel(t[2])
- if not level then return end
- local readonly = level == "ro"
- local seq, cmd = t[3], t[4]
- local reply = function(...)
- rednet.send(sender, textutils.serialize({"RFS", seq, ...}))
- end
- if cmd == "isReadOnly" then
- if not checkAuth(sender, t[5], "rw") then
- reply(true)
- else
- reply(fs.isReadOnly(prefix..path(t[5])))
- end
- elseif cmd == "exists" then
- assertAuth(sender, t[5], "ro")
- reply(fs.exists(prefix..path(t[5])))
- elseif cmd == "isDir" then
- assertAuth(sender, t[5], "ro")
- reply(fs.isDir(prefix..path(t[5])))
- elseif cmd == "list" then
- assertAuth(sender, t[5], "ro")
- reply(unpack(fs.list(prefix..path(t[5]))))
- elseif cmd == "getDrive" then
- assertAuth(sender, t[5], "ro")
- reply(fs.getDrive(prefix..path(t[5])))
- elseif cmd == "mkdir" then
- assertAuth(sender, t[5], "rw")
- reply(fs.makeDir(prefix..path(t[5])))
- elseif cmd == "delete" then
- assertAuth(sender, t[5], "rw")
- reply(fs.delete(prefix..path(t[5])))
- elseif cmd == "getSize" then
- assertAuth(sender, t[5], "ro")
- reply(fs.getSize(prefix..path(t[5])))
- elseif cmd == "getFreeSpace" then
- assertAuth(sender, t[5], "ro")
- reply(fs.getFreeSpace(prefix..t[5]))
- elseif cmd == "open" then
- if t[6] ~= "r" and t[6] ~= "rb" then
- assertAuth(sender, t[5], "rw")
- else
- assertAuth(sender, t[5], "ro")
- end
- local id = nextHandle
- handles[id] = fs.open(prefix..path(t[5]), t[6])
- if handles[id] == nil then
- reply(nil)
- else
- nextHandle = nextHandle + 1
- handleAuth[id] = sender
- reply(id)
- end
- elseif cmd == "readLine" then
- if handleAuth[t[5]] ~= sender then error("Invalid handle") end
- reply(handles[t[5]].readLine())
- elseif cmd == "readAll" then
- if handleAuth[t[5]] ~= sender then error("Invalid handle") end
- reply(handles[t[5]].readAll())
- elseif cmd == "write" then
- if handleAuth[t[5]] ~= sender then error("Invalid handle") end
- reply(handles[t[5]].write(t[6]))
- elseif cmd == "writeLine" then
- if handleAuth[t[5]] ~= sender then error("Invalid handle") end
- reply(handles[t[5]].writeLine(t[6]))
- elseif cmd == "close" then
- if handleAuth[t[5]] ~= sender then error("Invalid handle") end
- reply(handles[t[5]].close())
- handles[t[5]] = nil
- handleAuth[t[5]] = nil
- elseif cmd == "read" then
- if handleAuth[t[5]] ~= sender then error("Invalid handle") end
- reply(handles[t[5]].read())
- else
- error("Unknown RFS command "..cmd)
- end
- end
- while true do
- local s, m = rednet.receive()
- local ok, t = pcall(textutils.unserialize, m)
- --print(m)
- if ok and type(t) == "table" and t[1] == "RFS" then
- local o = t[2]
- t[2] = "*"
- print(s," ",table.concat(t, " "))
- t[2] = o
- local ok, err = pcall(process, s, t)
- if not ok then
- print("Error processing: " .. err)
- rednet.send(sender, textutils.serialize({"RFS-error", t[3], err}))
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement