forked from Hyperion/HyperionOS
185 lines
4.8 KiB
Plaintext
185 lines
4.8 KiB
Plaintext
local kernel = ...
|
|
local openFiles = {}
|
|
kernel.openFiles = openFiles
|
|
local vfs = {}
|
|
vfs.mounts = {}
|
|
local disks = kernel.disks
|
|
vfs.cwd = ""
|
|
|
|
local function resolvePath(path)
|
|
local mountPoint = "/"
|
|
local mountId = "$"
|
|
if path:sub(1,1)~="/" then path=vfs.cwd..path end
|
|
for k,v in pairs(vfs.mounts) do
|
|
if path:sub(1,#v) == v and #v > #mountPoint then
|
|
mountPoint = v
|
|
mountId = k
|
|
end
|
|
end
|
|
local diskPath = path:sub(#mountPoint+1)
|
|
return disks[mountId], diskPath
|
|
end
|
|
|
|
function vfs.mount(diskId, path)
|
|
if kernel.uid ~= 0 then error("Permission denied") end
|
|
if not disks[diskId] then
|
|
error("Attempted to mount unknown disk '"..diskId.."'")
|
|
return false
|
|
end
|
|
if vfs.mounts[diskId] then
|
|
error("Disk '"..diskId.."' is already mounted")
|
|
return false
|
|
end
|
|
if path:sub(#path,#path)~="/" then path=path.."/" end
|
|
for i,v in pairs(vfs.mounts) do
|
|
if v == path then
|
|
error("Mount point '"..path.."' is already in use")
|
|
return false
|
|
end
|
|
end
|
|
vfs.mounts[diskId] = path
|
|
end
|
|
|
|
function vfs.unmount(path)
|
|
if kernel.uid ~= 0 then error("Permission denied") end
|
|
for k,v in pairs(vfs.mounts) do
|
|
if v == path then
|
|
vfs.mounts[k] = nil
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function vfs.open(path, mode)
|
|
local disk, diskPath = resolvePath(path)
|
|
if not disk then
|
|
error("No disk mounted for path '"..path.."'")
|
|
return nil
|
|
end
|
|
local uuid = kernel.newUUID()
|
|
openFiles[uuid] = {disk=disk.address, path=path, mode=mode, handle=disk:open(diskPath, mode)}
|
|
return uuid
|
|
end
|
|
|
|
function vfs.close(fileId)
|
|
local file = openFiles[fileId]
|
|
if not file then
|
|
error("Invalid file handle")
|
|
return false
|
|
end
|
|
local disk = disks[file.disk]
|
|
disk:close(file.handle)
|
|
openFiles[fileId] = nil
|
|
return true
|
|
end
|
|
|
|
function vfs.read(fileId, count)
|
|
local file = openFiles[fileId]
|
|
if not file then
|
|
error("Invalid file handle")
|
|
return nil
|
|
end
|
|
if not file.mode:find("r") then
|
|
error("File not opened in read mode")
|
|
return nil
|
|
end
|
|
local disk = disks[file.disk]
|
|
return disk:read(file.handle, count)
|
|
end
|
|
|
|
function vfs.write(fileId, data)
|
|
local file = openFiles[fileId]
|
|
if not file then
|
|
error("Invalid file handle")
|
|
return false
|
|
end
|
|
if not file.mode:find("w") then
|
|
error("File not opened in write mode")
|
|
return false
|
|
end
|
|
local disk = disks[file.disk]
|
|
return disk:write(file.handle, data)
|
|
end
|
|
|
|
function vfs.mkdir(path)
|
|
local disk, diskPath = resolvePath(path)
|
|
if not disk then
|
|
error("No disk mounted for path '"..path.."'")
|
|
return false
|
|
end
|
|
return disk:mkdir(diskPath)
|
|
end
|
|
|
|
function vfs.remove(path)
|
|
local disk, diskPath = resolvePath(path)
|
|
if not disk then
|
|
error("No disk mounted for path '"..path.."'")
|
|
return false
|
|
end
|
|
return disk:remove(diskPath)
|
|
end
|
|
|
|
function vfs.atributes(path)
|
|
local disk, diskPath = resolvePath(path)
|
|
if not disk then
|
|
error("No disk mounted for path '"..path.."'")
|
|
return nil
|
|
end
|
|
return disk:attributes(diskPath)
|
|
end
|
|
|
|
function vfs.list(path)
|
|
local disk, diskPath = resolvePath(path)
|
|
if not disk then
|
|
error("No disk mounted for path '"..path.."'")
|
|
return nil
|
|
end
|
|
return disk:list(diskPath)
|
|
end
|
|
|
|
function vfs.exists(path)
|
|
local disk, diskPath = resolvePath(path)
|
|
if not disk then
|
|
error("No disk mounted for path '"..path.."'")
|
|
return false
|
|
end
|
|
return disk:directoryExists(diskPath) or disk:fileExists(diskPath)
|
|
end
|
|
|
|
function vfs.type(path)
|
|
local disk, diskPath = resolvePath(path)
|
|
if not disk then
|
|
error("No disk mounted for path '"..path.."'")
|
|
return nil
|
|
end
|
|
return disk:type(diskPath)
|
|
end
|
|
|
|
function vfs.getcwd()
|
|
return vfs.cwd
|
|
end
|
|
|
|
function vfs.setcwd(path)
|
|
if path:sub(#path,#path)~="/" then path=path.."/" end
|
|
if path:sub(1,1)~="/" then path="/"..path end
|
|
vfs.cwd=path
|
|
end
|
|
|
|
kernel.vfs = vfs
|
|
kernel.registerSyscall(0x01, vfs.open)
|
|
kernel.registerSyscall(0x02, vfs.read)
|
|
kernel.registerSyscall(0x03, vfs.write)
|
|
kernel.registerSyscall(0x04, vfs.close)
|
|
kernel.registerSyscall(0x05, vfs.list)
|
|
kernel.registerSyscall(0x06, vfs.type)
|
|
kernel.registerSyscall(0x07, vfs.atributes)
|
|
kernel.registerSyscall(0x08, vfs.mkdir)
|
|
kernel.registerSyscall(0x09, vfs.remove)
|
|
kernel.registerSyscall(0x0a, vfs.exists)
|
|
kernel.registerSyscall(0x0b, vfs.mount)
|
|
kernel.registerSyscall(0x0c, vfs.unmount)
|
|
kernel.registerSyscall(0x0d, vfs.getcwd)
|
|
kernel.registerSyscall(0x0e, vfs.setcwd)
|
|
|
|
kernel.log("VFS module loaded") |