finished vfs for a while
This commit is contained in:
@@ -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")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -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
|
||||
|
||||
8
Src/Hyperion-bash/bin/cat
Normal file
8
Src/Hyperion-bash/bin/cat
Normal 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
0
Src/Hyperion-bash/bin/cd
Normal file
1
Src/Hyperion-bash/bin/clear
Normal file
1
Src/Hyperion-bash/bin/clear
Normal file
@@ -0,0 +1 @@
|
||||
syscall.TTY_clear()
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
1
Src/Hyperion-bash/bin/pwd
Normal file
1
Src/Hyperion-bash/bin/pwd
Normal file
@@ -0,0 +1 @@
|
||||
print(syscall.getcwd())
|
||||
@@ -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
|
||||
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
|
||||
while true do coroutine.yield() end
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -124,35 +110,26 @@ local function createDisk(id, basePath, readonly, periph)
|
||||
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}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
U $;/
|
||||
U devfs0000;/dev/
|
||||
U tmpfs0000;/tmp/
|
||||
@@ -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
|
||||
@@ -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")
|
||||
|
||||
@@ -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,86 +55,20 @@ 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
|
||||
@@ -167,9 +78,7 @@ local function serialize(tbl, seen)
|
||||
|
||||
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
|
||||
@@ -202,16 +111,14 @@ local function serialize(tbl, seen)
|
||||
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
|
||||
|
||||
@@ -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")
|
||||
@@ -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,21 +21,42 @@ 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,7 +570,7 @@ 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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
128
Src/Hyperion-kernel/lib/modules/Hyperion/12_tmpfs.kmod
Normal file
128
Src/Hyperion-kernel/lib/modules/Hyperion/12_tmpfs.kmod
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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")
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
15
Src/Hyperion-kernel/lib/modules/Hyperion/50_gpio.kmod
Normal file
15
Src/Hyperion-kernel/lib/modules/Hyperion/50_gpio.kmod
Normal 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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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...")
|
||||
Reference in New Issue
Block a user