finished vfs for a while

This commit is contained in:
2026-02-12 11:43:41 -05:00
parent 1c4f48bd65
commit 33cd291c21
31 changed files with 1083 additions and 1097 deletions

View File

@@ -29,6 +29,8 @@ You can also view real-time loading logs during boot if `showModLoad` in boot.cf
To trigger a panic (for testing):
```lua
kernel.PANIC("Test panic message")
OR
kernel.log("Test log message")
```
---

View File

@@ -10,6 +10,7 @@ local pid=syscall.getpid()
local proc=0
local fs=require("sys.fs")
local timeout=false
syscall.setEnviron("SHELL","simpleshell")
printInline("> ")
while true do
local event = {syscall.IO_pullEvent()}
@@ -29,10 +30,11 @@ while true do
stopInput=false
else
local path=nil
if fs.exists("/bin/"..str) then
path="/bin/"..str
elseif fs.exists("/bin/"..str..".lua") then
path="/bin/"..str..".lua"
local split=string.split(str, " ")
if fs.exists("/bin/"..split[1]) then
path="/bin/"..split[1]
elseif fs.exists("/bin/"..split[1]..".lua") then
path="/bin/"..split[1]..".lua"
end
if not path then
print("Program not found")
@@ -46,11 +48,13 @@ while true do
printInline("> ")
end
syscall.IO_bind("bash:"..tostring(pid))
proc = syscall.spawn(program, path)
proc = syscall.spawn(program, path, nil, {table.unpack(split, 2)})
syscall.IO_bind(inputIO)
end
str=""
end
elseif event[1]=="keyTyped" and event[3]=="^d" then
syscall.exit(0)
else
str=str..event[3]
printInline(event[3])
@@ -64,7 +68,9 @@ while true do
if stopInput then
local exited, code = syscall.collect(proc)
if exited then
print("\nTask exited with code:\n"..tostring(code))
if code then
print("\nTask exited with code:\n"..tostring(code))
end
printInline("> ")
stopInput=false
else
@@ -74,9 +80,6 @@ while true do
print("Terminated")
printInline("> ")
stopInput=false
elseif event[1]=="keyTyped" and event[3]=="^d" then
syscall.kill(proc)
syscall.exit(0)
else
syscall.IO_pushEvent("bash:"..tostring(pid), table.unpack(event))
end

View File

@@ -0,0 +1,8 @@
local args = {...}
local file = syscall.open(args[1], "r")
local content=""
while content~=nil do
content=syscall.read(file, 1024)
syscall.TTY_printInline(content)
end
syscall.close(file)

0
Src/Hyperion-bash/bin/cd Normal file
View File

View File

@@ -0,0 +1 @@
syscall.TTY_clear()

View File

@@ -1,7 +1,11 @@
local fs = require("sys.fs")
local stuff = fs.list(syscall.getcwd())
local dir = (({...})[1] or "")
if dir~="" and dir:sub(#dir,#dir)~="/" then
dir=dir.."/"
end
local stuff = fs.list(dir)
for i,v in ipairs(stuff) do
if fs.isDir(v) then
if fs.isDir(dir..v) then
print(v.."/")
else
print(v)

View File

@@ -21,7 +21,7 @@ while true do
if str == "" then
printInline("> ")
stopInput=false
elseif str == "exit" then
elseif str == "exit()" then
break
else
local func=load(str,"@Lua","t",luaEnv)

View File

@@ -0,0 +1 @@
print(syscall.getcwd())

View File

@@ -1,5 +1,5 @@
--:Minify:--
local BOOT_DRIVE_PATH=({...})[1] or "/$"
-- :Minify:--
local BOOT_DRIVE_PATH = ({...})[1] or "/$"
---@diagnostic disable-next-line: undefined-global
local term = term
local os = os
@@ -38,7 +38,7 @@ local function write(text)
y = y + 1
end
if y-1 >= h then
if y - 1 >= h then
term.scroll(1)
y = h
term.setCursorPos(x, y)
@@ -61,7 +61,7 @@ end
term.setCursorBlink(false)
local ok, err = xpcall(function()
local apis={BOOT_DRIVE_PATH=BOOT_DRIVE_PATH}
local apis = {BOOT_DRIVE_PATH = BOOT_DRIVE_PATH}
local lua = {
coroutine = true,
@@ -93,14 +93,14 @@ local ok, err = xpcall(function()
tostring = true,
type = true,
xpcall = true,
_G=true
_G = true
}
local debug = debug
for i,v in pairs(_G) do
if not lua[i] or lua[i]==nil then
apis[i]=v
_G[i]=nil
for i, v in pairs(_G) do
if not lua[i] or lua[i] == nil then
apis[i] = v
_G[i] = nil
end
end
@@ -109,18 +109,18 @@ local ok, err = xpcall(function()
while stoptime > apis.os.clock() do end
end
apis.term.setPaletteColor(0x1, 0xFFFFFF) -- #000000
apis.term.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
apis.term.setPaletteColor(0x4, 0x00FF00) -- #FF0000
apis.term.setPaletteColor(0x8, 0x0000FF) -- #00FF00
apis.term.setPaletteColor(0x10, 0x00FFFF) -- #0000FF
apis.term.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF
apis.term.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF
apis.term.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00
apis.term.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00
apis.term.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55
apis.term.setPaletteColor(0x400, 0x924900) -- #24FFFF
apis.term.setPaletteColor(0x800, 0x6D6D55) -- #924900
apis.term.setPaletteColor(0x1, 0xFFFFFF) -- #000000
apis.term.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
apis.term.setPaletteColor(0x4, 0x00FF00) -- #FF0000
apis.term.setPaletteColor(0x8, 0x0000FF) -- #00FF00
apis.term.setPaletteColor(0x10, 0x00FFFF) -- #0000FF
apis.term.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF
apis.term.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF
apis.term.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00
apis.term.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00
apis.term.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55
apis.term.setPaletteColor(0x400, 0x924900) -- #24FFFF
apis.term.setPaletteColor(0x800, 0x6D6D55) -- #924900
apis.term.setPaletteColor(0x1000, 0xDBDBAA) -- #6D6D55
apis.term.setPaletteColor(0x2000, 0x6D00FF) -- #DBDBAA
apis.term.setPaletteColor(0x4000, 0xB6FF00) -- #6D00FF
@@ -128,28 +128,23 @@ local ok, err = xpcall(function()
local function getFile(path)
local file = apis.fs.open(path, "r")
if not file then displaySuperBadError("Could not open file: "..path) end
if not file then
displaySuperBadError("Could not open file: " .. path)
end
local content = file.readAll()
file.close()
return content
end
local Kernel = load(getFile(BOOT_DRIVE_PATH.."/boot/kernel.lua"),"@Kernel")
local initFs = load(getFile(BOOT_DRIVE_PATH.."/boot/cct/initdisks"),"@Init_disks")(apis)
local fs = load(getFile(BOOT_DRIVE_PATH.."/boot/initfs"),"@InitFs")()
local key = load(getFile(BOOT_DRIVE_PATH.."/boot/cct/keys.lua"),"@keyhelper")(apis)
if not Kernel then
displaySuperBadError("Could not load kernel.")
end
if not initFs then
displaySuperBadError("Could not load initdisks.")
end
if not fs then
displaySuperBadError("Could not load initfs.")
end
if not key then
displaySuperBadError("Could not load key helper.")
end
local Kernel = load(getFile(BOOT_DRIVE_PATH .. "/boot/kernel.lua"),"@Kernel")
local initFs = load(getFile(BOOT_DRIVE_PATH .. "/boot/cct/initdisks"),"@Init_disks")(apis)
local fs = load(getFile(BOOT_DRIVE_PATH .. "/boot/initfs"), "@InitFs")()
local key = load(getFile(BOOT_DRIVE_PATH .. "/boot/cct/keys.lua"),"@keyhelper")(apis)
if not Kernel then displaySuperBadError("Could not load kernel.") end
if not initFs then displaySuperBadError("Could not load initdisks.") end
if not fs then displaySuperBadError("Could not load initfs.") end
if not key then displaySuperBadError("Could not load key helper.") end
local eventQueue = {}
@@ -159,7 +154,7 @@ local ok, err = xpcall(function()
local computer = {
time = function() return apis.os.epoch("utc") end,
clock = function() return apis.os.clock()*1000 end,
clock = function() return apis.os.clock() * 1000 end,
shutdown = apis.os.shutdown,
reboot = apis.os.reboot,
getMachineEvent = function()
@@ -169,36 +164,34 @@ local ok, err = xpcall(function()
return nil
end
end,
getEEPROM = function()
return getFile("/startup.lua")
end,
setEEPROM = function(_,text)
getEEPROM = function() return getFile("/startup.lua") end,
setEEPROM = function(_, text)
local h = apis.fs.open("/startup.lua", "w")
h.write(text)
h.close()
end
}
local icolors={
[0x1] =1, -- #000000
[0x2] =2, -- #FFFFFF
[0x4] =3, -- #FF0000
[0x8] =4, -- #00FF00
[0x10] =5, -- #0000FF
[0x20] =6, -- #00FFFF
[0x40] =7, -- #FF00FF
[0x80] =8, -- #FFFF00
[0x100] =9, -- #FF6D00
[0x200] =10, -- #6DFF55
[0x400] =11, -- #24FFFF
[0x800] =12, -- #924900
[0x1000] =13, -- #6D6D55
[0x2000] =14, -- #DBDBAA
[0x4000] =15, -- #6D00FF
[0x8000] =16 -- #B6FF00
local icolors = {
[0x1] = 1, -- #000000
[0x2] = 2, -- #FFFFFF
[0x4] = 3, -- #FF0000
[0x8] = 4, -- #00FF00
[0x10] = 5, -- #0000FF
[0x20] = 6, -- #00FFFF
[0x40] = 7, -- #FF00FF
[0x80] = 8, -- #FFFF00
[0x100] = 9, -- #FF6D00
[0x200] = 10, -- #6DFF55
[0x400] = 11, -- #24FFFF
[0x800] = 12, -- #924900
[0x1000] = 13, -- #6D6D55
[0x2000] = 14, -- #DBDBAA
[0x4000] = 15, -- #6D00FF
[0x8000] = 16 -- #B6FF00
}
local colors={
local colors = {
0x0001, -- #000000
0x0002, -- #FFFFFF
0x0004, -- #FF0000
@@ -214,7 +207,7 @@ local ok, err = xpcall(function()
0x1000, -- #6D6D55
0x2000, -- #DBDBAA
0x4000, -- #6D00FF
0x8000 -- #B6FF00
0x8000 -- #B6FF00
}
apis.term.setBackgroundColor(0x8000)
@@ -224,21 +217,33 @@ local ok, err = xpcall(function()
local kernelCoro = coroutine.create(function()
---@diagnostic disable-next-line: param-type-mismatch
local ok, err = xpcall(Kernel, debug.traceback, apis, initFs, "cct", "/sbin/init", {
print=function(_,text) write(text.."\n") end,
printInline=function(_,text) write(text) end,
clear=function() apis.term.clear() apis.term.setCursorPos(1,1) end,
setCursorPos=function(_,x,y) apis.term.setCursorPos(x,y) end,
getCursorPos=function() return apis.term.getCursorPos() end,
getSize=function() return apis.term.getSize() end,
setBackgroundColor=function(_,color) apis.term.setBackgroundColor(colors[color]) end,
setTextColor=function(_,color) apis.term.setTextColor(colors[color]) end,
getBackgroundColor=function() return icolors[apis.term.getBackgroundColor()] end,
getTextColor=function() return icolors[apis.term.getTextColor()] end
local ok, err = xpcall(Kernel, debug.traceback, apis, initFs, "cct", "/sbin/init",
{
print = function(_, text) write(text .. "\n") end,
printInline = function(_, text) write(text) end,
clear = function()
apis.term.clear()
apis.term.setCursorPos(1, 1)
end,
setCursorPos = function(_, x, y)
apis.term.setCursorPos(x, y)
end,
getCursorPos = function() return apis.term.getCursorPos() end,
getSize = function() return apis.term.getSize() end,
setBackgroundColor = function(_, color)
apis.term.setBackgroundColor(colors[color])
end,
setTextColor = function(_, color)
apis.term.setTextColor(colors[color])
end,
getBackgroundColor = function()
return icolors[apis.term.getBackgroundColor()]
end,
getTextColor = function()
return icolors[apis.term.getTextColor()]
end
}, computer, fs, "$")
if not ok then
displaySuperBadError(err)
end
if not ok then displaySuperBadError(err) end
end)
-- time is in milliseconds
@@ -250,9 +255,9 @@ local ok, err = xpcall(function()
end
end, "", 1000)
local ret = {coroutine.resume(co, ...)}
if ret[1] and ret[2]=="timeout" then
if ret[1] and ret[2] == "timeout" then
return "timeout"
elseif ret[1]==false then
elseif ret[1] == false then
return "error", ret[2]
else
debug.sethook(co)
@@ -260,7 +265,7 @@ local ok, err = xpcall(function()
end
end
write("Loaded in "..tostring(apis.os.clock()).." seconds.\n")
write("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
while true do
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
@@ -279,17 +284,15 @@ local ok, err = xpcall(function()
elseif event[1] == "disk_eject" then
queueEvent("componentRemoved", "disk")
elseif event[1] == "NoSleep" then
exit=true
exit = true
end
end
if status == "error" or coroutine.status(kernelCoro)=="dead" then
displaySuperBadError("Kernel error: "..tostring(err))
if status == "error" or coroutine.status(kernelCoro) == "dead" then
displaySuperBadError("Kernel error: " .. tostring(err))
coroutine.yield("key")
end
end
end, debug.traceback)
if not ok then
displaySuperBadError("Fatal error during boot: "..err)
end
while true do coroutine.yield() end
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
while true do coroutine.yield() end

View File

@@ -16,7 +16,6 @@ local BOOT_DRIVE_PATH=({...})[1] or "/$"
-- * `turtle.equip[Left|Right]`
-- Licensed under the MIT license
local args = {...}
if _HOST:find("UnBIOS") then return end
local keptAPIs = {keys=true, bit32 = true, bit = true, ccemux = true, config = true, coroutine = true, debug = true, fs = true, http = true, mounter = true, os = true, periphemu = true, peripheral = true, redstone = true, rs = true, term = true, utf8 = true, _HOST = true, _CC_DEFAULT_SETTINGS = true, _CC_DISABLE_LUA51_FEATURES = true, _VERSION = true, assert = true, collectgarbage = true, error = true, gcinfo = true, getfenv = true, getmetatable = true, ipairs = true, __inext = true,load = true, loadstring = true, math = true, newproxy = true, next = true, pairs = true, pcall = true, rawequal = true, rawget = true, rawlen = true, rawset = true, select = true, setfenv = true, setmetatable = true, string = true, table = true, tonumber = true, tostring = true, type = true, unpack = true, xpcall = true, turtle = true, pocket = true, commands = true, _G = true}
local t = {}
for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end
@@ -32,7 +31,6 @@ if _G.commands then _G.commands = _G.commands.native end
if _G.turtle then _G.turtle.native, _G.turtle.craft = nil end
local delete = {os = {"version", "pullEventRaw", "pullEvent", "run", "loadAPI", "unloadAPI", "sleep"}, http = _G.http and {"get", "post", "put", "delete", "patch", "options", "head", "trace", "listen", "checkURLAsync", "websocketAsync"}, fs = {"complete", "isDriveRoot"}}
for k,v in pairs(delete) do for _,a in ipairs(v) do _G[k][a] = nil end end
_G._HOST = _G._HOST .. " (UnBIOS)"
-- Set up TLCO
-- This functions by crashing `rednet.run` by removing `os.pullEventRaw`. Normally
-- this would cause `parallel` to throw an error, but we replace `error` with an

View File

@@ -1,18 +1,17 @@
--:Minify:--
-- :Minify:--
local apis = ({...})[1]
local BOOT_DRIVE_PATH=apis.BOOT_DRIVE_PATH or "/$"
local BOOT_DRIVE_PATH = apis.BOOT_DRIVE_PATH or "/$"
local fs = apis.fs
local native = apis.peripheral
local peripheral = {}
local sides = {"top", "bottom", "left", "right", "front", "back"}
function peripheral.getType(name)
if native.isPresent(name) then
return native.getType(name)
end
if native.isPresent(name) then return native.getType(name) end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
if native.hasType(side, "peripheral_hub") and
native.call(side, "isPresentRemote", name) then
return native.call(side, "getTypeRemote", name)
end
end
@@ -23,9 +22,7 @@ function peripheral.getNames()
local names = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(names, side)
end
if native.isPresent(side) then table.insert(names, side) end
if native.hasType(side, "peripheral_hub") then
local hubSides = native.call(side, "getConnectedSides")
for _, hubSide in ipairs(hubSides) do
@@ -36,37 +33,30 @@ function peripheral.getNames()
return names
end
---------------------------------------------------------
-- STORAGE
---------------------------------------------------------
local disks = {} -- real disks
local internal = {} -- "$" disk
local disks = {}
local internal = {}
---------------------------------------------------------
-- HELPERS
---------------------------------------------------------
local function norm(path)
if not path or path == "" then return "/" end
return fs.combine("/", path)
end
--- Creates a disk object given a base path
local function createDisk(id, basePath, readonly, periph)
basePath = norm(basePath)
local disk = {address=id,isReadOnly=function() return readonly end}
local disk = {address = id, isReadOnly = function() return readonly end}
function disk:spaceUsed()
return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
end
function disk:spaceTotal()
return fs.getCapacity(basePath)
end
function disk:spaceTotal() return fs.getCapacity(basePath) end
function disk:list(path)
local p = fs.combine(basePath, path)
if not fs.exists(p) or not fs.isDir(p) then return nil, "not directory" end
if not fs.exists(p) or not fs.isDir(p) then
return nil, "not directory"
end
return fs.list(p)
end
@@ -103,13 +93,9 @@ local function createDisk(id, basePath, readonly, periph)
return true
end
function disk:setLabel(label)
periph.setLabel(label)
end
function disk:setLabel(label) periph.setLabel(label) end
function disk:getLabel(label)
return periph.getLabel()
end
function disk:getLabel(label) return periph.getLabel() end
function disk:attributes(path)
local p = fs.combine(basePath, path)
@@ -120,39 +106,30 @@ local function createDisk(id, basePath, readonly, periph)
local p = fs.combine(basePath, path)
return fs.open(p, mode)
end
return disk
end
---------------------------------------------------------
-- INTERNAL DISK "$" (mapped to "/")
---------------------------------------------------------
internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
setLabel=function(label)
setLabel = function(label)
local h = fs.open("/.label", "w")
h.write(label)
h.close()
end,
getLabel=function()
getLabel = function()
local h = fs.open("/.label", "r")
if not h then return "$" end
local label = h.readAll()
h.close()
return label
end
})
---------------------------------------------------------
-- SCAN REAL DISK PERIPHERALS
---------------------------------------------------------
local function refresh()
-- remove disks that no longer exist
for id, _ in pairs(disks) do
if not peripheral.getType(id) then
disks[id] = nil
end
if not peripheral.getType(id) then disks[id] = nil end
end
-- detect new disks
for _, name in ipairs(peripheral.getNames()) do
if peripheral.getType(name) == "disk" then
if not disks[name] then
@@ -165,28 +142,14 @@ local function refresh()
end
end
---------------------------------------------------------
-- ITERATOR
---------------------------------------------------------
local function iter()
refresh()
-- first internal
local combined = {}
for id, obj in pairs(internal) do
combined[id] = obj
end
for id, obj in pairs(disks) do
combined[id] = obj
end
for id, obj in pairs(internal) do combined[id] = obj end
for id, obj in pairs(disks) do combined[id] = obj end
return pairs(combined)
end
---------------------------------------------------------
-- MODULE RETURN
---------------------------------------------------------
return {
refresh = refresh,
list = iter
}
return {refresh = refresh, list = iter}

View File

@@ -1,6 +1,6 @@
--:Minify:--
local apis=...
local keys=apis.keys
-- :Minify:--
local apis = ...
local keys = apis.keys
local tKeys = {}
tKeys[keys.space] = ' '
tKeys[keys.grave] = '`'
@@ -63,13 +63,13 @@ tKeys[keys.pageUp] = '\x1b[5~'
tKeys[keys.pageDown] = '\x1b[6~'
tKeys[keys.home] = '\x1b[1~'
tKeys[keys["end"]] = '\x1b[4~'
--tKeys[keys.capsLock] = '\x1b[capsLock'
--tKeys[keys.scrollLock] = '\x1b[scrollLock'
--tKeys[keys.numLock] = '\x1b[numLock'
--if keys.printScreen then
-- tKeys[keys.capsLock] = '\x1b[capsLock'
-- tKeys[keys.scrollLock] = '\x1b[scrollLock'
-- tKeys[keys.numLock] = '\x1b[numLock'
-- if keys.printScreen then
-- tKeys[keys.printScreen] = '\x1b[printScreen'
--end
--tKeys[keys.pause] = '\x1b[pause'
-- end
-- tKeys[keys.pause] = '\x1b[pause'
tKeys[keys.f1] = '\x1b[11~'
tKeys[keys.f2] = '\x1b[12~'
tKeys[keys.f3] = '\x1b[13~'
@@ -82,19 +82,19 @@ tKeys[keys.f9] = '\x1b[20~'
tKeys[keys.f10] = '\x1b[21~'
tKeys[keys.f11] = '\x1b[23~'
tKeys[keys.f12] = '\x1b[24~'
--tKeys[keys.f13] = '\x1b[25~'
--tKeys[keys.f14] = '\x1b[26~'
--tKeys[keys.f15] = '\x1b[28~'
--tKeys[keys.f16] = '\x1b[29~'
--tKeys[keys.f17] = '\x1b[31~'
--tKeys[keys.f18] = '\x1b[32~'
--tKeys[keys.f19] = '\x1b[33~'
--tKeys[keys.f20] = '\x1b[34~'
--tKeys[keys.f21] = '\x1b[42~'
--tKeys[keys.f22] = '\x1b[43~'
--tKeys[keys.f23] = '\x1b[44~'
--tKeys[keys.f24] = '\x1b[45~'
--tKeys[keys.f25] = '\x1b[46~'
-- tKeys[keys.f13] = '\x1b[25~'
-- tKeys[keys.f14] = '\x1b[26~'
-- tKeys[keys.f15] = '\x1b[28~'
-- tKeys[keys.f16] = '\x1b[29~'
-- tKeys[keys.f17] = '\x1b[31~'
-- tKeys[keys.f18] = '\x1b[32~'
-- tKeys[keys.f19] = '\x1b[33~'
-- tKeys[keys.f20] = '\x1b[34~'
-- tKeys[keys.f21] = '\x1b[42~'
-- tKeys[keys.f22] = '\x1b[43~'
-- tKeys[keys.f23] = '\x1b[44~'
-- tKeys[keys.f24] = '\x1b[45~'
-- tKeys[keys.f25] = '\x1b[46~'
-- Numpad
tKeys[keys.numPad0] = '0'
@@ -108,15 +108,15 @@ tKeys[keys.numPad7] = '7'
tKeys[keys.numPad8] = '8'
tKeys[keys.numPad9] = '9'
--tKeys[340] = 'leftShift'
--tKeys[341] = 'leftCtrl'
--tKeys[342] = 'leftAlt'
--tKeys[343] = 'leftSuper'
--tKeys[344] = 'rightShift'
--tKeys[345] = 'rightCtrl'
--tKeys[346] = 'rightAlt'
--tKeys[347] = 'rightSuper'
--tKeys[348] = 'menu'
-- tKeys[340] = 'leftShift'
-- tKeys[341] = 'leftCtrl'
-- tKeys[342] = 'leftAlt'
-- tKeys[343] = 'leftSuper'
-- tKeys[344] = 'rightShift'
-- tKeys[345] = 'rightCtrl'
-- tKeys[346] = 'rightAlt'
-- tKeys[347] = 'rightSuper'
-- tKeys[348] = 'menu'
local shift = false
local ctrl = false
@@ -178,26 +178,34 @@ end
local function p()
local str = ""
if alt then
str=str.."\x1b"
end
if ctrl then
str=str.."^"
end
if alt then str = str .. "\x1b" end
if ctrl then str = str .. "^" end
return str
end
return function(event, q)
if event[1] == "key" then
if event[2]==keys.leftCtrl or event[2]==keys.rightCtrl then ctrl=true return
elseif event[2]==keys.leftAlt or event[2]==keys.rightAlt then alt=true return
elseif event[2]==keys.leftShift or event[2]==keys.rightCtrl then shift=true return
if event[2] == keys.leftCtrl or event[2] == keys.rightCtrl then
ctrl = true
return
elseif event[2] == keys.leftAlt or event[2] == keys.rightAlt then
alt = true
return
elseif event[2] == keys.leftShift or event[2] == keys.rightCtrl then
shift = true
return
end
q("keyTyped", 1, p()..s(tKeys[event[2]]))
q("keyTyped", 1, p() .. s(tKeys[event[2]]))
elseif event[1] == "key_up" then
if event[2]==keys.leftCtrl or event[2]==keys.rightCtrl then ctrl=false return
elseif event[2]==keys.leftAlt or event[2]==keys.rightAlt then alt=false return
elseif event[2]==keys.leftShift or event[2]==keys.rightCtrl then shift=false return
if event[2] == keys.leftCtrl or event[2] == keys.rightCtrl then
ctrl = false
return
elseif event[2] == keys.leftAlt or event[2] == keys.rightAlt then
alt = false
return
elseif event[2] == keys.leftShift or event[2] == keys.rightCtrl then
shift = false
return
end
end
end
end

View File

@@ -1,17 +1,16 @@
--:Minify:--
local kernel=...
local apis=kernel.apis
local main=apis.term
local native=apis.peripheral
-- :Minify:--
local kernel = ...
local apis = kernel.apis
local main = apis.term
local native = apis.peripheral
local sides = {"top", "bottom", "left", "right", "front", "back"}
local function getType(name)
if native.isPresent(name) then
return native.getType(name)
end
if native.isPresent(name) then return native.getType(name) end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
if native.hasType(side, "peripheral_hub") and
native.call(side, "isPresentRemote", name) then
return native.call(side, "getTypeRemote", name)
end
end
@@ -22,9 +21,7 @@ local function getNames()
local names = {}
for n = 1, #sides do
local side = sides[n]
if native.isPresent(side) then
table.insert(names, side)
end
if native.isPresent(side) then table.insert(names, side) end
if native.hasType(side, "peripheral_hub") then
local hubSides = native.call(side, "getConnectedSides")
for _, hubSide in ipairs(hubSides) do
@@ -36,38 +33,37 @@ local function getNames()
end
local function wrapPeripheral(name)
if native.isPresent(name) then
return wrapPeripheral(name)
end
if native.isPresent(name) then return wrapPeripheral(name) end
for n = 1, #sides do
local side = sides[n]
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
if native.hasType(side, "peripheral_hub") and
native.call(side, "isPresentRemote", name) then
return native.call(side, "wrapRemote", name)
end
end
return nil
end
local icolors={
[0x1] =1, -- #000000
[0x2] =2, -- #FFFFFF
[0x4] =3, -- #FF0000
[0x8] =4, -- #00FF00
[0x10] =5, -- #0000FF
[0x20] =6, -- #00FFFF
[0x40] =7, -- #FF00FF
[0x80] =8, -- #FFFF00
[0x100] =9, -- #FF6D00
[0x200] =10, -- #6DFF55
[0x400] =11, -- #24FFFF
[0x800] =12, -- #924900
[0x1000] =13, -- #6D6D55
[0x2000] =14, -- #DBDBAA
[0x4000] =15, -- #6D00FF
[0x8000] =16 -- #B6FF00
local icolors = {
[0x1] = 1, -- #000000
[0x2] = 2, -- #FFFFFF
[0x4] = 3, -- #FF0000
[0x8] = 4, -- #00FF00
[0x10] = 5, -- #0000FF
[0x20] = 6, -- #00FFFF
[0x40] = 7, -- #FF00FF
[0x80] = 8, -- #FFFF00
[0x100] = 9, -- #FF6D00
[0x200] = 10, -- #6DFF55
[0x400] = 11, -- #24FFFF
[0x800] = 12, -- #924900
[0x1000] = 13, -- #6D6D55
[0x2000] = 14, -- #DBDBAA
[0x4000] = 15, -- #6D00FF
[0x8000] = 16 -- #B6FF00
}
local colors={
local colors = {
0x0001, -- #000000
0x0002, -- #FFFFFF
0x0004, -- #FF0000
@@ -83,7 +79,7 @@ local colors={
0x1000, -- #6D6D55
0x2000, -- #DBDBAA
0x4000, -- #6D00FF
0x8000 -- #B6FF00
0x8000 -- #B6FF00
}
local function write(text, term)
@@ -121,7 +117,7 @@ local function write(text, term)
y = y + 1
end
if y-1 >= h then
if y - 1 >= h then
term.scroll(1)
y = h
term.setCursorPos(x, y)
@@ -132,38 +128,24 @@ local function write(text, term)
end
local function newTTY(term)
local ret={}
function ret.print(text)
write(text.."\n", term)
end
function ret.printInline(text)
write(text, term)
end
local ret = {}
function ret.print(text) write(text .. "\n", term) end
function ret.printInline(text) write(text, term) end
function ret.clear()
term.clear()
term.setCursorPos(1,1)
end
function ret.setCursorPos(x,y)
term.setCursorPos(x,y)
end
function ret.getCursorPos()
return term.getCursorPos()
end
function ret.getSize()
return term.getSize()
term.setCursorPos(1, 1)
end
function ret.setCursorPos(x, y) term.setCursorPos(x, y) end
function ret.getCursorPos() return term.getCursorPos() end
function ret.getSize() return term.getSize() end
function ret.setBackgroundColor(color)
term.setBackgroundColor(colors[color])
end
function ret.setTextColor(color)
term.setTextColor(colors[color])
end
function ret.setTextColor(color) term.setTextColor(colors[color]) end
function ret.getBackgroundColor()
return icolors[term.getBackgroundColor()]
end
function ret.getTextColor()
return icolors[term.getTextColor()]
end
function ret.getTextColor() return icolors[term.getTextColor()] end
return ret
end

View File

@@ -1 +1,3 @@
U $;/
U $;/
U devfs0000;/dev/
U tmpfs0000;/tmp/

View File

@@ -1,4 +1,4 @@
--:Minify:--
-- :Minify:--
local fs = {}
local disks = {}
local mounts = {}
@@ -15,39 +15,42 @@ local function resolve(path)
local newPath = path:sub(#mountPoint + 1)
return disks[mounts[mountPoint]], newPath
end
---------------------------------------------------------
function fs.update(initdisks)
disks = {}
for k, v in initdisks.list() do
disks[k] = v
end
for k, v in initdisks.list() do disks[k] = v end
end
function fs.exists(path)
local disk, newPath = resolve(path)
return disk:directoryExists(newPath) or disk:fileExists(newPath)
end
function fs.isFile(path)
local disk, newPath = resolve(path)
return disk:fileExists(newPath)
end
function fs.isDir(path)
local disk, newPath = resolve(path)
return disk:directoryExists(newPath)
end
function fs.list(path)
local disk, newPath = resolve(path)
return disk:list(newPath)
end
function fs.makeDir(path)
local disk, newPath = resolve(path)
return disk:makeDirectory(newPath)
end
function fs.remove(path)
local disk, newPath = resolve(path)
return disk:remove(newPath)
end
function fs.readAllText(path)
local disk, newPath = resolve(path)
local handle = disk:open(newPath, "r")
@@ -56,23 +59,26 @@ function fs.readAllText(path)
handle.close()
return content
end
function fs.writeAllText(path, text)
local disk, newPath = resolve(path)
local handle = disk:open(newPath, "w")
handle.write(text)
handle.close()
end
function fs.appendAllText(path, text)
local disk, newPath = resolve(path)
local handle = disk:open(newPath, "a")
handle.write(text)
handle.close()
end
function fs.load(path)
return load(fs.readAllText(path), path)
end
function fs.load(path) return load(fs.readAllText(path), path) end
function fs.mount(disk, mountPoint)
if not disks[disk] then return end
mounts[mountPoint] = disk
end
return fs
return fs

View File

@@ -12,7 +12,7 @@ kernel.version="HyperionOS V1.0.0"
kernel.process = "Kernel"
kernel.username = "root"
kernel.hostname = "hyperion"
kernel.groups = {0}
kernel.groups = {}
kernel.uid = 0
kernel.gid = 0
kernel.status = "start"
@@ -149,9 +149,6 @@ function kernel.saveLog()
ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text)
end
ifs.remove("/tmp")
ifs.makeDir("/tmp")
function kernel.newFifo()
local fifo = {}
fifo.push=function(data)
@@ -241,6 +238,7 @@ 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["setUsername"]=function(user) if kernel.uid~=0 then error("Permission denied") end kernel.currentTask.username=user end
kernel.syscalls["arch"]=function() return arch end
kernel.syscalls["test"]=function() return true end
kernel.log("Running modules")

View File

@@ -1,61 +1,38 @@
--:Minify:--
-- :Minify:--
function string.hasSuffix(str, suffix)
return string.sub(str, #suffix+1) == suffix
return string.sub(str, #suffix + 1) == suffix
end
function string.hasPrefix(str, prefix)
return string.sub(str, 1, #prefix) == prefix
end
function string.getSuffix(str, prefix)
return string.sub(str, #prefix+1)
end
function string.getSuffix(str, prefix) return string.sub(str, #prefix + 1) end
function string.getPrefix(str, suffix)
return string.sub(str, 1, #suffix)
end
function string.getPrefix(str, suffix) return string.sub(str, 1, #suffix) end
function string.join(str, ...)
return table.concat(table.pack(str, ...))
end
function string.join(str, ...) return table.concat(table.pack(str, ...)) end
function string.delim(str, ...)
return table.concat(table.pack(...), str)
end
function string.delim(str, ...) return table.concat(table.pack(...), str) end
function string.split(str, delim, maxResultCountOrNil)
assert(#delim == 1, "only delim len 1 supported for now")
maxResultCountOrNil = (maxResultCountOrNil or 0)-1
maxResultCountOrNil = (maxResultCountOrNil or 0) - 1
local rv = {}
local buf = ""
for i = 1, #str do
local c = string.sub(str,i,i)
local c = string.sub(str, i, i)
if #rv ~= maxResultCountOrNil and c == delim then
table.insert(rv, buf)
buf = ""
else
buf = buf..c
buf = buf .. c
end
end
table.insert(rv, buf)
return rv
end
function string.replace(str, search, replacement)
local rv = ""
local consumedLen = 1
local i = 1
while i<#str do
if string.sub(str, i, i+#search-1) == search then
rv = rv .. string.sub(str, consumedLen, i-1) .. replacement
i=i+#search
consumedLen = i
end
i=i+1
end
return rv .. string.sub(str, consumedLen)
end
function table.deepcopy(orig, copies)
copies = copies or {}
@@ -78,98 +55,30 @@ function table.deepcopy(orig, copies)
end
function table.hasKey(tabl, query)
for i,v in pairs(tabl) do
if i==query then
return v
end
end
for i, v in pairs(tabl) do if i == query then return v end end
return false
end
function table.hasVal(tabl, query)
for i,v in pairs(tabl) do
if v==query then
return i
end
end
for i, v in pairs(tabl) do if v == query then return i end end
return false
end
function table.proxy(tbl)
local proxies = setmetatable({}, {__mode = "k"}) -- Weak table to avoid cycles
local function createProxy(t)
if type(t) ~= "table" then return t end
if proxies[t] then return proxies[t] end -- reuse proxy for the same table (handle cycles)
local proxy = {}
proxies[t] = proxy
local mt
mt = {
__index = function(_, k)
local value = t[k]
if type(value) == "table" then
return createProxy(value) -- recursively proxy subtables
else
return value
end
end,
__newindex = function()
error("Attempt to modify table proxy", 2)
end,
__pairs = function()
return function(_, k)
local nextKey, nextValue = next(t, k)
if type(nextValue) == "table" then
nextValue = createProxy(nextValue)
end
return nextKey, nextValue
end, nil, nil
end,
__ipairs = function()
local i = 0
local n = #t
return function()
i = i + 1
if i <= n then
local v = t[i]
if type(v) == "table" then
v = createProxy(v)
end
return i, v
end
end
end,
__metatable = false
}
setmetatable(proxy, mt)
return proxy
end
return createProxy(tbl)
end
local function serialize(tbl, seen)
seen = seen or {}
-- If we've seen this table before, return a placeholder to prevent infinite loops
if seen[tbl] then
return '"[Circular Reference]"'
end
if seen[tbl] then return '"[Circular Reference]"' end
-- Mark this table as seen
seen[tbl] = true
local output = "{"
local first = true
for i, v in pairs(tbl) do
-- Handle comma placement more cleanly
if not first then
output = output .. ","
end
if not first then output = output .. "," end
first = false
-- Serialize Key
@@ -197,21 +106,19 @@ local function serialize(tbl, seen)
end
seen[tbl] = nil
output = output .. "}"
return output
end
local oldtype=type
local oldgetmetatable=getmetatable
local oldtype = type
local oldgetmetatable = getmetatable
function type(object, trueType)
if trueType then
return oldtype(object)
end
if oldtype(object)~="table" then
if trueType then return oldtype(object) end
if oldtype(object) ~= "table" then
return oldtype(object)
else
if oldtype(oldgetmetatable(object))=="table" then
if oldtype(oldgetmetatable(object)) == "table" then
local metatable = oldgetmetatable(object)
---@diagnostic disable-next-line: need-check-nil
if metatable.__type then return metatable.__type end
@@ -222,10 +129,10 @@ function type(object, trueType)
end
function getmetatable(object)
if oldtype(object)~="table" then return end
if oldtype(oldgetmetatable(object))=="table" then
if oldtype(object) ~= "table" then return end
if oldtype(oldgetmetatable(object)) == "table" then
if oldgetmetatable(object).__isuserdata then
if oldtype(oldgetmetatable(object).__usermeta)=="function" then
if oldtype(oldgetmetatable(object).__usermeta) == "function" then
return oldgetmetatable(object).__usermeta()
else
return oldgetmetatable(object).__usermeta
@@ -239,22 +146,14 @@ function getmetatable(object)
end
function isEqualToAny(a, ...)
local args={...}
for i=0, #args do
if a==args[i] then
return true
end
end
local args = {...}
for i = 0, #args do if a == args[i] then return true end end
return false
end
function isEqualToAll(a, ...)
local args={...}
for i=0, #args do
if a~=args[i] then
return false
end
end
local args = {...}
for i = 0, #args do if a ~= args[i] then return false end end
return true
end
@@ -271,12 +170,39 @@ function table.values(t)
end
function table.indexOf(t, value)
for i,v in ipairs(t) do
if v==value then
return i
for i, v in ipairs(t) do if v == value then return i end end
return -1
end
function string.replace(s, target, repl)
local result = {}
local i = 1
local n = #s
local t_len = #target
while i <= n do
local match = true
if i + t_len - 1 <= n then
for j = 1, t_len do
if s:sub(i + j - 1, i + j - 1) ~= target:sub(j, j) then
match = false
break
end
end
else
match = false
end
if match then
table.insert(result, repl)
i = i + t_len
else
table.insert(result, s:sub(i, i))
i = i + 1
end
end
return -1
return table.concat(result)
end
syscall = setmetatable({}, {
@@ -292,4 +218,4 @@ syscall = setmetatable({}, {
end
})
table.serialize=serialize
table.serialize = serialize

View File

@@ -1,42 +1,41 @@
--:Minify:--
local kernel=...
-- :Minify:--
local kernel = ...
local io = {}
kernel.io=io
io.eventq={}
kernel.io = io
io.eventq = {}
function io.pushEvent(queue, ...)
queue=tostring(queue)
if not io.eventq[queue] then
io.eventq[queue]={}
end
io.eventq[queue][#io.eventq[queue]+1]={...}
queue = tostring(queue)
if not io.eventq[queue] then io.eventq[queue] = {} end
io.eventq[queue][#io.eventq[queue] + 1] = {...}
end
function io.bind(queue)
queue=tostring(queue)
kernel.currentTask.eventq=queue
queue = tostring(queue)
kernel.currentTask.eventq = queue
end
function io.pullEvent()
if io.eventq[kernel.currentTask.eventq] then
if #io.eventq[kernel.currentTask.eventq]==1 then
if #io.eventq[kernel.currentTask.eventq] == 1 then
local event = table.remove(io.eventq[kernel.currentTask.eventq] or {}, 1)
io.eventq[kernel.currentTask.eventq]=nil
io.eventq[kernel.currentTask.eventq] = nil
return table.unpack(event)
end
local event = table.remove(io.eventq[kernel.currentTask.eventq] or {}, 1)
local event =
table.remove(io.eventq[kernel.currentTask.eventq] or {}, 1)
if not event then return end
return table.unpack(event)
end
end
function io.getBoundQueue()
return kernel.currentTask.eventq
end
function io.getBoundQueue() return kernel.currentTask.eventq end
kernel.syscalls["IO_pushEvent"]=io.pushEvent
kernel.syscalls["IO_pullEvent"]=io.pullEvent
kernel.syscalls["IO_bind"]=io.bind
kernel.syscalls["IO_getBoundQueue"]=io.getBoundQueue
kernel.syscalls["IO_pushEvent"] = io.pushEvent
kernel.syscalls["IO_pullEvent"] = io.pullEvent
kernel.syscalls["IO_bind"] = io.bind
kernel.syscalls["IO_getBoundQueue"] = io.getBoundQueue
kernel.log("IO pipeline initialized")
kernel.log("IO pipeline initialized")

View File

@@ -1,15 +1,15 @@
--:Minify:--
-- :Minify:--
local kernel = ...
local vfs = {}
kernel.vfs=vfs
vfs.mounts = { ["$"] = "/" }
kernel.vfs = vfs
vfs.mounts = {["$"] = "/"}
vfs.disks = kernel.disks
-- 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
if path:sub(1, 1) ~= "/" then path = cwd .. "/" .. path end
local parts = {}
for part in path:gmatch("[^/]+") do
if part == ".." then
@@ -21,22 +21,43 @@ local function normalizePath(path)
return "/" .. table.concat(parts, "/")
end
function vfs.splitPath(path)
local rv=string.split(path,"/")
while table.indexOf(rv, "") ~= -1 do
table.remove(rv, table.indexOf(rv, ""))
end
return rv
end
-- Resolve mount and disk path
local function resolvePath(path)
path = normalizePath(path)
local mountPoint = "/"
local mountId = "$"
for k,v in pairs(vfs.mounts) do
if path:sub(1,#v) == v and #v > #mountPoint then
mountPoint = v
mountId = k
local mountPoint = nil
local mountId = nil
for id, mp in pairs(vfs.mounts) do
if path == mp or (mp == "/" and path:sub(1, 1) == "/") or path:sub(1, #mp + 1) == mp .. "/" then
if not mountPoint or #mp > #mountPoint then
mountPoint = mp
mountId = id
end
end
end
local diskPath = path:sub(#mountPoint)
if diskPath == "" then diskPath = "/" end
if not mountId then
error("ENODEV")
end
local diskPath = path:sub(#mountPoint + 1)
if diskPath == "" then
diskPath = "/"
end
if kernel.config.logPathResolution then
kernel.log("Path '"..path.."' resolved to disk '"..mountId.."' and path '"..diskPath.."'")
end
return vfs.disks[mountId], diskPath
end
@@ -55,25 +76,26 @@ local function checkSystemLimit()
end
-- File object constructor
local function newFileObj(handle, mode, path, meta)
local function newFileObj(handle, mode, path, meta, type)
return {
handle = handle,
mode = mode,
path = path,
meta = meta
meta = meta,
type = type
}
end
-- Validate mode
local function ismode(mode)
if not (mode == "r" or mode == "w" or mode == "a") then error("EINVAL") end
function vfs.newfd(fdobj)
checkSystemLimit()
total=total+1
local fd = allocFD(kernel.currentTask)
kernel.currentTask.fd[fd]=fdobj
end
-- Parse metafile
local function parseMetafile(file)
if not file or file == "" then
return {}
end
if not file or file == "" then return {} end
local ret = {}
local pointer = 1
@@ -99,12 +121,7 @@ local function parseMetafile(file)
pointer = pointer + cmetalen
end
ret[name] = {
owner = owner,
group = group,
perms = perms,
cmeta = cmeta
}
ret[name] = {owner = owner, group = group, perms = perms, cmeta = cmeta}
end
return ret
@@ -112,7 +129,7 @@ end
-- Build metafile
local function makeMetafile(meta)
local file=""
local file = ""
for name, m in pairs(meta) do
local entry = ""
entry = entry .. string.char(#name) .. name
@@ -129,22 +146,18 @@ local function getFileMeta(path)
fullPath = normalizePath(fullPath)
local parts = {}
for p in fullPath:gmatch("[^/]+") do
table.insert(parts, p)
end
for p in fullPath:gmatch("[^/]+") do table.insert(parts, p) end
-- default fallback
local default = { owner=0, group=0, perms=62, cmeta="" }
local default = {owner = 0, group = 0, perms = 63, cmeta = ""}
-- walk from deepest parent upward
for i = #parts, 1, -1 do
local parent = "/" .. table.concat(parts, "/", 1, i-1)
local parent = "/" .. table.concat(parts, "/", 1, i - 1)
if parent ~= "/" then parent = parent .. "/" end
local target = parts[i]
if target == ".meta" then
error("Cannot open metafile")
end
if target == ".meta" then error("Cannot open metafile") end
local metaPath = parent .. ".meta"
if disk:fileExists(metaPath) then
@@ -153,9 +166,7 @@ local function getFileMeta(path)
f.close()
local parsed = parseMetafile(text)
if parsed[target] then
return parsed[target]
end
if parsed[target] then return parsed[target] end
end
end
@@ -173,13 +184,9 @@ local function ensureParentMeta(path)
name = fullPath:gsub("^/", "")
end
if name == ".meta" then
error("Cannot open metafile")
end
if name == ".meta" then error("Cannot open metafile") end
if parent ~= "/" and parent:sub(-1) ~= "/" then
parent = parent .. "/"
end
if parent ~= "/" and parent:sub(-1) ~= "/" then parent = parent .. "/" end
local metaPath = parent .. ".meta"
@@ -192,27 +199,32 @@ local function ensureParentMeta(path)
return metaPath, name
end
-- 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}
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
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 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
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
@@ -220,39 +232,55 @@ end
-- mounts
local function normalizeMountPoint(path)
path = normalizePath(path)
if path ~= "/" and path:sub(-1) == "/" then
path = path:sub(1, -2)
end
if path ~= "/" and path:sub(-1) == "/" then path = path:sub(1, -2) end
return path
end
local required = {
"open",
"type",
"list",
"attributes",
"fileExists",
"makeDirectory",
"remove"
}
local function check(disk)
for _, name in ipairs(required) do
if type(disk[name]) ~= "function" then
error("Invalid disk: missing method '" .. name .. "'")
end
end
end
function vfs.mount(target, diskOrId)
if kernel.uid ~= 0 then error("EPERM") end
if not target then error("EINVAL") end
target = normalizeMountPoint(target)
if not vfs.exists(target) then vfs.mkdir(target) end
if vfs.type(target) ~= "directory" then error("EINVAL") end
local disk
local id
if type(diskOrId) == "string" then
disk = kernel.disks[diskOrId]
id = diskOrId
if not disk then error("ENODEV") end
check(disk)
id = diskOrId
elseif type(diskOrId) == "table" then
check(disk)
disk = diskOrId
id = tostring(disk)
id = disk.address
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
for _, mp in pairs(vfs.mounts) do if mp == target then error("EBUSY") end end
vfs.mounts[id] = target
return true
@@ -277,7 +305,6 @@ end
-- Open file
function vfs.open(path, mode)
ismode(mode)
checkSystemLimit()
local task = kernel.currentTask
local fd = allocFD(task)
@@ -287,8 +314,13 @@ function vfs.open(path, mode)
local meta = getFileMeta(path)
checkperms(meta, mode)
local handle = disk:open(diskPath, mode)
task.fd[fd] = newFileObj(handle, mode, path, meta)
local handle
if disk:type(diskPath)~="directory" then
handle = disk:open(diskPath, mode)
if type(handle)~="table" then error("ENFILE") end
end
task.fd[fd] = newFileObj(handle, mode, path, meta, disk:type(diskPath))
total = total + 1
return fd
end
@@ -298,6 +330,7 @@ function vfs.read(fd, count)
local task = kernel.currentTask
local file = task.fd[fd]
if not file then error("EBADF") end
if not file.handle.read then error("EBADF") end
if file.mode ~= "r" then error("EBADF") end
return file.handle.read(count or 1)
end
@@ -307,6 +340,7 @@ function vfs.write(fd, content)
local task = kernel.currentTask
local file = task.fd[fd]
if not file then error("EBADF") end
if not file.handle.write then error("EBADF") end
if file.mode ~= "w" and file.mode ~= "a" then error("EBADF") end
return file.handle.write(content)
end
@@ -316,6 +350,8 @@ function vfs.pread(fd, count, offset)
local task = kernel.currentTask
local file = task.fd[fd]
if not file then error("EBADF") end
if not file.handle.read then error("EBADF") end
if not file.handle.seek then error("EBADF") end
if file.mode ~= "r" then error("EBADF") end
file.handle.seek("set", offset)
return file.handle.read(count or 1)
@@ -325,6 +361,8 @@ function vfs.pwrite(fd, content, offset)
local task = kernel.currentTask
local file = task.fd[fd]
if not file then error("EBADF") end
if not file.handle.write then error("EBADF") end
if not file.handle.seek 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)
@@ -335,6 +373,7 @@ function vfs.lseek(fd, offset, whence)
local task = kernel.currentTask
local file = task.fd[fd]
if not file then error("EBADF") end
if not file.handle.seek then error("EBADF") end
return file.handle.seek(whence or "set", offset)
end
@@ -343,6 +382,7 @@ function vfs.fsync(fd)
local task = kernel.currentTask
local file = task.fd[fd]
if not file then error("EBADF") end
if not file.handle.flush then error("EBADF") end
if file.mode ~= "w" and file.mode ~= "a" then error("EBADF") end
file.handle.flush()
end
@@ -352,7 +392,9 @@ function vfs.close(fd)
local task = kernel.currentTask
local file = task.fd[fd]
if not file then error("EBADF") end
file.handle.close()
if file.handle.close then
file.handle.close()
end
task.fd[fd] = nil
total = total - 1
end
@@ -364,8 +406,11 @@ function vfs.sendfile(outfd, infd, count)
local outFile = task.fd[outfd]
if not inFile or not outFile then error("EBADF") end
if inFile.mode ~= "r" then error("EBADF") end
if not inFile.handle.read then error("EBADF") end
if outFile.mode ~= "w" and outFile.mode ~= "a" then error("EBADF") end
if not outFile.handle.write then error("EBADF") end
local data = inFile.handle.read(count or 1024)
if not data or data == "" then return end
return outFile.handle.write(data)
end
@@ -403,12 +448,12 @@ end
-- Directory operations
function vfs.listdir(path)
local disk, diskPath = resolvePath(path)
if disk:type(diskPath) ~= "directory" then error("ENOTDIR") end
if disk:type(diskPath) ~= "directory" then error("ENOENT") end
local meta = getFileMeta(path)
checkperms(meta, "r")
local list = disk:list(diskPath)
if table.indexOf(list,".meta")~=-1 then
table.remove(list,table.indexOf(list,".meta"))
if table.indexOf(list, ".meta") ~= -1 then
table.remove(list, table.indexOf(list, ".meta"))
end
return list
end
@@ -431,8 +476,8 @@ end
function vfs.chmod(path, perms)
local disk, diskPath = resolvePath(path)
local meta = getFileMeta(path)
checkperms(meta, "w")
if meta.owner ~= kernel.currentTask.uid then error("EACCES") end
meta.perms = perms
local mpath, target = ensureParentMeta(path)
@@ -449,7 +494,6 @@ function vfs.chmod(path, perms)
f.close()
end
function vfs.fchmod(fd, perms)
local task = kernel.currentTask
local file = task.fd[fd]
@@ -460,8 +504,8 @@ end
function vfs.chown(path, uid, gid)
local disk, diskPath = resolvePath(path)
local meta = getFileMeta(path)
checkperms(meta, "w")
if meta.owner ~= kernel.currentTask.uid then error("EACCES") end
meta.owner = uid
meta.group = gid
@@ -479,7 +523,6 @@ function vfs.chown(path, uid, gid)
f.close()
end
function vfs.fchown(fd, uid, gid)
local task = kernel.currentTask
local file = task.fd[fd]
@@ -501,13 +544,9 @@ function vfs.type(path)
return disk:type(diskPath)
end
function vfs.getcwd()
return kernel.currentTask.cwd
end
function vfs.getcwd() return kernel.currentTask.cwd end
function vfs.chdir(path)
kernel.currentTask.cwd=path
end
function vfs.chdir(path) kernel.currentTask.cwd = path end
-- Export syscalls
local sys = kernel.syscalls
@@ -531,9 +570,9 @@ sys["chown"] = vfs.chown
sys["fchown"] = vfs.fchown
sys["exists"] = vfs.exists
sys["type"] = vfs.type
sys["mount"] = vfs.mount
sys["mount"] = vfs.mount
sys["umount"] = vfs.umount
sys["getcwd"] = vfs.getcwd
sys["chdir"] = vfs.chdir
kernel.log("VFS module loaded")
kernel.log("VFS module loaded")

View File

@@ -1,37 +1,33 @@
--:Minify:--
-- :Minify:--
local kernel = ...
local cache = {}
kernel.searchpaths = {
"/lib/?.lua",
"/lib/?",
"/usr/lib/?.lua",
"/usr/lib/?",
"/usr/local/lib/?.lua",
"/usr/local/lib/?",
"?.lua",
"?"
"/lib/?.lua", "/lib/?", "/usr/lib/?.lua", "/usr/lib/?",
"/usr/local/lib/?.lua", "/usr/local/lib/?", "?.lua", "?"
}
function require(module,...)
if cache[module] then
return cache[module]
end
function require(module, ...)
if cache[module] then return cache[module] end
local modpath = module:gsub("%.", "/")
local failed = {}
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
local full_path = string.replace(path, "?", modpath)
if full_path:sub(1, 1) ~= "/" then
full_path = kernel.currentTask.cwd .. full_path
end
if kernel.vfs.exists(full_path) then
if kernel.vfs.type(full_path)=="directory" then
if kernel.vfs.type(full_path) == "directory" then
full_path = full_path .. "/init"
end
if kernel.vfs.exists(full_path) then
local handle = kernel.vfs.open(full_path, "r")
local file_content = kernel.vfs.read(handle, 1024 * 1024 * 4)
kernel.vfs.close(handle)
return assert(load(file_content, full_path, "t", kernel._U))(...)
return
assert(load(file_content, full_path, "t", kernel._U))(...)
else
table.insert(failed, full_path)
end
@@ -39,5 +35,6 @@ function require(module,...)
table.insert(failed, full_path)
end
end
error("Module not found: " .. module .. " (searched paths: " .. table.concat(failed, ", ") .. ")")
end
end

View File

@@ -1,173 +1,143 @@
--: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 = function() return false end
proxy.spaceUsed = function() return 0 end
proxy.spaceTotal = function() return 0 end
proxy.makeDirectory = function() error("EACCES") end
proxy.remove = function() error("EACCES") end
proxy.setLabel = function() error("EACCES") end
proxy.getLabel = function() return "devfs" end
proxy.attributes = function(path) return {
size = 0,
modified = 0,
created = 0,
} end
function proxy:open(path, mode)
local steps = kernel.vfs.splitPath(path)
local step = data
for i=1, #steps-1 do
local dat = step[steps[i]]
if type(dat) ~= "table" then error("ENFILE") end
step=dat
end
if type(step[steps[#steps]]) == "function" then
return step[steps[#steps]]("open", mode)
end
error("ENFILE")
end
function proxy:type(path, mode)
local steps = kernel.vfs.splitPath(path)
local step = data
if #steps == 0 then
return "directory"
end
for i=1, #steps-1 do
local dat = step[steps[i]]
if type(dat) ~= "table" then error("ENFILE") end
step=dat
end
if type(step[steps[#steps]]) == "function" then
return step[steps[#steps]]("type", mode)
end
if type(step[steps[#steps]]) == "table" then
return "directory"
end
error("ENOENT")
end
function proxy:list(path)
local steps = kernel.vfs.splitPath(path)
local step = data
if #steps == 0 then
return table.keys(data)
end
for i=1, #steps-1 do
local dat = step[steps[i]]
if type(dat) ~= "table" then error("ENOENT") end
step=dat
end
if type(step[steps[#steps]]) == "table" then
return table.keys(step[steps[#steps]])
end
error("ENOENT")
end
function proxy:fileExists(path)
local ok = pcall(function()
return self:type(path)
end)
return ok
end
function data.random(op, mode)
if op=="type" then
return "character device"
elseif op=="open" then
if mode=="r" then
return {
read=function(amount)
local str = ""
for i=1, amount or 1 do
str=str..string.char(math.random(0, 255))
end
return str
end
}
elseif mode=="w" or mode=="a" then
return {
write=function() end
}
else error("EACCES")
end
end
end
function data.null(op, mode)
if op=="type" then
return "character device"
elseif op=="open" then
if mode=="r" then
return {
read=function(amount) end
}
elseif mode=="w" or mode=="a" then
return {
write=function() end
}
else error("EACCES")
end
end
end
function data.zero(op, mode)
if op=="type" then
return "character device"
elseif op=="open" then
if mode=="r" then
return {
read=function(amount)
local str = ""
for i=1, amount or 1 do
str=str..string.char(0)
end
return str
end
}
elseif mode=="w" or mode=="a" then
return {
write=function() end
}
else error("EACCES")
end
end
end
data["disk"]={}
kernel.disks["devfs0000"]=proxy

View File

@@ -0,0 +1,128 @@
local kernel = ...
local proxy = {}
local data = {}
proxy.address = "tmpfs0000"
proxy.isReadOnly = function() return false end
-- Space functions (just placeholders)
proxy.spaceUsed = function() return 0 end
proxy.spaceTotal = function() return 0 end
-- Writable operations
proxy.makeDirectory = function(_, path)
local steps = kernel.vfs.splitPath(path)
local step = data
for i=1,#steps do
if not step[steps[i]] then
step[steps[i]] = {}
elseif type(step[steps[i]]) ~= "table" then
error("ENOTDIR")
end
step = step[steps[i]]
end
end
proxy.remove = function(_, path)
local steps = kernel.vfs.splitPath(path)
local step = data
for i=1,#steps-1 do
step = step[steps[i]]
if not step then error("ENOENT") end
end
step[steps[#steps]] = nil
end
proxy.setLabel = function(_, label) end
proxy.getLabel = function() return "tmpfs" end
proxy.attributes = function(_, path)
local steps = kernel.vfs.splitPath(path)
local step = data
for i=1,#steps do
step = step[steps[i]]
if not step then error("ENOENT") end
end
return {
size = type(step) == "string" and #step or 0,
modified = 0,
created = 0,
}
end
-- Open files
function proxy:open(path, mode)
local steps = kernel.vfs.splitPath(path)
local step = data
for i=1,#steps-1 do
if not step[steps[i]] then
if mode == "w" then step[steps[i]] = {} else error("ENOENT") end
elseif type(step[steps[i]]) ~= "table" then
error("ENOTDIR")
end
step = step[steps[i]]
end
local filename = steps[#steps]
if mode == "r" then
if type(step[filename]) ~= "string" then error("ENOENT") end
local content = step[filename]
local pos = 1
return {
read = function(amount)
amount = amount or #content
local chunk = content:sub(pos, pos+amount-1)
pos = pos + #chunk
return chunk
end
}
elseif mode == "w" then
step[filename] = ""
return {
write = function(str)
step[filename] = str
end
}
elseif mode == "a" then
if type(step[filename]) ~= "string" then step[filename] = "" end
return {
write = function(str)
step[filename] = step[filename] .. str
end
}
else
error("EACCES")
end
end
function proxy:type(path)
local steps = kernel.vfs.splitPath(path)
local step = data
if #steps == 0 then return "directory" end
for i=1,#steps do
step = step[steps[i]]
if not step then error("ENOENT") end
end
if type(step) == "table" then return "directory" end
if type(step) == "string" then return "file" end
end
function proxy:list(path)
local steps = kernel.vfs.splitPath(path)
local step = data
for i=1,#steps do
step = step[steps[i]]
if not step then error("ENOENT") end
end
if type(step) ~= "table" then error("ENOTDIR") end
local keys = {}
for k,_ in pairs(step) do table.insert(keys, k) end
return keys
end
function proxy:fileExists(path)
return pcall(function() return self:type(path) end)
end
kernel.disks["tmpfs0000"] = proxy

View File

@@ -1,25 +1,23 @@
--:Minify:--
-- :Minify:--
local kernel = ...
local timeout=false
local timeout = false
kernel.processes.keventd = function()
while true do
local event = {kernel.computer:getMachineEvent()}
if event[1] then
if event[1]=="keyTyped" then
if event[3]=="\x1b^s" then
if event[1] == "keyTyped" then
if event[3] == "\x1b^s" then
kernel.shutdown()
elseif event[3]=="\x1b^r" then
elseif event[3] == "\x1b^r" then
kernel.reboot()
end
end
kernel.io.pushEvent("raw", table.unpack(event))
timeout=false
timeout = false
else
timeout=true
end
if timeout then
sleep(.05)
timeout = true
end
if timeout then sleep(.05) end
end
end
end

View File

@@ -1,18 +1,34 @@
--:Minify:--
local kernel=...
for i,v in ipairs(string.split(kernel.fstab,"\n")) do
if v:sub(1,1)=="U" then
local id=""
for i=3,#v do
if v:sub(i,i)==";" then
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN", 8) goto endline end
id=v:sub(3,i-1)
local kernel = ...
local function trim(str)
local s, e = 1, #str
while s <= e and (str:sub(s,s) == " " or str:sub(s,s) == "\t") do s = s + 1 end
while e >= s and (str:sub(e,e) == " " or str:sub(e,e) == "\t" or str:sub(e,e) == "\n" or str:sub(e,e) == "\r") do e = e - 1 end
if s > e then return "" end
return str:sub(s,e)
end
for _, line in ipairs(string.split(kernel.fstab, "\n")) do
line = trim(line)
if line ~= "" and line:sub(1,1) == "U" then
local semicolon_pos
for i = 3, #line do
if line:sub(i,i) == ";" then
semicolon_pos = i
break
end
end
local path=v:sub(#id+4)
if id~="$" then
kernel.vfs.mount(path, id)
if not semicolon_pos or semicolon_pos == 3 then
kernel.log("Invalid fstab line: "..line.." ... Skipping.", "WARN", 8)
else
local id = line:sub(3, semicolon_pos - 1)
local path = trim(line:sub(semicolon_pos + 1))
kernel.log("Mounted "..id.." to "..path)
if id ~= "$" then
kernel.vfs.mount(path, id)
end
end
::endline::
end
end

View File

@@ -6,5 +6,15 @@ function socket.socket()
end
function socket.bind()
end
kernel.syscalls["ioctl"]=function(fd, method, ...)
if not kernel.currentTask.fd[fd] then error("EBADF") end
if not kernel.currentTask.fd[fd][method] then error("EINVAL") end
end
kernel.socket=socket
kernel.log("Loaded socket module")

View File

@@ -1,24 +1,23 @@
--:Minify:--
local args={...}
local kernel=args[1]
kernel._G=_G
-- :Minify:--
local args = {...}
local kernel = args[1]
kernel._G = _G
local function readonly(tbl)
return setmetatable({}, {
__index = function(_, key)
local value = tbl[key]
if type(value) == "table" then
return readonly(value)
end
if type(value) == "table" then return readonly(value) end
return value
end,
__newindex = function(t,k,v)
if kernel.config.allowGlobalOverwrites or kernel.allowGlobalOverwrites then
rawset(tbl,k,v)
__newindex = function(t, k, v)
if kernel.config.allowGlobalOverwrites or
kernel.allowGlobalOverwrites then
rawset(tbl, k, v)
return
end
error("Attempt to modify global variable '"..k.."'",2)
error("Attempt to modify global variable '" .. k .. "'", 2)
end,
__pairs = function()
@@ -45,15 +44,13 @@ local function readonly(tbl)
end
end,
__len = function()
return #tbl
end,
__len = function() return #tbl end,
__metatable = false,
__metatable = false
})
end
kernel._U=readonly(kernel._G)
kernel.allowGlobalOverwrites=true
kernel._U._G=kernel._U
kernel.allowGlobalOverwrites=false
kernel._U = readonly(kernel._G)
kernel.allowGlobalOverwrites = true
kernel._U._G = kernel._U
kernel.allowGlobalOverwrites = false

View File

@@ -1,72 +1,82 @@
--:Minify:--
-- :Minify:--
local kernel = ...
local tasks = {}
local sys = {}
local nextpid = 2
kernel.exitMain=false
kernel.exitMain = false
function sys.spawn(func, name, envars, args, tgid)
local id = nextpid
nextpid = nextpid + 1
tasks[tostring(id)] = {
coro=coroutine.create(function()
local ok, err = xpcall(func, debug.traceback, table.unpack(args or {}))
coro = coroutine.create(function()
local ok, err = xpcall(func, debug.traceback,
table.unpack(args or {}))
if not ok then
if kernel.config.logTaskExit then
kernel.log("Task "..tostring(id).." exited with err: "..tostring(err), "ERROR", 2)
kernel.log(
"Task " .. tostring(id) .. " exited with err: " ..
tostring(err), "ERROR", 2)
end
tasks[tostring(id)].status="Z"
if type(err)=="number" then
tasks[tostring(id)].exit=err
tasks[tostring(id)].status = "Z"
if type(err) == "number" then
tasks[tostring(id)].exit = err
end
else
if kernel.config.logTaskExit then
if err then
kernel.log("Task "..tostring(id).." exited with code: "..tostring(err), "INFO")
kernel.log("Task " .. tostring(id) ..
" exited with code: " .. tostring(err),
"INFO")
else
kernel.log("Task "..tostring(id).." exited without code", "INFO")
kernel.log("Task " .. tostring(id) ..
" exited without code", "INFO")
end
end
tasks[tostring(id)].status="Z"
if type(err)=="number" then
tasks[tostring(id)].exit=err
tasks[tostring(id)].status = "Z"
if type(err) == "number" then
tasks[tostring(id)].exit = err
end
end
end),
name=name or ("task"..tostring(id)),
envars=envars or kernel.currentTask.envars,
args=args or {},
status="R",
pid=id,
tgid=tgid or kernel.currentTask.tgid,
username=kernel.username,
uid=kernel.uid,
fd={},
exit="",
sleep=0,
ivs=0,
vs=0,
children={},
parent=kernel.currentTask,
siblings=kernel.currentTask.children,
syscallReturn={},
cwd=kernel.currentTask.cwd,
term=kernel.currentTask.term,
timeSlice=0,
lastTime=0,
totalTime=0,
numRuns=0,
privacy=0,
debugger=false,
eventq=kernel.currentTask.eventq
name = name or ("task" .. tostring(id)),
envars = envars or kernel.currentTask.envars,
args = args or {},
status = "R",
pid = id,
tgid = tgid or kernel.currentTask.tgid,
username = kernel.username,
uid = kernel.uid,
fd = {
[0]=kernel.currentTask.fd[0],
[1]=kernel.currentTask.fd[1],
[2]=kernel.currentTask.fd[2]
},
sleep = 0,
ivs = 0,
vs = 0,
children = {},
parent = kernel.currentTask,
siblings = kernel.currentTask.children,
syscallReturn = {},
cwd = kernel.currentTask.cwd,
timeSlice = 0,
lastTime = 0,
totalTime = 0,
numRuns = 0,
privacy = 0,
debugger = false,
eventq = kernel.currentTask.eventq
}
table.insert(kernel.currentTask.children, tasks[tostring(id)])
return id
end
function sys.sleep(s)
kernel.currentTask.status="S"
kernel.currentTask.sleep=kernel.computer:time()+s*1000
kernel.currentTask.status = "S"
kernel.currentTask.sleep = kernel.computer:time() + s * 1000
coroutine.yield()
end
@@ -75,164 +85,161 @@ function sys.getTask(pid)
local task = tasks[tostring(pid)]
local children = {}
local siblings = {}
for i,v in ipairs(task.children) do
children[i]=v.pid
end
for i,v in ipairs(task.siblings) do
siblings[i]=v.pid
end
for i, v in ipairs(task.children) do children[i] = v.pid end
for i, v in ipairs(task.siblings) do siblings[i] = v.pid end
return {
name=task.name,
status=task.status,
pid=task.pid,
tgid=task.tgid,
username=task.username,
uid=task.uid,
exit=task.exit,
sleep=task.sleep,
ivs=task.ivs,
vs=task.vs,
children=children,
siblings=siblings,
parent=task.parent.pid,
cwd=task.cwd,
term=task.term
name = task.name,
status = task.status,
pid = task.pid,
tgid = task.tgid,
username = task.username,
uid = task.uid,
exit = task.exit,
sleep = task.sleep,
ivs = task.ivs,
vs = task.vs,
children = children,
siblings = siblings,
parent = task.parent.pid,
cwd = task.cwd,
term = task.term
}
end
end
function sys.collect(pid)
local children={}
for i,v in ipairs(kernel.currentTask.children) do
children[i]=v.pid
end
local children = {}
for i, v in ipairs(kernel.currentTask.children) do children[i] = v.pid end
if not tasks[tostring(pid)] then
return false, "Task does not exist"
elseif not isEqualToAny(tasks[tostring(pid)].pid,table.unpack(children)) then
elseif not isEqualToAny(tasks[tostring(pid)].pid, table.unpack(children)) then
return false, "You do not own this task"
elseif tasks[tostring(pid)].status~="Z" then
elseif tasks[tostring(pid)].status ~= "Z" then
return false, "Task must exit to collect status"
else
tasks[tostring(pid)].reapTime=0
tasks[tostring(pid)].reapTime = 0
return true, tasks[tostring(pid)].exit
end
end
function sys.kill(pid)
local children={}
for i,v in ipairs(kernel.currentTask.children) do
children[i]=v.pid
end
local children = {}
for i, v in ipairs(kernel.currentTask.children) do children[i] = v.pid end
if not tasks[tostring(pid)] then
return false, "Task does not exist"
elseif not isEqualToAny(tasks[tostring(pid)].pid,table.unpack(children)) and kernel.uid~=0 then
elseif not isEqualToAny(tasks[tostring(pid)].pid, table.unpack(children)) and
kernel.uid ~= 0 then
return false, "You do not own this task"
elseif tasks[tostring(pid)].status=="Z" then
elseif tasks[tostring(pid)].status == "Z" then
return false, "Task is already dead"
else
tasks[tostring(pid)].status="Z"
tasks[tostring(pid)].status = "Z"
return true
end
end
function sys.stop(pid)
local children={}
for i,v in ipairs(kernel.currentTask.children) do
children[i]=v.pid
end
local children = {}
for i, v in ipairs(kernel.currentTask.children) do children[i] = v.pid end
if not tasks[tostring(pid)] then
return false, "Task does not exist"
elseif not isEqualToAny(tasks[tostring(pid)].pid,table.unpack(children)) and kernel.uid~=0 then
elseif not isEqualToAny(tasks[tostring(pid)].pid, table.unpack(children)) and
kernel.uid ~= 0 then
return false, "You do not own this task"
elseif tasks[tostring(pid)].status~="R" then
elseif tasks[tostring(pid)].status ~= "R" then
return false, "Cannot stop non running task"
else
tasks[tostring(pid)].status="T"
tasks[tostring(pid)].status = "T"
return true
end
end
function sys.continue(pid)
local children={}
for i,v in ipairs(kernel.currentTask.children) do
children[i]=v.pid
end
local children = {}
for i, v in ipairs(kernel.currentTask.children) do children[i] = v.pid end
if not tasks[tostring(pid)] then
return false, "Task does not exist"
elseif not isEqualToAny(tasks[tostring(pid)].pid,table.unpack(children)) and kernel.uid~=0 then
elseif not isEqualToAny(tasks[tostring(pid)].pid, table.unpack(children)) and
kernel.uid ~= 0 then
return false, "You do not own this task"
elseif tasks[tostring(pid)].status~="T" then
elseif tasks[tostring(pid)].status ~= "T" then
return false, "Task is not stopped"
else
tasks[tostring(pid)].status="R"
tasks[tostring(pid)].status = "R"
return true
end
end
function sys.getpid()
return kernel.currentTask.pid
end
function sys.getpid() return kernel.currentTask.pid end
function sys.getppid()
return kernel.currentTask.parent.pid
end
function sys.getppid() return kernel.currentTask.parent.pid end
function sys.getTasks()
local ret={}
for i,v in pairs(tasks) do
ret[#ret+1]=v.pid
end
local ret = {}
for i, v in pairs(tasks) do ret[#ret + 1] = v.pid end
return ret
end
function sys.getEnviron(key)
return kernel.currentTask.envars[key]
end
function sys.getEnviron(key) return kernel.currentTask.envars[key] end
function sys.setEnviron(key, value)
kernel.currentTask.envars[key]=value
end
function sys.setEnviron(key, value) kernel.currentTask.envars[key] = value 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")
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")
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
tasks[tostring(kernel.currentTask.pid)].status = "Z"
if type(code) == "number" then
tasks[tostring(kernel.currentTask.pid)].exit = code
end
end
function sys.setuid(uid)
if kernel.uid~=0 then error("EACCES") end
kernel.currentTask.uid=uid
if kernel.uid ~= 0 then error("EACCES") end
kernel.currentTask.uid = uid
end
function sys.getuid()
return kernel.currentTask.uid
end
function sys.getuid() return kernel.currentTask.uid end
local sysc=kernel.syscalls
sysc["spawn"]=sys.spawn
sysc["sleep"]=sys.sleep
sysc["getTask"]=sys.getTask
sysc["collect"]=sys.collect
sysc["kill"]=sys.kill
sysc["stop"]=sys.stop
sysc["continue"]=sys.continue
sysc["getpid"]=sys.getpid
sysc["getppid"]=sys.getppid
sysc["getTasks"]=sys.getTasks
sysc["setEnviron"]=sys.setEnviron
sysc["getEnviron"]=sys.getEnviron
sysc["exit"]=sys.exit
sysc["setuid"]=sys.setuid
sysc["getuid"]=sys.getuid
kernel._G.sleep=function(...)coroutine.yield("syscall","sleep",...)end
local sysc = kernel.syscalls
sysc["spawn"] = sys.spawn
sysc["sleep"] = sys.sleep
sysc["getTask"] = sys.getTask
sysc["collect"] = sys.collect
sysc["kill"] = sys.kill
sysc["stop"] = sys.stop
sysc["continue"] = sys.continue
sysc["getpid"] = sys.getpid
sysc["getppid"] = sys.getppid
sysc["getTasks"] = sys.getTasks
sysc["setEnviron"] = sys.setEnviron
sysc["getEnviron"] = sys.getEnviron
sysc["exit"] = sys.exit
sysc["setuid"] = sys.setuid
sysc["getuid"] = sys.getuid
kernel._G.sleep = function(...) coroutine.yield("syscall", "sleep", ...) end
local function reapDeadTasks()
for pid, task in pairs(tasks) do
@@ -243,32 +250,33 @@ local function reapDeadTasks()
task.args = nil
task.envars = nil
task.cwd = nil
task.term = nil
task.numRuns = nil
task.totalTime = nil
task.lastTime = nil
task.timeSlice = nil
task.syscallReturn = nil
task.sleep = nil
for v,_ in ipairs(task.fd) do
kernel.vfs.close(v)
end
for v, _ in ipairs(task.fd) do kernel.vfs.close(v) end
task.fd = nil
task.debugger=nil
task.privacy=nil
task.debugger = nil
task.privacy = nil
task.reapTime = kernel.computer:time() + 30000
elseif task.reapTime and kernel.computer:time() > task.reapTime and task.status=="Z" then
for _,child in ipairs(task.children) do
elseif task.reapTime and kernel.computer:time() > task.reapTime and
task.status == "Z" then
for _, child in ipairs(task.children) do
child.parent = tasks["1"]
child.siblings = tasks["1"].children
table.insert(tasks["1"].children, child)
end
for i, sibling in ipairs(task.siblings) do
if sibling.pid == task.pid then
table.remove(task.siblings, i)
break
end
end
tasks[pid] = nil
end
end
@@ -296,8 +304,8 @@ function kernel.main()
for pid, task in pairs(tasks) do
if task.status == "S" then
if kernel.computer:time() >= task.sleep then
task.status="R"
task.sleep=0
task.status = "R"
task.sleep = 0
end
end
if task.status == "R" then
@@ -314,9 +322,20 @@ function kernel.main()
local startTime = kernel.computer:time()
local ret
if kernel.config.preempt then
ret = {coroutine.resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn))}
ret = {
coroutine.resumeWithTimeout(
task.coro,
task.timeSlice,
table.unpack(task.syscallReturn)
)
}
else
ret = {coroutine.resume(task.coro, table.unpack(task.syscallReturn))}
ret = {
coroutine.resume(
task.coro,
table.unpack(task.syscallReturn)
)
}
end
local elapsed = kernel.computer:time() - startTime
@@ -331,45 +350,70 @@ function kernel.main()
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
-- handle task results
if ret[1] == "error" or ret[1]==false then
kernel.log("processHandlerException: "..ret[2], "ERROR", 2)
if ret[1] == "error" or ret[1] == false then
kernel.log("processHandlerException: " .. ret[2], "ERROR", 2)
task.status = "Z"
task.exit = "processHandlerException: "..ret[2]
task.exit = "processHandlerException: " .. ret[2]
elseif ret[1] == "timeout" then
task.ivs=task.ivs+1
task.ivs = task.ivs + 1
task.syscallReturn = {}
elseif ret[1] == "success" or ret[1] == true then
task.vs=task.vs+1
if ret[2]=="syscall" then
task.vs = task.vs + 1
if ret[2] == "syscall" then
if kernel.syscalls[ret[3]] then
if kernel.config.debugSyscalls then
kernel.log("Task "..task.pid.." invoking syscall: "..ret[3], "DBUG", 5)
for i=4,#ret do
kernel.log(" inval["..tostring(i-3).."] = "..tostring(ret[i]), "DBUG", 5)
kernel.log("Task " .. task.pid .. " invoking syscall: " .. ret[3], "DBUG", 5)
for i = 4, #ret do
kernel.log(" inval[" .. tostring(i - 3) .. "] = " .. tostring(ret[i]), "DBUG", 5)
end
end
local sysret = {xpcall(kernel.syscalls[ret[3]], debug.traceback, table.unpack(ret, 4))}
local sysret = {
xpcall(kernel.syscalls[ret[3]], debug.traceback, table.unpack(ret, 4))
}
if kernel.config.debugSyscalls then
if not sysret[1] then
kernel.log("Task "..task.pid.." syscall "..ret[3].." failed: "..tostring(sysret[2]), "ERROR", 2)
kernel.log(
"Task " .. task.pid .. " syscall " .. ret[3] .. " failed: " .. tostring(sysret[2]), "ERROR", 2
)
else
kernel.log("Task "..task.pid.." syscall "..ret[3].." completed returning "..tostring(#sysret-1).." values", "DBUG", 5)
for i=2,#sysret do
if type(sysret[i])=="table" then
kernel.log(" retval["..tostring(i-1).."] = "..table.serialize(sysret[i]), "DBUG", 5)
kernel.log(
"Task " .. task.pid .. " syscall " .. ret[3] .. " completed returning " .. tostring(#sysret - 1) .. " values", "DBUG", 5
)
for i = 2, #sysret do
if type(sysret[i]) == "table" then
kernel.log(
" retval[" .. tostring(i - 1) .. "] = " .. table.serialize(sysret[i]),"DBUG", 5
)
else
kernel.log(" retval["..tostring(i-1).."] = "..tostring(sysret[i]), "DBUG", 5)
kernel.log(
" retval[" .. tostring(i - 1) .. "] = " .. tostring(sysret[i]), "DBUG", 5
)
end
end
end
end
if not sysret[1] then
task.syscallReturn={false, sysret[2]}
task.syscallReturn = {false, sysret[2]}
else
task.syscallReturn={true, table.unpack(sysret,2)}
task.syscallReturn = {
true, table.unpack(sysret, 2)
}
end
else
task.syscallReturn={false, "Unknown syscall: "..tostring(ret[3])}
task.syscallReturn = {
false, "Unknown syscall: " .. tostring(ret[3])
}
end
end
end
@@ -378,17 +422,18 @@ function kernel.main()
local T_prev_avg = (N > 0) and (totalTaskTime / N) or 0
local T_prev_var = 0
for _, t in ipairs(taskTimes) do
T_prev_var = T_prev_var + (t - T_prev_avg)^2
T_prev_var = T_prev_var + (t - T_prev_avg) ^ 2
end
if N > 0 then T_prev_var = T_prev_var / N end
if N > 0 then
local f_clamp = k_min*(Tmin_hit/N) - k_max*(Tmax_hit/N)
local B_budget = (C_target * (N^(alpha-1))) / math.max(T_prev_avg, 1e-8)
B = B + lambda_budget * (B_budget - B)
+ lambda_clamp * f_clamp
- lambda_var * T_prev_var
local f_clamp = k_min * (Tmin_hit / N) - k_max * (Tmax_hit / N)
local B_budget = (C_target * (N ^ (alpha - 1))) /
math.max(T_prev_avg, 1e-8)
B = B + lambda_budget * (B_budget - B) + lambda_clamp * f_clamp -
lambda_var * T_prev_var
end
-- clean up dead tasks
@@ -396,5 +441,5 @@ function kernel.main()
end
end
kernel.tasks=tasks
kernel.hpv=sys
kernel.tasks = tasks
kernel.hpv = sys

View File

@@ -0,0 +1,15 @@
local kernel=...
local sysc=kernel.syscalls
kernel.gpio={}
sysc["gpio_write"]=function(pin, data)
if kernel.gpio[pin] then
return kernel.gpio[pin]("w", data)
end
end
sysc["gpio_read"]=function(pin)
if kernel.gpio[pin] then
return kernel.gpio[pin]("r")
end
end

View File

@@ -1,129 +0,0 @@
--:Minify:--
local kernel=...
local tty={}
kernel.tty=tty
tty.inst={}
function tty.register(ttyn, ttyo)
tty.inst[ttyn]=ttyo
end
function tty.print(text)
local term=kernel.currentTask.term
if term and tty.inst[term] then
tty.inst[term].print(text)
end
end
function tty.printInline(text)
local term=kernel.currentTask.term
if term and tty.inst[term] then
tty.inst[term].printInline(text)
end
end
function tty.size()
local term=kernel.currentTask.term
if term and tty.inst[term] then
return tty.inst[term].size()
end
end
function tty.setCursorPos(x,y)
local term=kernel.currentTask.term
if term and tty.inst[term] then
return tty.inst[term].setCursorPos(x,y)
end
end
function tty.getCursorPos()
local term=kernel.currentTask.term
if term and tty.inst[term] then
return tty.inst[term].getCursorPos()
end
end
function tty.clear()
local term=kernel.currentTask.term
if term and tty.inst[term] then
return tty.inst[term].clear()
end
end
function tty.setTextColor(color)
local term=kernel.currentTask.term
if term and tty.inst[term] then
return tty.inst[term].setTextColor(color)
end
end
function tty.setBackgroundColor(color)
local term=kernel.currentTask.term
if term and tty.inst[term] then
return tty.inst[term].setBackgroundColor(color)
end
end
function tty.scroll(n)
local term=kernel.currentTask.term
if term and tty.inst[term] then
return tty.inst[term].scroll(n)
end
end
function tty.getTextColor()
local term=kernel.currentTask.term
if term and tty.inst[term] and tty.inst[term].getTextColor then
return tty.inst[term].getTextColor()
end
end
function tty.getBackgroundColor()
local term=kernel.currentTask.term
if term and tty.inst[term] and tty.inst[term].getBackgroundColor then
return tty.inst[term].getBackgroundColor()
end
end
function tty.bind(ttyid)
if not ttyid then
return false, "No TTY ID specified"
end
if not kernel.tty.inst[ttyid] then
return false, "TTY "..tostring(ttyid).." not registered"
end
kernel.currentTask.term=ttyid
return true
end
function tty.unbind()
kernel.currentTask.term=false
end
function tty.isBound()
return kernel.currentTask.term ~= nil
end
function tty.getBoundTTY()
return kernel.currentTask.term
end
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

@@ -1,28 +1,24 @@
--:Minify:--
local kernel=...
-- :Minify:--
local kernel = ...
function print(...)
local args={...}
local output=""
for i=1,#args do
output=output..tostring(args[i]).."\t"
end
output=output:sub(1,-2)
local args = {...}
local output = ""
for i = 1, #args do output = output .. tostring(args[i]) .. "\t" end
output = output:sub(1, -2)
syscall.TTY_print(output)
end
function printf(fmt, ...)
coroutine.yield()
local output=string.format(fmt,...)
local output = string.format(fmt, ...)
syscall.TTY_print(output)
end
function printInline(...)
coroutine.yield()
local args={...}
local output=""
for i=1,#args do
output=output..tostring(args[i]).."\t"
end
output=output:sub(1,-2)
local args = {...}
local output = ""
for i = 1, #args do output = output .. tostring(args[i]) .. "\t" end
output = output:sub(1, -2)
syscall.TTY_printInline(output)
end
end

View File

@@ -1,48 +1,48 @@
--:Minify:--
-- :Minify:--
local kernel = ...
kernel.log("Loading init system...")
kernel.log("InitPath: "..kernel.config.initPath)
kernel.log("InitPath: " .. kernel.config.initPath)
local handle = kernel.vfs.open(kernel.config.initPath, "r")
local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
kernel.vfs.close(handle)
local initFunc, err = load(data, "@sysinit", "t", kernel._U)
if not initFunc then
error("Failed to load init system: "..err)
end
if not initFunc then error("Failed to load init system: " .. err) end
kernel.tasks["1"] = {
coro=coroutine.create(function()
coro = coroutine.create(function()
local ok, err = xpcall(initFunc, debug.traceback, kernel)
if not ok then
kernel.panic("Init system crashed: "..tostring(err))
kernel.panic("Init system crashed: " .. tostring(err))
else
kernel.panic("Init system exited: "..tostring(err))
kernel.panic("Init system exited: " .. tostring(err))
end
end),
name="sysinit",
status="R",
pid=1,
tgid=1,
username="root",
uid=0,
fd={},
envars={},
args={},
exit="",
sleep=0,
ivs=0,
vs=0,
parent=kernel.kernelTask,
siblings=kernel.kernelTask.children,
children={},
syscallReturn={},
cwd="/",
timeSlice=0,
lastTime=0,
totalTime=0,
numRuns=0
name = "sysinit",
status = "R",
pid = 1,
tgid = 1,
username = "root",
uid = 0,
fd = {},
envars = {},
args = {},
exit = "",
sleep = 0,
ivs = 0,
vs = 0,
parent = kernel.kernelTask,
siblings = kernel.kernelTask.children,
children = {},
syscallReturn = {},
cwd = "/",
timeSlice = 0,
lastTime = 0,
totalTime = 0,
numRuns = 0
}
kernel.log("created init task with PID 1")
kernel.log("Initializing init system...")
kernel.log("Initializing init system...")