DevFS prototype
This commit is contained in:
parent
d3a43eab28
commit
423f622271
117
src/bin/devfs.lua
Normal file
117
src/bin/devfs.lua
Normal file
@ -0,0 +1,117 @@
|
||||
local vfs = {}
|
||||
|
||||
local getters = {"is", "has", "get"}
|
||||
local setters = {"set"}
|
||||
|
||||
function vfs.list(path)
|
||||
local segs = fs.segment(path)
|
||||
if #segs == 0 then
|
||||
return peripheral.getNames()
|
||||
elseif #segs == 1 then
|
||||
local methods = peripheral.getMethods(segs[1])
|
||||
local out = {}
|
||||
for _, v in pairs(methods) do
|
||||
local set
|
||||
for _, s in pairs(setters) do
|
||||
local mat = v:match("^" .. s .. "([A-Z].+)")
|
||||
if mat then
|
||||
set = mat
|
||||
break
|
||||
end
|
||||
end
|
||||
local get
|
||||
for _, g in pairs(getters) do
|
||||
local mat = v:match("^" .. g .. "([A-Z].+)")
|
||||
if mat then
|
||||
get = mat
|
||||
break
|
||||
end
|
||||
end
|
||||
if get then table.insert(out, get)
|
||||
elseif set then table.insert(out, set)
|
||||
else table.insert(out, v) end
|
||||
end
|
||||
return out
|
||||
elseif #segs == 2 then
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
local function write_handle(callback)
|
||||
local buffer = ""
|
||||
local write_handle = {}
|
||||
function write_handle.write(text)
|
||||
buffer = buffer .. text
|
||||
end
|
||||
function write_handle.close()
|
||||
callback(buffer)
|
||||
end
|
||||
function write_handle.flush() end
|
||||
function write_handle.writeLine(text) write_handle.write(text) write_handle.write("\n") end
|
||||
return write_handle
|
||||
end
|
||||
|
||||
function vfs.open(path, mode)
|
||||
local segs = fs.segment(path)
|
||||
if #segs == 2 and segs[2]:match "^[A-Z]" then -- getter/setter configuration
|
||||
if mode:match "w" then
|
||||
return write_handle(function(buffer)
|
||||
local ok, res
|
||||
for _, s in pairs(setters) do
|
||||
local ok2, res2 = pcall(peripheral.call, segs[1], s .. segs[2], json.decode(buffer))
|
||||
ok = ok or ok2
|
||||
res = res or res2
|
||||
end
|
||||
if not ok then error(res) end
|
||||
end)
|
||||
else
|
||||
-- TODO multiple returns
|
||||
local result
|
||||
for _, g in pairs(getters) do
|
||||
local ok, res = pcall(peripheral.call, segs[1], g .. segs[2])
|
||||
result = result or (ok and res)
|
||||
end
|
||||
local text = json.encode(result)
|
||||
return fs._make_handle(text)
|
||||
end
|
||||
elseif #segs == 2 then
|
||||
if mode:match "w" then
|
||||
return write_handle(function(buffer)
|
||||
peripheral.call(segs[1], segs[2], json.decode(buffer))
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function vfs.exists(path)
|
||||
local segs = fs.segment(path)
|
||||
if #segs == 0 then
|
||||
return true
|
||||
else
|
||||
return peripheral.getType(segs[1]) ~= nil
|
||||
end
|
||||
end
|
||||
|
||||
function vfs.isReadOnly(path)
|
||||
local segs = fs.segment(path)
|
||||
if #segs == 2 and segs[2]:match "^[A-Z]" then -- getter/setter configuration
|
||||
local methods = peripheral.getMethods(segs[1])
|
||||
for _, s in pairs(setters) do
|
||||
for _, m in pairs(methods) do
|
||||
if m == s .. segs[2] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function vfs.isDir(path)
|
||||
local segs = fs.segment(path)
|
||||
return #segs <= 1
|
||||
end
|
||||
function vfs.getDrive(path) return "devfs" end
|
||||
|
||||
fs.mountVFS(shell.resolve(...), vfs)
|
1
src/bin/umount.lua
Normal file
1
src/bin/umount.lua
Normal file
@ -0,0 +1 @@
|
||||
fs.unmountVFS(shell.resolve(...))
|
@ -11,21 +11,6 @@ local function copy(tabl)
|
||||
return new
|
||||
end
|
||||
|
||||
-- Deep-map all values in a table
|
||||
local function deepmap(table, f, path)
|
||||
local path = path or ""
|
||||
local new = {}
|
||||
for k, v in pairs(table) do
|
||||
local thisp = path .. "." .. k
|
||||
if type(v) == "table" and v ~= table then -- bodge it to not stackoverflow
|
||||
new[k] = deepmap(v, f, thisp)
|
||||
else
|
||||
new[k] = f(v, k, thisp)
|
||||
end
|
||||
end
|
||||
return new
|
||||
end
|
||||
|
||||
-- Takes a list of keys to copy, returns a function which takes a table and copies the given keys to a new table
|
||||
local function copy_some_keys(keys)
|
||||
return function(from)
|
||||
@ -41,13 +26,6 @@ local function copy_some_keys(keys)
|
||||
end
|
||||
end
|
||||
|
||||
-- Simple string operations
|
||||
local function starts_with(s, with)
|
||||
return string.sub(s, 1, #with) == with
|
||||
end
|
||||
local function ends_with(s, with)
|
||||
return string.sub(s, -#with, -1) == with
|
||||
end
|
||||
local function contains(s, subs)
|
||||
return string.find(s, subs) ~= nil
|
||||
end
|
||||
@ -83,16 +61,6 @@ local function canonicalize(path)
|
||||
return fscombine(path, "")
|
||||
end
|
||||
|
||||
-- Escapes lua patterns in a string. Should not be needed, but lua is stupid so the only string.replace thing is gsub
|
||||
local quotepattern = '(['..("%^$().[]*+-?"):gsub("(.)", "%%%1")..'])'
|
||||
local function escape(str)
|
||||
return str:gsub(quotepattern, "%%%1")
|
||||
end
|
||||
|
||||
local function strip(p, root)
|
||||
return p:gsub("^" .. escape(canonicalize(root)), "")
|
||||
end
|
||||
|
||||
local function segments(path)
|
||||
local segs, rest = {}, canonicalize(path)
|
||||
if rest == "" then return {} end -- otherwise we'd get "root" and ".." for some broken reason
|
||||
@ -110,14 +78,14 @@ local function combine(segs)
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
-- Fetch the contents of URL "u"
|
||||
local function fetch(u)
|
||||
local h = http.get(u)
|
||||
local c = h.readAll()
|
||||
h.close()
|
||||
return c
|
||||
end
|
||||
|
||||
local vfs_defaults = {}
|
||||
|
||||
function vfs_defaults.getSize(path) return 0 end
|
||||
function vfs_defaults.getFreeSpace(path) return 0 end
|
||||
function vfs_defaults.makeDir(path) error "Access denied" end
|
||||
function vfs_defaults.delete(path) error "Access denied" end
|
||||
function vfs_defaults.isReadOnly(path) return true end
|
||||
|
||||
-- Make a read handle for a string
|
||||
-- PS#8FE487EF: Incompletely implemented handle behaviour lead to strange bugs on recent CC
|
||||
@ -144,13 +112,6 @@ local function make_handle(text)
|
||||
return h
|
||||
end
|
||||
|
||||
-- Get a path from a filesystem overlay
|
||||
local function path_in_overlay(overlay, path)
|
||||
return overlay[canonicalize(path)]
|
||||
end
|
||||
|
||||
local this_level_env = _G
|
||||
|
||||
-- make virtual filesystem from files (no nested directories for simplicity)
|
||||
local function vfs_from_files(files)
|
||||
return {
|
||||
@ -234,7 +195,7 @@ local function create_FS(vfstree)
|
||||
local function lift_to_sandbox(f, n)
|
||||
return function(path)
|
||||
local vfs, path = resolve_path(path)
|
||||
return vfs[n](path)
|
||||
return (vfs[n] or vfs_defaults[n])(path)
|
||||
end
|
||||
end
|
||||
|
||||
@ -384,6 +345,9 @@ local function create_FS(vfstree)
|
||||
end
|
||||
end
|
||||
|
||||
new.segment = segments
|
||||
new._make_handle = make_handle
|
||||
|
||||
return new
|
||||
end
|
||||
|
||||
@ -458,8 +422,8 @@ local function make_environment(API_overrides, current_process)
|
||||
local environment = copy_some_keys(allowed_APIs)(_G)
|
||||
|
||||
-- I sure hope this doesn't readd the security issues!
|
||||
environment.getfenv = getfenv
|
||||
environment.setfenv = setfenv
|
||||
environment.getfenv = gf
|
||||
environment.setfenv = sf
|
||||
|
||||
local load = load
|
||||
function environment.load(code, file, mode, env)
|
||||
|
@ -1313,16 +1313,11 @@ local function run_with_sandbox()
|
||||
end
|
||||
|
||||
function drive_mounts.vfs.exists(path)
|
||||
return drive_mounts.children[path] ~= nil
|
||||
return path == "" or drive_mounts.children[path] ~= nil
|
||||
end
|
||||
|
||||
function drive_mounts.vfs.isDir(path) return true end
|
||||
function drive_mounts.vfs.getDrive(path) return "disks" end
|
||||
function drive_mounts.vfs.getSize(path) return 0 end
|
||||
function drive_mounts.vfs.getFreeSpace(path) return 0 end
|
||||
function drive_mounts.vfs.makeDir(path) end
|
||||
function drive_mounts.vfs.delete(path) end
|
||||
function drive_mounts.vfs.isReadOnly(path) return true end
|
||||
|
||||
local vfstree = {
|
||||
mount = "potatOS",
|
||||
|
Loading…
x
Reference in New Issue
Block a user