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,skipFileDirCheck) --go through mounts -- abc - / 1st iteration, does match -- def - /mnt 2nd iteration, matches better if not skipFileDirCheck then if not isFileOrDir(path) then path = removeFilename(path) end 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, nil, lastNum end end function filesystem.mount(disk, path) log(string.format(" [FILESYSTEM] mounting %sas %s", AlignString(disk,7),path),false) -- check if disk exists if component.get(disk, "filesystem") then table.insert(mounts, { ["disk"]=component.proxy(disk), ["path"]=path }) 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,lastNum = filesystem.findNode(path) assert(mount,reason) local id = mount.disk.open(path:sub(lastNum),mode) assert(id, string.format("id is '%s', not a handle, when opening '%s' (actually '%s') as '%s'",id,path,path:sub(lastNum),mode)) return {["id"]=id,["disk"]=mount} end function filesystem.write(handle, data) handle.disk.disk.write(handle.id,data) end function filesystem.read(handle,count) if count == nil then count = math.maxinteger or math.huge end local buffer = "" repeat local data = handle.disk.disk.read(handle.id, count) buffer = buffer .. (data or "") until not data return buffer end function filesystem.close(handle) return handle.disk.disk.close(handle.id) end -- Directory operations ---------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- function filesystem.makeDirectory(path) local addr,reason,lastNum = filesystem.findNode(path,true) assert(addr, reason) return addr.disk.makeDirectory(path:sub(lastNum)) end -- Misc ---------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- function filesystem.exists(path) local addr,reason,lastNum = filesystem.findNode(path) assert(addr, reason) if addr.disk.isDirectory(path:sub(lastNum)) or addr.disk.exists(path:sub(lastNum)) 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,lastNum = filesystem.findNode(path) assert(mount, reason) return mount.disk.list(path:sub(lastNum)) end return filesystem