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):
|
To trigger a panic (for testing):
|
||||||
```lua
|
```lua
|
||||||
kernel.PANIC("Test panic message")
|
kernel.PANIC("Test panic message")
|
||||||
|
OR
|
||||||
|
kernel.log("Test log message")
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ local pid=syscall.getpid()
|
|||||||
local proc=0
|
local proc=0
|
||||||
local fs=require("sys.fs")
|
local fs=require("sys.fs")
|
||||||
local timeout=false
|
local timeout=false
|
||||||
|
syscall.setEnviron("SHELL","simpleshell")
|
||||||
printInline("> ")
|
printInline("> ")
|
||||||
while true do
|
while true do
|
||||||
local event = {syscall.IO_pullEvent()}
|
local event = {syscall.IO_pullEvent()}
|
||||||
@@ -29,10 +30,11 @@ while true do
|
|||||||
stopInput=false
|
stopInput=false
|
||||||
else
|
else
|
||||||
local path=nil
|
local path=nil
|
||||||
if fs.exists("/bin/"..str) then
|
local split=string.split(str, " ")
|
||||||
path="/bin/"..str
|
if fs.exists("/bin/"..split[1]) then
|
||||||
elseif fs.exists("/bin/"..str..".lua") then
|
path="/bin/"..split[1]
|
||||||
path="/bin/"..str..".lua"
|
elseif fs.exists("/bin/"..split[1]..".lua") then
|
||||||
|
path="/bin/"..split[1]..".lua"
|
||||||
end
|
end
|
||||||
if not path then
|
if not path then
|
||||||
print("Program not found")
|
print("Program not found")
|
||||||
@@ -46,11 +48,13 @@ while true do
|
|||||||
printInline("> ")
|
printInline("> ")
|
||||||
end
|
end
|
||||||
syscall.IO_bind("bash:"..tostring(pid))
|
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)
|
syscall.IO_bind(inputIO)
|
||||||
end
|
end
|
||||||
str=""
|
str=""
|
||||||
end
|
end
|
||||||
|
elseif event[1]=="keyTyped" and event[3]=="^d" then
|
||||||
|
syscall.exit(0)
|
||||||
else
|
else
|
||||||
str=str..event[3]
|
str=str..event[3]
|
||||||
printInline(event[3])
|
printInline(event[3])
|
||||||
@@ -64,7 +68,9 @@ while true do
|
|||||||
if stopInput then
|
if stopInput then
|
||||||
local exited, code = syscall.collect(proc)
|
local exited, code = syscall.collect(proc)
|
||||||
if exited then
|
if exited then
|
||||||
print("\nTask exited with code:\n"..tostring(code))
|
if code then
|
||||||
|
print("\nTask exited with code:\n"..tostring(code))
|
||||||
|
end
|
||||||
printInline("> ")
|
printInline("> ")
|
||||||
stopInput=false
|
stopInput=false
|
||||||
else
|
else
|
||||||
@@ -74,9 +80,6 @@ while true do
|
|||||||
print("Terminated")
|
print("Terminated")
|
||||||
printInline("> ")
|
printInline("> ")
|
||||||
stopInput=false
|
stopInput=false
|
||||||
elseif event[1]=="keyTyped" and event[3]=="^d" then
|
|
||||||
syscall.kill(proc)
|
|
||||||
syscall.exit(0)
|
|
||||||
else
|
else
|
||||||
syscall.IO_pushEvent("bash:"..tostring(pid), table.unpack(event))
|
syscall.IO_pushEvent("bash:"..tostring(pid), table.unpack(event))
|
||||||
end
|
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 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
|
for i,v in ipairs(stuff) do
|
||||||
if fs.isDir(v) then
|
if fs.isDir(dir..v) then
|
||||||
print(v.."/")
|
print(v.."/")
|
||||||
else
|
else
|
||||||
print(v)
|
print(v)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ while true do
|
|||||||
if str == "" then
|
if str == "" then
|
||||||
printInline("> ")
|
printInline("> ")
|
||||||
stopInput=false
|
stopInput=false
|
||||||
elseif str == "exit" then
|
elseif str == "exit()" then
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
local func=load(str,"@Lua","t",luaEnv)
|
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:--
|
-- :Minify:--
|
||||||
local BOOT_DRIVE_PATH=({...})[1] or "/$"
|
local BOOT_DRIVE_PATH = ({...})[1] or "/$"
|
||||||
---@diagnostic disable-next-line: undefined-global
|
---@diagnostic disable-next-line: undefined-global
|
||||||
local term = term
|
local term = term
|
||||||
local os = os
|
local os = os
|
||||||
@@ -38,7 +38,7 @@ local function write(text)
|
|||||||
y = y + 1
|
y = y + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if y-1 >= h then
|
if y - 1 >= h then
|
||||||
term.scroll(1)
|
term.scroll(1)
|
||||||
y = h
|
y = h
|
||||||
term.setCursorPos(x, y)
|
term.setCursorPos(x, y)
|
||||||
@@ -61,7 +61,7 @@ end
|
|||||||
|
|
||||||
term.setCursorBlink(false)
|
term.setCursorBlink(false)
|
||||||
local ok, err = xpcall(function()
|
local ok, err = xpcall(function()
|
||||||
local apis={BOOT_DRIVE_PATH=BOOT_DRIVE_PATH}
|
local apis = {BOOT_DRIVE_PATH = BOOT_DRIVE_PATH}
|
||||||
|
|
||||||
local lua = {
|
local lua = {
|
||||||
coroutine = true,
|
coroutine = true,
|
||||||
@@ -93,14 +93,14 @@ local ok, err = xpcall(function()
|
|||||||
tostring = true,
|
tostring = true,
|
||||||
type = true,
|
type = true,
|
||||||
xpcall = true,
|
xpcall = true,
|
||||||
_G=true
|
_G = true
|
||||||
}
|
}
|
||||||
|
|
||||||
local debug = debug
|
local debug = debug
|
||||||
for i,v in pairs(_G) do
|
for i, v in pairs(_G) do
|
||||||
if not lua[i] or lua[i]==nil then
|
if not lua[i] or lua[i] == nil then
|
||||||
apis[i]=v
|
apis[i] = v
|
||||||
_G[i]=nil
|
_G[i] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -109,18 +109,18 @@ local ok, err = xpcall(function()
|
|||||||
while stoptime > apis.os.clock() do end
|
while stoptime > apis.os.clock() do end
|
||||||
end
|
end
|
||||||
|
|
||||||
apis.term.setPaletteColor(0x1, 0xFFFFFF) -- #000000
|
apis.term.setPaletteColor(0x1, 0xFFFFFF) -- #000000
|
||||||
apis.term.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
|
apis.term.setPaletteColor(0x2, 0xFF0000) -- #FFFFFF
|
||||||
apis.term.setPaletteColor(0x4, 0x00FF00) -- #FF0000
|
apis.term.setPaletteColor(0x4, 0x00FF00) -- #FF0000
|
||||||
apis.term.setPaletteColor(0x8, 0x0000FF) -- #00FF00
|
apis.term.setPaletteColor(0x8, 0x0000FF) -- #00FF00
|
||||||
apis.term.setPaletteColor(0x10, 0x00FFFF) -- #0000FF
|
apis.term.setPaletteColor(0x10, 0x00FFFF) -- #0000FF
|
||||||
apis.term.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF
|
apis.term.setPaletteColor(0x20, 0xFF00FF) -- #00FFFF
|
||||||
apis.term.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF
|
apis.term.setPaletteColor(0x40, 0xFFFF00) -- #FF00FF
|
||||||
apis.term.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00
|
apis.term.setPaletteColor(0x80, 0xFF6D00) -- #FFFF00
|
||||||
apis.term.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00
|
apis.term.setPaletteColor(0x100, 0x6DFF55) -- #FF6D00
|
||||||
apis.term.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55
|
apis.term.setPaletteColor(0x200, 0x24FFFF) -- #6DFF55
|
||||||
apis.term.setPaletteColor(0x400, 0x924900) -- #24FFFF
|
apis.term.setPaletteColor(0x400, 0x924900) -- #24FFFF
|
||||||
apis.term.setPaletteColor(0x800, 0x6D6D55) -- #924900
|
apis.term.setPaletteColor(0x800, 0x6D6D55) -- #924900
|
||||||
apis.term.setPaletteColor(0x1000, 0xDBDBAA) -- #6D6D55
|
apis.term.setPaletteColor(0x1000, 0xDBDBAA) -- #6D6D55
|
||||||
apis.term.setPaletteColor(0x2000, 0x6D00FF) -- #DBDBAA
|
apis.term.setPaletteColor(0x2000, 0x6D00FF) -- #DBDBAA
|
||||||
apis.term.setPaletteColor(0x4000, 0xB6FF00) -- #6D00FF
|
apis.term.setPaletteColor(0x4000, 0xB6FF00) -- #6D00FF
|
||||||
@@ -128,28 +128,23 @@ local ok, err = xpcall(function()
|
|||||||
|
|
||||||
local function getFile(path)
|
local function getFile(path)
|
||||||
local file = apis.fs.open(path, "r")
|
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()
|
local content = file.readAll()
|
||||||
file.close()
|
file.close()
|
||||||
return content
|
return content
|
||||||
end
|
end
|
||||||
|
|
||||||
local Kernel = load(getFile(BOOT_DRIVE_PATH.."/boot/kernel.lua"),"@Kernel")
|
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 initFs = load(getFile(BOOT_DRIVE_PATH .. "/boot/cct/initdisks"),"@Init_disks")(apis)
|
||||||
local fs = load(getFile(BOOT_DRIVE_PATH.."/boot/initfs"),"@InitFs")()
|
local fs = load(getFile(BOOT_DRIVE_PATH .. "/boot/initfs"), "@InitFs")()
|
||||||
local key = load(getFile(BOOT_DRIVE_PATH.."/boot/cct/keys.lua"),"@keyhelper")(apis)
|
local key = load(getFile(BOOT_DRIVE_PATH .. "/boot/cct/keys.lua"),"@keyhelper")(apis)
|
||||||
if not Kernel then
|
|
||||||
displaySuperBadError("Could not load kernel.")
|
if not Kernel then displaySuperBadError("Could not load kernel.") end
|
||||||
end
|
if not initFs then displaySuperBadError("Could not load initdisks.") end
|
||||||
if not initFs then
|
if not fs then displaySuperBadError("Could not load initfs.") end
|
||||||
displaySuperBadError("Could not load initdisks.")
|
if not key then displaySuperBadError("Could not load key helper.") end
|
||||||
end
|
|
||||||
if not fs then
|
|
||||||
displaySuperBadError("Could not load initfs.")
|
|
||||||
end
|
|
||||||
if not key then
|
|
||||||
displaySuperBadError("Could not load key helper.")
|
|
||||||
end
|
|
||||||
|
|
||||||
local eventQueue = {}
|
local eventQueue = {}
|
||||||
|
|
||||||
@@ -159,7 +154,7 @@ local ok, err = xpcall(function()
|
|||||||
|
|
||||||
local computer = {
|
local computer = {
|
||||||
time = function() return apis.os.epoch("utc") end,
|
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,
|
shutdown = apis.os.shutdown,
|
||||||
reboot = apis.os.reboot,
|
reboot = apis.os.reboot,
|
||||||
getMachineEvent = function()
|
getMachineEvent = function()
|
||||||
@@ -169,36 +164,34 @@ local ok, err = xpcall(function()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
getEEPROM = function()
|
getEEPROM = function() return getFile("/startup.lua") end,
|
||||||
return getFile("/startup.lua")
|
setEEPROM = function(_, text)
|
||||||
end,
|
|
||||||
setEEPROM = function(_,text)
|
|
||||||
local h = apis.fs.open("/startup.lua", "w")
|
local h = apis.fs.open("/startup.lua", "w")
|
||||||
h.write(text)
|
h.write(text)
|
||||||
h.close()
|
h.close()
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
local icolors={
|
local icolors = {
|
||||||
[0x1] =1, -- #000000
|
[0x1] = 1, -- #000000
|
||||||
[0x2] =2, -- #FFFFFF
|
[0x2] = 2, -- #FFFFFF
|
||||||
[0x4] =3, -- #FF0000
|
[0x4] = 3, -- #FF0000
|
||||||
[0x8] =4, -- #00FF00
|
[0x8] = 4, -- #00FF00
|
||||||
[0x10] =5, -- #0000FF
|
[0x10] = 5, -- #0000FF
|
||||||
[0x20] =6, -- #00FFFF
|
[0x20] = 6, -- #00FFFF
|
||||||
[0x40] =7, -- #FF00FF
|
[0x40] = 7, -- #FF00FF
|
||||||
[0x80] =8, -- #FFFF00
|
[0x80] = 8, -- #FFFF00
|
||||||
[0x100] =9, -- #FF6D00
|
[0x100] = 9, -- #FF6D00
|
||||||
[0x200] =10, -- #6DFF55
|
[0x200] = 10, -- #6DFF55
|
||||||
[0x400] =11, -- #24FFFF
|
[0x400] = 11, -- #24FFFF
|
||||||
[0x800] =12, -- #924900
|
[0x800] = 12, -- #924900
|
||||||
[0x1000] =13, -- #6D6D55
|
[0x1000] = 13, -- #6D6D55
|
||||||
[0x2000] =14, -- #DBDBAA
|
[0x2000] = 14, -- #DBDBAA
|
||||||
[0x4000] =15, -- #6D00FF
|
[0x4000] = 15, -- #6D00FF
|
||||||
[0x8000] =16 -- #B6FF00
|
[0x8000] = 16 -- #B6FF00
|
||||||
}
|
}
|
||||||
|
|
||||||
local colors={
|
local colors = {
|
||||||
0x0001, -- #000000
|
0x0001, -- #000000
|
||||||
0x0002, -- #FFFFFF
|
0x0002, -- #FFFFFF
|
||||||
0x0004, -- #FF0000
|
0x0004, -- #FF0000
|
||||||
@@ -214,7 +207,7 @@ local ok, err = xpcall(function()
|
|||||||
0x1000, -- #6D6D55
|
0x1000, -- #6D6D55
|
||||||
0x2000, -- #DBDBAA
|
0x2000, -- #DBDBAA
|
||||||
0x4000, -- #6D00FF
|
0x4000, -- #6D00FF
|
||||||
0x8000 -- #B6FF00
|
0x8000 -- #B6FF00
|
||||||
}
|
}
|
||||||
|
|
||||||
apis.term.setBackgroundColor(0x8000)
|
apis.term.setBackgroundColor(0x8000)
|
||||||
@@ -224,21 +217,33 @@ local ok, err = xpcall(function()
|
|||||||
|
|
||||||
local kernelCoro = coroutine.create(function()
|
local kernelCoro = coroutine.create(function()
|
||||||
---@diagnostic disable-next-line: param-type-mismatch
|
---@diagnostic disable-next-line: param-type-mismatch
|
||||||
local ok, err = xpcall(Kernel, debug.traceback, apis, initFs, "cct", "/sbin/init", {
|
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,
|
print = function(_, text) write(text .. "\n") end,
|
||||||
clear=function() apis.term.clear() apis.term.setCursorPos(1,1) end,
|
printInline = function(_, text) write(text) end,
|
||||||
setCursorPos=function(_,x,y) apis.term.setCursorPos(x,y) end,
|
clear = function()
|
||||||
getCursorPos=function() return apis.term.getCursorPos() end,
|
apis.term.clear()
|
||||||
getSize=function() return apis.term.getSize() end,
|
apis.term.setCursorPos(1, 1)
|
||||||
setBackgroundColor=function(_,color) apis.term.setBackgroundColor(colors[color]) end,
|
end,
|
||||||
setTextColor=function(_,color) apis.term.setTextColor(colors[color]) end,
|
setCursorPos = function(_, x, y)
|
||||||
getBackgroundColor=function() return icolors[apis.term.getBackgroundColor()] end,
|
apis.term.setCursorPos(x, y)
|
||||||
getTextColor=function() return icolors[apis.term.getTextColor()] end
|
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, "$")
|
}, computer, fs, "$")
|
||||||
if not ok then
|
if not ok then displaySuperBadError(err) end
|
||||||
displaySuperBadError(err)
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- time is in milliseconds
|
-- time is in milliseconds
|
||||||
@@ -250,9 +255,9 @@ local ok, err = xpcall(function()
|
|||||||
end
|
end
|
||||||
end, "", 1000)
|
end, "", 1000)
|
||||||
local ret = {coroutine.resume(co, ...)}
|
local ret = {coroutine.resume(co, ...)}
|
||||||
if ret[1] and ret[2]=="timeout" then
|
if ret[1] and ret[2] == "timeout" then
|
||||||
return "timeout"
|
return "timeout"
|
||||||
elseif ret[1]==false then
|
elseif ret[1] == false then
|
||||||
return "error", ret[2]
|
return "error", ret[2]
|
||||||
else
|
else
|
||||||
debug.sethook(co)
|
debug.sethook(co)
|
||||||
@@ -260,7 +265,7 @@ local ok, err = xpcall(function()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
write("Loaded in "..tostring(apis.os.clock()).." seconds.\n")
|
write("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
|
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
|
||||||
@@ -279,17 +284,15 @@ local ok, err = xpcall(function()
|
|||||||
elseif event[1] == "disk_eject" then
|
elseif event[1] == "disk_eject" then
|
||||||
queueEvent("componentRemoved", "disk")
|
queueEvent("componentRemoved", "disk")
|
||||||
elseif event[1] == "NoSleep" then
|
elseif event[1] == "NoSleep" then
|
||||||
exit=true
|
exit = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if status == "error" or coroutine.status(kernelCoro)=="dead" then
|
if status == "error" or coroutine.status(kernelCoro) == "dead" then
|
||||||
displaySuperBadError("Kernel error: "..tostring(err))
|
displaySuperBadError("Kernel error: " .. tostring(err))
|
||||||
coroutine.yield("key")
|
coroutine.yield("key")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end, debug.traceback)
|
end, debug.traceback)
|
||||||
|
|
||||||
if not ok then
|
if not ok then displaySuperBadError("Fatal error during boot: " .. err) end
|
||||||
displaySuperBadError("Fatal error during boot: "..err)
|
while true do coroutine.yield() end
|
||||||
end
|
|
||||||
while true do coroutine.yield() end
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ local BOOT_DRIVE_PATH=({...})[1] or "/$"
|
|||||||
-- * `turtle.equip[Left|Right]`
|
-- * `turtle.equip[Left|Right]`
|
||||||
-- Licensed under the MIT license
|
-- Licensed under the MIT license
|
||||||
local args = {...}
|
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 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 = {}
|
local t = {}
|
||||||
for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end
|
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
|
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"}}
|
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
|
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
|
-- Set up TLCO
|
||||||
-- This functions by crashing `rednet.run` by removing `os.pullEventRaw`. Normally
|
-- 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
|
-- this would cause `parallel` to throw an error, but we replace `error` with an
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
--:Minify:--
|
-- :Minify:--
|
||||||
local apis = ({...})[1]
|
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 fs = apis.fs
|
||||||
local native = apis.peripheral
|
local native = apis.peripheral
|
||||||
local peripheral = {}
|
local peripheral = {}
|
||||||
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
||||||
|
|
||||||
function peripheral.getType(name)
|
function peripheral.getType(name)
|
||||||
if native.isPresent(name) then
|
if native.isPresent(name) then return native.getType(name) end
|
||||||
return native.getType(name)
|
|
||||||
end
|
|
||||||
for n = 1, #sides do
|
for n = 1, #sides do
|
||||||
local side = sides[n]
|
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)
|
return native.call(side, "getTypeRemote", name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -23,9 +22,7 @@ function peripheral.getNames()
|
|||||||
local names = {}
|
local names = {}
|
||||||
for n = 1, #sides do
|
for n = 1, #sides do
|
||||||
local side = sides[n]
|
local side = sides[n]
|
||||||
if native.isPresent(side) then
|
if native.isPresent(side) then table.insert(names, side) end
|
||||||
table.insert(names, side)
|
|
||||||
end
|
|
||||||
if native.hasType(side, "peripheral_hub") then
|
if native.hasType(side, "peripheral_hub") then
|
||||||
local hubSides = native.call(side, "getConnectedSides")
|
local hubSides = native.call(side, "getConnectedSides")
|
||||||
for _, hubSide in ipairs(hubSides) do
|
for _, hubSide in ipairs(hubSides) do
|
||||||
@@ -36,37 +33,30 @@ function peripheral.getNames()
|
|||||||
return names
|
return names
|
||||||
end
|
end
|
||||||
|
|
||||||
---------------------------------------------------------
|
local disks = {}
|
||||||
-- STORAGE
|
local internal = {}
|
||||||
---------------------------------------------------------
|
|
||||||
local disks = {} -- real disks
|
|
||||||
local internal = {} -- "$" disk
|
|
||||||
|
|
||||||
---------------------------------------------------------
|
|
||||||
-- HELPERS
|
|
||||||
---------------------------------------------------------
|
|
||||||
local function norm(path)
|
local function norm(path)
|
||||||
if not path or path == "" then return "/" end
|
if not path or path == "" then return "/" end
|
||||||
return fs.combine("/", path)
|
return fs.combine("/", path)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Creates a disk object given a base path
|
|
||||||
local function createDisk(id, basePath, readonly, periph)
|
local function createDisk(id, basePath, readonly, periph)
|
||||||
basePath = norm(basePath)
|
basePath = norm(basePath)
|
||||||
|
|
||||||
local disk = {address=id,isReadOnly=function() return readonly end}
|
local disk = {address = id, isReadOnly = function() return readonly end}
|
||||||
|
|
||||||
function disk:spaceUsed()
|
function disk:spaceUsed()
|
||||||
return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
|
return fs.getCapacity(basePath) - fs.getFreeSpace(basePath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function disk:spaceTotal()
|
function disk:spaceTotal() return fs.getCapacity(basePath) end
|
||||||
return fs.getCapacity(basePath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function disk:list(path)
|
function disk:list(path)
|
||||||
local p = fs.combine(basePath, 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)
|
return fs.list(p)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -103,13 +93,9 @@ local function createDisk(id, basePath, readonly, periph)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function disk:setLabel(label)
|
function disk:setLabel(label) periph.setLabel(label) end
|
||||||
periph.setLabel(label)
|
|
||||||
end
|
|
||||||
|
|
||||||
function disk:getLabel(label)
|
function disk:getLabel(label) return periph.getLabel() end
|
||||||
return periph.getLabel()
|
|
||||||
end
|
|
||||||
|
|
||||||
function disk:attributes(path)
|
function disk:attributes(path)
|
||||||
local p = fs.combine(basePath, path)
|
local p = fs.combine(basePath, path)
|
||||||
@@ -120,39 +106,30 @@ local function createDisk(id, basePath, readonly, periph)
|
|||||||
local p = fs.combine(basePath, path)
|
local p = fs.combine(basePath, path)
|
||||||
return fs.open(p, mode)
|
return fs.open(p, mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
return disk
|
return disk
|
||||||
end
|
end
|
||||||
|
|
||||||
---------------------------------------------------------
|
|
||||||
-- INTERNAL DISK "$" (mapped to "/")
|
|
||||||
---------------------------------------------------------
|
|
||||||
internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
|
internal["$"] = createDisk("$", BOOT_DRIVE_PATH, false, {
|
||||||
setLabel=function(label)
|
setLabel = function(label)
|
||||||
local h = fs.open("/.label", "w")
|
local h = fs.open("/.label", "w")
|
||||||
h.write(label)
|
h.write(label)
|
||||||
h.close()
|
h.close()
|
||||||
end,
|
end,
|
||||||
getLabel=function()
|
getLabel = function()
|
||||||
local h = fs.open("/.label", "r")
|
local h = fs.open("/.label", "r")
|
||||||
|
if not h then return "$" end
|
||||||
local label = h.readAll()
|
local label = h.readAll()
|
||||||
h.close()
|
h.close()
|
||||||
return label
|
return label
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
---------------------------------------------------------
|
|
||||||
-- SCAN REAL DISK PERIPHERALS
|
|
||||||
---------------------------------------------------------
|
|
||||||
local function refresh()
|
local function refresh()
|
||||||
-- remove disks that no longer exist
|
|
||||||
for id, _ in pairs(disks) do
|
for id, _ in pairs(disks) do
|
||||||
if not peripheral.getType(id) then
|
if not peripheral.getType(id) then disks[id] = nil end
|
||||||
disks[id] = nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- detect new disks
|
|
||||||
for _, name in ipairs(peripheral.getNames()) do
|
for _, name in ipairs(peripheral.getNames()) do
|
||||||
if peripheral.getType(name) == "disk" then
|
if peripheral.getType(name) == "disk" then
|
||||||
if not disks[name] then
|
if not disks[name] then
|
||||||
@@ -165,28 +142,14 @@ local function refresh()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---------------------------------------------------------
|
|
||||||
-- ITERATOR
|
|
||||||
---------------------------------------------------------
|
|
||||||
local function iter()
|
local function iter()
|
||||||
refresh()
|
refresh()
|
||||||
-- first internal
|
|
||||||
local combined = {}
|
local combined = {}
|
||||||
|
|
||||||
for id, obj in pairs(internal) do
|
for id, obj in pairs(internal) do combined[id] = obj end
|
||||||
combined[id] = obj
|
for id, obj in pairs(disks) do combined[id] = obj end
|
||||||
end
|
|
||||||
for id, obj in pairs(disks) do
|
|
||||||
combined[id] = obj
|
|
||||||
end
|
|
||||||
|
|
||||||
return pairs(combined)
|
return pairs(combined)
|
||||||
end
|
end
|
||||||
|
|
||||||
---------------------------------------------------------
|
return {refresh = refresh, list = iter}
|
||||||
-- MODULE RETURN
|
|
||||||
---------------------------------------------------------
|
|
||||||
return {
|
|
||||||
refresh = refresh,
|
|
||||||
list = iter
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
--:Minify:--
|
-- :Minify:--
|
||||||
local apis=...
|
local apis = ...
|
||||||
local keys=apis.keys
|
local keys = apis.keys
|
||||||
local tKeys = {}
|
local tKeys = {}
|
||||||
tKeys[keys.space] = ' '
|
tKeys[keys.space] = ' '
|
||||||
tKeys[keys.grave] = '`'
|
tKeys[keys.grave] = '`'
|
||||||
@@ -63,13 +63,13 @@ tKeys[keys.pageUp] = '\x1b[5~'
|
|||||||
tKeys[keys.pageDown] = '\x1b[6~'
|
tKeys[keys.pageDown] = '\x1b[6~'
|
||||||
tKeys[keys.home] = '\x1b[1~'
|
tKeys[keys.home] = '\x1b[1~'
|
||||||
tKeys[keys["end"]] = '\x1b[4~'
|
tKeys[keys["end"]] = '\x1b[4~'
|
||||||
--tKeys[keys.capsLock] = '\x1b[capsLock'
|
-- tKeys[keys.capsLock] = '\x1b[capsLock'
|
||||||
--tKeys[keys.scrollLock] = '\x1b[scrollLock'
|
-- tKeys[keys.scrollLock] = '\x1b[scrollLock'
|
||||||
--tKeys[keys.numLock] = '\x1b[numLock'
|
-- tKeys[keys.numLock] = '\x1b[numLock'
|
||||||
--if keys.printScreen then
|
-- if keys.printScreen then
|
||||||
-- tKeys[keys.printScreen] = '\x1b[printScreen'
|
-- tKeys[keys.printScreen] = '\x1b[printScreen'
|
||||||
--end
|
-- end
|
||||||
--tKeys[keys.pause] = '\x1b[pause'
|
-- tKeys[keys.pause] = '\x1b[pause'
|
||||||
tKeys[keys.f1] = '\x1b[11~'
|
tKeys[keys.f1] = '\x1b[11~'
|
||||||
tKeys[keys.f2] = '\x1b[12~'
|
tKeys[keys.f2] = '\x1b[12~'
|
||||||
tKeys[keys.f3] = '\x1b[13~'
|
tKeys[keys.f3] = '\x1b[13~'
|
||||||
@@ -82,19 +82,19 @@ tKeys[keys.f9] = '\x1b[20~'
|
|||||||
tKeys[keys.f10] = '\x1b[21~'
|
tKeys[keys.f10] = '\x1b[21~'
|
||||||
tKeys[keys.f11] = '\x1b[23~'
|
tKeys[keys.f11] = '\x1b[23~'
|
||||||
tKeys[keys.f12] = '\x1b[24~'
|
tKeys[keys.f12] = '\x1b[24~'
|
||||||
--tKeys[keys.f13] = '\x1b[25~'
|
-- tKeys[keys.f13] = '\x1b[25~'
|
||||||
--tKeys[keys.f14] = '\x1b[26~'
|
-- tKeys[keys.f14] = '\x1b[26~'
|
||||||
--tKeys[keys.f15] = '\x1b[28~'
|
-- tKeys[keys.f15] = '\x1b[28~'
|
||||||
--tKeys[keys.f16] = '\x1b[29~'
|
-- tKeys[keys.f16] = '\x1b[29~'
|
||||||
--tKeys[keys.f17] = '\x1b[31~'
|
-- tKeys[keys.f17] = '\x1b[31~'
|
||||||
--tKeys[keys.f18] = '\x1b[32~'
|
-- tKeys[keys.f18] = '\x1b[32~'
|
||||||
--tKeys[keys.f19] = '\x1b[33~'
|
-- tKeys[keys.f19] = '\x1b[33~'
|
||||||
--tKeys[keys.f20] = '\x1b[34~'
|
-- tKeys[keys.f20] = '\x1b[34~'
|
||||||
--tKeys[keys.f21] = '\x1b[42~'
|
-- tKeys[keys.f21] = '\x1b[42~'
|
||||||
--tKeys[keys.f22] = '\x1b[43~'
|
-- tKeys[keys.f22] = '\x1b[43~'
|
||||||
--tKeys[keys.f23] = '\x1b[44~'
|
-- tKeys[keys.f23] = '\x1b[44~'
|
||||||
--tKeys[keys.f24] = '\x1b[45~'
|
-- tKeys[keys.f24] = '\x1b[45~'
|
||||||
--tKeys[keys.f25] = '\x1b[46~'
|
-- tKeys[keys.f25] = '\x1b[46~'
|
||||||
|
|
||||||
-- Numpad
|
-- Numpad
|
||||||
tKeys[keys.numPad0] = '0'
|
tKeys[keys.numPad0] = '0'
|
||||||
@@ -108,15 +108,15 @@ tKeys[keys.numPad7] = '7'
|
|||||||
tKeys[keys.numPad8] = '8'
|
tKeys[keys.numPad8] = '8'
|
||||||
tKeys[keys.numPad9] = '9'
|
tKeys[keys.numPad9] = '9'
|
||||||
|
|
||||||
--tKeys[340] = 'leftShift'
|
-- tKeys[340] = 'leftShift'
|
||||||
--tKeys[341] = 'leftCtrl'
|
-- tKeys[341] = 'leftCtrl'
|
||||||
--tKeys[342] = 'leftAlt'
|
-- tKeys[342] = 'leftAlt'
|
||||||
--tKeys[343] = 'leftSuper'
|
-- tKeys[343] = 'leftSuper'
|
||||||
--tKeys[344] = 'rightShift'
|
-- tKeys[344] = 'rightShift'
|
||||||
--tKeys[345] = 'rightCtrl'
|
-- tKeys[345] = 'rightCtrl'
|
||||||
--tKeys[346] = 'rightAlt'
|
-- tKeys[346] = 'rightAlt'
|
||||||
--tKeys[347] = 'rightSuper'
|
-- tKeys[347] = 'rightSuper'
|
||||||
--tKeys[348] = 'menu'
|
-- tKeys[348] = 'menu'
|
||||||
|
|
||||||
local shift = false
|
local shift = false
|
||||||
local ctrl = false
|
local ctrl = false
|
||||||
@@ -178,26 +178,34 @@ end
|
|||||||
|
|
||||||
local function p()
|
local function p()
|
||||||
local str = ""
|
local str = ""
|
||||||
if alt then
|
if alt then str = str .. "\x1b" end
|
||||||
str=str.."\x1b"
|
if ctrl then str = str .. "^" end
|
||||||
end
|
|
||||||
if ctrl then
|
|
||||||
str=str.."^"
|
|
||||||
end
|
|
||||||
return str
|
return str
|
||||||
end
|
end
|
||||||
|
|
||||||
return function(event, q)
|
return function(event, q)
|
||||||
if event[1] == "key" then
|
if event[1] == "key" then
|
||||||
if event[2]==keys.leftCtrl or event[2]==keys.rightCtrl then ctrl=true return
|
if event[2] == keys.leftCtrl or event[2] == keys.rightCtrl then
|
||||||
elseif event[2]==keys.leftAlt or event[2]==keys.rightAlt then alt=true return
|
ctrl = true
|
||||||
elseif event[2]==keys.leftShift or event[2]==keys.rightCtrl then shift=true return
|
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
|
end
|
||||||
q("keyTyped", 1, p()..s(tKeys[event[2]]))
|
q("keyTyped", 1, p() .. s(tKeys[event[2]]))
|
||||||
elseif event[1] == "key_up" then
|
elseif event[1] == "key_up" then
|
||||||
if event[2]==keys.leftCtrl or event[2]==keys.rightCtrl then ctrl=false return
|
if event[2] == keys.leftCtrl or event[2] == keys.rightCtrl then
|
||||||
elseif event[2]==keys.leftAlt or event[2]==keys.rightAlt then alt=false return
|
ctrl = false
|
||||||
elseif event[2]==keys.leftShift or event[2]==keys.rightCtrl then shift=false return
|
return
|
||||||
|
elseif event[2] == keys.leftAlt or event[2] == keys.rightAlt then
|
||||||
|
alt = false
|
||||||
|
return
|
||||||
|
elseif event[2] == keys.leftShift or event[2] == keys.rightCtrl then
|
||||||
|
shift = false
|
||||||
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
--:Minify:--
|
-- :Minify:--
|
||||||
local kernel=...
|
local kernel = ...
|
||||||
local apis=kernel.apis
|
local apis = kernel.apis
|
||||||
local main=apis.term
|
local main = apis.term
|
||||||
local native=apis.peripheral
|
local native = apis.peripheral
|
||||||
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
||||||
|
|
||||||
local function getType(name)
|
local function getType(name)
|
||||||
if native.isPresent(name) then
|
if native.isPresent(name) then return native.getType(name) end
|
||||||
return native.getType(name)
|
|
||||||
end
|
|
||||||
for n = 1, #sides do
|
for n = 1, #sides do
|
||||||
local side = sides[n]
|
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)
|
return native.call(side, "getTypeRemote", name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -22,9 +21,7 @@ local function getNames()
|
|||||||
local names = {}
|
local names = {}
|
||||||
for n = 1, #sides do
|
for n = 1, #sides do
|
||||||
local side = sides[n]
|
local side = sides[n]
|
||||||
if native.isPresent(side) then
|
if native.isPresent(side) then table.insert(names, side) end
|
||||||
table.insert(names, side)
|
|
||||||
end
|
|
||||||
if native.hasType(side, "peripheral_hub") then
|
if native.hasType(side, "peripheral_hub") then
|
||||||
local hubSides = native.call(side, "getConnectedSides")
|
local hubSides = native.call(side, "getConnectedSides")
|
||||||
for _, hubSide in ipairs(hubSides) do
|
for _, hubSide in ipairs(hubSides) do
|
||||||
@@ -36,38 +33,37 @@ local function getNames()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function wrapPeripheral(name)
|
local function wrapPeripheral(name)
|
||||||
if native.isPresent(name) then
|
if native.isPresent(name) then return wrapPeripheral(name) end
|
||||||
return wrapPeripheral(name)
|
|
||||||
end
|
|
||||||
for n = 1, #sides do
|
for n = 1, #sides do
|
||||||
local side = sides[n]
|
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)
|
return native.call(side, "wrapRemote", name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local icolors={
|
local icolors = {
|
||||||
[0x1] =1, -- #000000
|
[0x1] = 1, -- #000000
|
||||||
[0x2] =2, -- #FFFFFF
|
[0x2] = 2, -- #FFFFFF
|
||||||
[0x4] =3, -- #FF0000
|
[0x4] = 3, -- #FF0000
|
||||||
[0x8] =4, -- #00FF00
|
[0x8] = 4, -- #00FF00
|
||||||
[0x10] =5, -- #0000FF
|
[0x10] = 5, -- #0000FF
|
||||||
[0x20] =6, -- #00FFFF
|
[0x20] = 6, -- #00FFFF
|
||||||
[0x40] =7, -- #FF00FF
|
[0x40] = 7, -- #FF00FF
|
||||||
[0x80] =8, -- #FFFF00
|
[0x80] = 8, -- #FFFF00
|
||||||
[0x100] =9, -- #FF6D00
|
[0x100] = 9, -- #FF6D00
|
||||||
[0x200] =10, -- #6DFF55
|
[0x200] = 10, -- #6DFF55
|
||||||
[0x400] =11, -- #24FFFF
|
[0x400] = 11, -- #24FFFF
|
||||||
[0x800] =12, -- #924900
|
[0x800] = 12, -- #924900
|
||||||
[0x1000] =13, -- #6D6D55
|
[0x1000] = 13, -- #6D6D55
|
||||||
[0x2000] =14, -- #DBDBAA
|
[0x2000] = 14, -- #DBDBAA
|
||||||
[0x4000] =15, -- #6D00FF
|
[0x4000] = 15, -- #6D00FF
|
||||||
[0x8000] =16 -- #B6FF00
|
[0x8000] = 16 -- #B6FF00
|
||||||
}
|
}
|
||||||
|
|
||||||
local colors={
|
local colors = {
|
||||||
0x0001, -- #000000
|
0x0001, -- #000000
|
||||||
0x0002, -- #FFFFFF
|
0x0002, -- #FFFFFF
|
||||||
0x0004, -- #FF0000
|
0x0004, -- #FF0000
|
||||||
@@ -83,7 +79,7 @@ local colors={
|
|||||||
0x1000, -- #6D6D55
|
0x1000, -- #6D6D55
|
||||||
0x2000, -- #DBDBAA
|
0x2000, -- #DBDBAA
|
||||||
0x4000, -- #6D00FF
|
0x4000, -- #6D00FF
|
||||||
0x8000 -- #B6FF00
|
0x8000 -- #B6FF00
|
||||||
}
|
}
|
||||||
|
|
||||||
local function write(text, term)
|
local function write(text, term)
|
||||||
@@ -121,7 +117,7 @@ local function write(text, term)
|
|||||||
y = y + 1
|
y = y + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if y-1 >= h then
|
if y - 1 >= h then
|
||||||
term.scroll(1)
|
term.scroll(1)
|
||||||
y = h
|
y = h
|
||||||
term.setCursorPos(x, y)
|
term.setCursorPos(x, y)
|
||||||
@@ -132,38 +128,24 @@ local function write(text, term)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function newTTY(term)
|
local function newTTY(term)
|
||||||
local ret={}
|
local ret = {}
|
||||||
function ret.print(text)
|
function ret.print(text) write(text .. "\n", term) end
|
||||||
write(text.."\n", term)
|
function ret.printInline(text) write(text, term) end
|
||||||
end
|
|
||||||
function ret.printInline(text)
|
|
||||||
write(text, term)
|
|
||||||
end
|
|
||||||
function ret.clear()
|
function ret.clear()
|
||||||
term.clear()
|
term.clear()
|
||||||
term.setCursorPos(1,1)
|
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
|
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)
|
function ret.setBackgroundColor(color)
|
||||||
term.setBackgroundColor(colors[color])
|
term.setBackgroundColor(colors[color])
|
||||||
end
|
end
|
||||||
function ret.setTextColor(color)
|
function ret.setTextColor(color) term.setTextColor(colors[color]) end
|
||||||
term.setTextColor(colors[color])
|
|
||||||
end
|
|
||||||
function ret.getBackgroundColor()
|
function ret.getBackgroundColor()
|
||||||
return icolors[term.getBackgroundColor()]
|
return icolors[term.getBackgroundColor()]
|
||||||
end
|
end
|
||||||
function ret.getTextColor()
|
function ret.getTextColor() return icolors[term.getTextColor()] end
|
||||||
return icolors[term.getTextColor()]
|
|
||||||
end
|
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
U $;/
|
U $;/
|
||||||
|
U devfs0000;/dev/
|
||||||
|
U tmpfs0000;/tmp/
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
--:Minify:--
|
-- :Minify:--
|
||||||
local fs = {}
|
local fs = {}
|
||||||
local disks = {}
|
local disks = {}
|
||||||
local mounts = {}
|
local mounts = {}
|
||||||
@@ -15,39 +15,42 @@ local function resolve(path)
|
|||||||
local newPath = path:sub(#mountPoint + 1)
|
local newPath = path:sub(#mountPoint + 1)
|
||||||
return disks[mounts[mountPoint]], newPath
|
return disks[mounts[mountPoint]], newPath
|
||||||
end
|
end
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
function fs.update(initdisks)
|
function fs.update(initdisks)
|
||||||
disks = {}
|
disks = {}
|
||||||
for k, v in initdisks.list() do
|
for k, v in initdisks.list() do disks[k] = v end
|
||||||
disks[k] = v
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.exists(path)
|
function fs.exists(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
return disk:directoryExists(newPath) or disk:fileExists(newPath)
|
return disk:directoryExists(newPath) or disk:fileExists(newPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.isFile(path)
|
function fs.isFile(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
return disk:fileExists(newPath)
|
return disk:fileExists(newPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.isDir(path)
|
function fs.isDir(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
return disk:directoryExists(newPath)
|
return disk:directoryExists(newPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.list(path)
|
function fs.list(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
return disk:list(newPath)
|
return disk:list(newPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.makeDir(path)
|
function fs.makeDir(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
return disk:makeDirectory(newPath)
|
return disk:makeDirectory(newPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.remove(path)
|
function fs.remove(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
return disk:remove(newPath)
|
return disk:remove(newPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.readAllText(path)
|
function fs.readAllText(path)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
local handle = disk:open(newPath, "r")
|
local handle = disk:open(newPath, "r")
|
||||||
@@ -56,23 +59,26 @@ function fs.readAllText(path)
|
|||||||
handle.close()
|
handle.close()
|
||||||
return content
|
return content
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.writeAllText(path, text)
|
function fs.writeAllText(path, text)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
local handle = disk:open(newPath, "w")
|
local handle = disk:open(newPath, "w")
|
||||||
handle.write(text)
|
handle.write(text)
|
||||||
handle.close()
|
handle.close()
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.appendAllText(path, text)
|
function fs.appendAllText(path, text)
|
||||||
local disk, newPath = resolve(path)
|
local disk, newPath = resolve(path)
|
||||||
local handle = disk:open(newPath, "a")
|
local handle = disk:open(newPath, "a")
|
||||||
handle.write(text)
|
handle.write(text)
|
||||||
handle.close()
|
handle.close()
|
||||||
end
|
end
|
||||||
function fs.load(path)
|
|
||||||
return load(fs.readAllText(path), path)
|
function fs.load(path) return load(fs.readAllText(path), path) end
|
||||||
end
|
|
||||||
function fs.mount(disk, mountPoint)
|
function fs.mount(disk, mountPoint)
|
||||||
if not disks[disk] then return end
|
if not disks[disk] then return end
|
||||||
mounts[mountPoint] = disk
|
mounts[mountPoint] = disk
|
||||||
end
|
end
|
||||||
return fs
|
|
||||||
|
return fs
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ kernel.version="HyperionOS V1.0.0"
|
|||||||
kernel.process = "Kernel"
|
kernel.process = "Kernel"
|
||||||
kernel.username = "root"
|
kernel.username = "root"
|
||||||
kernel.hostname = "hyperion"
|
kernel.hostname = "hyperion"
|
||||||
kernel.groups = {0}
|
kernel.groups = {}
|
||||||
kernel.uid = 0
|
kernel.uid = 0
|
||||||
kernel.gid = 0
|
kernel.gid = 0
|
||||||
kernel.status = "start"
|
kernel.status = "start"
|
||||||
@@ -149,9 +149,6 @@ function kernel.saveLog()
|
|||||||
ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text)
|
ifs.writeAllText("/var/log/syslog.log", kernel.LOG_Text)
|
||||||
end
|
end
|
||||||
|
|
||||||
ifs.remove("/tmp")
|
|
||||||
ifs.makeDir("/tmp")
|
|
||||||
|
|
||||||
function kernel.newFifo()
|
function kernel.newFifo()
|
||||||
local fifo = {}
|
local fifo = {}
|
||||||
fifo.push=function(data)
|
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["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["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["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.syscalls["test"]=function() return true end
|
||||||
|
|
||||||
kernel.log("Running modules")
|
kernel.log("Running modules")
|
||||||
|
|||||||
@@ -1,61 +1,38 @@
|
|||||||
--:Minify:--
|
-- :Minify:--
|
||||||
function string.hasSuffix(str, suffix)
|
function string.hasSuffix(str, suffix)
|
||||||
return string.sub(str, #suffix+1) == suffix
|
return string.sub(str, #suffix + 1) == suffix
|
||||||
end
|
end
|
||||||
|
|
||||||
function string.hasPrefix(str, prefix)
|
function string.hasPrefix(str, prefix)
|
||||||
return string.sub(str, 1, #prefix) == prefix
|
return string.sub(str, 1, #prefix) == prefix
|
||||||
end
|
end
|
||||||
|
|
||||||
function string.getSuffix(str, prefix)
|
function string.getSuffix(str, prefix) return string.sub(str, #prefix + 1) end
|
||||||
return string.sub(str, #prefix+1)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.getPrefix(str, suffix)
|
function string.getPrefix(str, suffix) return string.sub(str, 1, #suffix) end
|
||||||
return string.sub(str, 1, #suffix)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.join(str, ...)
|
function string.join(str, ...) return table.concat(table.pack(str, ...)) end
|
||||||
return table.concat(table.pack(str, ...))
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.delim(str, ...)
|
function string.delim(str, ...) return table.concat(table.pack(...), str) end
|
||||||
return table.concat(table.pack(...), str)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.split(str, delim, maxResultCountOrNil)
|
function string.split(str, delim, maxResultCountOrNil)
|
||||||
assert(#delim == 1, "only delim len 1 supported for now")
|
assert(#delim == 1, "only delim len 1 supported for now")
|
||||||
maxResultCountOrNil = (maxResultCountOrNil or 0)-1
|
maxResultCountOrNil = (maxResultCountOrNil or 0) - 1
|
||||||
local rv = {}
|
local rv = {}
|
||||||
local buf = ""
|
local buf = ""
|
||||||
for i = 1, #str do
|
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
|
if #rv ~= maxResultCountOrNil and c == delim then
|
||||||
table.insert(rv, buf)
|
table.insert(rv, buf)
|
||||||
buf = ""
|
buf = ""
|
||||||
else
|
else
|
||||||
buf = buf..c
|
buf = buf .. c
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.insert(rv, buf)
|
table.insert(rv, buf)
|
||||||
return rv
|
return rv
|
||||||
end
|
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)
|
function table.deepcopy(orig, copies)
|
||||||
copies = copies or {}
|
copies = copies or {}
|
||||||
|
|
||||||
@@ -78,98 +55,30 @@ function table.deepcopy(orig, copies)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function table.hasKey(tabl, query)
|
function table.hasKey(tabl, query)
|
||||||
for i,v in pairs(tabl) do
|
for i, v in pairs(tabl) do if i == query then return v end end
|
||||||
if i==query then
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function table.hasVal(tabl, query)
|
function table.hasVal(tabl, query)
|
||||||
for i,v in pairs(tabl) do
|
for i, v in pairs(tabl) do if v == query then return i end end
|
||||||
if v==query then
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
return false
|
||||||
end
|
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)
|
local function serialize(tbl, seen)
|
||||||
seen = seen or {}
|
seen = seen or {}
|
||||||
|
|
||||||
-- If we've seen this table before, return a placeholder to prevent infinite loops
|
-- If we've seen this table before, return a placeholder to prevent infinite loops
|
||||||
if seen[tbl] then
|
if seen[tbl] then return '"[Circular Reference]"' end
|
||||||
return '"[Circular Reference]"'
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Mark this table as seen
|
-- Mark this table as seen
|
||||||
seen[tbl] = true
|
seen[tbl] = true
|
||||||
|
|
||||||
local output = "{"
|
local output = "{"
|
||||||
local first = true
|
local first = true
|
||||||
|
|
||||||
for i, v in pairs(tbl) do
|
for i, v in pairs(tbl) do
|
||||||
-- Handle comma placement more cleanly
|
-- Handle comma placement more cleanly
|
||||||
if not first then
|
if not first then output = output .. "," end
|
||||||
output = output .. ","
|
|
||||||
end
|
|
||||||
first = false
|
first = false
|
||||||
|
|
||||||
-- Serialize Key
|
-- Serialize Key
|
||||||
@@ -197,21 +106,19 @@ local function serialize(tbl, seen)
|
|||||||
end
|
end
|
||||||
|
|
||||||
seen[tbl] = nil
|
seen[tbl] = nil
|
||||||
|
|
||||||
output = output .. "}"
|
output = output .. "}"
|
||||||
return output
|
return output
|
||||||
end
|
end
|
||||||
|
|
||||||
local oldtype=type
|
local oldtype = type
|
||||||
local oldgetmetatable=getmetatable
|
local oldgetmetatable = getmetatable
|
||||||
function type(object, trueType)
|
function type(object, trueType)
|
||||||
if trueType then
|
if trueType then return oldtype(object) end
|
||||||
return oldtype(object)
|
if oldtype(object) ~= "table" then
|
||||||
end
|
|
||||||
if oldtype(object)~="table" then
|
|
||||||
return oldtype(object)
|
return oldtype(object)
|
||||||
else
|
else
|
||||||
if oldtype(oldgetmetatable(object))=="table" then
|
if oldtype(oldgetmetatable(object)) == "table" then
|
||||||
local metatable = oldgetmetatable(object)
|
local metatable = oldgetmetatable(object)
|
||||||
---@diagnostic disable-next-line: need-check-nil
|
---@diagnostic disable-next-line: need-check-nil
|
||||||
if metatable.__type then return metatable.__type end
|
if metatable.__type then return metatable.__type end
|
||||||
@@ -222,10 +129,10 @@ function type(object, trueType)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function getmetatable(object)
|
function getmetatable(object)
|
||||||
if oldtype(object)~="table" then return end
|
if oldtype(object) ~= "table" then return end
|
||||||
if oldtype(oldgetmetatable(object))=="table" then
|
if oldtype(oldgetmetatable(object)) == "table" then
|
||||||
if oldgetmetatable(object).__isuserdata then
|
if oldgetmetatable(object).__isuserdata then
|
||||||
if oldtype(oldgetmetatable(object).__usermeta)=="function" then
|
if oldtype(oldgetmetatable(object).__usermeta) == "function" then
|
||||||
return oldgetmetatable(object).__usermeta()
|
return oldgetmetatable(object).__usermeta()
|
||||||
else
|
else
|
||||||
return oldgetmetatable(object).__usermeta
|
return oldgetmetatable(object).__usermeta
|
||||||
@@ -239,22 +146,14 @@ function getmetatable(object)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function isEqualToAny(a, ...)
|
function isEqualToAny(a, ...)
|
||||||
local args={...}
|
local args = {...}
|
||||||
for i=0, #args do
|
for i = 0, #args do if a == args[i] then return true end end
|
||||||
if a==args[i] then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function isEqualToAll(a, ...)
|
function isEqualToAll(a, ...)
|
||||||
local args={...}
|
local args = {...}
|
||||||
for i=0, #args do
|
for i = 0, #args do if a ~= args[i] then return false end end
|
||||||
if a~=args[i] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -271,12 +170,39 @@ function table.values(t)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function table.indexOf(t, value)
|
function table.indexOf(t, value)
|
||||||
for i,v in ipairs(t) do
|
for i, v in ipairs(t) do if v == value then return i end end
|
||||||
if v==value then
|
return -1
|
||||||
return i
|
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
|
||||||
end
|
end
|
||||||
return -1
|
|
||||||
|
return table.concat(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
syscall = setmetatable({}, {
|
syscall = setmetatable({}, {
|
||||||
@@ -292,4 +218,4 @@ syscall = setmetatable({}, {
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
table.serialize=serialize
|
table.serialize = serialize
|
||||||
|
|||||||
@@ -1,42 +1,41 @@
|
|||||||
--:Minify:--
|
-- :Minify:--
|
||||||
local kernel=...
|
local kernel = ...
|
||||||
local io = {}
|
local io = {}
|
||||||
kernel.io=io
|
kernel.io = io
|
||||||
io.eventq={}
|
io.eventq = {}
|
||||||
|
|
||||||
function io.pushEvent(queue, ...)
|
function io.pushEvent(queue, ...)
|
||||||
queue=tostring(queue)
|
queue = tostring(queue)
|
||||||
if not io.eventq[queue] then
|
if not io.eventq[queue] then io.eventq[queue] = {} end
|
||||||
io.eventq[queue]={}
|
io.eventq[queue][#io.eventq[queue] + 1] = {...}
|
||||||
end
|
|
||||||
io.eventq[queue][#io.eventq[queue]+1]={...}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function io.bind(queue)
|
function io.bind(queue)
|
||||||
queue=tostring(queue)
|
queue = tostring(queue)
|
||||||
kernel.currentTask.eventq=queue
|
kernel.currentTask.eventq = queue
|
||||||
end
|
end
|
||||||
|
|
||||||
function io.pullEvent()
|
function io.pullEvent()
|
||||||
if io.eventq[kernel.currentTask.eventq] then
|
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)
|
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)
|
return table.unpack(event)
|
||||||
end
|
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
|
if not event then return end
|
||||||
return table.unpack(event)
|
return table.unpack(event)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function io.getBoundQueue()
|
function io.getBoundQueue() return kernel.currentTask.eventq end
|
||||||
return kernel.currentTask.eventq
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.syscalls["IO_pushEvent"]=io.pushEvent
|
kernel.syscalls["IO_pushEvent"] = io.pushEvent
|
||||||
kernel.syscalls["IO_pullEvent"]=io.pullEvent
|
kernel.syscalls["IO_pullEvent"] = io.pullEvent
|
||||||
kernel.syscalls["IO_bind"]=io.bind
|
kernel.syscalls["IO_bind"] = io.bind
|
||||||
kernel.syscalls["IO_getBoundQueue"]=io.getBoundQueue
|
kernel.syscalls["IO_getBoundQueue"] = io.getBoundQueue
|
||||||
|
|
||||||
kernel.log("IO pipeline initialized")
|
kernel.log("IO pipeline initialized")
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
--:Minify:--
|
-- :Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
local vfs = {}
|
local vfs = {}
|
||||||
kernel.vfs=vfs
|
kernel.vfs = vfs
|
||||||
vfs.mounts = { ["$"] = "/" }
|
vfs.mounts = {["$"] = "/"}
|
||||||
vfs.disks = kernel.disks
|
vfs.disks = kernel.disks
|
||||||
|
|
||||||
-- Path normalization
|
-- Path normalization
|
||||||
local function normalizePath(path)
|
local function normalizePath(path)
|
||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local cwd = task.cwd or "/"
|
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 = {}
|
local parts = {}
|
||||||
for part in path:gmatch("[^/]+") do
|
for part in path:gmatch("[^/]+") do
|
||||||
if part == ".." then
|
if part == ".." then
|
||||||
@@ -21,22 +21,43 @@ local function normalizePath(path)
|
|||||||
return "/" .. table.concat(parts, "/")
|
return "/" .. table.concat(parts, "/")
|
||||||
end
|
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
|
-- Resolve mount and disk path
|
||||||
local function resolvePath(path)
|
local function resolvePath(path)
|
||||||
path = normalizePath(path)
|
path = normalizePath(path)
|
||||||
|
|
||||||
local mountPoint = "/"
|
local mountPoint = nil
|
||||||
local mountId = "$"
|
local mountId = nil
|
||||||
for k,v in pairs(vfs.mounts) do
|
|
||||||
if path:sub(1,#v) == v and #v > #mountPoint then
|
for id, mp in pairs(vfs.mounts) do
|
||||||
mountPoint = v
|
if path == mp or (mp == "/" and path:sub(1, 1) == "/") or path:sub(1, #mp + 1) == mp .. "/" then
|
||||||
mountId = k
|
if not mountPoint or #mp > #mountPoint then
|
||||||
|
mountPoint = mp
|
||||||
|
mountId = id
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local diskPath = path:sub(#mountPoint)
|
if not mountId then
|
||||||
if diskPath == "" then diskPath = "/" end
|
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
|
return vfs.disks[mountId], diskPath
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -55,25 +76,26 @@ local function checkSystemLimit()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- File object constructor
|
-- File object constructor
|
||||||
local function newFileObj(handle, mode, path, meta)
|
local function newFileObj(handle, mode, path, meta, type)
|
||||||
return {
|
return {
|
||||||
handle = handle,
|
handle = handle,
|
||||||
mode = mode,
|
mode = mode,
|
||||||
path = path,
|
path = path,
|
||||||
meta = meta
|
meta = meta,
|
||||||
|
type = type
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Validate mode
|
function vfs.newfd(fdobj)
|
||||||
local function ismode(mode)
|
checkSystemLimit()
|
||||||
if not (mode == "r" or mode == "w" or mode == "a") then error("EINVAL") end
|
total=total+1
|
||||||
|
local fd = allocFD(kernel.currentTask)
|
||||||
|
kernel.currentTask.fd[fd]=fdobj
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Parse metafile
|
-- Parse metafile
|
||||||
local function parseMetafile(file)
|
local function parseMetafile(file)
|
||||||
if not file or file == "" then
|
if not file or file == "" then return {} end
|
||||||
return {}
|
|
||||||
end
|
|
||||||
|
|
||||||
local ret = {}
|
local ret = {}
|
||||||
local pointer = 1
|
local pointer = 1
|
||||||
@@ -99,12 +121,7 @@ local function parseMetafile(file)
|
|||||||
pointer = pointer + cmetalen
|
pointer = pointer + cmetalen
|
||||||
end
|
end
|
||||||
|
|
||||||
ret[name] = {
|
ret[name] = {owner = owner, group = group, perms = perms, cmeta = cmeta}
|
||||||
owner = owner,
|
|
||||||
group = group,
|
|
||||||
perms = perms,
|
|
||||||
cmeta = cmeta
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
@@ -112,7 +129,7 @@ end
|
|||||||
|
|
||||||
-- Build metafile
|
-- Build metafile
|
||||||
local function makeMetafile(meta)
|
local function makeMetafile(meta)
|
||||||
local file=""
|
local file = ""
|
||||||
for name, m in pairs(meta) do
|
for name, m in pairs(meta) do
|
||||||
local entry = ""
|
local entry = ""
|
||||||
entry = entry .. string.char(#name) .. name
|
entry = entry .. string.char(#name) .. name
|
||||||
@@ -129,22 +146,18 @@ local function getFileMeta(path)
|
|||||||
fullPath = normalizePath(fullPath)
|
fullPath = normalizePath(fullPath)
|
||||||
|
|
||||||
local parts = {}
|
local parts = {}
|
||||||
for p in fullPath:gmatch("[^/]+") do
|
for p in fullPath:gmatch("[^/]+") do table.insert(parts, p) end
|
||||||
table.insert(parts, p)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- default fallback
|
-- 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
|
-- walk from deepest parent upward
|
||||||
for i = #parts, 1, -1 do
|
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
|
if parent ~= "/" then parent = parent .. "/" end
|
||||||
|
|
||||||
local target = parts[i]
|
local target = parts[i]
|
||||||
if target == ".meta" then
|
if target == ".meta" then error("Cannot open metafile") end
|
||||||
error("Cannot open metafile")
|
|
||||||
end
|
|
||||||
local metaPath = parent .. ".meta"
|
local metaPath = parent .. ".meta"
|
||||||
|
|
||||||
if disk:fileExists(metaPath) then
|
if disk:fileExists(metaPath) then
|
||||||
@@ -153,9 +166,7 @@ local function getFileMeta(path)
|
|||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
local parsed = parseMetafile(text)
|
local parsed = parseMetafile(text)
|
||||||
if parsed[target] then
|
if parsed[target] then return parsed[target] end
|
||||||
return parsed[target]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -173,13 +184,9 @@ local function ensureParentMeta(path)
|
|||||||
name = fullPath:gsub("^/", "")
|
name = fullPath:gsub("^/", "")
|
||||||
end
|
end
|
||||||
|
|
||||||
if name == ".meta" then
|
if name == ".meta" then error("Cannot open metafile") end
|
||||||
error("Cannot open metafile")
|
|
||||||
end
|
|
||||||
|
|
||||||
if parent ~= "/" and parent:sub(-1) ~= "/" then
|
if parent ~= "/" and parent:sub(-1) ~= "/" then parent = parent .. "/" end
|
||||||
parent = parent .. "/"
|
|
||||||
end
|
|
||||||
|
|
||||||
local metaPath = parent .. ".meta"
|
local metaPath = parent .. ".meta"
|
||||||
|
|
||||||
@@ -192,27 +199,32 @@ local function ensureParentMeta(path)
|
|||||||
return metaPath, name
|
return metaPath, name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Permission checking
|
-- Permission checking
|
||||||
local function checkperms(meta, mode)
|
local function checkperms(meta, mode)
|
||||||
local modes = {
|
local modes = {
|
||||||
r = {owner=5, group=3, everyone=1},
|
r = {owner = 5, group = 3, everyone = 1},
|
||||||
w = {owner=4, group=2, everyone=0},
|
w = {owner = 4, group = 2, everyone = 0},
|
||||||
a = {owner=4, group=2, everyone=0}
|
a = {owner = 4, group = 2, everyone = 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
local bits = meta.perms
|
local bits = meta.perms
|
||||||
local function bit_is_set(num, bit)
|
local function bit_is_set(num, bit)
|
||||||
return math.floor(num / (2^bit)) % 2 == 1
|
return math.floor(num / (2 ^ bit)) % 2 == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if kernel.uid == 0 then return true 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
|
if meta.group and kernel.groups then
|
||||||
for _, gid in ipairs(kernel.groups) do
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
if bit_is_set(bits, modes[mode].everyone) then return true end
|
if bit_is_set(bits, modes[mode].everyone) then return true end
|
||||||
error("EACCES")
|
error("EACCES")
|
||||||
end
|
end
|
||||||
@@ -220,39 +232,55 @@ end
|
|||||||
-- mounts
|
-- mounts
|
||||||
local function normalizeMountPoint(path)
|
local function normalizeMountPoint(path)
|
||||||
path = normalizePath(path)
|
path = normalizePath(path)
|
||||||
if path ~= "/" and path:sub(-1) == "/" then
|
if path ~= "/" and path:sub(-1) == "/" then path = path:sub(1, -2) end
|
||||||
path = path:sub(1, -2)
|
|
||||||
end
|
|
||||||
return path
|
return path
|
||||||
end
|
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)
|
function vfs.mount(target, diskOrId)
|
||||||
if kernel.uid ~= 0 then error("EPERM") end
|
if kernel.uid ~= 0 then error("EPERM") end
|
||||||
if not target then error("EINVAL") end
|
if not target then error("EINVAL") end
|
||||||
|
|
||||||
target = normalizeMountPoint(target)
|
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 disk
|
||||||
local id
|
local id
|
||||||
|
|
||||||
if type(diskOrId) == "string" then
|
if type(diskOrId) == "string" then
|
||||||
disk = kernel.disks[diskOrId]
|
disk = kernel.disks[diskOrId]
|
||||||
id = diskOrId
|
|
||||||
if not disk then error("ENODEV") end
|
if not disk then error("ENODEV") end
|
||||||
|
check(disk)
|
||||||
|
id = diskOrId
|
||||||
elseif type(diskOrId) == "table" then
|
elseif type(diskOrId) == "table" then
|
||||||
|
check(disk)
|
||||||
disk = diskOrId
|
disk = diskOrId
|
||||||
id = tostring(disk)
|
id = disk.address
|
||||||
vfs.disks[id] = disk
|
vfs.disks[id] = disk
|
||||||
else
|
else
|
||||||
error("EINVAL")
|
error("EINVAL")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Prevent shadowing an existing mount
|
-- Prevent shadowing an existing mount
|
||||||
for _, mp in pairs(vfs.mounts) do
|
for _, mp in pairs(vfs.mounts) do if mp == target then error("EBUSY") end end
|
||||||
if mp == target then
|
|
||||||
error("EBUSY")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
vfs.mounts[id] = target
|
vfs.mounts[id] = target
|
||||||
return true
|
return true
|
||||||
@@ -277,7 +305,6 @@ end
|
|||||||
|
|
||||||
-- Open file
|
-- Open file
|
||||||
function vfs.open(path, mode)
|
function vfs.open(path, mode)
|
||||||
ismode(mode)
|
|
||||||
checkSystemLimit()
|
checkSystemLimit()
|
||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local fd = allocFD(task)
|
local fd = allocFD(task)
|
||||||
@@ -287,8 +314,13 @@ function vfs.open(path, mode)
|
|||||||
local meta = getFileMeta(path)
|
local meta = getFileMeta(path)
|
||||||
checkperms(meta, mode)
|
checkperms(meta, mode)
|
||||||
|
|
||||||
local handle = disk:open(diskPath, mode)
|
local handle
|
||||||
task.fd[fd] = newFileObj(handle, mode, path, meta)
|
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
|
total = total + 1
|
||||||
return fd
|
return fd
|
||||||
end
|
end
|
||||||
@@ -298,6 +330,7 @@ function vfs.read(fd, count)
|
|||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local file = task.fd[fd]
|
local file = task.fd[fd]
|
||||||
if not file then error("EBADF") end
|
if not file then error("EBADF") end
|
||||||
|
if not file.handle.read then error("EBADF") end
|
||||||
if file.mode ~= "r" then error("EBADF") end
|
if file.mode ~= "r" then error("EBADF") end
|
||||||
return file.handle.read(count or 1)
|
return file.handle.read(count or 1)
|
||||||
end
|
end
|
||||||
@@ -307,6 +340,7 @@ function vfs.write(fd, content)
|
|||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local file = task.fd[fd]
|
local file = task.fd[fd]
|
||||||
if not file then error("EBADF") end
|
if not file then error("EBADF") end
|
||||||
|
if not file.handle.write then error("EBADF") end
|
||||||
if file.mode ~= "w" and file.mode ~= "a" then error("EBADF") end
|
if file.mode ~= "w" and file.mode ~= "a" then error("EBADF") end
|
||||||
return file.handle.write(content)
|
return file.handle.write(content)
|
||||||
end
|
end
|
||||||
@@ -316,6 +350,8 @@ function vfs.pread(fd, count, offset)
|
|||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local file = task.fd[fd]
|
local file = task.fd[fd]
|
||||||
if not file then error("EBADF") end
|
if not file then error("EBADF") end
|
||||||
|
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
|
if file.mode ~= "r" then error("EBADF") end
|
||||||
file.handle.seek("set", offset)
|
file.handle.seek("set", offset)
|
||||||
return file.handle.read(count or 1)
|
return file.handle.read(count or 1)
|
||||||
@@ -325,6 +361,8 @@ function vfs.pwrite(fd, content, offset)
|
|||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local file = task.fd[fd]
|
local file = task.fd[fd]
|
||||||
if not file then error("EBADF") end
|
if not file then error("EBADF") end
|
||||||
|
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
|
if file.mode ~= "w" and file.mode ~= "a" then error("EBADF") end
|
||||||
file.handle.seek("set", offset)
|
file.handle.seek("set", offset)
|
||||||
return file.handle.write(content)
|
return file.handle.write(content)
|
||||||
@@ -335,6 +373,7 @@ function vfs.lseek(fd, offset, whence)
|
|||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local file = task.fd[fd]
|
local file = task.fd[fd]
|
||||||
if not file then error("EBADF") end
|
if not file then error("EBADF") end
|
||||||
|
if not file.handle.seek then error("EBADF") end
|
||||||
return file.handle.seek(whence or "set", offset)
|
return file.handle.seek(whence or "set", offset)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -343,6 +382,7 @@ function vfs.fsync(fd)
|
|||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local file = task.fd[fd]
|
local file = task.fd[fd]
|
||||||
if not file then error("EBADF") end
|
if not file then error("EBADF") end
|
||||||
|
if not file.handle.flush then error("EBADF") end
|
||||||
if file.mode ~= "w" and file.mode ~= "a" then error("EBADF") end
|
if file.mode ~= "w" and file.mode ~= "a" then error("EBADF") end
|
||||||
file.handle.flush()
|
file.handle.flush()
|
||||||
end
|
end
|
||||||
@@ -352,7 +392,9 @@ function vfs.close(fd)
|
|||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local file = task.fd[fd]
|
local file = task.fd[fd]
|
||||||
if not file then error("EBADF") end
|
if not file then error("EBADF") end
|
||||||
file.handle.close()
|
if file.handle.close then
|
||||||
|
file.handle.close()
|
||||||
|
end
|
||||||
task.fd[fd] = nil
|
task.fd[fd] = nil
|
||||||
total = total - 1
|
total = total - 1
|
||||||
end
|
end
|
||||||
@@ -364,8 +406,11 @@ function vfs.sendfile(outfd, infd, count)
|
|||||||
local outFile = task.fd[outfd]
|
local outFile = task.fd[outfd]
|
||||||
if not inFile or not outFile then error("EBADF") end
|
if not inFile or not outFile then error("EBADF") end
|
||||||
if inFile.mode ~= "r" 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 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)
|
local data = inFile.handle.read(count or 1024)
|
||||||
|
if not data or data == "" then return end
|
||||||
return outFile.handle.write(data)
|
return outFile.handle.write(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -403,12 +448,12 @@ end
|
|||||||
-- Directory operations
|
-- Directory operations
|
||||||
function vfs.listdir(path)
|
function vfs.listdir(path)
|
||||||
local disk, diskPath = resolvePath(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)
|
local meta = getFileMeta(path)
|
||||||
checkperms(meta, "r")
|
checkperms(meta, "r")
|
||||||
local list = disk:list(diskPath)
|
local list = disk:list(diskPath)
|
||||||
if table.indexOf(list,".meta")~=-1 then
|
if table.indexOf(list, ".meta") ~= -1 then
|
||||||
table.remove(list,table.indexOf(list,".meta"))
|
table.remove(list, table.indexOf(list, ".meta"))
|
||||||
end
|
end
|
||||||
return list
|
return list
|
||||||
end
|
end
|
||||||
@@ -431,8 +476,8 @@ end
|
|||||||
function vfs.chmod(path, perms)
|
function vfs.chmod(path, perms)
|
||||||
local disk, diskPath = resolvePath(path)
|
local disk, diskPath = resolvePath(path)
|
||||||
local meta = getFileMeta(path)
|
local meta = getFileMeta(path)
|
||||||
checkperms(meta, "w")
|
|
||||||
|
|
||||||
|
if meta.owner ~= kernel.currentTask.uid then error("EACCES") end
|
||||||
meta.perms = perms
|
meta.perms = perms
|
||||||
|
|
||||||
local mpath, target = ensureParentMeta(path)
|
local mpath, target = ensureParentMeta(path)
|
||||||
@@ -449,7 +494,6 @@ function vfs.chmod(path, perms)
|
|||||||
f.close()
|
f.close()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function vfs.fchmod(fd, perms)
|
function vfs.fchmod(fd, perms)
|
||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local file = task.fd[fd]
|
local file = task.fd[fd]
|
||||||
@@ -460,8 +504,8 @@ end
|
|||||||
function vfs.chown(path, uid, gid)
|
function vfs.chown(path, uid, gid)
|
||||||
local disk, diskPath = resolvePath(path)
|
local disk, diskPath = resolvePath(path)
|
||||||
local meta = getFileMeta(path)
|
local meta = getFileMeta(path)
|
||||||
checkperms(meta, "w")
|
|
||||||
|
|
||||||
|
if meta.owner ~= kernel.currentTask.uid then error("EACCES") end
|
||||||
meta.owner = uid
|
meta.owner = uid
|
||||||
meta.group = gid
|
meta.group = gid
|
||||||
|
|
||||||
@@ -479,7 +523,6 @@ function vfs.chown(path, uid, gid)
|
|||||||
f.close()
|
f.close()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function vfs.fchown(fd, uid, gid)
|
function vfs.fchown(fd, uid, gid)
|
||||||
local task = kernel.currentTask
|
local task = kernel.currentTask
|
||||||
local file = task.fd[fd]
|
local file = task.fd[fd]
|
||||||
@@ -501,13 +544,9 @@ function vfs.type(path)
|
|||||||
return disk:type(diskPath)
|
return disk:type(diskPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vfs.getcwd()
|
function vfs.getcwd() return kernel.currentTask.cwd end
|
||||||
return kernel.currentTask.cwd
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.chdir(path)
|
function vfs.chdir(path) kernel.currentTask.cwd = path end
|
||||||
kernel.currentTask.cwd=path
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Export syscalls
|
-- Export syscalls
|
||||||
local sys = kernel.syscalls
|
local sys = kernel.syscalls
|
||||||
@@ -531,9 +570,9 @@ sys["chown"] = vfs.chown
|
|||||||
sys["fchown"] = vfs.fchown
|
sys["fchown"] = vfs.fchown
|
||||||
sys["exists"] = vfs.exists
|
sys["exists"] = vfs.exists
|
||||||
sys["type"] = vfs.type
|
sys["type"] = vfs.type
|
||||||
sys["mount"] = vfs.mount
|
sys["mount"] = vfs.mount
|
||||||
sys["umount"] = vfs.umount
|
sys["umount"] = vfs.umount
|
||||||
sys["getcwd"] = vfs.getcwd
|
sys["getcwd"] = vfs.getcwd
|
||||||
sys["chdir"] = vfs.chdir
|
sys["chdir"] = vfs.chdir
|
||||||
|
|
||||||
kernel.log("VFS module loaded")
|
kernel.log("VFS module loaded")
|
||||||
|
|||||||
@@ -1,37 +1,33 @@
|
|||||||
--:Minify:--
|
-- :Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
local cache = {}
|
local cache = {}
|
||||||
kernel.searchpaths = {
|
kernel.searchpaths = {
|
||||||
"/lib/?.lua",
|
"/lib/?.lua", "/lib/?", "/usr/lib/?.lua", "/usr/lib/?",
|
||||||
"/lib/?",
|
"/usr/local/lib/?.lua", "/usr/local/lib/?", "?.lua", "?"
|
||||||
"/usr/lib/?.lua",
|
|
||||||
"/usr/lib/?",
|
|
||||||
"/usr/local/lib/?.lua",
|
|
||||||
"/usr/local/lib/?",
|
|
||||||
"?.lua",
|
|
||||||
"?"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function require(module,...)
|
function require(module, ...)
|
||||||
if cache[module] then
|
if cache[module] then return cache[module] end
|
||||||
return cache[module]
|
|
||||||
end
|
|
||||||
local modpath = module:gsub("%.", "/")
|
local modpath = module:gsub("%.", "/")
|
||||||
local failed = {}
|
local failed = {}
|
||||||
for _, path in ipairs(kernel.searchpaths) do
|
for _, path in ipairs(kernel.searchpaths) do
|
||||||
local full_path = string.gsub(path, "%?", modpath)
|
local full_path = string.replace(path, "?", modpath)
|
||||||
if full_path:sub(1,1)~="/" then
|
if full_path:sub(1, 1) ~= "/" then
|
||||||
full_path=kernel.currentTask.cwd..full_path
|
full_path = kernel.currentTask.cwd .. full_path
|
||||||
end
|
end
|
||||||
|
|
||||||
if kernel.vfs.exists(full_path) then
|
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"
|
full_path = full_path .. "/init"
|
||||||
end
|
end
|
||||||
|
|
||||||
if kernel.vfs.exists(full_path) then
|
if kernel.vfs.exists(full_path) then
|
||||||
local handle = kernel.vfs.open(full_path, "r")
|
local handle = kernel.vfs.open(full_path, "r")
|
||||||
local file_content = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
local file_content = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
||||||
kernel.vfs.close(handle)
|
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
|
else
|
||||||
table.insert(failed, full_path)
|
table.insert(failed, full_path)
|
||||||
end
|
end
|
||||||
@@ -39,5 +35,6 @@ function require(module,...)
|
|||||||
table.insert(failed, full_path)
|
table.insert(failed, full_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
error("Module not found: " .. module .. " (searched paths: " .. table.concat(failed, ", ") .. ")")
|
error("Module not found: " .. module .. " (searched paths: " .. table.concat(failed, ", ") .. ")")
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,173 +1,143 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
--local kernel = ...
|
local kernel = ...
|
||||||
--
|
|
||||||
--local proxy = {}
|
local proxy = {}
|
||||||
--local data = {}
|
local data = {}
|
||||||
--
|
|
||||||
--proxy.address = "devfs0000"
|
proxy.address = "devfs0000"
|
||||||
--proxy.isReadOnly = false
|
proxy.isReadOnly = function() return false end
|
||||||
--proxy.spaceUsed = function() return 0 end
|
proxy.spaceUsed = function() return 0 end
|
||||||
--proxy.spaceTotal = function() return 0 end
|
proxy.spaceTotal = function() return 0 end
|
||||||
--proxy.makeDirectory = function() error("Permission denied") end
|
proxy.makeDirectory = function() error("EACCES") end
|
||||||
--proxy.remove = function() error("Permission denied") end
|
proxy.remove = function() error("EACCES") end
|
||||||
--proxy.setLabel = function() error("Permission denied") end
|
proxy.setLabel = function() error("EACCES") end
|
||||||
--proxy.getLabel = function() return "devfs" end
|
proxy.getLabel = function() return "devfs" end
|
||||||
--proxy.attributes = function(path) return {
|
proxy.attributes = function(path) return {
|
||||||
-- type = proxy.type(path),
|
size = 0,
|
||||||
-- isReadOnly = false,
|
modified = 0,
|
||||||
-- size = 0,
|
created = 0,
|
||||||
-- lastModified = 0,
|
} end
|
||||||
-- created = 0,
|
|
||||||
-- Permissions = "666",
|
function proxy:open(path, mode)
|
||||||
-- owner = "root",
|
local steps = kernel.vfs.splitPath(path)
|
||||||
-- group = "root"
|
local step = data
|
||||||
--} end
|
for i=1, #steps-1 do
|
||||||
--
|
local dat = step[steps[i]]
|
||||||
--local function getNode(path)
|
if type(dat) ~= "table" then error("ENFILE") end
|
||||||
-- local parts = string.split(path, "/")
|
step=dat
|
||||||
-- if parts[1] == "" then
|
end
|
||||||
-- table.remove(parts, 1)
|
if type(step[steps[#steps]]) == "function" then
|
||||||
-- end
|
return step[steps[#steps]]("open", mode)
|
||||||
--
|
end
|
||||||
-- local node = data
|
error("ENFILE")
|
||||||
-- for _, part in ipairs(parts) do
|
end
|
||||||
-- if node[part] then
|
|
||||||
-- node = node[part]
|
function proxy:type(path, mode)
|
||||||
-- else
|
local steps = kernel.vfs.splitPath(path)
|
||||||
-- return nil
|
local step = data
|
||||||
-- end
|
if #steps == 0 then
|
||||||
-- end
|
return "directory"
|
||||||
--
|
end
|
||||||
-- return node
|
for i=1, #steps-1 do
|
||||||
--end
|
local dat = step[steps[i]]
|
||||||
--
|
if type(dat) ~= "table" then error("ENFILE") end
|
||||||
--proxy.type = function(path)
|
step=dat
|
||||||
-- local node = getNode(path)
|
end
|
||||||
-- if node then
|
if type(step[steps[#steps]]) == "function" then
|
||||||
-- return node.type
|
return step[steps[#steps]]("type", mode)
|
||||||
-- else
|
end
|
||||||
-- return nil
|
if type(step[steps[#steps]]) == "table" then
|
||||||
-- end
|
return "directory"
|
||||||
--end
|
end
|
||||||
--
|
error("ENOENT")
|
||||||
--proxy.list = function(path)
|
end
|
||||||
-- local node = getNode(path)
|
|
||||||
-- if node and node.type == "directory" then
|
function proxy:list(path)
|
||||||
-- local content = table.keys(node)
|
local steps = kernel.vfs.splitPath(path)
|
||||||
-- table.remove(content, table.indexOf(content, "type"))
|
local step = data
|
||||||
-- return content
|
if #steps == 0 then
|
||||||
-- else
|
return table.keys(data)
|
||||||
-- error("Not a directory")
|
end
|
||||||
-- end
|
for i=1, #steps-1 do
|
||||||
--end
|
local dat = step[steps[i]]
|
||||||
--
|
if type(dat) ~= "table" then error("ENOENT") end
|
||||||
--proxy.open = function(path, mode)
|
step=dat
|
||||||
-- local node = getNode(path)
|
end
|
||||||
-- if node and (node.type == "file" or node.type == "character device") then
|
if type(step[steps[#steps]]) == "table" then
|
||||||
-- if mode == "r" then
|
return table.keys(step[steps[#steps]])
|
||||||
-- return {
|
end
|
||||||
-- read = node.read,
|
error("ENOENT")
|
||||||
-- close = function() end
|
end
|
||||||
-- }
|
|
||||||
-- elseif mode == "w" then
|
function proxy:fileExists(path)
|
||||||
-- return {
|
local ok = pcall(function()
|
||||||
-- write = node.write,
|
return self:type(path)
|
||||||
-- close = function() end
|
end)
|
||||||
-- }
|
return ok
|
||||||
-- else
|
end
|
||||||
-- error("Invalid mode")
|
|
||||||
-- end
|
function data.random(op, mode)
|
||||||
-- else
|
if op=="type" then
|
||||||
-- error("Not a file"..type(node))
|
return "character device"
|
||||||
-- end
|
elseif op=="open" then
|
||||||
--end
|
if mode=="r" then
|
||||||
--
|
return {
|
||||||
--local function newStringFile(content)
|
read=function(amount)
|
||||||
-- return {
|
local str = ""
|
||||||
-- type = "file",
|
for i=1, amount or 1 do
|
||||||
-- read = function() return content end,
|
str=str..string.char(math.random(0, 255))
|
||||||
-- write = function(newContent) content = newContent end
|
end
|
||||||
-- }
|
return str
|
||||||
--end
|
end
|
||||||
--
|
}
|
||||||
--local function newDirectory()
|
elseif mode=="w" or mode=="a" then
|
||||||
-- return {
|
return {
|
||||||
-- type = "directory"
|
write=function() end
|
||||||
-- }
|
}
|
||||||
--end
|
else error("EACCES")
|
||||||
--
|
end
|
||||||
--data["random"] = {
|
end
|
||||||
-- type = "character device",
|
end
|
||||||
-- read = function(amount)
|
|
||||||
-- local result = ""
|
function data.null(op, mode)
|
||||||
-- for _ = 1, amount do
|
if op=="type" then
|
||||||
-- result = result .. string.char(math.random(0, 255))
|
return "character device"
|
||||||
-- end
|
elseif op=="open" then
|
||||||
-- return result
|
if mode=="r" then
|
||||||
-- end,
|
return {
|
||||||
-- write = function() error("Permission denied") end
|
read=function(amount) end
|
||||||
--}
|
}
|
||||||
--
|
elseif mode=="w" or mode=="a" then
|
||||||
--data["null"] = {
|
return {
|
||||||
-- type = "character device",
|
write=function() end
|
||||||
-- read = function() return "" end,
|
}
|
||||||
-- write = function() end
|
else error("EACCES")
|
||||||
--}
|
end
|
||||||
--
|
end
|
||||||
--data["zero"] = {
|
end
|
||||||
-- type = "character device",
|
|
||||||
-- read = function(amount)
|
function data.zero(op, mode)
|
||||||
-- return string.rep("\0", amount)
|
if op=="type" then
|
||||||
-- end,
|
return "character device"
|
||||||
-- write = function() error("Permission denied") end
|
elseif op=="open" then
|
||||||
--}
|
if mode=="r" then
|
||||||
--
|
return {
|
||||||
--data["rtc"] = {
|
read=function(amount)
|
||||||
-- type = "character device",
|
local str = ""
|
||||||
-- read = function() return kernel.computer:time() end,
|
for i=1, amount or 1 do
|
||||||
-- write = function() error("Permission denied") end
|
str=str..string.char(0)
|
||||||
--}
|
end
|
||||||
--
|
return str
|
||||||
--data["rtc0"] = {
|
end
|
||||||
-- type = "character device",
|
}
|
||||||
-- read = function() return kernel.computer:time() end,
|
elseif mode=="w" or mode=="a" then
|
||||||
-- write = function() error("Permission denied") end
|
return {
|
||||||
--}
|
write=function() end
|
||||||
--
|
}
|
||||||
--data["eeprom"] = {
|
else error("EACCES")
|
||||||
-- type = "character device",
|
end
|
||||||
-- read = function() return kernel.computer:getEEPROM() end,
|
end
|
||||||
-- write = function(data)
|
end
|
||||||
-- if kernel.uid ~= 0 then
|
|
||||||
-- error("Permission denied")
|
data["disk"]={}
|
||||||
-- end
|
kernel.disks["devfs0000"]=proxy
|
||||||
-- 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)
|
|
||||||
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 kernel = ...
|
||||||
|
|
||||||
local timeout=false
|
local timeout = false
|
||||||
kernel.processes.keventd = function()
|
kernel.processes.keventd = function()
|
||||||
while true do
|
while true do
|
||||||
local event = {kernel.computer:getMachineEvent()}
|
local event = {kernel.computer:getMachineEvent()}
|
||||||
if event[1] then
|
if event[1] then
|
||||||
if event[1]=="keyTyped" then
|
if event[1] == "keyTyped" then
|
||||||
if event[3]=="\x1b^s" then
|
if event[3] == "\x1b^s" then
|
||||||
kernel.shutdown()
|
kernel.shutdown()
|
||||||
elseif event[3]=="\x1b^r" then
|
elseif event[3] == "\x1b^r" then
|
||||||
kernel.reboot()
|
kernel.reboot()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
kernel.io.pushEvent("raw", table.unpack(event))
|
kernel.io.pushEvent("raw", table.unpack(event))
|
||||||
timeout=false
|
timeout = false
|
||||||
else
|
else
|
||||||
timeout=true
|
timeout = true
|
||||||
end
|
|
||||||
if timeout then
|
|
||||||
sleep(.05)
|
|
||||||
end
|
end
|
||||||
|
if timeout then sleep(.05) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1,18 +1,34 @@
|
|||||||
--:Minify:--
|
--:Minify:--
|
||||||
local kernel=...
|
local kernel = ...
|
||||||
for i,v in ipairs(string.split(kernel.fstab,"\n")) do
|
|
||||||
if v:sub(1,1)=="U" then
|
local function trim(str)
|
||||||
local id=""
|
local s, e = 1, #str
|
||||||
for i=3,#v do
|
while s <= e and (str:sub(s,s) == " " or str:sub(s,s) == "\t") do s = s + 1 end
|
||||||
if v:sub(i,i)==";" then
|
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 i==3 then kernel.log("Invalid fstab line... Skipping.","WARN", 8) goto endline end
|
if s > e then return "" end
|
||||||
id=v:sub(3,i-1)
|
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
|
||||||
end
|
end
|
||||||
local path=v:sub(#id+4)
|
|
||||||
if id~="$" then
|
if not semicolon_pos or semicolon_pos == 3 then
|
||||||
kernel.vfs.mount(path, id)
|
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
|
end
|
||||||
::endline::
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -6,5 +6,15 @@ function socket.socket()
|
|||||||
|
|
||||||
end
|
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.socket=socket
|
||||||
kernel.log("Loaded socket module")
|
kernel.log("Loaded socket module")
|
||||||
@@ -1,24 +1,23 @@
|
|||||||
--:Minify:--
|
-- :Minify:--
|
||||||
local args={...}
|
local args = {...}
|
||||||
local kernel=args[1]
|
local kernel = args[1]
|
||||||
kernel._G=_G
|
kernel._G = _G
|
||||||
|
|
||||||
local function readonly(tbl)
|
local function readonly(tbl)
|
||||||
return setmetatable({}, {
|
return setmetatable({}, {
|
||||||
__index = function(_, key)
|
__index = function(_, key)
|
||||||
local value = tbl[key]
|
local value = tbl[key]
|
||||||
if type(value) == "table" then
|
if type(value) == "table" then return readonly(value) end
|
||||||
return readonly(value)
|
|
||||||
end
|
|
||||||
return value
|
return value
|
||||||
end,
|
end,
|
||||||
|
|
||||||
__newindex = function(t,k,v)
|
__newindex = function(t, k, v)
|
||||||
if kernel.config.allowGlobalOverwrites or kernel.allowGlobalOverwrites then
|
if kernel.config.allowGlobalOverwrites or
|
||||||
rawset(tbl,k,v)
|
kernel.allowGlobalOverwrites then
|
||||||
|
rawset(tbl, k, v)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
error("Attempt to modify global variable '"..k.."'",2)
|
error("Attempt to modify global variable '" .. k .. "'", 2)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
__pairs = function()
|
__pairs = function()
|
||||||
@@ -45,15 +44,13 @@ local function readonly(tbl)
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
__len = function()
|
__len = function() return #tbl end,
|
||||||
return #tbl
|
|
||||||
end,
|
|
||||||
|
|
||||||
__metatable = false,
|
__metatable = false
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
kernel._U=readonly(kernel._G)
|
kernel._U = readonly(kernel._G)
|
||||||
kernel.allowGlobalOverwrites=true
|
kernel.allowGlobalOverwrites = true
|
||||||
kernel._U._G=kernel._U
|
kernel._U._G = kernel._U
|
||||||
kernel.allowGlobalOverwrites=false
|
kernel.allowGlobalOverwrites = false
|
||||||
|
|||||||
@@ -1,72 +1,82 @@
|
|||||||
--:Minify:--
|
-- :Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
local tasks = {}
|
local tasks = {}
|
||||||
local sys = {}
|
local sys = {}
|
||||||
local nextpid = 2
|
local nextpid = 2
|
||||||
kernel.exitMain=false
|
kernel.exitMain = false
|
||||||
|
|
||||||
function sys.spawn(func, name, envars, args, tgid)
|
function sys.spawn(func, name, envars, args, tgid)
|
||||||
local id = nextpid
|
local id = nextpid
|
||||||
nextpid = nextpid + 1
|
nextpid = nextpid + 1
|
||||||
|
|
||||||
tasks[tostring(id)] = {
|
tasks[tostring(id)] = {
|
||||||
coro=coroutine.create(function()
|
coro = coroutine.create(function()
|
||||||
local ok, err = xpcall(func, debug.traceback, table.unpack(args or {}))
|
local ok, err = xpcall(func, debug.traceback,
|
||||||
|
table.unpack(args or {}))
|
||||||
if not ok then
|
if not ok then
|
||||||
if kernel.config.logTaskExit 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
|
end
|
||||||
tasks[tostring(id)].status="Z"
|
tasks[tostring(id)].status = "Z"
|
||||||
if type(err)=="number" then
|
if type(err) == "number" then
|
||||||
tasks[tostring(id)].exit=err
|
tasks[tostring(id)].exit = err
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if kernel.config.logTaskExit then
|
if kernel.config.logTaskExit then
|
||||||
if err 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
|
else
|
||||||
kernel.log("Task "..tostring(id).." exited without code", "INFO")
|
kernel.log("Task " .. tostring(id) ..
|
||||||
|
" exited without code", "INFO")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
tasks[tostring(id)].status="Z"
|
tasks[tostring(id)].status = "Z"
|
||||||
if type(err)=="number" then
|
if type(err) == "number" then
|
||||||
tasks[tostring(id)].exit=err
|
tasks[tostring(id)].exit = err
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end),
|
end),
|
||||||
name=name or ("task"..tostring(id)),
|
name = name or ("task" .. tostring(id)),
|
||||||
envars=envars or kernel.currentTask.envars,
|
envars = envars or kernel.currentTask.envars,
|
||||||
args=args or {},
|
args = args or {},
|
||||||
status="R",
|
status = "R",
|
||||||
pid=id,
|
pid = id,
|
||||||
tgid=tgid or kernel.currentTask.tgid,
|
tgid = tgid or kernel.currentTask.tgid,
|
||||||
username=kernel.username,
|
username = kernel.username,
|
||||||
uid=kernel.uid,
|
uid = kernel.uid,
|
||||||
fd={},
|
fd = {
|
||||||
exit="",
|
[0]=kernel.currentTask.fd[0],
|
||||||
sleep=0,
|
[1]=kernel.currentTask.fd[1],
|
||||||
ivs=0,
|
[2]=kernel.currentTask.fd[2]
|
||||||
vs=0,
|
},
|
||||||
children={},
|
sleep = 0,
|
||||||
parent=kernel.currentTask,
|
ivs = 0,
|
||||||
siblings=kernel.currentTask.children,
|
vs = 0,
|
||||||
syscallReturn={},
|
children = {},
|
||||||
cwd=kernel.currentTask.cwd,
|
parent = kernel.currentTask,
|
||||||
term=kernel.currentTask.term,
|
siblings = kernel.currentTask.children,
|
||||||
timeSlice=0,
|
syscallReturn = {},
|
||||||
lastTime=0,
|
cwd = kernel.currentTask.cwd,
|
||||||
totalTime=0,
|
timeSlice = 0,
|
||||||
numRuns=0,
|
lastTime = 0,
|
||||||
privacy=0,
|
totalTime = 0,
|
||||||
debugger=false,
|
numRuns = 0,
|
||||||
eventq=kernel.currentTask.eventq
|
privacy = 0,
|
||||||
|
debugger = false,
|
||||||
|
eventq = kernel.currentTask.eventq
|
||||||
}
|
}
|
||||||
|
|
||||||
table.insert(kernel.currentTask.children, tasks[tostring(id)])
|
table.insert(kernel.currentTask.children, tasks[tostring(id)])
|
||||||
return id
|
return id
|
||||||
end
|
end
|
||||||
|
|
||||||
function sys.sleep(s)
|
function sys.sleep(s)
|
||||||
kernel.currentTask.status="S"
|
kernel.currentTask.status = "S"
|
||||||
kernel.currentTask.sleep=kernel.computer:time()+s*1000
|
kernel.currentTask.sleep = kernel.computer:time() + s * 1000
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -75,164 +85,161 @@ function sys.getTask(pid)
|
|||||||
local task = tasks[tostring(pid)]
|
local task = tasks[tostring(pid)]
|
||||||
local children = {}
|
local children = {}
|
||||||
local siblings = {}
|
local siblings = {}
|
||||||
for i,v in ipairs(task.children) do
|
|
||||||
children[i]=v.pid
|
for i, v in ipairs(task.children) do children[i] = v.pid end
|
||||||
end
|
for i, v in ipairs(task.siblings) do siblings[i] = v.pid end
|
||||||
for i,v in ipairs(task.siblings) do
|
|
||||||
siblings[i]=v.pid
|
|
||||||
end
|
|
||||||
return {
|
return {
|
||||||
name=task.name,
|
name = task.name,
|
||||||
status=task.status,
|
status = task.status,
|
||||||
pid=task.pid,
|
pid = task.pid,
|
||||||
tgid=task.tgid,
|
tgid = task.tgid,
|
||||||
username=task.username,
|
username = task.username,
|
||||||
uid=task.uid,
|
uid = task.uid,
|
||||||
exit=task.exit,
|
exit = task.exit,
|
||||||
sleep=task.sleep,
|
sleep = task.sleep,
|
||||||
ivs=task.ivs,
|
ivs = task.ivs,
|
||||||
vs=task.vs,
|
vs = task.vs,
|
||||||
children=children,
|
children = children,
|
||||||
siblings=siblings,
|
siblings = siblings,
|
||||||
parent=task.parent.pid,
|
parent = task.parent.pid,
|
||||||
cwd=task.cwd,
|
cwd = task.cwd,
|
||||||
term=task.term
|
term = task.term
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function sys.collect(pid)
|
function sys.collect(pid)
|
||||||
local children={}
|
local children = {}
|
||||||
for i,v in ipairs(kernel.currentTask.children) do
|
for i, v in ipairs(kernel.currentTask.children) do children[i] = v.pid end
|
||||||
children[i]=v.pid
|
|
||||||
end
|
|
||||||
if not tasks[tostring(pid)] then
|
if not tasks[tostring(pid)] then
|
||||||
return false, "Task does not exist"
|
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"
|
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"
|
return false, "Task must exit to collect status"
|
||||||
|
|
||||||
else
|
else
|
||||||
tasks[tostring(pid)].reapTime=0
|
tasks[tostring(pid)].reapTime = 0
|
||||||
return true, tasks[tostring(pid)].exit
|
return true, tasks[tostring(pid)].exit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function sys.kill(pid)
|
function sys.kill(pid)
|
||||||
local children={}
|
local children = {}
|
||||||
for i,v in ipairs(kernel.currentTask.children) do
|
for i, v in ipairs(kernel.currentTask.children) do children[i] = v.pid end
|
||||||
children[i]=v.pid
|
|
||||||
end
|
|
||||||
if not tasks[tostring(pid)] then
|
if not tasks[tostring(pid)] then
|
||||||
return false, "Task does not exist"
|
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"
|
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"
|
return false, "Task is already dead"
|
||||||
|
|
||||||
else
|
else
|
||||||
tasks[tostring(pid)].status="Z"
|
tasks[tostring(pid)].status = "Z"
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function sys.stop(pid)
|
function sys.stop(pid)
|
||||||
local children={}
|
local children = {}
|
||||||
for i,v in ipairs(kernel.currentTask.children) do
|
for i, v in ipairs(kernel.currentTask.children) do children[i] = v.pid end
|
||||||
children[i]=v.pid
|
|
||||||
end
|
|
||||||
if not tasks[tostring(pid)] then
|
if not tasks[tostring(pid)] then
|
||||||
return false, "Task does not exist"
|
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"
|
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"
|
return false, "Cannot stop non running task"
|
||||||
|
|
||||||
else
|
else
|
||||||
tasks[tostring(pid)].status="T"
|
tasks[tostring(pid)].status = "T"
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function sys.continue(pid)
|
function sys.continue(pid)
|
||||||
local children={}
|
local children = {}
|
||||||
for i,v in ipairs(kernel.currentTask.children) do
|
for i, v in ipairs(kernel.currentTask.children) do children[i] = v.pid end
|
||||||
children[i]=v.pid
|
|
||||||
end
|
|
||||||
if not tasks[tostring(pid)] then
|
if not tasks[tostring(pid)] then
|
||||||
return false, "Task does not exist"
|
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"
|
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"
|
return false, "Task is not stopped"
|
||||||
|
|
||||||
else
|
else
|
||||||
tasks[tostring(pid)].status="R"
|
tasks[tostring(pid)].status = "R"
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function sys.getpid()
|
function sys.getpid() return kernel.currentTask.pid end
|
||||||
return kernel.currentTask.pid
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.getppid()
|
function sys.getppid() return kernel.currentTask.parent.pid end
|
||||||
return kernel.currentTask.parent.pid
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.getTasks()
|
function sys.getTasks()
|
||||||
local ret={}
|
local ret = {}
|
||||||
for i,v in pairs(tasks) do
|
for i, v in pairs(tasks) do ret[#ret + 1] = v.pid end
|
||||||
ret[#ret+1]=v.pid
|
|
||||||
end
|
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function sys.getEnviron(key)
|
function sys.getEnviron(key) return kernel.currentTask.envars[key] end
|
||||||
return kernel.currentTask.envars[key]
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.setEnviron(key, value)
|
function sys.setEnviron(key, value) kernel.currentTask.envars[key] = value end
|
||||||
kernel.currentTask.envars[key]=value
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.exit(code)
|
function sys.exit(code)
|
||||||
if kernel.config.logTaskExit then
|
if kernel.config.logTaskExit then
|
||||||
if code 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
|
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
|
||||||
end
|
end
|
||||||
tasks[tostring(kernel.currentTask.pid)].status="Z"
|
|
||||||
if type(code)=="number" then
|
tasks[tostring(kernel.currentTask.pid)].status = "Z"
|
||||||
tasks[tostring(kernel.currentTask.pid)].exit=code
|
if type(code) == "number" then
|
||||||
|
tasks[tostring(kernel.currentTask.pid)].exit = code
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function sys.setuid(uid)
|
function sys.setuid(uid)
|
||||||
if kernel.uid~=0 then error("EACCES") end
|
if kernel.uid ~= 0 then error("EACCES") end
|
||||||
kernel.currentTask.uid=uid
|
kernel.currentTask.uid = uid
|
||||||
end
|
end
|
||||||
|
|
||||||
function sys.getuid()
|
function sys.getuid() return kernel.currentTask.uid end
|
||||||
return kernel.currentTask.uid
|
|
||||||
end
|
|
||||||
|
|
||||||
local sysc=kernel.syscalls
|
local sysc = kernel.syscalls
|
||||||
sysc["spawn"]=sys.spawn
|
sysc["spawn"] = sys.spawn
|
||||||
sysc["sleep"]=sys.sleep
|
sysc["sleep"] = sys.sleep
|
||||||
sysc["getTask"]=sys.getTask
|
sysc["getTask"] = sys.getTask
|
||||||
sysc["collect"]=sys.collect
|
sysc["collect"] = sys.collect
|
||||||
sysc["kill"]=sys.kill
|
sysc["kill"] = sys.kill
|
||||||
sysc["stop"]=sys.stop
|
sysc["stop"] = sys.stop
|
||||||
sysc["continue"]=sys.continue
|
sysc["continue"] = sys.continue
|
||||||
sysc["getpid"]=sys.getpid
|
sysc["getpid"] = sys.getpid
|
||||||
sysc["getppid"]=sys.getppid
|
sysc["getppid"] = sys.getppid
|
||||||
sysc["getTasks"]=sys.getTasks
|
sysc["getTasks"] = sys.getTasks
|
||||||
sysc["setEnviron"]=sys.setEnviron
|
sysc["setEnviron"] = sys.setEnviron
|
||||||
sysc["getEnviron"]=sys.getEnviron
|
sysc["getEnviron"] = sys.getEnviron
|
||||||
sysc["exit"]=sys.exit
|
sysc["exit"] = sys.exit
|
||||||
sysc["setuid"]=sys.setuid
|
sysc["setuid"] = sys.setuid
|
||||||
sysc["getuid"]=sys.getuid
|
sysc["getuid"] = sys.getuid
|
||||||
kernel._G.sleep=function(...)coroutine.yield("syscall","sleep",...)end
|
kernel._G.sleep = function(...) coroutine.yield("syscall", "sleep", ...) end
|
||||||
|
|
||||||
local function reapDeadTasks()
|
local function reapDeadTasks()
|
||||||
for pid, task in pairs(tasks) do
|
for pid, task in pairs(tasks) do
|
||||||
@@ -243,32 +250,33 @@ local function reapDeadTasks()
|
|||||||
task.args = nil
|
task.args = nil
|
||||||
task.envars = nil
|
task.envars = nil
|
||||||
task.cwd = nil
|
task.cwd = nil
|
||||||
task.term = nil
|
|
||||||
task.numRuns = nil
|
task.numRuns = nil
|
||||||
task.totalTime = nil
|
task.totalTime = nil
|
||||||
task.lastTime = nil
|
task.lastTime = nil
|
||||||
task.timeSlice = nil
|
task.timeSlice = nil
|
||||||
task.syscallReturn = nil
|
task.syscallReturn = nil
|
||||||
task.sleep = nil
|
task.sleep = nil
|
||||||
for v,_ in ipairs(task.fd) do
|
for v, _ in ipairs(task.fd) do kernel.vfs.close(v) end
|
||||||
kernel.vfs.close(v)
|
|
||||||
end
|
|
||||||
task.fd = nil
|
task.fd = nil
|
||||||
task.debugger=nil
|
task.debugger = nil
|
||||||
task.privacy=nil
|
task.privacy = nil
|
||||||
task.reapTime = kernel.computer:time() + 30000
|
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.parent = tasks["1"]
|
||||||
child.siblings = tasks["1"].children
|
child.siblings = tasks["1"].children
|
||||||
table.insert(tasks["1"].children, child)
|
table.insert(tasks["1"].children, child)
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, sibling in ipairs(task.siblings) do
|
for i, sibling in ipairs(task.siblings) do
|
||||||
if sibling.pid == task.pid then
|
if sibling.pid == task.pid then
|
||||||
table.remove(task.siblings, i)
|
table.remove(task.siblings, i)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
tasks[pid] = nil
|
tasks[pid] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -296,8 +304,8 @@ function kernel.main()
|
|||||||
for pid, task in pairs(tasks) do
|
for pid, task in pairs(tasks) do
|
||||||
if task.status == "S" then
|
if task.status == "S" then
|
||||||
if kernel.computer:time() >= task.sleep then
|
if kernel.computer:time() >= task.sleep then
|
||||||
task.status="R"
|
task.status = "R"
|
||||||
task.sleep=0
|
task.sleep = 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if task.status == "R" then
|
if task.status == "R" then
|
||||||
@@ -314,9 +322,20 @@ function kernel.main()
|
|||||||
local startTime = kernel.computer:time()
|
local startTime = kernel.computer:time()
|
||||||
local ret
|
local ret
|
||||||
if kernel.config.preempt then
|
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
|
else
|
||||||
ret = {coroutine.resume(task.coro, table.unpack(task.syscallReturn))}
|
ret = {
|
||||||
|
coroutine.resume(
|
||||||
|
task.coro,
|
||||||
|
table.unpack(task.syscallReturn)
|
||||||
|
)
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local elapsed = kernel.computer:time() - startTime
|
local elapsed = kernel.computer:time() - startTime
|
||||||
@@ -331,45 +350,70 @@ function kernel.main()
|
|||||||
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
|
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
|
||||||
|
|
||||||
-- handle task results
|
-- handle task results
|
||||||
if ret[1] == "error" or ret[1]==false then
|
if ret[1] == "error" or ret[1] == false then
|
||||||
kernel.log("processHandlerException: "..ret[2], "ERROR", 2)
|
kernel.log("processHandlerException: " .. ret[2], "ERROR", 2)
|
||||||
task.status = "Z"
|
task.status = "Z"
|
||||||
task.exit = "processHandlerException: "..ret[2]
|
task.exit = "processHandlerException: " .. ret[2]
|
||||||
|
|
||||||
elseif ret[1] == "timeout" then
|
elseif ret[1] == "timeout" then
|
||||||
task.ivs=task.ivs+1
|
task.ivs = task.ivs + 1
|
||||||
task.syscallReturn = {}
|
task.syscallReturn = {}
|
||||||
|
|
||||||
elseif ret[1] == "success" or ret[1] == true then
|
elseif ret[1] == "success" or ret[1] == true then
|
||||||
task.vs=task.vs+1
|
task.vs = task.vs + 1
|
||||||
if ret[2]=="syscall" then
|
|
||||||
|
if ret[2] == "syscall" then
|
||||||
if kernel.syscalls[ret[3]] then
|
if kernel.syscalls[ret[3]] then
|
||||||
if kernel.config.debugSyscalls then
|
if kernel.config.debugSyscalls then
|
||||||
kernel.log("Task "..task.pid.." invoking syscall: "..ret[3], "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)
|
for i = 4, #ret do
|
||||||
|
kernel.log(" inval[" .. tostring(i - 3) .. "] = " .. tostring(ret[i]), "DBUG", 5)
|
||||||
end
|
end
|
||||||
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 kernel.config.debugSyscalls then
|
||||||
if not sysret[1] 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
|
else
|
||||||
kernel.log("Task "..task.pid.." syscall "..ret[3].." completed returning "..tostring(#sysret-1).." values", "DBUG", 5)
|
kernel.log(
|
||||||
for i=2,#sysret do
|
"Task " .. task.pid .. " syscall " .. ret[3] .. " completed returning " .. tostring(#sysret - 1) .. " values", "DBUG", 5
|
||||||
if type(sysret[i])=="table" then
|
)
|
||||||
kernel.log(" retval["..tostring(i-1).."] = "..table.serialize(sysret[i]), "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
|
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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if not sysret[1] then
|
if not sysret[1] then
|
||||||
task.syscallReturn={false, sysret[2]}
|
task.syscallReturn = {false, sysret[2]}
|
||||||
|
|
||||||
else
|
else
|
||||||
task.syscallReturn={true, table.unpack(sysret,2)}
|
task.syscallReturn = {
|
||||||
|
true, table.unpack(sysret, 2)
|
||||||
|
}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
task.syscallReturn={false, "Unknown syscall: "..tostring(ret[3])}
|
task.syscallReturn = {
|
||||||
|
false, "Unknown syscall: " .. tostring(ret[3])
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -378,17 +422,18 @@ function kernel.main()
|
|||||||
|
|
||||||
local T_prev_avg = (N > 0) and (totalTaskTime / N) or 0
|
local T_prev_avg = (N > 0) and (totalTaskTime / N) or 0
|
||||||
local T_prev_var = 0
|
local T_prev_var = 0
|
||||||
|
|
||||||
for _, t in ipairs(taskTimes) do
|
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
|
end
|
||||||
if N > 0 then T_prev_var = T_prev_var / N end
|
if N > 0 then T_prev_var = T_prev_var / N end
|
||||||
|
|
||||||
if N > 0 then
|
if N > 0 then
|
||||||
local f_clamp = k_min*(Tmin_hit/N) - k_max*(Tmax_hit/N)
|
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)
|
local B_budget = (C_target * (N ^ (alpha - 1))) /
|
||||||
B = B + lambda_budget * (B_budget - B)
|
math.max(T_prev_avg, 1e-8)
|
||||||
+ lambda_clamp * f_clamp
|
B = B + lambda_budget * (B_budget - B) + lambda_clamp * f_clamp -
|
||||||
- lambda_var * T_prev_var
|
lambda_var * T_prev_var
|
||||||
end
|
end
|
||||||
|
|
||||||
-- clean up dead tasks
|
-- clean up dead tasks
|
||||||
@@ -396,5 +441,5 @@ function kernel.main()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
kernel.tasks=tasks
|
kernel.tasks = tasks
|
||||||
kernel.hpv=sys
|
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:--
|
-- :Minify:--
|
||||||
local kernel=...
|
local kernel = ...
|
||||||
function print(...)
|
function print(...)
|
||||||
local args={...}
|
local args = {...}
|
||||||
local output=""
|
local output = ""
|
||||||
for i=1,#args do
|
for i = 1, #args do output = output .. tostring(args[i]) .. "\t" end
|
||||||
output=output..tostring(args[i]).."\t"
|
output = output:sub(1, -2)
|
||||||
end
|
|
||||||
output=output:sub(1,-2)
|
|
||||||
syscall.TTY_print(output)
|
syscall.TTY_print(output)
|
||||||
end
|
end
|
||||||
|
|
||||||
function printf(fmt, ...)
|
function printf(fmt, ...)
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
local output=string.format(fmt,...)
|
local output = string.format(fmt, ...)
|
||||||
syscall.TTY_print(output)
|
syscall.TTY_print(output)
|
||||||
end
|
end
|
||||||
|
|
||||||
function printInline(...)
|
function printInline(...)
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
local args={...}
|
local args = {...}
|
||||||
local output=""
|
local output = ""
|
||||||
for i=1,#args do
|
for i = 1, #args do output = output .. tostring(args[i]) .. "\t" end
|
||||||
output=output..tostring(args[i]).."\t"
|
output = output:sub(1, -2)
|
||||||
end
|
|
||||||
output=output:sub(1,-2)
|
|
||||||
syscall.TTY_printInline(output)
|
syscall.TTY_printInline(output)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,48 +1,48 @@
|
|||||||
--:Minify:--
|
-- :Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
kernel.log("Loading init system...")
|
kernel.log("Loading init system...")
|
||||||
kernel.log("InitPath: "..kernel.config.initPath)
|
kernel.log("InitPath: " .. kernel.config.initPath)
|
||||||
|
|
||||||
local handle = kernel.vfs.open(kernel.config.initPath, "r")
|
local handle = kernel.vfs.open(kernel.config.initPath, "r")
|
||||||
local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
||||||
kernel.vfs.close(handle)
|
kernel.vfs.close(handle)
|
||||||
|
|
||||||
local initFunc, err = load(data, "@sysinit", "t", kernel._U)
|
local initFunc, err = load(data, "@sysinit", "t", kernel._U)
|
||||||
if not initFunc then
|
if not initFunc then error("Failed to load init system: " .. err) end
|
||||||
error("Failed to load init system: "..err)
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.tasks["1"] = {
|
kernel.tasks["1"] = {
|
||||||
coro=coroutine.create(function()
|
coro = coroutine.create(function()
|
||||||
local ok, err = xpcall(initFunc, debug.traceback, kernel)
|
local ok, err = xpcall(initFunc, debug.traceback, kernel)
|
||||||
if not ok then
|
if not ok then
|
||||||
kernel.panic("Init system crashed: "..tostring(err))
|
kernel.panic("Init system crashed: " .. tostring(err))
|
||||||
else
|
else
|
||||||
kernel.panic("Init system exited: "..tostring(err))
|
kernel.panic("Init system exited: " .. tostring(err))
|
||||||
end
|
end
|
||||||
end),
|
end),
|
||||||
name="sysinit",
|
|
||||||
status="R",
|
name = "sysinit",
|
||||||
pid=1,
|
status = "R",
|
||||||
tgid=1,
|
pid = 1,
|
||||||
username="root",
|
tgid = 1,
|
||||||
uid=0,
|
username = "root",
|
||||||
fd={},
|
uid = 0,
|
||||||
envars={},
|
fd = {},
|
||||||
args={},
|
envars = {},
|
||||||
exit="",
|
args = {},
|
||||||
sleep=0,
|
exit = "",
|
||||||
ivs=0,
|
sleep = 0,
|
||||||
vs=0,
|
ivs = 0,
|
||||||
parent=kernel.kernelTask,
|
vs = 0,
|
||||||
siblings=kernel.kernelTask.children,
|
parent = kernel.kernelTask,
|
||||||
children={},
|
siblings = kernel.kernelTask.children,
|
||||||
syscallReturn={},
|
children = {},
|
||||||
cwd="/",
|
syscallReturn = {},
|
||||||
timeSlice=0,
|
cwd = "/",
|
||||||
lastTime=0,
|
timeSlice = 0,
|
||||||
totalTime=0,
|
lastTime = 0,
|
||||||
numRuns=0
|
totalTime = 0,
|
||||||
|
numRuns = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
kernel.log("created init task with PID 1")
|
kernel.log("created init task with PID 1")
|
||||||
kernel.log("Initializing init system...")
|
kernel.log("Initializing init system...")
|
||||||
|
|||||||
Reference in New Issue
Block a user