223 lines
6.1 KiB
Lua
223 lines
6.1 KiB
Lua
local debug = ...
|
|
|
|
local filesystem = {}
|
|
local component = require("component")
|
|
local computer = require("computer")
|
|
local mounts = {}
|
|
|
|
--false if file, true if dir
|
|
local function isFileOrDir(path)
|
|
return (string.sub(path, -1) == "/")
|
|
end
|
|
local function removeFilename(path) -- this sucks
|
|
local t = {}
|
|
local s = ""
|
|
|
|
for i in string.gmatch(path, "[^/]+") do
|
|
table.insert(t,i)
|
|
end
|
|
|
|
table.remove(t,#t)
|
|
|
|
if #t == 0 then
|
|
return "/"
|
|
end
|
|
for i=1,#t do
|
|
s = s .. t[i] .. "/"
|
|
end
|
|
if s:sub(1,1) ~= "/" then
|
|
s = "/" .. s
|
|
end
|
|
|
|
return s
|
|
end
|
|
local function log(msg,d)
|
|
if d then
|
|
if debug then
|
|
Journal.write(msg)
|
|
end
|
|
elseif not d then
|
|
Journal.write(msg)
|
|
end
|
|
end
|
|
|
|
|
|
-- Mount/node handling
|
|
----------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
function filesystem.findNode(path)
|
|
--go through mounts
|
|
-- abc - / 1st iteration, does match
|
|
-- def - /mnt 2nd iteration, matches better
|
|
|
|
if not isFileOrDir(path) then
|
|
path = removeFilename(path)
|
|
end
|
|
|
|
local candidate = nil
|
|
local lastNum = 0
|
|
for i=1, #mounts do
|
|
local s,e = string.find(path,mounts[i].path)
|
|
log(string.format(" [FILESYSTEM.findNode] s:%s e:%s path:%s candidate:%s lastNum:%s - tagainst %s, is id %s",s,e,path,candidate,lastNum,mounts[i].path,mounts[i].disk.address or "n/a"), true)
|
|
if e == nil then
|
|
e = 0
|
|
end
|
|
if e > lastNum and s == 1 then
|
|
candidate = mounts[i]
|
|
lastNum = e
|
|
end
|
|
end
|
|
|
|
if lastNum == 0 then
|
|
log(" [FILESYSTEM.findNode] failed", true)
|
|
return false, "did not find any matching"
|
|
else
|
|
log(" [FILESYSTEM.findNode] candidate has addr "..candidate.disk.address, true)
|
|
return candidate
|
|
end
|
|
end
|
|
|
|
function filesystem.mount(disk, path)
|
|
log(string.format(" [FILESYSTEM] mounting %sas %s", AlignString(disk,7),path),false)
|
|
|
|
if disk == nil then
|
|
table.insert(mounts, {
|
|
["disk"]={["address"]="n/a"},
|
|
["path"]=path,
|
|
["isVirtual"]=true,
|
|
["files"]={}, -- {[path] = data}
|
|
["handles"]={}
|
|
})
|
|
log(" [FILESYSTEM] drive is virtual")
|
|
return mounts
|
|
end
|
|
|
|
-- check if disk exists
|
|
|
|
if component.get(disk, "filesystem") then
|
|
table.insert(mounts, {
|
|
["disk"]=component.proxy(disk),
|
|
["path"]=path,
|
|
["isVirtual"]=false
|
|
})
|
|
return mounts[#mounts]
|
|
else
|
|
log(string.format(" [FILESYSTEM] drive does not exist", false))
|
|
return nil, "no filesystem at address"
|
|
end
|
|
end
|
|
|
|
-- File operations
|
|
----------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
function filesystem.open(path, mode)
|
|
local mount, reason = filesystem.findNode(path)
|
|
assert(mount,reason)
|
|
if mount.isVirtual then
|
|
table.insert(mount.handles,{
|
|
["path"] = path,
|
|
["mode"] = mode,
|
|
["ptr"] = 1
|
|
})
|
|
return {["id"]=#mount.handles,["disk"]=mount}
|
|
else --untested
|
|
local id = mount.disk.open(path,mode)
|
|
assert(id, string.format("id is '%s', not a handle, when opening '%s' as '%s'",id,path,mode))
|
|
return {["id"]=id,["disk"]=mount}
|
|
end
|
|
end
|
|
function filesystem.write(handle, data)
|
|
if handle.disk.isVirtual then
|
|
local mode = handle.disk.handles[handle.id].mode
|
|
local path = handle.disk.handles[handle.id].path
|
|
if mode == "a" or mode == "ab" then
|
|
error("not implemented")
|
|
elseif mode == "w" or mode == "wb" then
|
|
handle.disk.files[path] = data
|
|
return
|
|
else
|
|
error(string.format("mode '%s' not understood",mode))
|
|
end
|
|
else
|
|
handle.disk.disk.write(handle.id,data)
|
|
end
|
|
end
|
|
|
|
function filesystem.read(handle,count)
|
|
if count == nil then
|
|
count = math.maxinteger or math.huge
|
|
end
|
|
if handle.disk.isVirtual then
|
|
local d = handle.disk
|
|
local a = d.files[d.handles[handle.id].path]
|
|
:sub(d.handles[handle.id].ptr,d.handles[handle.id].ptr+count-1)
|
|
d.handles[handle.id].ptr = d.handles[handle.id].ptr +count
|
|
return a
|
|
else --untested
|
|
local buffer = ""
|
|
|
|
repeat
|
|
local data = handle.disk.disk.read(handle.id, count)
|
|
buffer = buffer .. (data or "")
|
|
until not data
|
|
|
|
return buffer
|
|
end
|
|
end
|
|
|
|
function filesystem.close(handle)
|
|
if handle.disk.isVirtual then
|
|
handle.disk.handles[handle.id] = nil
|
|
return
|
|
else --untested
|
|
return handle.disk.disk.close(handle.id)
|
|
end
|
|
end
|
|
|
|
|
|
-- Misc
|
|
----------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
function filesystem.exists(path) -- weird, doesnt w
|
|
local addr = filesystem.findNode(path)
|
|
if addr == nil then
|
|
return false
|
|
end
|
|
if addr.disk.isDirectory(path) or
|
|
addr.disk.exists(path) then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function filesystem.loadfile(path, workspace)
|
|
local handle = filesystem.open(path, "r")
|
|
local data = filesystem.read(handle)
|
|
filesystem.close(handle)
|
|
if workspace == nil then
|
|
return load(data, "=" .. path, "bt", _G)
|
|
else
|
|
return load(data, "=" .. path, "bt", workspace)
|
|
end
|
|
end
|
|
|
|
function filesystem.getlisting(path) -- handle.disk.files[path]
|
|
local mount, reason = filesystem.findNode(path)
|
|
assert(mount, reason)
|
|
if mount.isVirtual then
|
|
local a = {}
|
|
print(#mount.files)
|
|
for b=1, #mount.files do
|
|
error(b)
|
|
table.insert(a, mount.files[b]:gmatch("[^/]+"))
|
|
end
|
|
print(a[1])
|
|
else
|
|
return mount.disk.list(path)
|
|
end
|
|
end
|
|
|
|
return filesystem |