mirror of
https://github.com/20kdc/OC-KittenOS.git
synced 2024-11-01 08:10:58 +11:00
166 lines
4.4 KiB
Lua
166 lines
4.4 KiB
Lua
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
|
|
--
|
|
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
|
--
|
|
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
|
-- THIS SOFTWARE.
|
|
|
|
-- 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
|