vfs rewrite lol fml
This commit is contained in:
@@ -70,6 +70,9 @@ while true do
|
|||||||
print("Terminated")
|
print("Terminated")
|
||||||
printInline("> ")
|
printInline("> ")
|
||||||
stopInput=false
|
stopInput=false
|
||||||
|
elseif event[1]=="keyTyped" and event[3]=="^d" then
|
||||||
|
syscall.HPV_kill(proc)
|
||||||
|
syscall.HPV_exit(0)
|
||||||
else
|
else
|
||||||
syscall.IO_pushEvent("bash:"..tostring(pid), table.unpack(event))
|
syscall.IO_pushEvent("bash:"..tostring(pid), table.unpack(event))
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
local userhost = (syscall.OS_getUser() or "Unknown").."@"..(syscall.OS_getHostname() or "Unknown")
|
local userhost = (syscall.OS_getUser() or "Unknown").."@"..(syscall.OS_getHostname() or "Unknown")
|
||||||
print(".. *. .. | "..userhost)
|
print(".. *. .. | "..userhost)
|
||||||
print(" *= +@* +* | "..string.rep("-",#userhost))
|
print(" *= +@* +* | "../rep("-",#userhost))
|
||||||
print(" .@#. -@@@= :#@. | OS: "..(syscall.OS_version() or "Unknown"))
|
print(" .@#. -@@@= :#@. | OS: "..(syscall.OS_version() or "Unknown"))
|
||||||
print(" =@@+ *@@@# +@@= | Host: "..(syscall.OS_getHost() or "Unknown"))
|
print(" =@@+ *@@@# +@@= | Host: "..(syscall.OS_getHost() or "Unknown"))
|
||||||
print(" %@@%: *@@@# -%@@% | Uptime: "..(syscall.OS_getUptime() or "Unknown"))
|
print(" %@@%: *@@@# -%@@% | Uptime: "..(syscall.OS_getUptime() or "Unknown"))
|
||||||
|
|||||||
0
Src/Hyperion-bash/bin/sudo
Normal file
0
Src/Hyperion-bash/bin/sudo
Normal file
@@ -1,3 +1,4 @@
|
|||||||
|
--:Minify:--
|
||||||
-- blake2s.lua
|
-- blake2s.lua
|
||||||
-- Pure Lua 5.2, 32-bit only, supports keyed hashing
|
-- Pure Lua 5.2, 32-bit only, supports keyed hashing
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local fs={}
|
local fs={}
|
||||||
|
|
||||||
-- "VFS_open" : open
|
-- "open" : open
|
||||||
-- "VFS_read" : read
|
-- "read" : read
|
||||||
-- "VFS_write" : write
|
-- "write" : write
|
||||||
-- "VFS_close" : close
|
-- "close" : close
|
||||||
|
|
||||||
function fs.open(path, mode)
|
function fs.open(path, mode)
|
||||||
local fd=syscall.VFS_open(path,mode)
|
local fd=syscall.open(path,mode)
|
||||||
local ret={
|
local ret={
|
||||||
close=function()
|
close=function()
|
||||||
-- close file
|
-- close file
|
||||||
return syscall.VFS_close(fd)
|
return syscall.close(fd)
|
||||||
end,
|
end,
|
||||||
flush=function()
|
flush=function()
|
||||||
-- close and reopen file to flush buffers
|
-- close and reopen file to flush buffers
|
||||||
syscall.VFS_close(fd)
|
syscall.close(fd)
|
||||||
fd=syscall.VFS_open(path,mode)
|
fd=syscall.open(path,mode)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
if mode=="r" then
|
if mode=="r" then
|
||||||
ret.read=function(count)
|
ret.read=function(count)
|
||||||
local data = syscall.VFS_read(fd,count)
|
local data = syscall.read(fd,count)
|
||||||
return data
|
return data
|
||||||
end
|
end
|
||||||
ret.readAll=function(chunkSize)
|
ret.readAll=function(chunkSize)
|
||||||
local chunks={} -- to store read chunks
|
local chunks={} -- to store read chunks
|
||||||
while true do
|
while true do
|
||||||
local chunk=syscall.VFS_read(fd,chunkSize or 65536)
|
local chunk=syscall.read(fd,chunkSize or 65536)
|
||||||
if chunk==nil or #chunk==0 then break end
|
if chunk==nil or #chunk==0 then break end
|
||||||
table.insert(chunks,chunk)
|
table.insert(chunks,chunk)
|
||||||
end
|
end
|
||||||
@@ -60,7 +60,7 @@ function fs.open(path, mode)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Read the next chunk
|
-- Read the next chunk
|
||||||
local chunk = syscall.VFS_read(fd, chunk_size)
|
local chunk = syscall.read(fd, chunk_size)
|
||||||
if not chunk or chunk == "" then
|
if not chunk or chunk == "" then
|
||||||
eof = true
|
eof = true
|
||||||
else
|
else
|
||||||
@@ -71,12 +71,12 @@ function fs.open(path, mode)
|
|||||||
elseif mode=="w" then
|
elseif mode=="w" then
|
||||||
ret.write=function(data)
|
ret.write=function(data)
|
||||||
-- write data to file
|
-- write data to file
|
||||||
return syscall.VFS_write(fd,data)
|
return syscall.write(fd,data)
|
||||||
end
|
end
|
||||||
elseif mode=="a" then
|
elseif mode=="a" then
|
||||||
ret.write=function(data)
|
ret.write=function(data)
|
||||||
-- append data to file
|
-- append data to file
|
||||||
return syscall.VFS_write(fd,data)
|
return syscall.write(fd,data)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
error("Invalid mode '"..mode.."'",2)
|
error("Invalid mode '"..mode.."'",2)
|
||||||
@@ -106,39 +106,39 @@ function fs.appendAllText(path, data)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function fs.mkdir(path)
|
function fs.mkdir(path)
|
||||||
return syscall.VFS_mkdir(path)
|
return syscall.mkdir(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.remove(path)
|
function fs.remove(path)
|
||||||
return syscall.VFS_remove(path)
|
return syscall.remove(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.list(path)
|
function fs.list(path)
|
||||||
return syscall.VFS_list(path)
|
return syscall.list(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.type(path)
|
function fs.type(path)
|
||||||
return syscall.VFS_type(path)
|
return syscall.type(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.attributes(path)
|
function fs.attributes(path)
|
||||||
return syscall.VFS_attributes(path)
|
return syscall.attributes(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.exists(path)
|
function fs.exists(path)
|
||||||
return syscall.VFS_exists(path)
|
return syscall.exists(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.getcwd()
|
function fs.getcwd()
|
||||||
return syscall.VFS_getcwd()
|
return syscall.getcwd()
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.setcwd(path)
|
function fs.setcwd(path)
|
||||||
return syscall.VFS_setcwd(path)
|
return syscall.setcwd(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.isDir(path)
|
function fs.isDir(path)
|
||||||
return syscall.VFS_isDirectory(path)
|
return syscall.isDirectory(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
return fs
|
return fs
|
||||||
@@ -6,7 +6,7 @@ syscall.IO_bind("raw")
|
|||||||
|
|
||||||
for i,v in pairs(kernel.processes) do
|
for i,v in pairs(kernel.processes) do
|
||||||
kernel.log("Spawning kernel task "..i)
|
kernel.log("Spawning kernel task "..i)
|
||||||
syscall.HPV_spawn(function()
|
syscall.spawn(function()
|
||||||
local status, err = pcall(v)
|
local status, err = pcall(v)
|
||||||
if not status then
|
if not status then
|
||||||
kernel.log("Error executing kernel task '" .. i .. "': " .. err, "ERROR")
|
kernel.log("Error executing kernel task '" .. i .. "': " .. err, "ERROR")
|
||||||
|
|||||||
@@ -13,11 +13,6 @@ local function write(text)
|
|||||||
if c == "\n" then
|
if c == "\n" then
|
||||||
y = y + 1
|
y = y + 1
|
||||||
x = 1
|
x = 1
|
||||||
if y-1 >= h then
|
|
||||||
term.scroll(1)
|
|
||||||
y = h
|
|
||||||
term.setCursorPos(x, y)
|
|
||||||
end
|
|
||||||
elseif c == "\t" then
|
elseif c == "\t" then
|
||||||
local tabSize = 4
|
local tabSize = 4
|
||||||
local spaces = tabSize - ((x - 1) % tabSize)
|
local spaces = tabSize - ((x - 1) % tabSize)
|
||||||
|
|||||||
@@ -116,14 +116,12 @@ local function write(text, term)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Handle wrapping if we go past right edge
|
|
||||||
if x > w then
|
if x > w then
|
||||||
x = 1
|
x = 1
|
||||||
y = y + 1
|
y = y + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Handle scrolling if we go past bottom
|
if y-1 >= h then
|
||||||
if y-1 > h then
|
|
||||||
term.scroll(1)
|
term.scroll(1)
|
||||||
y = h
|
y = h
|
||||||
term.setCursorPos(x, y)
|
term.setCursorPos(x, y)
|
||||||
@@ -175,8 +173,10 @@ for _, name in ipairs(getNames()) do
|
|||||||
local t = getType(name)
|
local t = getType(name)
|
||||||
if t == "monitor" then
|
if t == "monitor" then
|
||||||
local monitorTerm = wrapPeripheral(name)
|
local monitorTerm = wrapPeripheral(name)
|
||||||
|
if not monitorTerm then
|
||||||
|
error("Failed to wrap monitor peripheral")
|
||||||
|
end
|
||||||
monitorTerm.setTextScale(0.5)
|
monitorTerm.setTextScale(0.5)
|
||||||
kernel.tty.register(name, newTTY(monitorTerm))
|
kernel.tty.register(name, newTTY(monitorTerm))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
U $;/
|
U $;/
|
||||||
U devfs0000;/dev/
|
|
||||||
@@ -233,19 +233,21 @@ function kernel.reboot()
|
|||||||
kernel.computer:reboot()
|
kernel.computer:reboot()
|
||||||
end
|
end
|
||||||
|
|
||||||
kernel.syscalls["OS_time"]=function() return kernel.computer:time() end
|
kernel.syscalls["time"]=function() return kernel.computer:time() end
|
||||||
kernel.syscalls["OS_log"]=kernel.log
|
kernel.syscalls["log"]=kernel.log
|
||||||
kernel.syscalls["OS_getUptime"]=function() return kernel.computer:clock() end
|
kernel.syscalls["getUptime"]=function() return kernel.computer:clock() end
|
||||||
kernel.syscalls["OS_getUser"]=function() return kernel.user end
|
kernel.syscalls["getUser"]=function() return kernel.user end
|
||||||
kernel.syscalls["OS_getHostname"]=function() return kernel.host end
|
kernel.syscalls["getHostname"]=function() return kernel.host end
|
||||||
kernel.syscalls["OS_getHost"]=function() return kernel.apis._HOST end
|
kernel.syscalls["getHost"]=function() return kernel.apis._HOST end
|
||||||
kernel.syscalls["OS_version"]=function() return kernel.version end
|
kernel.syscalls["version"]=function() return kernel.version end
|
||||||
kernel.syscalls["OS_setHostname"]=function(name) if kernel.uid~=0 then error("Permission denied") end kernel.hostname=name end
|
kernel.syscalls["setHostname"]=function(name) if kernel.uid~=0 then error("Permission denied") end kernel.hostname=name end
|
||||||
kernel.syscalls["OS_setUser"]=function(uid) if kernel.uid~=0 then error("Permission denied") end kernel.currentTask.uid=uid end
|
kernel.syscalls["setUser"]=function(uid) if kernel.uid~=0 then error("Permission denied") end kernel.currentTask.uid=uid end
|
||||||
|
kernel.syscalls["test"]=function() return true end
|
||||||
|
|
||||||
kernel.log("Running modules")
|
kernel.log("Running modules")
|
||||||
for _,p in ipairs(modules) do
|
for _,p in ipairs(modules) do
|
||||||
for _,v in ipairs(p) do
|
for _,v in ipairs(p) do
|
||||||
|
if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG") end
|
||||||
local code=ifs.readAllText(v)
|
local code=ifs.readAllText(v)
|
||||||
if not code then
|
if not code then
|
||||||
kernel.log("ModuReadErr: "..v, "WARN", 8)
|
kernel.log("ModuReadErr: "..v, "WARN", 8)
|
||||||
@@ -255,6 +257,7 @@ for _,p in ipairs(modules) do
|
|||||||
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) goto skip end
|
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) goto skip end
|
||||||
local status, err = xpcall(func,debug.traceback, kernel)
|
local status, err = xpcall(func,debug.traceback, kernel)
|
||||||
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
||||||
|
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG") end
|
||||||
::skip::
|
::skip::
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
local vfs = {}
|
local vfs = {}
|
||||||
|
kernel.vfs=vfs
|
||||||
vfs.mounts = { ["$"] = "/" }
|
vfs.mounts = { ["$"] = "/" }
|
||||||
local disks = kernel.disks
|
vfs.disks = kernel.disks
|
||||||
|
|
||||||
-- Path handling
|
-- Path normalization
|
||||||
local function normalizePath(path)
|
local function normalizePath(path)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local cwd = task.cwd or "/"
|
||||||
|
if path:sub(1,1) ~= "/" then path = cwd .. "/" .. path end
|
||||||
local parts = {}
|
local parts = {}
|
||||||
for part in path:gmatch("[^/]+") do
|
for part in path:gmatch("[^/]+") do
|
||||||
if part == ".." then
|
if part == ".." then
|
||||||
@@ -17,14 +20,8 @@ local function normalizePath(path)
|
|||||||
return "/" .. table.concat(parts, "/") .. (path:sub(-1) == "/" and "/" or "")
|
return "/" .. table.concat(parts, "/") .. (path:sub(-1) == "/" and "/" or "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Resolve mount and disk path
|
||||||
local function resolvePath(path)
|
local function resolvePath(path)
|
||||||
local task = kernel.currentTask
|
|
||||||
local cwd = task.cwd or "/"
|
|
||||||
|
|
||||||
if path:sub(1,1) ~= "/" then
|
|
||||||
path = cwd .. path
|
|
||||||
end
|
|
||||||
|
|
||||||
path = normalizePath(path)
|
path = normalizePath(path)
|
||||||
|
|
||||||
local mountPoint = "/"
|
local mountPoint = "/"
|
||||||
@@ -36,246 +33,429 @@ local function resolvePath(path)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local diskPath = path:sub(#mountPoint + 1)
|
local diskPath = path:sub(#mountPoint)
|
||||||
return disks[mountId], diskPath
|
if diskPath == "" then diskPath = "/" end
|
||||||
|
|
||||||
|
return vfs.disks[mountId], diskPath
|
||||||
end
|
end
|
||||||
|
|
||||||
-- File object creation
|
-- Allocate file descriptor for current task
|
||||||
local function newFileObject(disk, handle, mode, path)
|
local function allocFD(task)
|
||||||
|
local fd = 0
|
||||||
|
while task.fd[fd] do fd = fd + 1 end
|
||||||
|
if fd >= kernel.config.maxFilesPerTask then error("ENFILE") end
|
||||||
|
return fd
|
||||||
|
end
|
||||||
|
|
||||||
|
-- System-wide open file limit
|
||||||
|
local total = 0
|
||||||
|
local function checkSystemLimit()
|
||||||
|
if total >= kernel.config.maxOpenFiles - 16 then error("ENFILE") end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- File object constructor
|
||||||
|
local function newFileObj(handle, mode, path, meta)
|
||||||
return {
|
return {
|
||||||
disk = disk,
|
|
||||||
handle = handle,
|
handle = handle,
|
||||||
mode = mode,
|
mode = mode,
|
||||||
path = path,
|
path = path,
|
||||||
refcount = 1
|
meta = meta
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local function allocFD(task)
|
-- Validate mode
|
||||||
local fd = 0
|
local function ismode(mode)
|
||||||
while task.fd[fd] do fd = fd + 1 end
|
if not (mode == "r" or mode == "w" or mode == "a") then error("EINVAL") end
|
||||||
return fd
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function allocFD(task)
|
-- Parse metafile
|
||||||
local count = 0
|
local function parseMetafile(file)
|
||||||
for _ in pairs(task.fd) do count = count + 1 end
|
local ret={}
|
||||||
if count >= kernel.config.maxFilesPerTask then
|
local pointer=1
|
||||||
error("EMFILE")
|
while pointer <= #file do
|
||||||
|
local namelen = file:byte(pointer)
|
||||||
|
pointer = pointer + 1
|
||||||
|
local name = file:sub(pointer, pointer + namelen - 1)
|
||||||
|
pointer = pointer + namelen
|
||||||
|
local owner = file:byte(pointer)
|
||||||
|
local group = file:byte(pointer+1)
|
||||||
|
local perms = file:byte(pointer+2)
|
||||||
|
pointer = pointer + 3
|
||||||
|
local cmetalen = file:byte(pointer)
|
||||||
|
pointer = pointer + 1
|
||||||
|
local cmeta = ""
|
||||||
|
if cmetalen > 0 then
|
||||||
|
cmeta = file:sub(pointer, pointer + cmetalen - 1)
|
||||||
|
pointer = pointer + cmetalen
|
||||||
|
end
|
||||||
|
ret[name] = {
|
||||||
|
owner = owner,
|
||||||
|
group = group,
|
||||||
|
perms = perms,
|
||||||
|
cmeta = cmeta
|
||||||
|
}
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Build metafile
|
||||||
|
local function makeMetafile(meta)
|
||||||
|
local file=""
|
||||||
|
for name, m in pairs(meta) do
|
||||||
|
local entry = ""
|
||||||
|
entry = entry .. string.char(#name) .. name
|
||||||
|
entry = entry .. string.char(m.owner, m.group, m.perms)
|
||||||
|
entry = entry .. string.char(#m.cmeta) .. m.cmeta
|
||||||
|
file = file .. entry
|
||||||
|
end
|
||||||
|
return file
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get metafile path and target
|
||||||
|
local function getMeta(path)
|
||||||
|
local disk, newPath = resolvePath(path)
|
||||||
|
|
||||||
|
kernel.log(newPath)
|
||||||
|
while newPath ~= "/" and newPath~="" do
|
||||||
|
local target = newPath:match("([^/]+)/?$")
|
||||||
|
kernel.log(target)
|
||||||
|
if target == ".meta" then error("Cannot open metafile") end
|
||||||
|
if disk:fileExists(newPath .. ".meta") then
|
||||||
|
return newPath .. ".meta", target
|
||||||
|
end
|
||||||
|
newPath = newPath:gsub("/[^/]+/?$", "")
|
||||||
|
kernel.log(newPath)
|
||||||
|
kernel.saveLog()
|
||||||
end
|
end
|
||||||
|
|
||||||
local fd = 0
|
return nil
|
||||||
while task.fd[fd] do fd = fd + 1 end
|
|
||||||
return fd
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local total=0
|
-- Get file metadata object
|
||||||
local function checkSystemLimit()
|
local function getFileMeta(path)
|
||||||
if total >= kernel.config.maxOpenFiles-16 then
|
local mpath, target = getMeta(path)
|
||||||
error("ENFILE")
|
if not mpath then
|
||||||
|
return { owner=0, group=0, perms=62, cmeta="" }
|
||||||
end
|
end
|
||||||
|
local disk, _ = resolvePath(mpath)
|
||||||
|
local file = disk:open(mpath, "r")
|
||||||
|
local text = file.read(65535)
|
||||||
|
file.close()
|
||||||
|
return parseMetafile(text)[target]
|
||||||
end
|
end
|
||||||
|
|
||||||
-- VFS syscalls
|
-- Permission checking
|
||||||
|
local function checkperms(meta, mode)
|
||||||
|
local modes = {
|
||||||
|
r = {owner=5, group=3, everyone=1},
|
||||||
|
w = {owner=4, group=2, everyone=0},
|
||||||
|
a = {owner=4, group=2, everyone=0}
|
||||||
|
}
|
||||||
|
|
||||||
|
local bits = meta.perms
|
||||||
|
local function bit_is_set(num, bit)
|
||||||
|
return math.floor(num / (2^bit)) % 2 == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if kernel.uid == 0 then return true end
|
||||||
|
if kernel.uid == meta.owner and bit_is_set(bits, modes[mode].owner) then return true end
|
||||||
|
if meta.group and kernel.groups then
|
||||||
|
for _, gid in ipairs(kernel.groups) do
|
||||||
|
if gid == meta.group and bit_is_set(bits, modes[mode].group) then return true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if bit_is_set(bits, modes[mode].everyone) then return true end
|
||||||
|
error("EACCES")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- mounts
|
||||||
|
local function normalizeMountPoint(path)
|
||||||
|
path = normalizePath(path)
|
||||||
|
if path ~= "/" and path:sub(-1) == "/" then
|
||||||
|
path = path:sub(1, -2)
|
||||||
|
end
|
||||||
|
return path
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.mount(target, diskOrId)
|
||||||
|
if kernel.uid ~= 0 then error("EPERM") end
|
||||||
|
if not target then error("EINVAL") end
|
||||||
|
|
||||||
|
target = normalizeMountPoint(target)
|
||||||
|
|
||||||
|
local disk
|
||||||
|
local id
|
||||||
|
|
||||||
|
if type(diskOrId) == "string" then
|
||||||
|
disk = kernel.disks[diskOrId]
|
||||||
|
id = diskOrId
|
||||||
|
if not disk then error("ENODEV") end
|
||||||
|
elseif type(diskOrId) == "table" then
|
||||||
|
disk = diskOrId
|
||||||
|
id = tostring(disk)
|
||||||
|
vfs.disks[id] = disk
|
||||||
|
else
|
||||||
|
error("EINVAL")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Prevent shadowing an existing mount
|
||||||
|
for _, mp in pairs(vfs.mounts) do
|
||||||
|
if mp == target then
|
||||||
|
error("EBUSY")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vfs.mounts[id] = target
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.umount(target)
|
||||||
|
if kernel.uid ~= 0 then error("EPERM") end
|
||||||
|
if not target then error("EINVAL") end
|
||||||
|
|
||||||
|
target = normalizeMountPoint(target)
|
||||||
|
|
||||||
|
for id, mp in pairs(vfs.mounts) do
|
||||||
|
if mp == target then
|
||||||
|
if id == "$" then error("EBUSY") end -- root fs
|
||||||
|
vfs.mounts[id] = nil
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
error("EINVAL")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Open file
|
||||||
function vfs.open(path, mode)
|
function vfs.open(path, mode)
|
||||||
local task = kernel.currentTask
|
ismode(mode)
|
||||||
|
|
||||||
-- check limits
|
|
||||||
checkSystemLimit()
|
checkSystemLimit()
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local fd = allocFD(task)
|
||||||
local disk, diskPath = resolvePath(path)
|
local disk, diskPath = resolvePath(path)
|
||||||
if not disk then
|
if not disk then error("NODISK") end
|
||||||
error("No disk mounted for path '"..path.."'")
|
|
||||||
end
|
local meta = getFileMeta(path)
|
||||||
|
checkperms(meta, mode)
|
||||||
|
|
||||||
local handle = disk:open(diskPath, mode)
|
local handle = disk:open(diskPath, mode)
|
||||||
if not handle then return nil end
|
task.fd[fd] = newFileObj(handle, mode, path, meta)
|
||||||
|
total = total + 1
|
||||||
local file = newFileObject(disk.address, handle, mode, path)
|
|
||||||
local fd = allocFD(task)
|
|
||||||
task.fd[fd] = file
|
|
||||||
total=total+1
|
|
||||||
|
|
||||||
return fd
|
return fd
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Read
|
||||||
|
function vfs.read(fd, count)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local file = task.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
if file.mode ~= "r" then error("EBADF") end
|
||||||
|
return file.handle.read(count or 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Write
|
||||||
|
function vfs.write(fd, content)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local file = task.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
if file.mode ~= "w" and file.mode ~= "a" then error("EBADF") end
|
||||||
|
return file.handle.write(content)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Pread / Pwrite
|
||||||
|
function vfs.pread(fd, count, offset)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local file = task.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
if file.mode ~= "r" then error("EBADF") end
|
||||||
|
file.handle.seek("set", offset)
|
||||||
|
return file.handle.read(count or 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.pwrite(fd, content, offset)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local file = task.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
if file.mode ~= "w" and file.mode ~= "a" then error("EBADF") end
|
||||||
|
file.handle.seek("set", offset)
|
||||||
|
return file.handle.write(content)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Seek
|
||||||
|
function vfs.lseek(fd, offset, whence)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local file = task.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
return file.handle.seek(whence or "set", offset)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Fsync
|
||||||
|
function vfs.fsync(fd)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local file = task.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
if file.mode ~= "w" and file.mode ~= "a" then error("EBADF") end
|
||||||
|
file.handle.flush()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Close
|
||||||
function vfs.close(fd)
|
function vfs.close(fd)
|
||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local file = task.fd[fd]
|
local file = task.fd[fd]
|
||||||
if not file then error("EBADF") end
|
if not file then error("EBADF") end
|
||||||
|
file.handle.close()
|
||||||
task.fd[fd] = nil
|
task.fd[fd] = nil
|
||||||
file.refcount = file.refcount - 1
|
total = total - 1
|
||||||
if file.refcount == 0 then
|
|
||||||
file.handle.close()
|
|
||||||
end
|
|
||||||
total=total-1
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function vfs.read(fd, count)
|
-- Sendfile
|
||||||
local file = kernel.currentTask.fd[fd]
|
function vfs.sendfile(outfd, infd, count)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local inFile = task.fd[infd]
|
||||||
|
local outFile = task.fd[outfd]
|
||||||
|
if not inFile or not outFile then error("EBADF") end
|
||||||
|
if inFile.mode ~= "r" then error("EBADF") end
|
||||||
|
if outFile.mode ~= "w" and outFile.mode ~= "a" then error("EBADF") end
|
||||||
|
local data = inFile.handle.read(count or 1024)
|
||||||
|
return outFile.handle.write(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Stat / Fstat
|
||||||
|
function vfs.stat(path)
|
||||||
|
local disk, diskPath = resolvePath(path)
|
||||||
|
local meta = getFileMeta(path)
|
||||||
|
local attrs = disk:attributes(diskPath)
|
||||||
|
return {
|
||||||
|
size = attrs.size,
|
||||||
|
modified = attrs.modified,
|
||||||
|
created = attrs.created,
|
||||||
|
owner = meta.owner,
|
||||||
|
group = meta.group,
|
||||||
|
xattr = meta.cmeta
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.fstat(fd)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local file = task.fd[fd]
|
||||||
if not file then error("EBADF") end
|
if not file then error("EBADF") end
|
||||||
if not file.mode:find("r") then error("File not open for reading") end
|
local disk, path = resolvePath(file.path)
|
||||||
return file.handle.read(count)
|
local attrs = disk:attributes(path)
|
||||||
|
return {
|
||||||
|
size = attrs.size,
|
||||||
|
modified = attrs.modified,
|
||||||
|
created = attrs.created,
|
||||||
|
owner = file.meta.owner,
|
||||||
|
group = file.meta.group,
|
||||||
|
xattr = file.meta.cmeta
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function vfs.write(fd, data)
|
-- Directory operations
|
||||||
local file = kernel.currentTask.fd[fd]
|
function vfs.listdir(path)
|
||||||
if not file then error("EBADF") end
|
local disk, diskPath = resolvePath(path)
|
||||||
if not file.mode:find("w") then error("File not open for writing") end
|
if disk:type(diskPath) ~= "directory" then error("ENOTDIR") end
|
||||||
return file.handle.write(data)
|
local meta = getFileMeta(path)
|
||||||
|
checkperms(meta, "r")
|
||||||
|
return disk:list(diskPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vfs.whereis(fd)
|
|
||||||
local file = kernel.currentTask.fd[fd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
return file.path
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Filesystem operations
|
|
||||||
function vfs.mkdir(path)
|
function vfs.mkdir(path)
|
||||||
local disk, diskPath = resolvePath(path)
|
local disk, diskPath = resolvePath(path)
|
||||||
if not disk then error("No disk mounted") end
|
local meta = getFileMeta(path)
|
||||||
return disk:makeDirectory(diskPath)
|
checkperms(meta, "w")
|
||||||
|
disk:makeDirectory(diskPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vfs.remove(path)
|
function vfs.remove(path)
|
||||||
local disk, diskPath = resolvePath(path)
|
local disk, diskPath = resolvePath(path)
|
||||||
if not disk then error("No disk mounted") end
|
local meta = getFileMeta(path)
|
||||||
return disk:remove(diskPath)
|
checkperms(meta, "w")
|
||||||
|
disk:remove(diskPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vfs.attributes(path)
|
-- Permission functions
|
||||||
if type(path) == "number" then
|
function vfs.chmod(path, perms)
|
||||||
local file = kernel.currentTask.fd[path]
|
local disk, diskPath = resolvePath(path)
|
||||||
if not file then error("EBADF") end
|
local meta = getFileMeta(path)
|
||||||
return disks[file.disk]:attributes(file.path)
|
checkperms(meta, "w")
|
||||||
|
meta.perms = perms
|
||||||
|
local mpath, target = getMeta(path)
|
||||||
|
if mpath then
|
||||||
|
local mf = disk:open(mpath,"r")
|
||||||
|
local text = mf.read(65535)
|
||||||
|
mf.close()
|
||||||
|
local parsed = parseMetafile(text)
|
||||||
|
parsed[target] = meta
|
||||||
|
local file = disk:open(mpath,"w")
|
||||||
|
file.write(makeMetafile(parsed))
|
||||||
|
file.close()
|
||||||
end
|
end
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then error("No disk mounted") end
|
|
||||||
return disk:attributes(diskPath)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function vfs.list(path)
|
function vfs.fchmod(fd, perms)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local file = task.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
vfs.chmod(file.path, perms)
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.chown(path, uid, gid)
|
||||||
local disk, diskPath = resolvePath(path)
|
local disk, diskPath = resolvePath(path)
|
||||||
if not disk then error("No disk mounted") end
|
local meta = getFileMeta(path)
|
||||||
return disk:list(diskPath)
|
checkperms(meta, "w")
|
||||||
|
meta.owner = uid
|
||||||
|
meta.group = gid
|
||||||
|
local mpath, target = getMeta(path)
|
||||||
|
if mpath then
|
||||||
|
local mf = disk:open(mpath,"r")
|
||||||
|
local text = mf.read(65535)
|
||||||
|
mf.close()
|
||||||
|
local parsed = parseMetafile(text)
|
||||||
|
parsed[target] = meta
|
||||||
|
local file = disk:open(mpath,"w")
|
||||||
|
file.write(makeMetafile(parsed))
|
||||||
|
file.close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function vfs.fchown(fd, uid, gid)
|
||||||
|
local task = kernel.currentTask
|
||||||
|
local file = task.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
|
vfs.chown(file.path, uid, gid)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vfs.exists(path)
|
function vfs.exists(path)
|
||||||
local disk, diskPath = resolvePath(path)
|
local disk, diskPath = resolvePath(path)
|
||||||
if not disk then return false end
|
local meta = getFileMeta(path)
|
||||||
return disk:directoryExists(diskPath) or disk:fileExists(diskPath)
|
checkperms(meta, "r")
|
||||||
|
disk:fileExists(diskPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vfs.type(path)
|
-- Export syscalls
|
||||||
if type(path) == "number" then
|
local sys = kernel.syscalls
|
||||||
local file = kernel.currentTask.fd[path]
|
sys["open"] = vfs.open
|
||||||
if not file then error("EBADF") end
|
sys["close"] = vfs.close
|
||||||
return disks[file.disk]:type(file.path)
|
sys["read"] = vfs.read
|
||||||
end
|
sys["write"] = vfs.write
|
||||||
local disk, diskPath = resolvePath(path)
|
sys["pread"] = vfs.pread
|
||||||
if not disk then error("No disk mounted") end
|
sys["pwrite"] = vfs.pwrite
|
||||||
return disk:type(diskPath)
|
sys["lseek"] = vfs.lseek
|
||||||
end
|
sys["fsync"] = vfs.fsync
|
||||||
|
sys["sendfile"] = vfs.sendfile
|
||||||
function vfs.isDirectory(path)
|
sys["stat"] = vfs.stat
|
||||||
local disk, diskPath = resolvePath(path)
|
sys["fstat"] = vfs.fstat
|
||||||
if not disk then return false end
|
sys["mkdir"] = vfs.mkdir
|
||||||
return disk:directoryExists(diskPath)
|
sys["remove"] = vfs.remove
|
||||||
end
|
sys["listdir"] = vfs.listdir
|
||||||
|
sys["chmod"] = vfs.chmod
|
||||||
-- CWD
|
sys["fchmod"] = vfs.fchmod
|
||||||
function vfs.getcwd()
|
sys["chown"] = vfs.chown
|
||||||
return kernel.currentTask.cwd
|
sys["fchown"] = vfs.fchown
|
||||||
end
|
sys["exists"]=vfs.exists
|
||||||
|
sys["mount"] = vfs.mount
|
||||||
function vfs.setcwd(path)
|
sys["umount"] = vfs.umount
|
||||||
if path:sub(-1) ~= "/" then path = path .. "/" end
|
|
||||||
if path:sub(1,1) ~= "/" then path = "/" .. path end
|
|
||||||
kernel.currentTask.cwd = normalizePath(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Mounting
|
|
||||||
function vfs.mount(diskId, path)
|
|
||||||
if kernel.uid ~= 0 then error("Permission denied") end
|
|
||||||
if not disks[diskId] then error("Unknown disk '"..diskId.."'") end
|
|
||||||
if path:sub(-1) ~= "/" then path = path .. "/" end
|
|
||||||
|
|
||||||
for _,v in pairs(vfs.mounts) do
|
|
||||||
if v == path then error("Mount point already used") 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.getMounts()
|
|
||||||
return vfs.mounts
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.virtdisk(obj)
|
|
||||||
kernel.disks[obj.address] = obj
|
|
||||||
kernel.log("Registered virtual disk at "..obj.address)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Redirect file operations to VFS
|
|
||||||
function vfs.dup(oldfd)
|
|
||||||
local task = kernel.currentTask
|
|
||||||
local file = task.fd[oldfd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
|
|
||||||
local newfd = allocFD(task)
|
|
||||||
task.fd[newfd] = file
|
|
||||||
file.refcount = file.refcount + 1
|
|
||||||
return newfd
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.dup2(oldfd, newfd)
|
|
||||||
local task = kernel.currentTask
|
|
||||||
local file = task.fd[oldfd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
|
|
||||||
if oldfd == newfd then return newfd end
|
|
||||||
|
|
||||||
if task.fd[newfd] then
|
|
||||||
vfs.close(newfd)
|
|
||||||
end
|
|
||||||
|
|
||||||
task.fd[newfd] = file
|
|
||||||
file.refcount = file.refcount + 1
|
|
||||||
return newfd
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Syscall registration
|
|
||||||
kernel.vfs = vfs
|
|
||||||
kernel.syscalls["VFS_open"] = vfs.open
|
|
||||||
kernel.syscalls["VFS_read"] = vfs.read
|
|
||||||
kernel.syscalls["VFS_write"] = vfs.write
|
|
||||||
kernel.syscalls["VFS_close"] = vfs.close
|
|
||||||
kernel.syscalls["VFS_list"] = vfs.list
|
|
||||||
kernel.syscalls["VFS_type"] = vfs.type
|
|
||||||
kernel.syscalls["VFS_attributes"] = vfs.attributes
|
|
||||||
kernel.syscalls["VFS_mkdir"] = vfs.mkdir
|
|
||||||
kernel.syscalls["VFS_remove"] = vfs.remove
|
|
||||||
kernel.syscalls["VFS_exists"] = vfs.exists
|
|
||||||
kernel.syscalls["VFS_mount"] = vfs.mount
|
|
||||||
kernel.syscalls["VFS_unmount"] = vfs.unmount
|
|
||||||
kernel.syscalls["VFS_getcwd"] = vfs.getcwd
|
|
||||||
kernel.syscalls["VFS_setcwd"] = vfs.setcwd
|
|
||||||
kernel.syscalls["VFS_whereis"] = vfs.whereis
|
|
||||||
kernel.syscalls["VFS_dup"] = vfs.dup
|
|
||||||
kernel.syscalls["VFS_dup2"] = vfs.dup2
|
|
||||||
kernel.syscalls["VFS_isDirectory"]= vfs.isDirectory
|
|
||||||
|
|
||||||
kernel.log("VFS module loaded")
|
kernel.log("VFS module loaded")
|
||||||
|
return vfs
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
local cache = {}
|
local cache = {}
|
||||||
local searchpaths = {
|
kernel.searchpaths = {
|
||||||
"/lib/?.lua",
|
"/lib/?.lua",
|
||||||
"/lib/?",
|
"/lib/?",
|
||||||
"/usr/lib/?.lua",
|
"/usr/lib/?.lua",
|
||||||
@@ -18,7 +18,7 @@ function require(module,...)
|
|||||||
end
|
end
|
||||||
local modpath = module:gsub("%.", "/")
|
local modpath = module:gsub("%.", "/")
|
||||||
local failed = {}
|
local failed = {}
|
||||||
for _, path in ipairs(searchpaths) do
|
for _, path in ipairs(kernel.searchpaths) do
|
||||||
local full_path = string.gsub(path, "%?", modpath)
|
local full_path = string.gsub(path, "%?", modpath)
|
||||||
if full_path:sub(1,1)~="/" then
|
if full_path:sub(1,1)~="/" then
|
||||||
full_path=kernel.currentTask.cwd..full_path
|
full_path=kernel.currentTask.cwd..full_path
|
||||||
|
|||||||
@@ -1,173 +1,173 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local kernel = ...
|
--local kernel = ...
|
||||||
|
--
|
||||||
local proxy = {}
|
--local proxy = {}
|
||||||
local data = {}
|
--local data = {}
|
||||||
|
--
|
||||||
proxy.address = "devfs0000"
|
--proxy.address = "devfs0000"
|
||||||
proxy.isReadOnly = false
|
--proxy.isReadOnly = false
|
||||||
proxy.spaceUsed = function() return 0 end
|
--proxy.spaceUsed = function() return 0 end
|
||||||
proxy.spaceTotal = function() return 0 end
|
--proxy.spaceTotal = function() return 0 end
|
||||||
proxy.makeDirectory = function() error("Permission denied") end
|
--proxy.makeDirectory = function() error("Permission denied") end
|
||||||
proxy.remove = function() error("Permission denied") end
|
--proxy.remove = function() error("Permission denied") end
|
||||||
proxy.setLabel = function() error("Permission denied") end
|
--proxy.setLabel = function() error("Permission denied") end
|
||||||
proxy.getLabel = function() return "devfs" end
|
--proxy.getLabel = function() return "devfs" end
|
||||||
proxy.attributes = function(path) return {
|
--proxy.attributes = function(path) return {
|
||||||
type = proxy.type(path),
|
-- type = proxy.type(path),
|
||||||
isReadOnly = false,
|
-- isReadOnly = false,
|
||||||
size = 0,
|
-- size = 0,
|
||||||
lastModified = 0,
|
-- lastModified = 0,
|
||||||
created = 0,
|
-- created = 0,
|
||||||
Permissions = "666",
|
-- Permissions = "666",
|
||||||
owner = "root",
|
-- owner = "root",
|
||||||
group = "root"
|
-- group = "root"
|
||||||
} end
|
--} end
|
||||||
|
--
|
||||||
local function getNode(path)
|
--local function getNode(path)
|
||||||
local parts = string.split(path, "/")
|
-- local parts = string.split(path, "/")
|
||||||
if parts[1] == "" then
|
-- if parts[1] == "" then
|
||||||
table.remove(parts, 1)
|
-- table.remove(parts, 1)
|
||||||
end
|
-- end
|
||||||
|
--
|
||||||
local node = data
|
-- local node = data
|
||||||
for _, part in ipairs(parts) do
|
-- for _, part in ipairs(parts) do
|
||||||
if node[part] then
|
-- if node[part] then
|
||||||
node = node[part]
|
-- node = node[part]
|
||||||
else
|
-- else
|
||||||
return nil
|
-- return nil
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
|
--
|
||||||
return node
|
-- return node
|
||||||
end
|
--end
|
||||||
|
--
|
||||||
proxy.type = function(path)
|
--proxy.type = function(path)
|
||||||
local node = getNode(path)
|
-- local node = getNode(path)
|
||||||
if node then
|
-- if node then
|
||||||
return node.type
|
-- return node.type
|
||||||
else
|
-- else
|
||||||
return nil
|
-- return nil
|
||||||
end
|
-- end
|
||||||
end
|
--end
|
||||||
|
--
|
||||||
proxy.list = function(path)
|
--proxy.list = function(path)
|
||||||
local node = getNode(path)
|
-- local node = getNode(path)
|
||||||
if node and node.type == "directory" then
|
-- if node and node.type == "directory" then
|
||||||
local content = table.keys(node)
|
-- local content = table.keys(node)
|
||||||
table.remove(content, table.indexOf(content, "type"))
|
-- table.remove(content, table.indexOf(content, "type"))
|
||||||
return content
|
-- return content
|
||||||
else
|
-- else
|
||||||
error("Not a directory")
|
-- error("Not a directory")
|
||||||
end
|
-- end
|
||||||
end
|
--end
|
||||||
|
--
|
||||||
proxy.open = function(path, mode)
|
--proxy.open = function(path, mode)
|
||||||
local node = getNode(path)
|
-- local node = getNode(path)
|
||||||
if node and (node.type == "file" or node.type == "character device") then
|
-- if node and (node.type == "file" or node.type == "character device") then
|
||||||
if mode == "r" then
|
-- if mode == "r" then
|
||||||
return {
|
-- return {
|
||||||
read = node.read,
|
-- read = node.read,
|
||||||
close = function() end
|
-- close = function() end
|
||||||
}
|
-- }
|
||||||
elseif mode == "w" then
|
-- elseif mode == "w" then
|
||||||
return {
|
-- return {
|
||||||
write = node.write,
|
-- write = node.write,
|
||||||
close = function() end
|
-- close = function() end
|
||||||
}
|
-- }
|
||||||
else
|
-- else
|
||||||
error("Invalid mode")
|
-- error("Invalid mode")
|
||||||
end
|
-- end
|
||||||
else
|
-- else
|
||||||
error("Not a file"..type(node))
|
-- error("Not a file"..type(node))
|
||||||
end
|
-- end
|
||||||
end
|
--end
|
||||||
|
--
|
||||||
local function newStringFile(content)
|
--local function newStringFile(content)
|
||||||
return {
|
-- return {
|
||||||
type = "file",
|
-- type = "file",
|
||||||
read = function() return content end,
|
-- read = function() return content end,
|
||||||
write = function(newContent) content = newContent end
|
-- write = function(newContent) content = newContent end
|
||||||
}
|
-- }
|
||||||
end
|
--end
|
||||||
|
--
|
||||||
local function newDirectory()
|
--local function newDirectory()
|
||||||
return {
|
-- return {
|
||||||
type = "directory"
|
-- type = "directory"
|
||||||
}
|
-- }
|
||||||
end
|
--end
|
||||||
|
--
|
||||||
data["random"] = {
|
--data["random"] = {
|
||||||
type = "character device",
|
-- type = "character device",
|
||||||
read = function(amount)
|
-- read = function(amount)
|
||||||
local result = ""
|
-- local result = ""
|
||||||
for _ = 1, amount do
|
-- for _ = 1, amount do
|
||||||
result = result .. string.char(math.random(0, 255))
|
-- result = result .. string.char(math.random(0, 255))
|
||||||
end
|
-- end
|
||||||
return result
|
-- return result
|
||||||
end,
|
-- end,
|
||||||
write = function() error("Permission denied") end
|
-- write = function() error("Permission denied") end
|
||||||
}
|
--}
|
||||||
|
--
|
||||||
data["null"] = {
|
--data["null"] = {
|
||||||
type = "character device",
|
-- type = "character device",
|
||||||
read = function() return "" end,
|
-- read = function() return "" end,
|
||||||
write = function() end
|
-- write = function() end
|
||||||
}
|
--}
|
||||||
|
--
|
||||||
data["zero"] = {
|
--data["zero"] = {
|
||||||
type = "character device",
|
-- type = "character device",
|
||||||
read = function(amount)
|
-- read = function(amount)
|
||||||
return string.rep("\0", amount)
|
-- return string.rep("\0", amount)
|
||||||
end,
|
-- end,
|
||||||
write = function() error("Permission denied") end
|
-- write = function() error("Permission denied") end
|
||||||
}
|
--}
|
||||||
|
--
|
||||||
data["rtc"] = {
|
--data["rtc"] = {
|
||||||
type = "character device",
|
-- type = "character device",
|
||||||
read = function() return kernel.computer:time() end,
|
-- read = function() return kernel.computer:time() end,
|
||||||
write = function() error("Permission denied") end
|
-- write = function() error("Permission denied") end
|
||||||
}
|
--}
|
||||||
|
--
|
||||||
data["rtc0"] = {
|
--data["rtc0"] = {
|
||||||
type = "character device",
|
-- type = "character device",
|
||||||
read = function() return kernel.computer:time() end,
|
-- read = function() return kernel.computer:time() end,
|
||||||
write = function() error("Permission denied") end
|
-- write = function() error("Permission denied") end
|
||||||
}
|
--}
|
||||||
|
--
|
||||||
data["eeprom"] = {
|
--data["eeprom"] = {
|
||||||
type = "character device",
|
-- type = "character device",
|
||||||
read = function() return kernel.computer:getEEPROM() end,
|
-- read = function() return kernel.computer:getEEPROM() end,
|
||||||
write = function(data)
|
-- write = function(data)
|
||||||
if kernel.uid ~= 0 then
|
-- if kernel.uid ~= 0 then
|
||||||
error("Permission denied")
|
-- error("Permission denied")
|
||||||
end
|
-- end
|
||||||
kernel.computer:setEEPROM(data)
|
-- kernel.computer:setEEPROM(data)
|
||||||
end
|
-- end
|
||||||
}
|
--}
|
||||||
|
--
|
||||||
local keyboard = kernel.newFifo()
|
--local keyboard = kernel.newFifo()
|
||||||
local mouse = kernel.newFifo()
|
--local mouse = kernel.newFifo()
|
||||||
data["input"] = newDirectory()
|
--data["input"] = newDirectory()
|
||||||
data["input"]["keyboard"] = {
|
--data["input"]["keyboard"] = {
|
||||||
type = "pipe",
|
-- type = "pipe",
|
||||||
read = function(amount)
|
-- read = function(amount)
|
||||||
return keyboard.pop()
|
-- return keyboard.pop()
|
||||||
end,
|
-- end,
|
||||||
write = function() error("Permission denied") end
|
-- write = function() error("Permission denied") end
|
||||||
}
|
--}
|
||||||
data["input"]["mouse"] = {
|
--data["input"]["mouse"] = {
|
||||||
type = "pipe",
|
-- type = "pipe",
|
||||||
read = function(amount)
|
-- read = function(amount)
|
||||||
return mouse.pop()
|
-- return mouse.pop()
|
||||||
end,
|
-- end,
|
||||||
write = function() error("Permission denied") end
|
-- write = function() error("Permission denied") end
|
||||||
}
|
--}
|
||||||
|
--
|
||||||
data["pts"] = newDirectory()
|
--data["pts"] = newDirectory()
|
||||||
|
--
|
||||||
kernel.devfs = {}
|
--kernel.devfs = {}
|
||||||
kernel.devfs.keyboard = keyboard
|
--kernel.devfs.keyboard = keyboard
|
||||||
kernel.devfs.mouse = mouse
|
--kernel.devfs.mouse = mouse
|
||||||
kernel.devfs.proxy = proxy
|
--kernel.devfs.proxy = proxy
|
||||||
kernel.devfs.data = data
|
--kernel.devfs.data = data
|
||||||
kernel.vfs.virtdisk(proxy)
|
--kernel.vfs.virtdisk(proxy)
|
||||||
@@ -11,7 +11,7 @@ for i,v in ipairs(string.split(kernel.fstab,"\n")) do
|
|||||||
end
|
end
|
||||||
local path=v:sub(#id+4)
|
local path=v:sub(#id+4)
|
||||||
if id~="$" then
|
if id~="$" then
|
||||||
kernel.vfs.mount(id,path)
|
kernel.vfs.mount(path, id)
|
||||||
end
|
end
|
||||||
::endline::
|
::endline::
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
--:Minify:--
|
|
||||||
local kernel = ...
|
|
||||||
local ports = {}
|
|
||||||
local signals = {}
|
|
||||||
local ipc = {}
|
|
||||||
|
|
||||||
function ipc.open(port)
|
|
||||||
if not ports[port] then
|
|
||||||
local handle = kernel.newUUID()
|
|
||||||
ports[port] = {owner = kernel.currentProcess.pid, handle = handle, messages = {}}
|
|
||||||
return ports[port].handle
|
|
||||||
end
|
|
||||||
error("Port already opened")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.close(port)
|
|
||||||
if ports[port] then
|
|
||||||
if ports[port].owner == kernel.currentProcess.pid then
|
|
||||||
ports[port] = nil
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
error("Cannot close port you do not own")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
error("Port not opened")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.send(port, message)
|
|
||||||
if ports[port] then
|
|
||||||
table.insert(ports[port].messages, {from = kernel.currentProcess.pid, message = message})
|
|
||||||
if signals[ports[port].owner] then
|
|
||||||
signals[ports[port].owner](port, message)
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
error("Port not opened")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.receive(port)
|
|
||||||
if ports[port] then
|
|
||||||
if #ports[port].messages > 0 then
|
|
||||||
return table.remove(ports[port].messages, 1)
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
error("Port not opened")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.setSignalHandler(pid, handler)
|
|
||||||
signals[pid] = handler
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.clearSignalHandler(pid)
|
|
||||||
signals[pid] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.sendSignal(pid, ...)
|
|
||||||
coroutine.resumeWithTimeout(coroutine.create(function(...)
|
|
||||||
if signals[pid] then
|
|
||||||
signals[pid](...)
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end), 100)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.ipc = ipc
|
|
||||||
kernel.syscalls["ipc_open"] = ipc.open
|
|
||||||
kernel.syscalls["ipc_close"] = ipc.close
|
|
||||||
kernel.syscalls["ipc_send"] = ipc.send
|
|
||||||
kernel.syscalls["ipc_receive"] = ipc.receive
|
|
||||||
kernel.syscalls["ipc_setSignalHandler"] = ipc.setSignalHandler
|
|
||||||
kernel.syscalls["ipc_clearSignalHandler"] = ipc.clearSignalHandler
|
|
||||||
kernel.syscalls["ipc_sendSignal"] = ipc.sendSignal
|
|
||||||
kernel.log("Loaded IPC module")
|
|
||||||
10
Src/Hyperion-kernel/lib/modules/Hyperion/20_socket.kmod
Normal file
10
Src/Hyperion-kernel/lib/modules/Hyperion/20_socket.kmod
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
--:Minify:--
|
||||||
|
local kernel = ...
|
||||||
|
local socket = {}
|
||||||
|
|
||||||
|
function socket.socket()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.socket=socket
|
||||||
|
kernel.log("Loaded socket module")
|
||||||
@@ -1,66 +1,238 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local kernel = ...
|
--local kernel = ...
|
||||||
local pam = {}
|
--local pam = {}
|
||||||
kernel.pam = pam
|
--kernel.pam = pam
|
||||||
local loggedIn = {}
|
--local loggedIn = {}
|
||||||
|
--
|
||||||
local function getFile(path)
|
--local function getFile(path)
|
||||||
local file = kernel.vfs.open(path, "r")
|
-- local file = kernel.vfs.open(path, "r")
|
||||||
if not file then error("Failed to open file: "..path) end
|
-- if not file then error("Failed to open file: "..path) end
|
||||||
local content = kernel.vfs.read(file, 1024000)
|
-- local content = kernel.vfs.read(file, 1024000)
|
||||||
kernel.vfs.close(file)
|
-- kernel.vfs.close(file)
|
||||||
return content
|
-- return content
|
||||||
end
|
--end
|
||||||
|
--
|
||||||
local blake2s = require("crypto.blake2s")
|
--local blake2s
|
||||||
if not blake2s then error("Failed to load blake2s") end
|
--
|
||||||
|
--do
|
||||||
if not kernel.vfs.exists("/etc/pam.d/secret") then
|
-- local MOD32 = 2^32
|
||||||
local key = ""
|
-- local function norm(x)
|
||||||
for i=1, 256 do
|
-- return x % MOD32
|
||||||
key=key..string.char(math.random(1,255))
|
-- end
|
||||||
end
|
--
|
||||||
local handle = kernel.vfs.open("/etc/pam.d/secret", "w")
|
-- local function tobits(x)
|
||||||
kernel.vfs.write(handle, key)
|
-- x = norm(x)
|
||||||
kernel.vfs.close(handle)
|
-- local t = {}
|
||||||
end
|
-- for i = 0, 31 do
|
||||||
|
-- local b = x % 2
|
||||||
local pepper = getFile("/etc/pam.d/secret")
|
-- t[i] = b
|
||||||
|
-- x = (x - b) / 2
|
||||||
function pam.authenticate(username, password)
|
-- end
|
||||||
local fpasswd = getFile("/etc/passwd")
|
-- return t
|
||||||
local fshadow = getFile("/etc/shadow")
|
-- end
|
||||||
|
--
|
||||||
local passwdLines = string.split(fpasswd, "\n")
|
-- local function frombits(t)
|
||||||
local shadowLines = string.split(fshadow, "\n")
|
-- local x = 0
|
||||||
|
-- local p = 1
|
||||||
local passwd = {}
|
-- for i = 0, 31 do
|
||||||
local shadow = {}
|
-- if t[i] == 1 then
|
||||||
for _, line in ipairs(passwdLines) do
|
-- x = x + p
|
||||||
local fields = string.split(line, ":")
|
-- end
|
||||||
passwd[fields[1]] = fields
|
-- p = p * 2
|
||||||
end
|
-- end
|
||||||
for _, line in ipairs(shadowLines) do
|
-- return norm(x)
|
||||||
local fields = string.split(line, ":")
|
-- end
|
||||||
shadow[fields[1]] = fields
|
--
|
||||||
end
|
-- local function bor(...)
|
||||||
|
-- local args = {...}
|
||||||
for user, fields in pairs(passwd) do
|
-- if #args == 0 then return 0 end
|
||||||
if user == username then
|
-- local bits = tobits(args[1])
|
||||||
local shadowPasswd = string.split(shadow[user][2], "$")
|
-- for i = 2, #args do
|
||||||
local salt = shadowPasswd[2]
|
-- local b = tobits(args[i])
|
||||||
local hashedPassword = blake2s(password .. salt, pepper)
|
-- for j = 0, 31 do
|
||||||
if hashedPassword == shadowPasswd[3] then
|
-- bits[j] = (bits[j] == 1 or b[j] == 1) and 1 or 0
|
||||||
loggedIn[username] = kernel.newUUID()
|
-- end
|
||||||
return loggedIn[username]
|
-- end
|
||||||
else
|
-- return frombits(bits)
|
||||||
return false
|
-- end
|
||||||
end
|
--
|
||||||
end
|
-- local function bxor(...)
|
||||||
end
|
-- local args = {...}
|
||||||
end
|
-- if #args == 0 then return 0 end
|
||||||
|
-- local bits = tobits(args[1])
|
||||||
function pam.authToken(username, token)
|
-- for i = 2, #args do
|
||||||
return loggedIn[username] == token
|
-- local b = tobits(args[i])
|
||||||
end
|
-- for j = 0, 31 do
|
||||||
|
-- bits[j] = (bits[j] ~= b[j]) and 1 or 0
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- return frombits(bits)
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- local function lshift(x, n)
|
||||||
|
-- return norm(norm(x) * 2^n)
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- local function rshift(x, n)
|
||||||
|
-- return math.floor(norm(x) / 2^n)
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- local function rotr(x, n)
|
||||||
|
-- return bor(rshift(x, n), lshift(x, 32 - n))
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- local IV = {
|
||||||
|
-- 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
||||||
|
-- 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
|
||||||
|
-- }
|
||||||
|
--
|
||||||
|
-- local SIGMA = {
|
||||||
|
-- {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
|
||||||
|
-- {14,10,4,8,9,15,13,6,1,12,0,2,11,7,5,3},
|
||||||
|
-- {11,8,12,0,5,2,15,13,10,14,3,6,7,1,9,4},
|
||||||
|
-- {7,9,3,1,13,12,11,14,2,6,5,10,4,0,15,8},
|
||||||
|
-- {9,0,5,7,2,4,10,15,14,1,11,12,6,8,3,13},
|
||||||
|
-- {2,12,6,10,0,11,8,3,4,13,7,5,15,14,1,9},
|
||||||
|
-- {12,5,1,15,14,13,4,10,0,7,6,3,9,2,8,11},
|
||||||
|
-- {13,11,7,14,12,1,3,9,5,0,15,4,8,6,2,10},
|
||||||
|
-- {6,15,14,9,11,3,0,8,12,2,13,7,1,4,10,5},
|
||||||
|
-- {10,2,8,4,7,6,1,5,15,11,9,14,3,12,13,0}
|
||||||
|
-- }
|
||||||
|
--
|
||||||
|
-- local function G(v, a, b, c, d, x, y)
|
||||||
|
-- v[a] = (v[a] + v[b] + x) % MOD32
|
||||||
|
-- v[d] = rotr(bxor(v[d], v[a]), 16)
|
||||||
|
-- v[c] = (v[c] + v[d]) % MOD32
|
||||||
|
-- v[b] = rotr(bxor(v[b], v[c]), 12)
|
||||||
|
-- v[a] = (v[a] + v[b] + y) % MOD32
|
||||||
|
-- v[d] = rotr(bxor(v[d], v[a]), 8)
|
||||||
|
-- v[c] = (v[c] + v[d]) % MOD32
|
||||||
|
-- v[b] = rotr(bxor(v[b], v[c]), 7)
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- local function compress(h, block, t, last)
|
||||||
|
-- local v = {}
|
||||||
|
-- for i = 1, 8 do v[i] = h[i] end
|
||||||
|
-- for i = 1, 8 do v[i + 8] = IV[i] end
|
||||||
|
--
|
||||||
|
-- v[13] = bxor(v[13], t)
|
||||||
|
-- if last then
|
||||||
|
-- v[15] = bxor(v[15], 0xFFFFFFFF)
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- local m = {}
|
||||||
|
-- for i = 0, 15 do
|
||||||
|
-- local p = i * 4 + 1
|
||||||
|
-- m[i] =
|
||||||
|
-- (block:byte(p) or 0) +
|
||||||
|
-- ((block:byte(p + 1) or 0) * 0x100) +
|
||||||
|
-- ((block:byte(p + 2) or 0) * 0x10000) +
|
||||||
|
-- ((block:byte(p + 3) or 0) * 0x1000000)
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- for r = 1, 10 do
|
||||||
|
-- local s = SIGMA[r]
|
||||||
|
-- G(v,1,5,9,13, m[s[1]], m[s[2]])
|
||||||
|
-- G(v,2,6,10,14, m[s[3]], m[s[4]])
|
||||||
|
-- G(v,3,7,11,15, m[s[5]], m[s[6]])
|
||||||
|
-- G(v,4,8,12,16, m[s[7]], m[s[8]])
|
||||||
|
-- G(v,1,6,11,16, m[s[9]], m[s[10]])
|
||||||
|
-- G(v,2,7,12,13, m[s[11]], m[s[12]])
|
||||||
|
-- G(v,3,8,9,14, m[s[13]], m[s[14]])
|
||||||
|
-- G(v,4,5,10,15, m[s[15]], m[s[16]])
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- for i = 1, 8 do
|
||||||
|
-- h[i] = bxor(h[i], v[i], v[i + 8])
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- function blake2s(msg, key)
|
||||||
|
-- key = key or ""
|
||||||
|
--
|
||||||
|
-- local h = {}
|
||||||
|
-- for i = 1, 8 do h[i] = IV[i] end
|
||||||
|
--
|
||||||
|
-- local outlen = 32 -- bytes
|
||||||
|
-- h[1] = bxor(
|
||||||
|
-- h[1],
|
||||||
|
-- 0x01010000 + lshift(#key, 8) + outlen
|
||||||
|
-- )
|
||||||
|
--
|
||||||
|
-- local t = 0
|
||||||
|
--
|
||||||
|
-- if #key > 0 then
|
||||||
|
-- local block = key .. string.rep("\0", 64 - #key)
|
||||||
|
-- t = #key
|
||||||
|
-- compress(h, block, t, false)
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- for i = 1, #msg, 64 do
|
||||||
|
-- local block = msg:sub(i, i + 63)
|
||||||
|
-- if #block < 64 then
|
||||||
|
-- block = block .. string.rep("\0", 64 - #block)
|
||||||
|
-- end
|
||||||
|
-- t = t + math.min(64, #msg - i + 1)
|
||||||
|
-- compress(h, block, t, i + 64 > #msg)
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- local out = ""
|
||||||
|
-- for i = 1, 8 do
|
||||||
|
-- out = out .. string.format("%08x", h[i])
|
||||||
|
-- end
|
||||||
|
-- return out
|
||||||
|
-- end
|
||||||
|
--end
|
||||||
|
--
|
||||||
|
--if not blake2s then error("Failed to load blake2s") end
|
||||||
|
--
|
||||||
|
--if not kernel.vfs.exists("/etc/pam.d/secret") then
|
||||||
|
-- local key = ""
|
||||||
|
-- for i=1, 256 do
|
||||||
|
-- key=key..string.char(math.random(1,255))
|
||||||
|
-- end
|
||||||
|
-- local handle = kernel.vfs.open("/etc/pam.d/secret", "w")
|
||||||
|
-- kernel.vfs.write(handle, key)
|
||||||
|
-- kernel.vfs.close(handle)
|
||||||
|
--end
|
||||||
|
--
|
||||||
|
--local pepper = getFile("/etc/pam.d/secret")
|
||||||
|
--
|
||||||
|
--function pam.authenticate(username, password)
|
||||||
|
-- local fpasswd = getFile("/etc/passwd")
|
||||||
|
-- local fshadow = getFile("/etc/shadow")
|
||||||
|
--
|
||||||
|
-- local passwdLines = string.split(fpasswd, "\n")
|
||||||
|
-- local shadowLines = string.split(fshadow, "\n")
|
||||||
|
--
|
||||||
|
-- local passwd = {}
|
||||||
|
-- local shadow = {}
|
||||||
|
-- for _, line in ipairs(passwdLines) do
|
||||||
|
-- local fields = string.split(line, ":")
|
||||||
|
-- passwd[fields[1]] = fields
|
||||||
|
-- end
|
||||||
|
-- for _, line in ipairs(shadowLines) do
|
||||||
|
-- local fields = string.split(line, ":")
|
||||||
|
-- shadow[fields[1]] = fields
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- for user, fields in pairs(passwd) do
|
||||||
|
-- if user == username then
|
||||||
|
-- local shadowPasswd = string.split(shadow[user][2], "$")
|
||||||
|
-- local salt = shadowPasswd[2]
|
||||||
|
-- local hashedPassword = blake2s(password .. salt, pepper)
|
||||||
|
-- if hashedPassword == shadowPasswd[3] then
|
||||||
|
-- loggedIn[username] = kernel.newUUID()
|
||||||
|
-- return loggedIn[username]
|
||||||
|
-- else
|
||||||
|
-- return false
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
--end
|
||||||
|
--
|
||||||
|
--function pam.authToken(username, token)
|
||||||
|
-- return loggedIn[username] == token
|
||||||
|
--end
|
||||||
|
--
|
||||||
|
--
|
||||||
@@ -16,7 +16,9 @@ function sys.spawn(func, name, envars, args, tgid)
|
|||||||
kernel.log("Task "..tostring(id).." exited with err: "..tostring(err), "ERROR", 2)
|
kernel.log("Task "..tostring(id).." exited with err: "..tostring(err), "ERROR", 2)
|
||||||
end
|
end
|
||||||
tasks[tostring(id)].status="Z"
|
tasks[tostring(id)].status="Z"
|
||||||
tasks[tostring(id)].exit=err
|
if type(err)=="number" then
|
||||||
|
tasks[tostring(id)].exit=err
|
||||||
|
end
|
||||||
else
|
else
|
||||||
if kernel.config.logTaskExit then
|
if kernel.config.logTaskExit then
|
||||||
if err then
|
if err then
|
||||||
@@ -26,7 +28,9 @@ function sys.spawn(func, name, envars, args, tgid)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
tasks[tostring(id)].status="Z"
|
tasks[tostring(id)].status="Z"
|
||||||
tasks[tostring(id)].exit=err
|
if type(err)=="number" then
|
||||||
|
tasks[tostring(id)].exit=err
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end),
|
end),
|
||||||
name=name or ("task"..tostring(id)),
|
name=name or ("task"..tostring(id)),
|
||||||
@@ -79,8 +83,6 @@ function sys.getTaskInfo(pid)
|
|||||||
end
|
end
|
||||||
return {
|
return {
|
||||||
name=task.name,
|
name=task.name,
|
||||||
envars=table.deepcopy(task.envars),
|
|
||||||
args=table.deepcopy(task.args),
|
|
||||||
status=task.status,
|
status=task.status,
|
||||||
pid=task.pid,
|
pid=task.pid,
|
||||||
tgid=task.tgid,
|
tgid=task.tgid,
|
||||||
@@ -173,7 +175,7 @@ end
|
|||||||
|
|
||||||
function sys.list()
|
function sys.list()
|
||||||
local ret={}
|
local ret={}
|
||||||
for i,_ in ipairs(tasks) do
|
for i,_ in pairs(tasks) do
|
||||||
ret[i]=sys.getTaskInfo(i)
|
ret[i]=sys.getTaskInfo(i)
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
@@ -187,18 +189,33 @@ function sys.setEnviron(key, value)
|
|||||||
kernel.currentTask.envars[key]=value
|
kernel.currentTask.envars[key]=value
|
||||||
end
|
end
|
||||||
|
|
||||||
kernel.syscalls["HPV_spawn"]=sys.spawn
|
function sys.exit(code)
|
||||||
kernel.syscalls["HPV_sleep"]=sys.sleep
|
if kernel.config.logTaskExit then
|
||||||
kernel.syscalls["HPV_getTaskInfo"]=sys.getTaskInfo
|
if code then
|
||||||
kernel.syscalls["HPV_collect"]=sys.collect
|
kernel.log("Task "..tostring(kernel.currentTask.pid).." exited with code: "..tostring(code), "INFO")
|
||||||
kernel.syscalls["HPV_kill"]=sys.kill
|
else
|
||||||
kernel.syscalls["HPV_stop"]=sys.stop
|
kernel.log("Task "..tostring(kernel.currentTask.pid).." exited without code", "INFO")
|
||||||
kernel.syscalls["HPV_continue"]=sys.continue
|
end
|
||||||
kernel.syscalls["HPV_getPid"]=sys.getPid
|
end
|
||||||
kernel.syscalls["HPV_list"]=sys.list
|
tasks[tostring(kernel.currentTask.pid)].status="Z"
|
||||||
kernel.syscalls["HPV_setEnviron"]=sys.setEnviron
|
if type(code)=="number" then
|
||||||
kernel.syscalls["HPV_getEnviron"]=sys.getEnviron
|
tasks[tostring(kernel.currentTask.pid)].exit=code
|
||||||
kernel._G.sleep=function(...)coroutine.yield("syscall","HPV_sleep",...)end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
kernel.syscalls["spawn"]=sys.spawn
|
||||||
|
kernel.syscalls["sleep"]=sys.sleep
|
||||||
|
kernel.syscalls["getTaskInfo"]=sys.getTaskInfo
|
||||||
|
kernel.syscalls["collect"]=sys.collect
|
||||||
|
kernel.syscalls["kill"]=sys.kill
|
||||||
|
kernel.syscalls["stop"]=sys.stop
|
||||||
|
kernel.syscalls["continue"]=sys.continue
|
||||||
|
kernel.syscalls["getPid"]=sys.getPid
|
||||||
|
kernel.syscalls["list"]=sys.list
|
||||||
|
kernel.syscalls["setEnviron"]=sys.setEnviron
|
||||||
|
kernel.syscalls["getEnviron"]=sys.getEnviron
|
||||||
|
kernel.syscalls["exit"]=sys.exit
|
||||||
|
kernel._G.sleep=function(...)coroutine.yield("syscall","sleep",...)end
|
||||||
|
|
||||||
local function reapDeadTasks()
|
local function reapDeadTasks()
|
||||||
for pid, task in pairs(tasks) do
|
for pid, task in pairs(tasks) do
|
||||||
@@ -216,7 +233,7 @@ local function reapDeadTasks()
|
|||||||
task.timeSlice = nil
|
task.timeSlice = nil
|
||||||
task.syscallReturn = nil
|
task.syscallReturn = nil
|
||||||
task.sleep = nil
|
task.sleep = nil
|
||||||
for k,v in pairs(task.fd) do
|
for v,_ in ipairs(task.fd) do
|
||||||
kernel.vfs.close(v)
|
kernel.vfs.close(v)
|
||||||
end
|
end
|
||||||
task.fd = nil
|
task.fd = nil
|
||||||
|
|||||||
@@ -1,90 +1,91 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local kernel=...
|
local kernel=...
|
||||||
kernel.tty={}
|
local tty={}
|
||||||
kernel.tty.inst={}
|
kernel.tty=tty
|
||||||
|
tty.inst={}
|
||||||
|
|
||||||
function kernel.tty.register(tty, ttyo)
|
function tty.register(ttyn, ttyo)
|
||||||
kernel.tty.inst[tty]=ttyo
|
tty.inst[ttyn]=ttyo
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.print(text)
|
function tty.print(text)
|
||||||
local term=kernel.currentTask.term
|
local term=kernel.currentTask.term
|
||||||
if term and kernel.tty.inst[term] then
|
if term and tty.inst[term] then
|
||||||
kernel.tty.inst[term].print(text)
|
tty.inst[term].print(text)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.printInline(text)
|
function tty.printInline(text)
|
||||||
local term=kernel.currentTask.term
|
local term=kernel.currentTask.term
|
||||||
if term and kernel.tty.inst[term] then
|
if term and tty.inst[term] then
|
||||||
kernel.tty.inst[term].printInline(text)
|
tty.inst[term].printInline(text)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.size()
|
function tty.size()
|
||||||
local term=kernel.currentTask.term
|
local term=kernel.currentTask.term
|
||||||
if term and kernel.tty.inst[term] then
|
if term and tty.inst[term] then
|
||||||
return kernel.tty.inst[term].size()
|
return tty.inst[term].size()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.setCursorPos(x,y)
|
function tty.setCursorPos(x,y)
|
||||||
local term=kernel.currentTask.term
|
local term=kernel.currentTask.term
|
||||||
if term and kernel.tty.inst[term] then
|
if term and tty.inst[term] then
|
||||||
return kernel.tty.inst[term].setCursorPos(x,y)
|
return tty.inst[term].setCursorPos(x,y)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.getCursorPos()
|
function tty.getCursorPos()
|
||||||
local term=kernel.currentTask.term
|
local term=kernel.currentTask.term
|
||||||
if term and kernel.tty.inst[term] then
|
if term and tty.inst[term] then
|
||||||
return kernel.tty.inst[term].getCursorPos()
|
return tty.inst[term].getCursorPos()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.clear()
|
function tty.clear()
|
||||||
local term=kernel.currentTask.term
|
local term=kernel.currentTask.term
|
||||||
if term and kernel.tty.inst[term] then
|
if term and tty.inst[term] then
|
||||||
return kernel.tty.inst[term].clear()
|
return tty.inst[term].clear()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.setTextColor(color)
|
function tty.setTextColor(color)
|
||||||
local term=kernel.currentTask.term
|
local term=kernel.currentTask.term
|
||||||
if term and kernel.tty.inst[term] then
|
if term and tty.inst[term] then
|
||||||
return kernel.tty.inst[term].setTextColor(color)
|
return tty.inst[term].setTextColor(color)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.setBackgroundColor(color)
|
function tty.setBackgroundColor(color)
|
||||||
local term=kernel.currentTask.term
|
local term=kernel.currentTask.term
|
||||||
if term and kernel.tty.inst[term] then
|
if term and tty.inst[term] then
|
||||||
return kernel.tty.inst[term].setBackgroundColor(color)
|
return tty.inst[term].setBackgroundColor(color)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.scroll(n)
|
function tty.scroll(n)
|
||||||
local term=kernel.currentTask.term
|
local term=kernel.currentTask.term
|
||||||
if term and kernel.tty.inst[term] then
|
if term and tty.inst[term] then
|
||||||
return kernel.tty.inst[term].scroll(n)
|
return tty.inst[term].scroll(n)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.getTextColor()
|
function tty.getTextColor()
|
||||||
local term=kernel.currentTask.term
|
local term=kernel.currentTask.term
|
||||||
if term and kernel.tty.inst[term] and kernel.tty.inst[term].getTextColor then
|
if term and tty.inst[term] and tty.inst[term].getTextColor then
|
||||||
return kernel.tty.inst[term].getTextColor()
|
return tty.inst[term].getTextColor()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.getBackgroundColor()
|
function tty.getBackgroundColor()
|
||||||
local term=kernel.currentTask.term
|
local term=kernel.currentTask.term
|
||||||
if term and kernel.tty.inst[term] and kernel.tty.inst[term].getBackgroundColor then
|
if term and tty.inst[term] and tty.inst[term].getBackgroundColor then
|
||||||
return kernel.tty.inst[term].getBackgroundColor()
|
return tty.inst[term].getBackgroundColor()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.bind(ttyid)
|
function tty.bind(ttyid)
|
||||||
if not ttyid then
|
if not ttyid then
|
||||||
return false, "No TTY ID specified"
|
return false, "No TTY ID specified"
|
||||||
end
|
end
|
||||||
@@ -95,33 +96,34 @@ function kernel.tty.bind(ttyid)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.unbind()
|
function tty.unbind()
|
||||||
kernel.currentTask.term=false
|
kernel.currentTask.term=false
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.isBound()
|
function tty.isBound()
|
||||||
return kernel.currentTask.term ~= nil
|
return kernel.currentTask.term ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function kernel.tty.getBoundTTY()
|
function tty.getBoundTTY()
|
||||||
return kernel.currentTask.term
|
return kernel.currentTask.term
|
||||||
end
|
end
|
||||||
|
|
||||||
kernel.syscalls["TTY_print"]=kernel.tty.print
|
local sys=kernel.syscalls
|
||||||
kernel.syscalls["TTY_printInline"]=kernel.tty.printInline
|
sys["TTY_print"]=tty.print
|
||||||
kernel.syscalls["TTY_size"]=kernel.tty.size
|
sys["TTY_printInline"]=tty.printInline
|
||||||
kernel.syscalls["TTY_setCursorPos"]=kernel.tty.setCursorPos
|
sys["TTY_size"]=tty.size
|
||||||
kernel.syscalls["TTY_getCursorPos"]=kernel.tty.getCursorPos
|
sys["TTY_setCursorPos"]=tty.setCursorPos
|
||||||
kernel.syscalls["TTY_clear"]=kernel.tty.clear
|
sys["TTY_getCursorPos"]=tty.getCursorPos
|
||||||
kernel.syscalls["TTY_setTextColor"]=kernel.tty.setTextColor
|
sys["TTY_clear"]=tty.clear
|
||||||
kernel.syscalls["TTY_setBackgroundColor"]=kernel.tty.setBackgroundColor
|
sys["TTY_setTextColor"]=tty.setTextColor
|
||||||
kernel.syscalls["TTY_scroll"]=kernel.tty.scroll
|
sys["TTY_setBackgroundColor"]=tty.setBackgroundColor
|
||||||
kernel.syscalls["TTY_getTextColor"]=kernel.tty.getTextColor
|
sys["TTY_scroll"]=tty.scroll
|
||||||
kernel.syscalls["TTY_getBackgroundColor"]=kernel.tty.getBackgroundColor
|
sys["TTY_getTextColor"]=tty.getTextColor
|
||||||
kernel.syscalls["TTY_bind"]=kernel.tty.bind
|
sys["TTY_getBackgroundColor"]=tty.getBackgroundColor
|
||||||
kernel.syscalls["TTY_unbind"]=kernel.tty.unbind
|
sys["TTY_bind"]=tty.bind
|
||||||
kernel.syscalls["TTY_isBound"]=kernel.tty.isBound
|
sys["TTY_unbind"]=tty.unbind
|
||||||
kernel.syscalls["TTY_getBoundTTY"]=kernel.tty.getBoundTTY
|
sys["TTY_isBound"]=tty.isBound
|
||||||
|
sys["TTY_getBoundTTY"]=tty.getBoundTTY
|
||||||
|
|
||||||
kernel.log("TTY module loaded attempting to register console tty")
|
kernel.log("TTY module loaded attempting to register console tty")
|
||||||
kernel.status="init"
|
kernel.status="init"
|
||||||
@@ -3,8 +3,11 @@ local kernel = ...
|
|||||||
kernel.log("Loading init system...")
|
kernel.log("Loading init system...")
|
||||||
kernel.log("InitPath: "..kernel.config.initPath)
|
kernel.log("InitPath: "..kernel.config.initPath)
|
||||||
local handle = kernel.vfs.open(kernel.config.initPath, "r")
|
local handle = kernel.vfs.open(kernel.config.initPath, "r")
|
||||||
|
kernel.log("O")
|
||||||
local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
||||||
|
kernel.log("R")
|
||||||
kernel.vfs.close(handle)
|
kernel.vfs.close(handle)
|
||||||
|
kernel.log("C")
|
||||||
|
|
||||||
local initFunc, err = load(data, "@sysinit")
|
local initFunc, err = load(data, "@sysinit")
|
||||||
if not initFunc then
|
if not initFunc then
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
local fs=require("sys.fs")
|
||||||
|
local units=fs.list("/usr/lib/hunit/")
|
||||||
|
fs.mkdir("/tmp/hunit/")
|
||||||
|
local errors={}
|
||||||
|
for i,v in ipairs(units) do
|
||||||
|
print("running unit "..v)
|
||||||
|
local code=fs.readAllText("/usr/lib/hunit/"..v)
|
||||||
|
local func, err=load(code, "@"..v)
|
||||||
|
if not func then
|
||||||
|
print(" [ERROR]:"..err)
|
||||||
|
end
|
||||||
|
---@diagnostic disable-next-line: param-type-mismatch
|
||||||
|
local ok, err=pcall(func)
|
||||||
|
if not ok then
|
||||||
|
print(" [ERROR]:"..err)
|
||||||
|
table.insert(errors, v)
|
||||||
|
else
|
||||||
|
print(" [SUCCESS]")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print(tostring(#errors).." units failed")
|
||||||
|
return 0
|
||||||
3
Test/HyperionOS-units/usr/lib/hunit/dir.unit
Normal file
3
Test/HyperionOS-units/usr/lib/hunit/dir.unit
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
local fs = require("sys.fs")
|
||||||
|
assert(fs.mkdir("/tmp/hunit/testdir"), "failed to make directory")
|
||||||
|
assert(fs.isDir("/tmp/hunit/testdir"), "directory does not exist")
|
||||||
10
Test/HyperionOS-units/usr/lib/hunit/file.unit
Normal file
10
Test/HyperionOS-units/usr/lib/hunit/file.unit
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
local fd = syscall.VFS_open("/tmp/hunit/testfile.txt", "w")
|
||||||
|
syscall.VFS_write(fd, "This is a test file")
|
||||||
|
syscall.VFS_close(fd)
|
||||||
|
local fd = syscall.VFS_open("/tmp/hunit/testfile.txt", "r")
|
||||||
|
local text = syscall.VFS_read(fd, 64)
|
||||||
|
syscall.VFS_close(fd)
|
||||||
|
|
||||||
|
if text~="This is a test file" then
|
||||||
|
error("File failed to write/read")
|
||||||
|
end
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
---@diagnostic disable: undefined-global
|
||||||
local diskpath="put your path here"
|
local diskpath="put your path here"
|
||||||
periphemu.create("right", "drive")
|
periphemu.create("right", "drive")
|
||||||
disk.insertDisk("right", diskpath)
|
disk.insertDisk("right", diskpath)
|
||||||
@@ -7,4 +8,5 @@ file.close()
|
|||||||
|
|
||||||
local func = load(text, "@bios.lua")
|
local func = load(text, "@bios.lua")
|
||||||
|
|
||||||
|
---@diagnostic disable-next-line: need-check-nil
|
||||||
func("/disk")
|
func("/disk")
|
||||||
Reference in New Issue
Block a user