-- Copyright (C) 2025 ASTRONAND -- File open modes -- M | H | D -- rc | r | Read and close -- r | r | Read -- w | w | Write -- o | w | Overite file -- om | m | Overite and modify -- rw | m | Read and write -- x | f | get function local args=({...})[1] local fs={} local disks={} local mounts={} local bootDrive=args.bootDrive local auth=args.auth local log=args.logging for t, o in component.list() do if t=="disk" then if o.id==bootDrive.id then else disks[o.id]=o end end end local function resolve(path) if string.sub(path,1,1)~="/" then path="/"..path end local drive=bootDrive for i,v in pairs(mounts) do if string.hasPrefix(path,v) then drive=disks[i] path=string.getSuffix(path,v) break end end return drive, path end local function checkPerms(path, mode) end local function getHandle(backing,typ,clear) local ret={} local close=false ret.close=function() close=true end if typ=="r" then ret.read=function() if close then return "Handle closed" end return backing.read() end ret.lines=function() if close then error() end local lines=string.split(backing.read(), "\n") local i=0 return function() i=i+1 return lines[i] end end elseif typ=="w" then ret.write=function(data) if close then return "Handle closed" end backing.append(data) end elseif typ=="m" then ret.read=function() if close then return "Handle closed" end return backing.read() end ret.lines=function() if close then error() end local lines=string.split(backing.read(), "\n") local i=0 return function() i=i+1 return lines[i] end end ret.write=function(data) if close then return "Handle closed" end backing.append(data) end end if clear then ret.clear=function() if close then return "Handle closed" end backing.write() end end return ret end local function open(path, mode, arg, pc) if pc then checkPerms(path, mode) end local drive, newPath = resolve(path) if drive:directoryExists(newPath) then error("Cannot open directory") end if not drive:fileExists(newPath) then error("File does not exist") end local backing=drive:open(newPath) if mode=="rc" then local file=getHandle(backing,"r") local text=file.read() file.close() return text elseif mode=="r" then return getHandle(backing,"r") elseif mode=="w" then return getHandle(backing,"w") elseif mode=="o" then local file=getHandle(backing,"w",true) file.clear() file.clear=nil return file elseif mode=="om" then local file=getHandle(backing,"m",true) file.clear() file.clear=nil return file elseif mode=="rw" then return getHandle(backing,"m") elseif mode=="x" then local file=getHandle(backing,"r") local text=file.read() file.close() return load(text, path, nil, table.deepcopy(_G)) elseif mode=="xe" then local file=getHandle(backing,"r") local text=file.read() file.close() return load(text, path, nil, arg) else error("Invailid mode") end end function fs.open(path, mode, arg) return open(path, mode, arg, true) end function fs.copy(orig, dest) local destFile = fs.open(dest,"o") local origFile = fs.open(orig, "rc") destFile.write(origFile) destFile.close() end function fs.move(orig, dest) local destFile = fs.open(dest,"o") local origFile = fs.open(orig, "rc") destFile.write(origFile) destFile.close() fs.delete(orig) end -- This fixes the weirdest bug ever local isDir = function(path, pc) if pc then checkPerms(path, "r") end local drive, newPath = resolve(path) return drive:directoryExists(newPath) end local exists = function(path, pc) if pc then checkPerms(path, "r") end local drive, newPath = resolve(path) return ((drive:directoryExists(newPath)) or (drive:fileExists(newPath))) end local delete = function(path, pc) if pc then checkPerms(path, "w") end local drive, newPath = resolve(path) return drive:delete(newPath) end local list = function(path, pc) if pc then checkPerms(path, "w") end local drive, newPath = resolve(path) return drive:list(newPath) end function fs.list(path) return list(path, true) end function fs.isDir(path) return isDir(path, true) end function fs.exists(path) return exists(path, true) end function fs.delete(path) return delete(path, true) end function fs.getSudo(key) if auth.sudo.isAproved(key) then return { createVirtDisk=function(virtualDiskName,virtualDiskObj) disks[virtualDiskName]=virtualDiskObj log.log("Created VirtIO disk named "..virtualDiskName) end, mount=function(hardwareDir,path) mounts[hardwareDir]=path log.log("Mounted disk ") end, unmount=function(hardwareDir) mounts[hardwareDir]=nil end, eject=function(hardwareDir) disks[hardwareDir]=nil end, sfs={ open=function(path, mode, arg) return open(path, mode, arg) end, delete=function(path) return delete(path) end, copy=fs.copy, move=fs.move, exists=function(path) return exists(path) end, isDir=function(path) return isDir(path) end, list=function(path) return list(path) end } } else error("sudo request denied") end end return fs