vfs rewrite lol fml
This commit is contained in:
@@ -70,6 +70,9 @@ while true do
|
||||
print("Terminated")
|
||||
printInline("> ")
|
||||
stopInput=false
|
||||
elseif event[1]=="keyTyped" and event[3]=="^d" then
|
||||
syscall.HPV_kill(proc)
|
||||
syscall.HPV_exit(0)
|
||||
else
|
||||
syscall.IO_pushEvent("bash:"..tostring(pid), table.unpack(event))
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
local userhost = (syscall.OS_getUser() or "Unknown").."@"..(syscall.OS_getHostname() or "Unknown")
|
||||
print(".. *. .. | "..userhost)
|
||||
print(" *= +@* +* | "..string.rep("-",#userhost))
|
||||
print(" *= +@* +* | "../rep("-",#userhost))
|
||||
print(" .@#. -@@@= :#@. | OS: "..(syscall.OS_version() or "Unknown"))
|
||||
print(" =@@+ *@@@# +@@= | Host: "..(syscall.OS_getHost() 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
|
||||
-- Pure Lua 5.2, 32-bit only, supports keyed hashing
|
||||
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
--:Minify:--
|
||||
local fs={}
|
||||
|
||||
-- "VFS_open" : open
|
||||
-- "VFS_read" : read
|
||||
-- "VFS_write" : write
|
||||
-- "VFS_close" : close
|
||||
-- "open" : open
|
||||
-- "read" : read
|
||||
-- "write" : write
|
||||
-- "close" : close
|
||||
|
||||
function fs.open(path, mode)
|
||||
local fd=syscall.VFS_open(path,mode)
|
||||
local fd=syscall.open(path,mode)
|
||||
local ret={
|
||||
close=function()
|
||||
-- close file
|
||||
return syscall.VFS_close(fd)
|
||||
return syscall.close(fd)
|
||||
end,
|
||||
flush=function()
|
||||
-- close and reopen file to flush buffers
|
||||
syscall.VFS_close(fd)
|
||||
fd=syscall.VFS_open(path,mode)
|
||||
syscall.close(fd)
|
||||
fd=syscall.open(path,mode)
|
||||
end
|
||||
}
|
||||
if mode=="r" then
|
||||
ret.read=function(count)
|
||||
local data = syscall.VFS_read(fd,count)
|
||||
local data = syscall.read(fd,count)
|
||||
return data
|
||||
end
|
||||
ret.readAll=function(chunkSize)
|
||||
local chunks={} -- to store read chunks
|
||||
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
|
||||
table.insert(chunks,chunk)
|
||||
end
|
||||
@@ -60,7 +60,7 @@ function fs.open(path, mode)
|
||||
end
|
||||
|
||||
-- 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
|
||||
eof = true
|
||||
else
|
||||
@@ -71,12 +71,12 @@ function fs.open(path, mode)
|
||||
elseif mode=="w" then
|
||||
ret.write=function(data)
|
||||
-- write data to file
|
||||
return syscall.VFS_write(fd,data)
|
||||
return syscall.write(fd,data)
|
||||
end
|
||||
elseif mode=="a" then
|
||||
ret.write=function(data)
|
||||
-- append data to file
|
||||
return syscall.VFS_write(fd,data)
|
||||
return syscall.write(fd,data)
|
||||
end
|
||||
else
|
||||
error("Invalid mode '"..mode.."'",2)
|
||||
@@ -106,39 +106,39 @@ function fs.appendAllText(path, data)
|
||||
end
|
||||
|
||||
function fs.mkdir(path)
|
||||
return syscall.VFS_mkdir(path)
|
||||
return syscall.mkdir(path)
|
||||
end
|
||||
|
||||
function fs.remove(path)
|
||||
return syscall.VFS_remove(path)
|
||||
return syscall.remove(path)
|
||||
end
|
||||
|
||||
function fs.list(path)
|
||||
return syscall.VFS_list(path)
|
||||
return syscall.list(path)
|
||||
end
|
||||
|
||||
function fs.type(path)
|
||||
return syscall.VFS_type(path)
|
||||
return syscall.type(path)
|
||||
end
|
||||
|
||||
function fs.attributes(path)
|
||||
return syscall.VFS_attributes(path)
|
||||
return syscall.attributes(path)
|
||||
end
|
||||
|
||||
function fs.exists(path)
|
||||
return syscall.VFS_exists(path)
|
||||
return syscall.exists(path)
|
||||
end
|
||||
|
||||
function fs.getcwd()
|
||||
return syscall.VFS_getcwd()
|
||||
return syscall.getcwd()
|
||||
end
|
||||
|
||||
function fs.setcwd(path)
|
||||
return syscall.VFS_setcwd(path)
|
||||
return syscall.setcwd(path)
|
||||
end
|
||||
|
||||
function fs.isDir(path)
|
||||
return syscall.VFS_isDirectory(path)
|
||||
return syscall.isDirectory(path)
|
||||
end
|
||||
|
||||
return fs
|
||||
@@ -6,7 +6,7 @@ syscall.IO_bind("raw")
|
||||
|
||||
for i,v in pairs(kernel.processes) do
|
||||
kernel.log("Spawning kernel task "..i)
|
||||
syscall.HPV_spawn(function()
|
||||
syscall.spawn(function()
|
||||
local status, err = pcall(v)
|
||||
if not status then
|
||||
kernel.log("Error executing kernel task '" .. i .. "': " .. err, "ERROR")
|
||||
|
||||
@@ -13,11 +13,6 @@ local function write(text)
|
||||
if c == "\n" then
|
||||
y = y + 1
|
||||
x = 1
|
||||
if y-1 >= h then
|
||||
term.scroll(1)
|
||||
y = h
|
||||
term.setCursorPos(x, y)
|
||||
end
|
||||
elseif c == "\t" then
|
||||
local tabSize = 4
|
||||
local spaces = tabSize - ((x - 1) % tabSize)
|
||||
|
||||
@@ -116,14 +116,12 @@ local function write(text, term)
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle wrapping if we go past right edge
|
||||
if x > w then
|
||||
x = 1
|
||||
y = y + 1
|
||||
end
|
||||
|
||||
-- Handle scrolling if we go past bottom
|
||||
if y-1 > h then
|
||||
if y-1 >= h then
|
||||
term.scroll(1)
|
||||
y = h
|
||||
term.setCursorPos(x, y)
|
||||
@@ -175,8 +173,10 @@ for _, name in ipairs(getNames()) do
|
||||
local t = getType(name)
|
||||
if t == "monitor" then
|
||||
local monitorTerm = wrapPeripheral(name)
|
||||
if not monitorTerm then
|
||||
error("Failed to wrap monitor peripheral")
|
||||
end
|
||||
monitorTerm.setTextScale(0.5)
|
||||
kernel.tty.register(name, newTTY(monitorTerm))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,2 +1 @@
|
||||
U $;/
|
||||
U devfs0000;/dev/
|
||||
U $;/
|
||||
@@ -233,28 +233,31 @@ function kernel.reboot()
|
||||
kernel.computer:reboot()
|
||||
end
|
||||
|
||||
kernel.syscalls["OS_time"]=function() return kernel.computer:time() end
|
||||
kernel.syscalls["OS_log"]=kernel.log
|
||||
kernel.syscalls["OS_getUptime"]=function() return kernel.computer:clock() end
|
||||
kernel.syscalls["OS_getUser"]=function() return kernel.user end
|
||||
kernel.syscalls["OS_getHostname"]=function() return kernel.host end
|
||||
kernel.syscalls["OS_getHost"]=function() return kernel.apis._HOST end
|
||||
kernel.syscalls["OS_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["OS_setUser"]=function(uid) if kernel.uid~=0 then error("Permission denied") end kernel.currentTask.uid=uid end
|
||||
kernel.syscalls["time"]=function() return kernel.computer:time() end
|
||||
kernel.syscalls["log"]=kernel.log
|
||||
kernel.syscalls["getUptime"]=function() return kernel.computer:clock() end
|
||||
kernel.syscalls["getUser"]=function() return kernel.user end
|
||||
kernel.syscalls["getHostname"]=function() return kernel.host end
|
||||
kernel.syscalls["getHost"]=function() return kernel.apis._HOST end
|
||||
kernel.syscalls["version"]=function() return kernel.version end
|
||||
kernel.syscalls["setHostname"]=function(name) if kernel.uid~=0 then error("Permission denied") end kernel.hostname=name 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")
|
||||
for _,p in ipairs(modules) do
|
||||
for _,v in ipairs(p) do
|
||||
if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG") end
|
||||
local code=ifs.readAllText(v)
|
||||
if not code then
|
||||
kernel.log("ModuReadErr: "..v, "WARN", 8)
|
||||
if not code then
|
||||
kernel.log("ModuReadErr: "..v, "WARN", 8)
|
||||
goto skip
|
||||
end
|
||||
local func,err=load(code,"@"..v)
|
||||
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) goto skip end
|
||||
local status, err = xpcall(func,debug.traceback, kernel)
|
||||
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
||||
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG") end
|
||||
::skip::
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
--:Minify:--
|
||||
local kernel = ...
|
||||
local vfs = {}
|
||||
kernel.vfs=vfs
|
||||
vfs.mounts = { ["$"] = "/" }
|
||||
local disks = kernel.disks
|
||||
vfs.disks = kernel.disks
|
||||
|
||||
-- Path handling
|
||||
-- Path normalization
|
||||
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 = {}
|
||||
for part in path:gmatch("[^/]+") do
|
||||
if part == ".." then
|
||||
@@ -17,14 +20,8 @@ local function normalizePath(path)
|
||||
return "/" .. table.concat(parts, "/") .. (path:sub(-1) == "/" and "/" or "")
|
||||
end
|
||||
|
||||
-- Resolve mount and disk 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)
|
||||
|
||||
local mountPoint = "/"
|
||||
@@ -36,246 +33,429 @@ local function resolvePath(path)
|
||||
end
|
||||
end
|
||||
|
||||
local diskPath = path:sub(#mountPoint + 1)
|
||||
return disks[mountId], diskPath
|
||||
local diskPath = path:sub(#mountPoint)
|
||||
if diskPath == "" then diskPath = "/" end
|
||||
|
||||
return vfs.disks[mountId], diskPath
|
||||
end
|
||||
|
||||
-- File object creation
|
||||
local function newFileObject(disk, handle, mode, path)
|
||||
-- Allocate file descriptor for current task
|
||||
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 {
|
||||
disk = disk,
|
||||
handle = handle,
|
||||
mode = mode,
|
||||
path = path,
|
||||
refcount = 1
|
||||
meta = meta
|
||||
}
|
||||
end
|
||||
|
||||
local function allocFD(task)
|
||||
local fd = 0
|
||||
while task.fd[fd] do fd = fd + 1 end
|
||||
return fd
|
||||
-- Validate mode
|
||||
local function ismode(mode)
|
||||
if not (mode == "r" or mode == "w" or mode == "a") then error("EINVAL") end
|
||||
end
|
||||
|
||||
local function allocFD(task)
|
||||
local count = 0
|
||||
for _ in pairs(task.fd) do count = count + 1 end
|
||||
if count >= kernel.config.maxFilesPerTask then
|
||||
error("EMFILE")
|
||||
-- Parse metafile
|
||||
local function parseMetafile(file)
|
||||
local ret={}
|
||||
local pointer=1
|
||||
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
|
||||
|
||||
local fd = 0
|
||||
while task.fd[fd] do fd = fd + 1 end
|
||||
return fd
|
||||
return nil
|
||||
end
|
||||
|
||||
local total=0
|
||||
local function checkSystemLimit()
|
||||
if total >= kernel.config.maxOpenFiles-16 then
|
||||
error("ENFILE")
|
||||
-- Get file metadata object
|
||||
local function getFileMeta(path)
|
||||
local mpath, target = getMeta(path)
|
||||
if not mpath then
|
||||
return { owner=0, group=0, perms=62, cmeta="" }
|
||||
end
|
||||
local disk, _ = resolvePath(mpath)
|
||||
local file = disk:open(mpath, "r")
|
||||
local text = file.read(65535)
|
||||
file.close()
|
||||
return parseMetafile(text)[target]
|
||||
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)
|
||||
local task = kernel.currentTask
|
||||
|
||||
-- check limits
|
||||
ismode(mode)
|
||||
checkSystemLimit()
|
||||
|
||||
local task = kernel.currentTask
|
||||
local fd = allocFD(task)
|
||||
local disk, diskPath = resolvePath(path)
|
||||
if not disk then
|
||||
error("No disk mounted for path '"..path.."'")
|
||||
end
|
||||
if not disk then error("NODISK") end
|
||||
|
||||
local meta = getFileMeta(path)
|
||||
checkperms(meta, mode)
|
||||
|
||||
local handle = disk:open(diskPath, mode)
|
||||
if not handle then return nil end
|
||||
|
||||
local file = newFileObject(disk.address, handle, mode, path)
|
||||
local fd = allocFD(task)
|
||||
task.fd[fd] = file
|
||||
total=total+1
|
||||
|
||||
task.fd[fd] = newFileObj(handle, mode, path, meta)
|
||||
total = total + 1
|
||||
return fd
|
||||
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)
|
||||
local task = kernel.currentTask
|
||||
local file = task.fd[fd]
|
||||
if not file then error("EBADF") end
|
||||
|
||||
file.handle.close()
|
||||
task.fd[fd] = nil
|
||||
file.refcount = file.refcount - 1
|
||||
if file.refcount == 0 then
|
||||
file.handle.close()
|
||||
end
|
||||
total=total-1
|
||||
return true
|
||||
total = total - 1
|
||||
end
|
||||
|
||||
function vfs.read(fd, count)
|
||||
local file = kernel.currentTask.fd[fd]
|
||||
-- Sendfile
|
||||
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.mode:find("r") then error("File not open for reading") end
|
||||
return file.handle.read(count)
|
||||
local disk, path = resolvePath(file.path)
|
||||
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
|
||||
|
||||
function vfs.write(fd, data)
|
||||
local file = kernel.currentTask.fd[fd]
|
||||
if not file then error("EBADF") end
|
||||
if not file.mode:find("w") then error("File not open for writing") end
|
||||
return file.handle.write(data)
|
||||
-- Directory operations
|
||||
function vfs.listdir(path)
|
||||
local disk, diskPath = resolvePath(path)
|
||||
if disk:type(diskPath) ~= "directory" then error("ENOTDIR") end
|
||||
local meta = getFileMeta(path)
|
||||
checkperms(meta, "r")
|
||||
return disk:list(diskPath)
|
||||
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)
|
||||
local disk, diskPath = resolvePath(path)
|
||||
if not disk then error("No disk mounted") end
|
||||
return disk:makeDirectory(diskPath)
|
||||
local meta = getFileMeta(path)
|
||||
checkperms(meta, "w")
|
||||
disk:makeDirectory(diskPath)
|
||||
end
|
||||
|
||||
function vfs.remove(path)
|
||||
local disk, diskPath = resolvePath(path)
|
||||
if not disk then error("No disk mounted") end
|
||||
return disk:remove(diskPath)
|
||||
local meta = getFileMeta(path)
|
||||
checkperms(meta, "w")
|
||||
disk:remove(diskPath)
|
||||
end
|
||||
|
||||
function vfs.attributes(path)
|
||||
if type(path) == "number" then
|
||||
local file = kernel.currentTask.fd[path]
|
||||
if not file then error("EBADF") end
|
||||
return disks[file.disk]:attributes(file.path)
|
||||
-- Permission functions
|
||||
function vfs.chmod(path, perms)
|
||||
local disk, diskPath = resolvePath(path)
|
||||
local meta = getFileMeta(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
|
||||
local disk, diskPath = resolvePath(path)
|
||||
if not disk then error("No disk mounted") end
|
||||
return disk:attributes(diskPath)
|
||||
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)
|
||||
if not disk then error("No disk mounted") end
|
||||
return disk:list(diskPath)
|
||||
local meta = getFileMeta(path)
|
||||
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
|
||||
|
||||
function vfs.exists(path)
|
||||
local disk, diskPath = resolvePath(path)
|
||||
if not disk then return false end
|
||||
return disk:directoryExists(diskPath) or disk:fileExists(diskPath)
|
||||
local meta = getFileMeta(path)
|
||||
checkperms(meta, "r")
|
||||
disk:fileExists(diskPath)
|
||||
end
|
||||
|
||||
function vfs.type(path)
|
||||
if type(path) == "number" then
|
||||
local file = kernel.currentTask.fd[path]
|
||||
if not file then error("EBADF") end
|
||||
return disks[file.disk]:type(file.path)
|
||||
end
|
||||
local disk, diskPath = resolvePath(path)
|
||||
if not disk then error("No disk mounted") end
|
||||
return disk:type(diskPath)
|
||||
end
|
||||
-- Export syscalls
|
||||
local sys = kernel.syscalls
|
||||
sys["open"] = vfs.open
|
||||
sys["close"] = vfs.close
|
||||
sys["read"] = vfs.read
|
||||
sys["write"] = vfs.write
|
||||
sys["pread"] = vfs.pread
|
||||
sys["pwrite"] = vfs.pwrite
|
||||
sys["lseek"] = vfs.lseek
|
||||
sys["fsync"] = vfs.fsync
|
||||
sys["sendfile"] = vfs.sendfile
|
||||
sys["stat"] = vfs.stat
|
||||
sys["fstat"] = vfs.fstat
|
||||
sys["mkdir"] = vfs.mkdir
|
||||
sys["remove"] = vfs.remove
|
||||
sys["listdir"] = vfs.listdir
|
||||
sys["chmod"] = vfs.chmod
|
||||
sys["fchmod"] = vfs.fchmod
|
||||
sys["chown"] = vfs.chown
|
||||
sys["fchown"] = vfs.fchown
|
||||
sys["exists"]=vfs.exists
|
||||
sys["mount"] = vfs.mount
|
||||
sys["umount"] = vfs.umount
|
||||
|
||||
function vfs.isDirectory(path)
|
||||
local disk, diskPath = resolvePath(path)
|
||||
if not disk then return false end
|
||||
return disk:directoryExists(diskPath)
|
||||
end
|
||||
|
||||
-- CWD
|
||||
function vfs.getcwd()
|
||||
return kernel.currentTask.cwd
|
||||
end
|
||||
|
||||
function vfs.setcwd(path)
|
||||
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:--
|
||||
local kernel = ...
|
||||
local cache = {}
|
||||
local searchpaths = {
|
||||
kernel.searchpaths = {
|
||||
"/lib/?.lua",
|
||||
"/lib/?",
|
||||
"/usr/lib/?.lua",
|
||||
@@ -18,7 +18,7 @@ function require(module,...)
|
||||
end
|
||||
local modpath = module:gsub("%.", "/")
|
||||
local failed = {}
|
||||
for _, path in ipairs(searchpaths) do
|
||||
for _, path in ipairs(kernel.searchpaths) do
|
||||
local full_path = string.gsub(path, "%?", modpath)
|
||||
if full_path:sub(1,1)~="/" then
|
||||
full_path=kernel.currentTask.cwd..full_path
|
||||
|
||||
@@ -1,173 +1,173 @@
|
||||
--:Minify:--
|
||||
local kernel = ...
|
||||
|
||||
local proxy = {}
|
||||
local data = {}
|
||||
|
||||
proxy.address = "devfs0000"
|
||||
proxy.isReadOnly = false
|
||||
proxy.spaceUsed = function() return 0 end
|
||||
proxy.spaceTotal = function() return 0 end
|
||||
proxy.makeDirectory = function() error("Permission denied") end
|
||||
proxy.remove = function() error("Permission denied") end
|
||||
proxy.setLabel = function() error("Permission denied") end
|
||||
proxy.getLabel = function() return "devfs" end
|
||||
proxy.attributes = function(path) return {
|
||||
type = proxy.type(path),
|
||||
isReadOnly = false,
|
||||
size = 0,
|
||||
lastModified = 0,
|
||||
created = 0,
|
||||
Permissions = "666",
|
||||
owner = "root",
|
||||
group = "root"
|
||||
} end
|
||||
|
||||
local function getNode(path)
|
||||
local parts = string.split(path, "/")
|
||||
if parts[1] == "" then
|
||||
table.remove(parts, 1)
|
||||
end
|
||||
|
||||
local node = data
|
||||
for _, part in ipairs(parts) do
|
||||
if node[part] then
|
||||
node = node[part]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
return node
|
||||
end
|
||||
|
||||
proxy.type = function(path)
|
||||
local node = getNode(path)
|
||||
if node then
|
||||
return node.type
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
proxy.list = function(path)
|
||||
local node = getNode(path)
|
||||
if node and node.type == "directory" then
|
||||
local content = table.keys(node)
|
||||
table.remove(content, table.indexOf(content, "type"))
|
||||
return content
|
||||
else
|
||||
error("Not a directory")
|
||||
end
|
||||
end
|
||||
|
||||
proxy.open = function(path, mode)
|
||||
local node = getNode(path)
|
||||
if node and (node.type == "file" or node.type == "character device") then
|
||||
if mode == "r" then
|
||||
return {
|
||||
read = node.read,
|
||||
close = function() end
|
||||
}
|
||||
elseif mode == "w" then
|
||||
return {
|
||||
write = node.write,
|
||||
close = function() end
|
||||
}
|
||||
else
|
||||
error("Invalid mode")
|
||||
end
|
||||
else
|
||||
error("Not a file"..type(node))
|
||||
end
|
||||
end
|
||||
|
||||
local function newStringFile(content)
|
||||
return {
|
||||
type = "file",
|
||||
read = function() return content end,
|
||||
write = function(newContent) content = newContent end
|
||||
}
|
||||
end
|
||||
|
||||
local function newDirectory()
|
||||
return {
|
||||
type = "directory"
|
||||
}
|
||||
end
|
||||
|
||||
data["random"] = {
|
||||
type = "character device",
|
||||
read = function(amount)
|
||||
local result = ""
|
||||
for _ = 1, amount do
|
||||
result = result .. string.char(math.random(0, 255))
|
||||
end
|
||||
return result
|
||||
end,
|
||||
write = function() error("Permission denied") end
|
||||
}
|
||||
|
||||
data["null"] = {
|
||||
type = "character device",
|
||||
read = function() return "" end,
|
||||
write = function() end
|
||||
}
|
||||
|
||||
data["zero"] = {
|
||||
type = "character device",
|
||||
read = function(amount)
|
||||
return string.rep("\0", amount)
|
||||
end,
|
||||
write = function() error("Permission denied") end
|
||||
}
|
||||
|
||||
data["rtc"] = {
|
||||
type = "character device",
|
||||
read = function() return kernel.computer:time() end,
|
||||
write = function() error("Permission denied") end
|
||||
}
|
||||
|
||||
data["rtc0"] = {
|
||||
type = "character device",
|
||||
read = function() return kernel.computer:time() end,
|
||||
write = function() error("Permission denied") end
|
||||
}
|
||||
|
||||
data["eeprom"] = {
|
||||
type = "character device",
|
||||
read = function() return kernel.computer:getEEPROM() end,
|
||||
write = function(data)
|
||||
if kernel.uid ~= 0 then
|
||||
error("Permission denied")
|
||||
end
|
||||
kernel.computer:setEEPROM(data)
|
||||
end
|
||||
}
|
||||
|
||||
local keyboard = kernel.newFifo()
|
||||
local mouse = kernel.newFifo()
|
||||
data["input"] = newDirectory()
|
||||
data["input"]["keyboard"] = {
|
||||
type = "pipe",
|
||||
read = function(amount)
|
||||
return keyboard.pop()
|
||||
end,
|
||||
write = function() error("Permission denied") end
|
||||
}
|
||||
data["input"]["mouse"] = {
|
||||
type = "pipe",
|
||||
read = function(amount)
|
||||
return mouse.pop()
|
||||
end,
|
||||
write = function() error("Permission denied") end
|
||||
}
|
||||
|
||||
data["pts"] = newDirectory()
|
||||
|
||||
kernel.devfs = {}
|
||||
kernel.devfs.keyboard = keyboard
|
||||
kernel.devfs.mouse = mouse
|
||||
kernel.devfs.proxy = proxy
|
||||
kernel.devfs.data = data
|
||||
kernel.vfs.virtdisk(proxy)
|
||||
--local kernel = ...
|
||||
--
|
||||
--local proxy = {}
|
||||
--local data = {}
|
||||
--
|
||||
--proxy.address = "devfs0000"
|
||||
--proxy.isReadOnly = false
|
||||
--proxy.spaceUsed = function() return 0 end
|
||||
--proxy.spaceTotal = function() return 0 end
|
||||
--proxy.makeDirectory = function() error("Permission denied") end
|
||||
--proxy.remove = function() error("Permission denied") end
|
||||
--proxy.setLabel = function() error("Permission denied") end
|
||||
--proxy.getLabel = function() return "devfs" end
|
||||
--proxy.attributes = function(path) return {
|
||||
-- type = proxy.type(path),
|
||||
-- isReadOnly = false,
|
||||
-- size = 0,
|
||||
-- lastModified = 0,
|
||||
-- created = 0,
|
||||
-- Permissions = "666",
|
||||
-- owner = "root",
|
||||
-- group = "root"
|
||||
--} end
|
||||
--
|
||||
--local function getNode(path)
|
||||
-- local parts = string.split(path, "/")
|
||||
-- if parts[1] == "" then
|
||||
-- table.remove(parts, 1)
|
||||
-- end
|
||||
--
|
||||
-- local node = data
|
||||
-- for _, part in ipairs(parts) do
|
||||
-- if node[part] then
|
||||
-- node = node[part]
|
||||
-- else
|
||||
-- return nil
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- return node
|
||||
--end
|
||||
--
|
||||
--proxy.type = function(path)
|
||||
-- local node = getNode(path)
|
||||
-- if node then
|
||||
-- return node.type
|
||||
-- else
|
||||
-- return nil
|
||||
-- end
|
||||
--end
|
||||
--
|
||||
--proxy.list = function(path)
|
||||
-- local node = getNode(path)
|
||||
-- if node and node.type == "directory" then
|
||||
-- local content = table.keys(node)
|
||||
-- table.remove(content, table.indexOf(content, "type"))
|
||||
-- return content
|
||||
-- else
|
||||
-- error("Not a directory")
|
||||
-- end
|
||||
--end
|
||||
--
|
||||
--proxy.open = function(path, mode)
|
||||
-- local node = getNode(path)
|
||||
-- if node and (node.type == "file" or node.type == "character device") then
|
||||
-- if mode == "r" then
|
||||
-- return {
|
||||
-- read = node.read,
|
||||
-- close = function() end
|
||||
-- }
|
||||
-- elseif mode == "w" then
|
||||
-- return {
|
||||
-- write = node.write,
|
||||
-- close = function() end
|
||||
-- }
|
||||
-- else
|
||||
-- error("Invalid mode")
|
||||
-- end
|
||||
-- else
|
||||
-- error("Not a file"..type(node))
|
||||
-- end
|
||||
--end
|
||||
--
|
||||
--local function newStringFile(content)
|
||||
-- return {
|
||||
-- type = "file",
|
||||
-- read = function() return content end,
|
||||
-- write = function(newContent) content = newContent end
|
||||
-- }
|
||||
--end
|
||||
--
|
||||
--local function newDirectory()
|
||||
-- return {
|
||||
-- type = "directory"
|
||||
-- }
|
||||
--end
|
||||
--
|
||||
--data["random"] = {
|
||||
-- type = "character device",
|
||||
-- read = function(amount)
|
||||
-- local result = ""
|
||||
-- for _ = 1, amount do
|
||||
-- result = result .. string.char(math.random(0, 255))
|
||||
-- end
|
||||
-- return result
|
||||
-- end,
|
||||
-- write = function() error("Permission denied") end
|
||||
--}
|
||||
--
|
||||
--data["null"] = {
|
||||
-- type = "character device",
|
||||
-- read = function() return "" end,
|
||||
-- write = function() end
|
||||
--}
|
||||
--
|
||||
--data["zero"] = {
|
||||
-- type = "character device",
|
||||
-- read = function(amount)
|
||||
-- return string.rep("\0", amount)
|
||||
-- end,
|
||||
-- write = function() error("Permission denied") end
|
||||
--}
|
||||
--
|
||||
--data["rtc"] = {
|
||||
-- type = "character device",
|
||||
-- read = function() return kernel.computer:time() end,
|
||||
-- write = function() error("Permission denied") end
|
||||
--}
|
||||
--
|
||||
--data["rtc0"] = {
|
||||
-- type = "character device",
|
||||
-- read = function() return kernel.computer:time() end,
|
||||
-- write = function() error("Permission denied") end
|
||||
--}
|
||||
--
|
||||
--data["eeprom"] = {
|
||||
-- type = "character device",
|
||||
-- read = function() return kernel.computer:getEEPROM() end,
|
||||
-- write = function(data)
|
||||
-- if kernel.uid ~= 0 then
|
||||
-- error("Permission denied")
|
||||
-- end
|
||||
-- kernel.computer:setEEPROM(data)
|
||||
-- end
|
||||
--}
|
||||
--
|
||||
--local keyboard = kernel.newFifo()
|
||||
--local mouse = kernel.newFifo()
|
||||
--data["input"] = newDirectory()
|
||||
--data["input"]["keyboard"] = {
|
||||
-- type = "pipe",
|
||||
-- read = function(amount)
|
||||
-- return keyboard.pop()
|
||||
-- end,
|
||||
-- write = function() error("Permission denied") end
|
||||
--}
|
||||
--data["input"]["mouse"] = {
|
||||
-- type = "pipe",
|
||||
-- read = function(amount)
|
||||
-- return mouse.pop()
|
||||
-- end,
|
||||
-- write = function() error("Permission denied") end
|
||||
--}
|
||||
--
|
||||
--data["pts"] = newDirectory()
|
||||
--
|
||||
--kernel.devfs = {}
|
||||
--kernel.devfs.keyboard = keyboard
|
||||
--kernel.devfs.mouse = mouse
|
||||
--kernel.devfs.proxy = proxy
|
||||
--kernel.devfs.data = data
|
||||
--kernel.vfs.virtdisk(proxy)
|
||||
@@ -11,7 +11,7 @@ for i,v in ipairs(string.split(kernel.fstab,"\n")) do
|
||||
end
|
||||
local path=v:sub(#id+4)
|
||||
if id~="$" then
|
||||
kernel.vfs.mount(id,path)
|
||||
kernel.vfs.mount(path, id)
|
||||
end
|
||||
::endline::
|
||||
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:--
|
||||
local kernel = ...
|
||||
local pam = {}
|
||||
kernel.pam = pam
|
||||
local loggedIn = {}
|
||||
|
||||
local function getFile(path)
|
||||
local file = kernel.vfs.open(path, "r")
|
||||
if not file then error("Failed to open file: "..path) end
|
||||
local content = kernel.vfs.read(file, 1024000)
|
||||
kernel.vfs.close(file)
|
||||
return content
|
||||
end
|
||||
|
||||
local blake2s = require("crypto.blake2s")
|
||||
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
|
||||
|
||||
--local kernel = ...
|
||||
--local pam = {}
|
||||
--kernel.pam = pam
|
||||
--local loggedIn = {}
|
||||
--
|
||||
--local function getFile(path)
|
||||
-- local file = kernel.vfs.open(path, "r")
|
||||
-- if not file then error("Failed to open file: "..path) end
|
||||
-- local content = kernel.vfs.read(file, 1024000)
|
||||
-- kernel.vfs.close(file)
|
||||
-- return content
|
||||
--end
|
||||
--
|
||||
--local blake2s
|
||||
--
|
||||
--do
|
||||
-- local MOD32 = 2^32
|
||||
-- local function norm(x)
|
||||
-- return x % MOD32
|
||||
-- end
|
||||
--
|
||||
-- local function tobits(x)
|
||||
-- x = norm(x)
|
||||
-- local t = {}
|
||||
-- for i = 0, 31 do
|
||||
-- local b = x % 2
|
||||
-- t[i] = b
|
||||
-- x = (x - b) / 2
|
||||
-- end
|
||||
-- return t
|
||||
-- end
|
||||
--
|
||||
-- local function frombits(t)
|
||||
-- local x = 0
|
||||
-- local p = 1
|
||||
-- for i = 0, 31 do
|
||||
-- if t[i] == 1 then
|
||||
-- x = x + p
|
||||
-- end
|
||||
-- p = p * 2
|
||||
-- end
|
||||
-- return norm(x)
|
||||
-- end
|
||||
--
|
||||
-- local function bor(...)
|
||||
-- local args = {...}
|
||||
-- if #args == 0 then return 0 end
|
||||
-- local bits = tobits(args[1])
|
||||
-- for i = 2, #args do
|
||||
-- local b = tobits(args[i])
|
||||
-- for j = 0, 31 do
|
||||
-- bits[j] = (bits[j] == 1 or b[j] == 1) and 1 or 0
|
||||
-- end
|
||||
-- end
|
||||
-- return frombits(bits)
|
||||
-- end
|
||||
--
|
||||
-- local function bxor(...)
|
||||
-- local args = {...}
|
||||
-- if #args == 0 then return 0 end
|
||||
-- local bits = tobits(args[1])
|
||||
-- for i = 2, #args do
|
||||
-- local b = tobits(args[i])
|
||||
-- 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)
|
||||
end
|
||||
tasks[tostring(id)].status="Z"
|
||||
tasks[tostring(id)].exit=err
|
||||
if type(err)=="number" then
|
||||
tasks[tostring(id)].exit=err
|
||||
end
|
||||
else
|
||||
if kernel.config.logTaskExit then
|
||||
if err then
|
||||
@@ -26,7 +28,9 @@ function sys.spawn(func, name, envars, args, tgid)
|
||||
end
|
||||
end
|
||||
tasks[tostring(id)].status="Z"
|
||||
tasks[tostring(id)].exit=err
|
||||
if type(err)=="number" then
|
||||
tasks[tostring(id)].exit=err
|
||||
end
|
||||
end
|
||||
end),
|
||||
name=name or ("task"..tostring(id)),
|
||||
@@ -79,8 +83,6 @@ function sys.getTaskInfo(pid)
|
||||
end
|
||||
return {
|
||||
name=task.name,
|
||||
envars=table.deepcopy(task.envars),
|
||||
args=table.deepcopy(task.args),
|
||||
status=task.status,
|
||||
pid=task.pid,
|
||||
tgid=task.tgid,
|
||||
@@ -173,7 +175,7 @@ end
|
||||
|
||||
function sys.list()
|
||||
local ret={}
|
||||
for i,_ in ipairs(tasks) do
|
||||
for i,_ in pairs(tasks) do
|
||||
ret[i]=sys.getTaskInfo(i)
|
||||
end
|
||||
return ret
|
||||
@@ -187,18 +189,33 @@ function sys.setEnviron(key, value)
|
||||
kernel.currentTask.envars[key]=value
|
||||
end
|
||||
|
||||
kernel.syscalls["HPV_spawn"]=sys.spawn
|
||||
kernel.syscalls["HPV_sleep"]=sys.sleep
|
||||
kernel.syscalls["HPV_getTaskInfo"]=sys.getTaskInfo
|
||||
kernel.syscalls["HPV_collect"]=sys.collect
|
||||
kernel.syscalls["HPV_kill"]=sys.kill
|
||||
kernel.syscalls["HPV_stop"]=sys.stop
|
||||
kernel.syscalls["HPV_continue"]=sys.continue
|
||||
kernel.syscalls["HPV_getPid"]=sys.getPid
|
||||
kernel.syscalls["HPV_list"]=sys.list
|
||||
kernel.syscalls["HPV_setEnviron"]=sys.setEnviron
|
||||
kernel.syscalls["HPV_getEnviron"]=sys.getEnviron
|
||||
kernel._G.sleep=function(...)coroutine.yield("syscall","HPV_sleep",...)end
|
||||
function sys.exit(code)
|
||||
if kernel.config.logTaskExit then
|
||||
if code then
|
||||
kernel.log("Task "..tostring(kernel.currentTask.pid).." exited with code: "..tostring(code), "INFO")
|
||||
else
|
||||
kernel.log("Task "..tostring(kernel.currentTask.pid).." exited without code", "INFO")
|
||||
end
|
||||
end
|
||||
tasks[tostring(kernel.currentTask.pid)].status="Z"
|
||||
if type(code)=="number" then
|
||||
tasks[tostring(kernel.currentTask.pid)].exit=code
|
||||
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()
|
||||
for pid, task in pairs(tasks) do
|
||||
@@ -216,7 +233,7 @@ local function reapDeadTasks()
|
||||
task.timeSlice = nil
|
||||
task.syscallReturn = nil
|
||||
task.sleep = nil
|
||||
for k,v in pairs(task.fd) do
|
||||
for v,_ in ipairs(task.fd) do
|
||||
kernel.vfs.close(v)
|
||||
end
|
||||
task.fd = nil
|
||||
|
||||
@@ -1,90 +1,91 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
kernel.tty={}
|
||||
kernel.tty.inst={}
|
||||
local tty={}
|
||||
kernel.tty=tty
|
||||
tty.inst={}
|
||||
|
||||
function kernel.tty.register(tty, ttyo)
|
||||
kernel.tty.inst[tty]=ttyo
|
||||
function tty.register(ttyn, ttyo)
|
||||
tty.inst[ttyn]=ttyo
|
||||
end
|
||||
|
||||
function kernel.tty.print(text)
|
||||
function tty.print(text)
|
||||
local term=kernel.currentTask.term
|
||||
if term and kernel.tty.inst[term] then
|
||||
kernel.tty.inst[term].print(text)
|
||||
if term and tty.inst[term] then
|
||||
tty.inst[term].print(text)
|
||||
end
|
||||
end
|
||||
|
||||
function kernel.tty.printInline(text)
|
||||
function tty.printInline(text)
|
||||
local term=kernel.currentTask.term
|
||||
if term and kernel.tty.inst[term] then
|
||||
kernel.tty.inst[term].printInline(text)
|
||||
if term and tty.inst[term] then
|
||||
tty.inst[term].printInline(text)
|
||||
end
|
||||
end
|
||||
|
||||
function kernel.tty.size()
|
||||
function tty.size()
|
||||
local term=kernel.currentTask.term
|
||||
if term and kernel.tty.inst[term] then
|
||||
return kernel.tty.inst[term].size()
|
||||
if term and tty.inst[term] then
|
||||
return tty.inst[term].size()
|
||||
end
|
||||
end
|
||||
|
||||
function kernel.tty.setCursorPos(x,y)
|
||||
function tty.setCursorPos(x,y)
|
||||
local term=kernel.currentTask.term
|
||||
if term and kernel.tty.inst[term] then
|
||||
return kernel.tty.inst[term].setCursorPos(x,y)
|
||||
if term and tty.inst[term] then
|
||||
return tty.inst[term].setCursorPos(x,y)
|
||||
end
|
||||
end
|
||||
|
||||
function kernel.tty.getCursorPos()
|
||||
function tty.getCursorPos()
|
||||
local term=kernel.currentTask.term
|
||||
if term and kernel.tty.inst[term] then
|
||||
return kernel.tty.inst[term].getCursorPos()
|
||||
if term and tty.inst[term] then
|
||||
return tty.inst[term].getCursorPos()
|
||||
end
|
||||
end
|
||||
|
||||
function kernel.tty.clear()
|
||||
function tty.clear()
|
||||
local term=kernel.currentTask.term
|
||||
if term and kernel.tty.inst[term] then
|
||||
return kernel.tty.inst[term].clear()
|
||||
if term and tty.inst[term] then
|
||||
return tty.inst[term].clear()
|
||||
end
|
||||
end
|
||||
|
||||
function kernel.tty.setTextColor(color)
|
||||
function tty.setTextColor(color)
|
||||
local term=kernel.currentTask.term
|
||||
if term and kernel.tty.inst[term] then
|
||||
return kernel.tty.inst[term].setTextColor(color)
|
||||
if term and tty.inst[term] then
|
||||
return tty.inst[term].setTextColor(color)
|
||||
end
|
||||
end
|
||||
|
||||
function kernel.tty.setBackgroundColor(color)
|
||||
function tty.setBackgroundColor(color)
|
||||
local term=kernel.currentTask.term
|
||||
if term and kernel.tty.inst[term] then
|
||||
return kernel.tty.inst[term].setBackgroundColor(color)
|
||||
if term and tty.inst[term] then
|
||||
return tty.inst[term].setBackgroundColor(color)
|
||||
end
|
||||
end
|
||||
|
||||
function kernel.tty.scroll(n)
|
||||
function tty.scroll(n)
|
||||
local term=kernel.currentTask.term
|
||||
if term and kernel.tty.inst[term] then
|
||||
return kernel.tty.inst[term].scroll(n)
|
||||
if term and tty.inst[term] then
|
||||
return tty.inst[term].scroll(n)
|
||||
end
|
||||
end
|
||||
|
||||
function kernel.tty.getTextColor()
|
||||
function tty.getTextColor()
|
||||
local term=kernel.currentTask.term
|
||||
if term and kernel.tty.inst[term] and kernel.tty.inst[term].getTextColor then
|
||||
return kernel.tty.inst[term].getTextColor()
|
||||
if term and tty.inst[term] and tty.inst[term].getTextColor then
|
||||
return tty.inst[term].getTextColor()
|
||||
end
|
||||
end
|
||||
|
||||
function kernel.tty.getBackgroundColor()
|
||||
function tty.getBackgroundColor()
|
||||
local term=kernel.currentTask.term
|
||||
if term and kernel.tty.inst[term] and kernel.tty.inst[term].getBackgroundColor then
|
||||
return kernel.tty.inst[term].getBackgroundColor()
|
||||
if term and tty.inst[term] and tty.inst[term].getBackgroundColor then
|
||||
return tty.inst[term].getBackgroundColor()
|
||||
end
|
||||
end
|
||||
|
||||
function kernel.tty.bind(ttyid)
|
||||
function tty.bind(ttyid)
|
||||
if not ttyid then
|
||||
return false, "No TTY ID specified"
|
||||
end
|
||||
@@ -95,33 +96,34 @@ function kernel.tty.bind(ttyid)
|
||||
return true
|
||||
end
|
||||
|
||||
function kernel.tty.unbind()
|
||||
function tty.unbind()
|
||||
kernel.currentTask.term=false
|
||||
end
|
||||
|
||||
function kernel.tty.isBound()
|
||||
function tty.isBound()
|
||||
return kernel.currentTask.term ~= nil
|
||||
end
|
||||
|
||||
function kernel.tty.getBoundTTY()
|
||||
function tty.getBoundTTY()
|
||||
return kernel.currentTask.term
|
||||
end
|
||||
|
||||
kernel.syscalls["TTY_print"]=kernel.tty.print
|
||||
kernel.syscalls["TTY_printInline"]=kernel.tty.printInline
|
||||
kernel.syscalls["TTY_size"]=kernel.tty.size
|
||||
kernel.syscalls["TTY_setCursorPos"]=kernel.tty.setCursorPos
|
||||
kernel.syscalls["TTY_getCursorPos"]=kernel.tty.getCursorPos
|
||||
kernel.syscalls["TTY_clear"]=kernel.tty.clear
|
||||
kernel.syscalls["TTY_setTextColor"]=kernel.tty.setTextColor
|
||||
kernel.syscalls["TTY_setBackgroundColor"]=kernel.tty.setBackgroundColor
|
||||
kernel.syscalls["TTY_scroll"]=kernel.tty.scroll
|
||||
kernel.syscalls["TTY_getTextColor"]=kernel.tty.getTextColor
|
||||
kernel.syscalls["TTY_getBackgroundColor"]=kernel.tty.getBackgroundColor
|
||||
kernel.syscalls["TTY_bind"]=kernel.tty.bind
|
||||
kernel.syscalls["TTY_unbind"]=kernel.tty.unbind
|
||||
kernel.syscalls["TTY_isBound"]=kernel.tty.isBound
|
||||
kernel.syscalls["TTY_getBoundTTY"]=kernel.tty.getBoundTTY
|
||||
local sys=kernel.syscalls
|
||||
sys["TTY_print"]=tty.print
|
||||
sys["TTY_printInline"]=tty.printInline
|
||||
sys["TTY_size"]=tty.size
|
||||
sys["TTY_setCursorPos"]=tty.setCursorPos
|
||||
sys["TTY_getCursorPos"]=tty.getCursorPos
|
||||
sys["TTY_clear"]=tty.clear
|
||||
sys["TTY_setTextColor"]=tty.setTextColor
|
||||
sys["TTY_setBackgroundColor"]=tty.setBackgroundColor
|
||||
sys["TTY_scroll"]=tty.scroll
|
||||
sys["TTY_getTextColor"]=tty.getTextColor
|
||||
sys["TTY_getBackgroundColor"]=tty.getBackgroundColor
|
||||
sys["TTY_bind"]=tty.bind
|
||||
sys["TTY_unbind"]=tty.unbind
|
||||
sys["TTY_isBound"]=tty.isBound
|
||||
sys["TTY_getBoundTTY"]=tty.getBoundTTY
|
||||
|
||||
kernel.log("TTY module loaded attempting to register console tty")
|
||||
kernel.status="init"
|
||||
@@ -3,8 +3,11 @@ local kernel = ...
|
||||
kernel.log("Loading init system...")
|
||||
kernel.log("InitPath: "..kernel.config.initPath)
|
||||
local handle = kernel.vfs.open(kernel.config.initPath, "r")
|
||||
kernel.log("O")
|
||||
local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
||||
kernel.log("R")
|
||||
kernel.vfs.close(handle)
|
||||
kernel.log("C")
|
||||
|
||||
local initFunc, err = load(data, "@sysinit")
|
||||
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"
|
||||
periphemu.create("right", "drive")
|
||||
disk.insertDisk("right", diskpath)
|
||||
@@ -7,4 +8,5 @@ file.close()
|
||||
|
||||
local func = load(text, "@bios.lua")
|
||||
|
||||
---@diagnostic disable-next-line: need-check-nil
|
||||
func("/disk")
|
||||
Reference in New Issue
Block a user