do fs = {} local fsmounts = {} -- basics function fs.segments(path) -- string -- table -- Splits *path* on each / local segments = {} for segment in path:gmatch("[^/]+") do segments[#segments+1] = segment end return segments end function fs.resolve(path) -- string -- string string -- Resolves *path* to a specific filesystem mount and path if not path or path == "." then path = os.getenv("PWD") end if path:sub(1,1) ~= "/" then path=(os.getenv("PWD") or "").."/"..path end local segments, rpath, rfs= fs.segments(path) local rc = #segments for i = #segments, 1, -1 do if fsmounts[table.concat(segments, "/", 1, i)] ~= nil then return table.concat(segments, "/", 1, i), table.concat(segments, "/", i+1) end end return "/", table.concat(segments,"/") end -- generate some simple functions for k,v in pairs({"makeDirectory","exists","isDirectory","list","lastModified","remove","size","spaceUsed","spaceTotal","isReadOnly","getLabel"}) do fs[v] = function(path) local fsi,path = fs.resolve(path) return fsmounts[fsi][v](path) end end local function fread(self,length) return fsmounts[self.fs].read(self.fid,length) end local function fwrite(self,data) return fsmounts[self.fs].write(self.fid,data) end local function fseek(self,dist) return fsmounts[self.fs].seek(self.fid,dist) end local function fclose(self) return fsmounts[self.fs].close(self.fid) end function fs.open(path,mode) -- string string -- table -- Opens file *path* with mode *mode*, returning a file object. mode = mode or "rb" local fsi,path = fs.resolve(path) if not fsmounts[fsi] then return false end local fid = fsmounts[fsi].open(path,mode) if fid then local fobj = {["fs"]=fsi,["fid"]=fid,["seek"]=fseek,["close"]=fclose} if mode:find("r") then fobj.read = fread end if mode:find("w") or mode:find("a") then fobj.write = fwrite end return fobj end return false end function fs.copy(from,to) -- string string -- boolean -- copies a file from *from* to *to* local of = fs.open(from,"rb") local df = fs.open(to,"wb") if not of or not df then return false end local tmp repeat tmp = of:read(2048) df:write(tmp or "") until not tmp df:close() of:close() return true end function fs.rename(from,to) -- string string -- boolean -- Moves file *from* to *to* local ofsi, opath = fs.resolve(from) local dfsi, dpath = fs.resolve(to) if ofsi == dfsi then fsmounts[ofsi].rename(opath,dpath) return true end if not fs.copy(from,to) then return false end if not fs.remove(from) then return false end return true end function fs.mount(path,proxy) -- string table -- boolean -- Mounts the filesystem *proxy* to the mount point *path* if it is a directory. BYO proxy. if fs.isDirectory(path) and not fsmounts[table.concat(fs.segments(path),"/")] then fsmounts[table.concat(fs.segments(path),"/")] = proxy return true end return false, "path is not a directory" end function fs.umount(path) -- string -- -- Unmounts filesystem from *path*. local fsi,_ = fs.resolve(path) fsmounts[fsi] = nil end function fs.mounts() -- -- table -- Returns a table containing the mount points of all mounted filesystems local rt = {} for k,v in pairs(fsmounts) do rt[#rt+1] = k,v.address or "unknown" end table.sort(rt) return rt end function fs.address(path) -- string -- string -- Returns the address of the filesystem at a given path, if applicable; do not expect a sensical response local fsi,_ = fs.resolve(path) return fsmounts[fsi].address end function fs.type(path) -- string -- string -- Returns the component type of the filesystem at a given path, if applicable local fsi,_ = fs.resolve(path) return fsmounts[fsi].fstype or fsmounts[fsi].type or "filesystem" end fsmounts["/"] = component.proxy(computer.tmpAddress()) fs.makeDirectory("temp") if computer.getBootAddress and component.type(computer.getBootAddress()) == "filesystem" then fs.makeDirectory("boot") fs.mount("boot",component.proxy(computer.getBootAddress())) end end