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