vfs rewrite lol fml

This commit is contained in:
2026-01-29 20:29:06 -05:00
parent 9bd9cdaba4
commit 1c3d2c8b48
25 changed files with 980 additions and 633 deletions

View File

@@ -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

View File

@@ -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"))

View File

View File

@@ -1,3 +1,4 @@
--:Minify:--
-- blake2s.lua
-- Pure Lua 5.2, 32-bit only, supports keyed hashing

View File

@@ -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

View File

@@ -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")

View File

@@ -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)

View File

@@ -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

View File

@@ -1,2 +1 @@
U $;/
U devfs0000;/dev/

View File

@@ -233,19 +233,21 @@ 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)
@@ -255,6 +257,7 @@ for _,p in ipairs(modules) do
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

View File

@@ -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
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
-- 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
kernel.log("VFS module loaded")
return vfs

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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")

View File

@@ -0,0 +1,10 @@
--:Minify:--
local kernel = ...
local socket = {}
function socket.socket()
end
kernel.socket=socket
kernel.log("Loaded socket module")

View File

@@ -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
--
--

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View 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")

View 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

View File

@@ -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")