mirror of
https://github.com/20kdc/OC-KittenOS.git
synced 2024-11-01 16:20:58 +11:00
162 lines
3.8 KiB
Lua
162 lines
3.8 KiB
Lua
-- This is released into the public domain.
|
|
-- No warranty is provided, implied or otherwise.
|
|
|
|
-- metamachine-vgpu.lua : Virtual GPU library
|
|
-- Authors: 20kdc
|
|
|
|
return function (icecap, address, path, ro)
|
|
if path ~= "/" then
|
|
icecap.makeDirectory(path:sub(1, #path - 1))
|
|
end
|
|
local function resolvePath(p, post)
|
|
local pth = {}
|
|
local issue = false
|
|
string.gsub(p, "[^\\/]+", function (str)
|
|
if str == ".." then
|
|
if not pth[1] then
|
|
issue = true
|
|
else
|
|
table.remove(pth, #pth)
|
|
end
|
|
elseif str ~= "." then
|
|
table.insert(pth, str)
|
|
end
|
|
end)
|
|
if issue then
|
|
return
|
|
end
|
|
local str = path
|
|
if post then
|
|
str = str:sub(1, #str - 1)
|
|
end
|
|
for k, v in ipairs(pth) do
|
|
if k > 1 or post then
|
|
str = str .. "/"
|
|
end
|
|
str = str .. v
|
|
end
|
|
return str
|
|
end
|
|
local function wrapThing(fn, post, roStop)
|
|
-- If we're adding a "/", we get rid of the original "/".
|
|
--
|
|
local pofx = ""
|
|
if post then
|
|
pofx = "/"
|
|
end
|
|
return function (p)
|
|
if ro and roStop then
|
|
return false, "read-only filesystem"
|
|
end
|
|
p = resolvePath(p, post)
|
|
if p then
|
|
local nt = {pcall(fn, p .. pofx)}
|
|
if nt[1] then
|
|
return table.unpack(nt, 2)
|
|
end
|
|
end
|
|
return nil, "no such file or directory"
|
|
end
|
|
end
|
|
local function wrapStat(s)
|
|
return wrapThing(function (px)
|
|
local stat = icecap.stat(px)
|
|
if stat then
|
|
return stat[s]
|
|
end
|
|
end, false, false)
|
|
end
|
|
local handles = {}
|
|
local lHandle = 0
|
|
local modeMapping = {
|
|
r = false,
|
|
rb = false,
|
|
w = true,
|
|
wb = true,
|
|
a = "append",
|
|
ab = "append"
|
|
}
|
|
return {
|
|
type = "filesystem",
|
|
getLabel = function ()
|
|
return "VFS"
|
|
end,
|
|
setLabel = function (label)
|
|
end,
|
|
isReadOnly = function ()
|
|
return ro or icecap.isReadOnly()
|
|
end,
|
|
spaceUsed = function ()
|
|
return icecap.spaceUsed()
|
|
end,
|
|
spaceTotal = function ()
|
|
return icecap.spaceTotal()
|
|
end,
|
|
list = wrapThing(icecap.list, true, false),
|
|
exists = wrapThing(function (px)
|
|
if icecap.stat(px) then
|
|
return true
|
|
end
|
|
return false
|
|
end, false, false),
|
|
isDirectory = wrapStat(1),
|
|
size = wrapStat(2),
|
|
lastModified = wrapStat(3),
|
|
makeDirectory = wrapThing(icecap.makeDirectory, false, true),
|
|
rename = function (a, b)
|
|
if ro then return false, "read-only filesystem" end
|
|
a = resolvePath(a)
|
|
b = resolvePath(b)
|
|
if not (a and b) then
|
|
return nil, a
|
|
end
|
|
return icecap.rename(a, b)
|
|
end,
|
|
remove = wrapThing(icecap.remove, false, true),
|
|
--
|
|
open = function (p, mode)
|
|
checkArg(1, p, "string")
|
|
p = resolvePath(p)
|
|
if not p then return nil, "failed to open" end
|
|
if rawequal(mode, nil) then mode = "r" end
|
|
if modeMapping[mode] == nil then
|
|
error("unsupported mode " .. tostring(mode))
|
|
end
|
|
mode = modeMapping[mode]
|
|
if (mode ~= false) and ro then return nil, "read-only filesystem" end
|
|
lHandle = lHandle + 1
|
|
handles[lHandle] = icecap.open(p, mode)
|
|
if not handles[lHandle] then
|
|
return nil, "failed to open"
|
|
end
|
|
return lHandle
|
|
end,
|
|
read = function (fh, len)
|
|
checkArg(1, fh, "number")
|
|
checkArg(2, len, "number")
|
|
if not handles[fh] then return nil, "bad file descriptor" end
|
|
if not handles[fh].read then return nil, "bad file descriptor" end
|
|
return handles[fh].read(len)
|
|
end,
|
|
write = function (fh, data)
|
|
checkArg(1, fh, "number")
|
|
if not handles[fh] then return nil, "bad file descriptor" end
|
|
if not handles[fh].write then return nil, "bad file descriptor" end
|
|
return handles[fh].write(data)
|
|
end,
|
|
seek = function (fh, whence, point)
|
|
checkArg(1, fh, "number")
|
|
if not handles[fh] then return nil, "bad file descriptor" end
|
|
if not handles[fh].seek then return nil, "bad file descriptor" end
|
|
return handles[fh].seek(whence, point)
|
|
end,
|
|
close = function (fh)
|
|
checkArg(1, fh, "number")
|
|
if not handles[fh] then return nil, "bad file descriptor" end
|
|
handles[fh].close()
|
|
handles[fh] = nil
|
|
return true
|
|
end,
|
|
}
|
|
end
|