forked from Hyperion/HyperionOS
moved stuff to src/ from test/ and made better build scripts
This commit is contained in:
1 parent
0d46054e56
commit
e203f9f36d
84 files changed
+2095
-3618
No files matched your search
Vendored
+86
-43
@@ -1,46 +1,89 @@
|
|||||||
{
|
{
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Build (Minfiyed)",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "powershell",
|
||||||
|
"args": [
|
||||||
|
"-NoProfile",
|
||||||
|
"-ExecutionPolicy",
|
||||||
|
"Bypass",
|
||||||
|
"-File",
|
||||||
|
"${workspaceFolder}\\tools\\buildMini.ps1"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build (Source)",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "powershell",
|
||||||
|
"args": [
|
||||||
|
"-NoProfile",
|
||||||
|
"-ExecutionPolicy",
|
||||||
|
"Bypass",
|
||||||
|
"-File",
|
||||||
|
"${workspaceFolder}\\tools\\build.ps1"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "shared"
|
||||||
|
},
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "Build",
|
"label": "Test (Minfiyed)",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
|
"command": "powershell",
|
||||||
"windows": {
|
"args": [
|
||||||
"command": "powershell",
|
"-NoProfile",
|
||||||
"args": [
|
"-ExecutionPolicy",
|
||||||
"-NoProfile",
|
"Bypass",
|
||||||
"-ExecutionPolicy",
|
"-File",
|
||||||
"Bypass",
|
"${workspaceFolder}\\tools\\buildMiniTest.ps1"
|
||||||
"-Command",
|
],
|
||||||
"if (Test-Path '${workspaceFolder}\\Build') { Remove-Item -LiteralPath '${workspaceFolder}\\Build' -Recurse -Force -ErrorAction SilentlyContinue }; New-Item -ItemType Directory -Path '${workspaceFolder}\\Build' | Out-Null; Get-ChildItem -Path '${workspaceFolder}\\Test' -Directory | ForEach-Object { $base = $_.FullName; Get-ChildItem -Path $base -File -Recurse | ForEach-Object { $rel = $_.FullName.Substring($base.Length).TrimStart(\"\\\"); $destPath = Join-Path '${workspaceFolder}\\Build' $rel; $destDir = Split-Path $destPath; if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Path $destDir | Out-Null }; Copy-Item -LiteralPath $_.FullName -Destination $destPath -Force } }"
|
"group": {
|
||||||
]
|
"kind": "test",
|
||||||
},
|
"isDefault": true
|
||||||
|
},
|
||||||
"linux": {
|
"presentation": {
|
||||||
"command": "bash",
|
"reveal": "always",
|
||||||
"args": [
|
"panel": "shared"
|
||||||
"-c",
|
},
|
||||||
"[ -d \"${workspaceFolder}/Build\" ] && rm -rf \"${workspaceFolder}/Build\"; mkdir -p \"${workspaceFolder}/Build\"; for d in \"${workspaceFolder}/Test\"/*; do if [ -d \"$d\" ]; then find \"$d\" -type f | while read f; do rel=\"${f#$d/}\"; mkdir -p \"${workspaceFolder}/Build/$(dirname \"$rel\")\"; cp \"$f\" \"${workspaceFolder}/Build/$rel\"; done; fi; done"
|
"problemMatcher": []
|
||||||
]
|
},
|
||||||
},
|
{
|
||||||
|
"label": "Test (Source)",
|
||||||
"osx": {
|
"type": "shell",
|
||||||
"command": "bash",
|
"command": "powershell",
|
||||||
"args": [
|
"args": [
|
||||||
"-c",
|
"-NoProfile",
|
||||||
"[ -d \"${workspaceFolder}/Build\" ] && rm -rf \"${workspaceFolder}/Build\"; mkdir -p \"${workspaceFolder}/Build\"; for d in \"${workspaceFolder}/Test\"/*; do if [ -d \"$d\" ]; then find \"$d\" -type f | while read f; do rel=\"${f#$d/}\"; mkdir -p \"${workspaceFolder}/Build/$(dirname \"$rel\")\"; cp \"$f\" \"${workspaceFolder}/Build/$rel\"; done; fi; done"
|
"-ExecutionPolicy",
|
||||||
]
|
"Bypass",
|
||||||
},
|
"-File",
|
||||||
|
"${workspaceFolder}\\tools\\buildTest.ps1"
|
||||||
"presentation": {
|
],
|
||||||
"reveal": "always",
|
"group": {
|
||||||
"panel": "shared"
|
"kind": "test",
|
||||||
},
|
"isDefault": true
|
||||||
"problemMatcher": [],
|
},
|
||||||
"group": {
|
"presentation": {
|
||||||
"kind": "build",
|
"reveal": "always",
|
||||||
"isDefault": true
|
"panel": "shared"
|
||||||
}
|
},
|
||||||
}
|
"problemMatcher": []
|
||||||
]
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
local args={...}
|
||||||
|
<<<<<<< HEAD
|
||||||
|
local sys = require("sys")
|
||||||
|
=======
|
||||||
|
local os=require("os")
|
||||||
|
local io=require("io")
|
||||||
|
local text=""
|
||||||
|
local blockKeyEvents=false
|
||||||
|
io.link(io.focas)
|
||||||
|
|
||||||
|
os.hookSignal("keyTyped", function(_, screen, key)
|
||||||
|
if blockKeyEvents then return end
|
||||||
|
if key == "\n" then
|
||||||
|
blockKeyEvents=true
|
||||||
|
elseif key == "\b" then
|
||||||
|
text=text:sub(1,#text-1)
|
||||||
|
io.stdout.printInline("\b")
|
||||||
|
else
|
||||||
|
text=text..key
|
||||||
|
io.stdout.printInline(key)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
>>>>>>> 9b268810a7ea44e586d5faf6e2717f1d02497c03
|
||||||
+1
-77
@@ -1,77 +1 @@
|
|||||||
local fs = {}
|
local a={}local b={}local c={}local function d(e)local f="/"for g,h in pairs(c)do if e:sub(1,#g)==g then if not f or#g>#f then f=g end end end;local i=e:sub(#f+1)return b[c[f]],i end;function a.update(j)b={}for k,l in j.list()do b[k]=l end end;function a.exists(e)local h,i=d(e)return h:directoryExists(i)or h:fileExists(i)end;function a.isFile(e)local h,i=d(e)return h:fileExists(i)end;function a.isDir(e)local h,i=d(e)return h:directoryExists(i)end;function a.list(e)local h,i=d(e)return h:list(i)end;function a.makeDir(e)local h,i=d(e)return h:makeDirectory(i)end;function a.remove(e)local h,i=d(e)return h:remove(i)end;function a.readAllText(e)local h,i=d(e)local m=h:open(i,"r")if not m then return nil end;local n=m.readAll()m.close()return n end;function a.writeAllText(e,o)local h,i=d(e)local m=h:open(i,"w")m.write(o)m.close()end;function a.appendAllText(e,o)local h,i=d(e)local m=h:open(i,"a")m.write(o)m.close()end;function a.load(e)return load(a.readAllText(e),e)end;function a.mount(h,f)if not b[h]then return end;c[f]=h end;return a
|
||||||
local disks = {}
|
|
||||||
local mounts = {}
|
|
||||||
|
|
||||||
local function resolve(path)
|
|
||||||
local mountPoint = "/"
|
|
||||||
for mount, disk in pairs(mounts) do
|
|
||||||
if path:sub(1, #mount) == mount then
|
|
||||||
if not mountPoint or #mount > #mountPoint then
|
|
||||||
mountPoint = mount
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local newPath = path:sub(#mountPoint + 1)
|
|
||||||
return disks[mounts[mountPoint]], newPath
|
|
||||||
end
|
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
function fs.update(initdisks)
|
|
||||||
disks = {}
|
|
||||||
for k, v in initdisks.list() do
|
|
||||||
disks[k] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function fs.exists(path)
|
|
||||||
local disk, newPath = resolve(path)
|
|
||||||
return disk:directoryExists(newPath) or disk:fileExists(newPath)
|
|
||||||
end
|
|
||||||
function fs.isFile(path)
|
|
||||||
local disk, newPath = resolve(path)
|
|
||||||
return disk:fileExists(newPath)
|
|
||||||
end
|
|
||||||
function fs.isDir(path)
|
|
||||||
local disk, newPath = resolve(path)
|
|
||||||
return disk:directoryExists(newPath)
|
|
||||||
end
|
|
||||||
function fs.list(path)
|
|
||||||
local disk, newPath = resolve(path)
|
|
||||||
return disk:list(newPath)
|
|
||||||
end
|
|
||||||
function fs.makeDir(path)
|
|
||||||
local disk, newPath = resolve(path)
|
|
||||||
return disk:makeDirectory(newPath)
|
|
||||||
end
|
|
||||||
function fs.remove(path)
|
|
||||||
local disk, newPath = resolve(path)
|
|
||||||
return disk:remove(newPath)
|
|
||||||
end
|
|
||||||
function fs.readAllText(path)
|
|
||||||
local disk, newPath = resolve(path)
|
|
||||||
local handle = disk:open(newPath, "r")
|
|
||||||
if not handle then return nil end
|
|
||||||
local content = handle.readAll()
|
|
||||||
handle.close()
|
|
||||||
return content
|
|
||||||
end
|
|
||||||
function fs.writeAllText(path, text)
|
|
||||||
local disk, newPath = resolve(path)
|
|
||||||
local handle = disk:open(newPath, "w")
|
|
||||||
handle.write(text)
|
|
||||||
handle.close()
|
|
||||||
end
|
|
||||||
function fs.appendAllText(path, text)
|
|
||||||
local disk, newPath = resolve(path)
|
|
||||||
local handle = disk:open(newPath, "a")
|
|
||||||
handle.write(text)
|
|
||||||
handle.close()
|
|
||||||
end
|
|
||||||
function fs.load(path)
|
|
||||||
return load(fs.readAllText(path), path)
|
|
||||||
end
|
|
||||||
function fs.mount(disk, mountPoint)
|
|
||||||
if not disks[disk] then return end
|
|
||||||
mounts[mountPoint] = disk
|
|
||||||
end
|
|
||||||
return fs
|
|
||||||
+1
-250
@@ -1,250 +1 @@
|
|||||||
local args = {...}
|
local a={...}local b=a[1]local c=a[2]local d=a[3]local e=a[5]local f=a[6]local g=a[7]local h=""local i={}i.process="Kernel"i.user="root"i.group="root"i.groups={0}i.uid=0;i.gid=0;i.status="start"i.key={}i.cache={}i.cache.preload={}i._G=_G;i.sleep=sleep;i.debug=true;_G.sleep=nil;local j=false;function i.log(k,l)h=h..tostring(f:time()).." "..i.user.." "..i.process.."["..tostring(l or"INFO").."]: "..k.."\n"if i.status=="start"then e:print(tostring(f:time()).." "..i.user.." "..i.process.."["..tostring(l or"INFO").."]: "..k)elseif i.status=="init"then i.standbyTask=i.currentTask;i.currentTask=i.kernelTask;i.tty.print(tostring(f:time()).." "..i.user.." "..i.process.."["..tostring(l or"INFO").."]: "..k)i.currentTask=i.standbyTask end end;function i.PANIC(k)if i.status~="Panic"then i.log("PANIC: "..k,"PANIC")pcall(i["saveLog"])i.status="Panic"i.reason=k;e:setTextColor(2)e:setBackgroundColor(0)e:clear()e:setCursorPos(1,1)e:print(h)e:print("KERNEL PANIC!\n"..k.."\nSystem halted.")e:print("Press any key to continue...")end;while true do local m={f:getMachineEvent()}if m[1]=="keyPressed"then break end end;f:reboot()end;i.panic=i.PANIC;if j then e:setTextColor(1)e:setBackgroundColor(4)e:clear()local n,o=e:getSize()e:setCursorPos(3,5)e:print(":(")e:setCursorPos(3,7)e:print("Your PC ran into a problem and needs to restart. We're just collecting some error")e:setCursorPos(3,8)e:print("info, and then we'll restart for you.\n")e:setCursorPos(3,o-5)e:print("Stop code: average windows experience")e:setCursorPos(1,o)e:print("Press any key to continue... jk reboot it yourself lazy")while true do end end;i.log("Kernel loaded.")i.log("Mounting init disks...")c.refresh()g.update(c)i.disks={}for p,q in c.list()do i.disks[q.address]=q end;g.mount("$","/")local r=g.readAllText("/boot/fstab")local s=function(t,u,v)assert(#u==1,"only delim len 1 supported for now")v=(v or 0)-1;local w={}local x=""for y=1,#t do local z=string.sub(t,y,y)if#w~=v and z==u then table.insert(w,x)x=""else x=x..z end end;table.insert(w,x)return w end;if not g.isFile("/boot/boot.cfg")then i.log("boot.cfg missing or corrupted!, Attempting to write recovery boot.cfg","ERROR")g.writeAllText("/boot/boot.cfg",g.readAllText("/boot/safeboot.cfg"))end;local A,B=load(g.readAllText("/boot/boot.cfg"),"@boot.cfg")if not A then i.PANIC("Failed to load /boot/boot.cfg: "..tostring(B))end;local C,D=pcall(A)if not C then i.PANIC("Error in /boot/boot.cfg: "..tostring(D))end;i.config=D;for y,q in ipairs(s(r,"\n"))do if q:sub(1,1)=="U"then local E=""for y=3,#q do if q:sub(y,y)==";"then if y==3 then i.log("Invalid fstab line... Skipping.","WARN")goto F end;E=q:sub(3,y-1)end end;local G=q:sub(#E+4)g.mount(E,G)::F::end end;i.log("Disks initialized")function i.saveLog()g.writeAllText("/var/log/syslog.log",h)end;g.remove("/tmp")g.makeDir("/tmp")function i.newFifo()local H={}H.push=function(I)table.insert(I)end;H.pop=function()return table.remove(H,1)end;return H end;function i.newUUID()local J="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"local K=""for y=1,#J do local z=J:sub(y,y)if z=="x"then K=K..string.format("%x",math.random(0,15))elseif z=="y"then K=K..string.format("%x",math.random(8,11))else K=K..z end end;return K end;i.syscalls={}local L={[0]={}}for y=0,100 do L[y]={}end;i.log("Gathering modules")for p,y in ipairs(g.list("/lib/modules"))do for p,q in ipairs(g.list("/lib/modules/"..y))do local M=tonumber(q:sub(1,2))L[M+1][#L[M+1]+1]="/lib/modules/"..y.."/"..q end end;i.ifs=g;i.apis=b;i.computer=f;i.arch=d;i.initdisks=c;i.screen=e;i.processes={}i.fstab=r;i.kernelTask={name="kernel",status="R",pid=0,tgid=0,user="root",uid=0,fd={},exit="",sleep=0,ivs=0,vs=0,children={},syscallReturn={},cwd="/",timeSlice=0,lastTime=0,totalTime=0,numRuns=0}i.currentTask=i.kernelTask;i.syscalls["OS_time"]=function()return i.computer:time()end;i.syscalls["OS_log"]=i.log;i.log("Running modules")for p,N in ipairs(L)do for p,q in ipairs(N)do local O=g.readAllText(q)if not O then i.log("ModuReadErr: "..q,"WARN")goto P end;local Q,B=load(O,"@"..q)if not Q then i.panic("ModuLoadErr: "..tostring(B))goto P end;local R,B=xpcall(Q,debug.traceback,i)if not R then i.panic("ModuRunErr: "..tostring(B))end::P::end end;i.log("Kernel initialized successfully.")i.status="running"i.main()i.PANIC("Execution complete")
|
||||||
local apis = args[1]
|
|
||||||
local disks = args[2]
|
|
||||||
local arch = args[3]
|
|
||||||
local screen = args[5]
|
|
||||||
local computer = args[6]
|
|
||||||
local ifs = args[7]
|
|
||||||
local LOG_Text = ""
|
|
||||||
local kernel = {}
|
|
||||||
kernel.process = "Kernel"
|
|
||||||
kernel.user = "root"
|
|
||||||
kernel.group = "root"
|
|
||||||
kernel.groups = {0}
|
|
||||||
kernel.uid = 0
|
|
||||||
kernel.gid = 0
|
|
||||||
kernel.status = "start"
|
|
||||||
kernel.key = {}
|
|
||||||
kernel.cache = {}
|
|
||||||
kernel.cache.preload = {}
|
|
||||||
kernel._G=_G
|
|
||||||
kernel.sleep=sleep
|
|
||||||
kernel.debug=true
|
|
||||||
|
|
||||||
_G.sleep=nil
|
|
||||||
local windowsExp = false
|
|
||||||
|
|
||||||
function kernel.log(msg, level)
|
|
||||||
LOG_Text = LOG_Text..tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
|
|
||||||
if kernel.status == "start" then
|
|
||||||
screen:print(tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
|
||||||
elseif kernel.status == "init" then
|
|
||||||
kernel.standbyTask=kernel.currentTask
|
|
||||||
kernel.currentTask=kernel.kernelTask
|
|
||||||
kernel.tty.print(tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
|
||||||
kernel.currentTask=kernel.standbyTask
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.PANIC(msg)
|
|
||||||
if kernel.status~="Panic" then
|
|
||||||
kernel.log("PANIC: "..msg, "PANIC")
|
|
||||||
pcall(kernel["saveLog"])
|
|
||||||
kernel.status="Panic"
|
|
||||||
kernel.reason=msg
|
|
||||||
screen:setTextColor(2)
|
|
||||||
screen:setBackgroundColor(0)
|
|
||||||
screen:clear()
|
|
||||||
screen:setCursorPos(1,1)
|
|
||||||
screen:print(LOG_Text)
|
|
||||||
screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.")
|
|
||||||
screen:print("Press any key to continue...")
|
|
||||||
end
|
|
||||||
while true do
|
|
||||||
local event={computer:getMachineEvent()}
|
|
||||||
if event[1]=="keyPressed" then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
computer:reboot()
|
|
||||||
end
|
|
||||||
kernel.panic=kernel.PANIC
|
|
||||||
|
|
||||||
if windowsExp then
|
|
||||||
screen:setTextColor(1)
|
|
||||||
screen:setBackgroundColor(4)
|
|
||||||
screen:clear()
|
|
||||||
local w,h = screen:getSize()
|
|
||||||
screen:setCursorPos(3,5)
|
|
||||||
screen:print(":(")
|
|
||||||
screen:setCursorPos(3,7)
|
|
||||||
screen:print("Your PC ran into a problem and needs to restart. We're just collecting some error")
|
|
||||||
screen:setCursorPos(3,8)
|
|
||||||
screen:print("info, and then we'll restart for you.\n")
|
|
||||||
screen:setCursorPos(3,h-5)
|
|
||||||
screen:print("Stop code: average windows experience")
|
|
||||||
screen:setCursorPos(1,h)
|
|
||||||
screen:print("Press any key to continue... jk reboot it yourself lazy")
|
|
||||||
while true do end
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.log("Kernel loaded.")
|
|
||||||
kernel.log("Mounting init disks...")
|
|
||||||
disks.refresh()
|
|
||||||
ifs.update(disks)
|
|
||||||
kernel.disks={}
|
|
||||||
for _,v in disks.list() do
|
|
||||||
kernel.disks[v.address] = v
|
|
||||||
end
|
|
||||||
ifs.mount("$", "/")
|
|
||||||
|
|
||||||
local fstab=ifs.readAllText("/boot/fstab")
|
|
||||||
local split = function(str, delim, maxResultCountOrNil)
|
|
||||||
assert(#delim == 1, "only delim len 1 supported for now")
|
|
||||||
maxResultCountOrNil = (maxResultCountOrNil or 0)-1
|
|
||||||
local rv = {}
|
|
||||||
local buf = ""
|
|
||||||
for i = 1, #str do
|
|
||||||
local c = string.sub(str,i,i)
|
|
||||||
if #rv ~= maxResultCountOrNil and c == delim then
|
|
||||||
table.insert(rv, buf)
|
|
||||||
buf = ""
|
|
||||||
else
|
|
||||||
buf = buf..c
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table.insert(rv, buf)
|
|
||||||
return rv
|
|
||||||
end
|
|
||||||
|
|
||||||
if not ifs.isFile("/boot/boot.cfg") then
|
|
||||||
kernel.log("boot.cfg missing or corrupted!, Attempting to write recovery boot.cfg", "ERROR")
|
|
||||||
ifs.writeAllText("/boot/boot.cfg",[[
|
|
||||||
-- DO NOT EDIT THIS FILE IF YOU DO NOT KNOW WHAT YOU ARE DOING!
|
|
||||||
-- DOING SO MAY RENDER YOUR SYSTEM UNBOOTABLE!
|
|
||||||
|
|
||||||
-- This file is auto-generated during the build process.
|
|
||||||
-- RECOVERY BOOT CONFIGURATION FILE
|
|
||||||
return {
|
|
||||||
initPath = "/sbin/init.lua",
|
|
||||||
maxOpenFiles = 128,
|
|
||||||
maxFilesPerTask = 16,
|
|
||||||
preempt=true
|
|
||||||
}
|
|
||||||
]])
|
|
||||||
end
|
|
||||||
local initCfgFunc, err = load(ifs.readAllText("/boot/boot.cfg"), "@boot.cfg")
|
|
||||||
if not initCfgFunc then
|
|
||||||
kernel.PANIC("Failed to load /boot/boot.cfg: "..tostring(err))
|
|
||||||
end
|
|
||||||
|
|
||||||
local initCfgStatus, config = pcall(initCfgFunc)
|
|
||||||
if not initCfgStatus then
|
|
||||||
kernel.PANIC("Error in /boot/boot.cfg: "..tostring(config))
|
|
||||||
end
|
|
||||||
kernel.config = config
|
|
||||||
|
|
||||||
for i,v in ipairs(split(fstab,"\n")) do
|
|
||||||
if v:sub(1,1)=="U" then
|
|
||||||
local id=""
|
|
||||||
for i=3,#v do
|
|
||||||
if v:sub(i,i)==";" then
|
|
||||||
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN") goto endline end
|
|
||||||
id=v:sub(3,i-1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local path=v:sub(#id+4)
|
|
||||||
ifs.mount(id,path)
|
|
||||||
::endline::
|
|
||||||
end
|
|
||||||
end
|
|
||||||
kernel.log("Disks initialized")
|
|
||||||
|
|
||||||
function kernel.saveLog()
|
|
||||||
ifs.writeAllText("/var/log/syslog.log", LOG_Text)
|
|
||||||
end
|
|
||||||
|
|
||||||
ifs.remove("/tmp")
|
|
||||||
ifs.makeDir("/tmp")
|
|
||||||
|
|
||||||
function kernel.newFifo()
|
|
||||||
local fifo = {}
|
|
||||||
fifo.push=function(data)
|
|
||||||
table.insert(data)
|
|
||||||
end
|
|
||||||
fifo.pop=function()
|
|
||||||
return table.remove(fifo,1)
|
|
||||||
end
|
|
||||||
return fifo
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.newUUID()
|
|
||||||
local template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
|
|
||||||
local uuid = ""
|
|
||||||
for i = 1, #template do
|
|
||||||
local c = template:sub(i,i)
|
|
||||||
if c == "x" then
|
|
||||||
uuid = uuid .. string.format("%x", math.random(0, 15))
|
|
||||||
elseif c == "y" then
|
|
||||||
uuid = uuid .. string.format("%x", math.random(8, 11))
|
|
||||||
else
|
|
||||||
uuid = uuid .. c
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return uuid
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.syscalls={}
|
|
||||||
local modules={[0]={}}
|
|
||||||
for i=0, 100 do
|
|
||||||
modules[i]={}
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.log("Gathering modules")
|
|
||||||
for _, i in ipairs(ifs.list("/lib/modules")) do
|
|
||||||
for _,v in ipairs(ifs.list("/lib/modules/"..i)) do
|
|
||||||
local prior=tonumber(v:sub(1,2))
|
|
||||||
modules[prior+1][#modules[prior+1]+1]="/lib/modules/"..i.."/"..v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.ifs=ifs
|
|
||||||
kernel.apis=apis
|
|
||||||
kernel.computer=computer
|
|
||||||
kernel.arch=arch
|
|
||||||
kernel.initdisks=disks
|
|
||||||
kernel.screen=screen
|
|
||||||
kernel.processes={}
|
|
||||||
kernel.fstab=fstab
|
|
||||||
|
|
||||||
kernel.kernelTask = {
|
|
||||||
name="kernel",
|
|
||||||
status="R",
|
|
||||||
pid=0,
|
|
||||||
tgid=0,
|
|
||||||
user="root",
|
|
||||||
uid=0,
|
|
||||||
fd={},
|
|
||||||
exit="",
|
|
||||||
sleep=0,
|
|
||||||
ivs=0,
|
|
||||||
vs=0,
|
|
||||||
children={},
|
|
||||||
syscallReturn={},
|
|
||||||
cwd="/",
|
|
||||||
timeSlice=0,
|
|
||||||
lastTime=0,
|
|
||||||
totalTime=0,
|
|
||||||
numRuns=0
|
|
||||||
}
|
|
||||||
kernel.currentTask = kernel.kernelTask
|
|
||||||
|
|
||||||
kernel.log("Running modules")
|
|
||||||
for _,p in ipairs(modules) do
|
|
||||||
for _,v in ipairs(p) do
|
|
||||||
local code=ifs.readAllText(v)
|
|
||||||
if not code then
|
|
||||||
kernel.log("ModuReadErr: "..v, "WARN")
|
|
||||||
goto skip
|
|
||||||
end
|
|
||||||
local func,err=load(code,"@"..v)
|
|
||||||
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) goto skip end
|
|
||||||
local status, err = xpcall(func,debug.traceback, kernel)
|
|
||||||
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
|
||||||
::skip::
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.log("Kernel initialized successfully.")
|
|
||||||
kernel.main()
|
|
||||||
kernel.PANIC("Execution complete")
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
-- DO NOT EDIT THIS FILE IF YOU DO NOT KNOW WHAT YOU ARE DOING!
|
||||||
|
-- DOING SO MAY RENDER YOUR SYSTEM UNBOOTABLE!
|
||||||
|
|
||||||
|
-- This file is auto-generated during the build process.
|
||||||
|
-- RECOVERY BOOT CONFIGURATION FILE
|
||||||
|
return {
|
||||||
|
initPath = "/sbin/init.lua",
|
||||||
|
maxOpenFiles = 128,
|
||||||
|
maxFilesPerTask = 16,
|
||||||
|
preempt=true
|
||||||
|
}
|
||||||
@@ -36,7 +36,7 @@ end
|
|||||||
|
|
||||||
local function wrapPeripheral(name)
|
local function wrapPeripheral(name)
|
||||||
if native.isPresent(name) then
|
if native.isPresent(name) then
|
||||||
return native.wrap(name)
|
return wrapPeripheral(name)
|
||||||
end
|
end
|
||||||
for n = 1, #sides do
|
for n = 1, #sides do
|
||||||
local side = sides[n]
|
local side = sides[n]
|
||||||
|
|||||||
@@ -1,284 +1 @@
|
|||||||
function string.hasSuffix(str, suffix)
|
function string.hasSuffix(a,b)return string.sub(a,#b+1)==b end;function string.hasPrefix(a,c)return string.sub(a,1,#c)==c end;function string.getSuffix(a,c)return string.sub(a,#c+1)end;function string.getPrefix(a,b)return string.sub(a,1,#b)end;function string.join(a,...)return table.concat(table.pack(a,...))end;function string.delim(a,...)return table.concat(table.pack(...),a)end;function string.split(a,d,e)assert(#d==1,"only delim len 1 supported for now")e=(e or 0)-1;local f={}local g=""for h=1,#a do local i=string.sub(a,h,h)if#f~=e and i==d then table.insert(f,g)g=""else g=g..i end end;table.insert(f,g)return f end;function string.replace(a,j,k)local f=""local l=1;local h=1;while h<#a do if string.sub(a,h,h+#j-1)==j then f=f..string.sub(a,l,h-1)..k;h=h+#j;l=h end;h=h+1 end;return f..string.sub(a,l)end;function table.deepcopy(m,n)n=n or{}if type(m)~='table'then return m elseif n[m]then return n[m]end;local o={}n[m]=o;for p,q in next,m,nil do local r=table.deepcopy(p,n)local s=table.deepcopy(q,n)o[r]=s end;return o end;function table.hasKey(t,u)for h,q in pairs(t)do if h==u then return true end end;return false end;function table.hasVal(t,u)for h,q in pairs(t)do if q==u then return true end end;return false end;function table.proxy(v)local w=setmetatable({},{__mode="k"})local function x(y)if type(y)~="table"then return y end;if w[y]then return w[y]end;local z={}w[y]=z;local A;A={__index=function(B,p)local C=y[p]if type(C)=="table"then return x(C)else return C end end,__newindex=function()error("Attempt to modify table proxy",2)end,__pairs=function()return function(B,p)local D,E=next(y,p)if type(E)=="table"then E=x(E)end;return D,E end,nil,nil end,__ipairs=function()local h=0;local F=#y;return function()h=h+1;if h<=F then local q=y[h]if type(q)=="table"then q=x(q)end;return h,q end end end,__metatable=false}setmetatable(z,A)return z end;return x(v)end;local function G(table)local H="{"for h,q in pairs(table)do local I=true;if type(h)=="string"then H=H.."[\""..h.."\"]="elseif type(h)=="number"then H=H.."["..tostring(h).."]="end;if type(q)=="table"then if q==table then H=string.sub(H,1,#H-(#h+1))I=false else H=H..G(q)end elseif type(q)=="string"then H=H.."[=["..q.."]=]"elseif type(q)=="number"then H=H..tostring(q)elseif type(q)=="boolean"then if q==true then H=H.."true"else H=H.."false"end elseif type(q)=="function"then H=H..tostring(q)else error("serialization of type \""..type(q).."\" is not supported")end;if I then H=H..","end end;if#table>0 or string.sub(H,#H,#H)==","then H=string.sub(H,1,#H-1)end;H=H.."}"return H end;local J=type;local K=getmetatable;function type(L,M)if M then return J(L)end;if J(L)~="table"then return J(L)else if J(K(L))=="table"then local N=K(L)if N.__type then return N.__type end else return"table"end end end;function getmetatable(L)if J(L)~="table"then return end;if J(K(L))=="table"then if K(L).__isuserdata then if J(K(L).__usermeta)=="function"then return K(L).__usermeta()else return K(L).__usermeta end else return K(L)end else return K(L)end end;function isEqualToAny(O,...)local P={...}for h=0,#P do if O==P[h]then return true end end;return false end;function isEqualToAll(O,...)local P={...}for h=0,#P do if O~=P[h]then return false end end;return true end;function table.keys(y)local O={}for F in pairs(y)do table.insert(O,F)end;return O end;function table.values(y)local O={}for B,F in pairs(y)do table.insert(O,F)end;return O end;function table.indexOf(y,C)for h,q in ipairs(y)do if q==C then return h end end;return-1 end;syscall=setmetatable({},{__index=function(self,Q)return function(...)local R=table.pack(coroutine.yield("syscall",Q,...))if R[1]then return table.unpack(R,2,R.n)else error(R[2],2)end end end})table.serialize=G
|
||||||
return string.sub(str, #suffix+1) == suffix
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.hasPrefix(str, prefix)
|
|
||||||
return string.sub(str, 1, #prefix) == prefix
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.getSuffix(str, prefix)
|
|
||||||
return string.sub(str, #prefix+1)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.getPrefix(str, suffix)
|
|
||||||
return string.sub(str, 1, #suffix)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.join(str, ...)
|
|
||||||
return table.concat(table.pack(str, ...))
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.delim(str, ...)
|
|
||||||
return table.concat(table.pack(...), str)
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.split(str, delim, maxResultCountOrNil)
|
|
||||||
assert(#delim == 1, "only delim len 1 supported for now")
|
|
||||||
maxResultCountOrNil = (maxResultCountOrNil or 0)-1
|
|
||||||
local rv = {}
|
|
||||||
local buf = ""
|
|
||||||
for i = 1, #str do
|
|
||||||
local c = string.sub(str,i,i)
|
|
||||||
if #rv ~= maxResultCountOrNil and c == delim then
|
|
||||||
table.insert(rv, buf)
|
|
||||||
buf = ""
|
|
||||||
else
|
|
||||||
buf = buf..c
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table.insert(rv, buf)
|
|
||||||
return rv
|
|
||||||
end
|
|
||||||
|
|
||||||
function string.replace(str, search, replacement)
|
|
||||||
local rv = ""
|
|
||||||
local consumedLen = 1
|
|
||||||
local i = 1
|
|
||||||
while i<#str do
|
|
||||||
if string.sub(str, i, i+#search-1) == search then
|
|
||||||
rv = rv .. string.sub(str, consumedLen, i-1) .. replacement
|
|
||||||
i=i+#search
|
|
||||||
consumedLen = i
|
|
||||||
end
|
|
||||||
i=i+1
|
|
||||||
end
|
|
||||||
return rv .. string.sub(str, consumedLen)
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.deepcopy(orig, copies)
|
|
||||||
copies = copies or {}
|
|
||||||
|
|
||||||
if type(orig) ~= 'table' then
|
|
||||||
return orig
|
|
||||||
elseif copies[orig] then
|
|
||||||
return copies[orig]
|
|
||||||
end
|
|
||||||
|
|
||||||
local copy = {}
|
|
||||||
copies[orig] = copy
|
|
||||||
|
|
||||||
for k, v in next, orig, nil do
|
|
||||||
local copied_key = table.deepcopy(k, copies)
|
|
||||||
local copied_val = table.deepcopy(v, copies)
|
|
||||||
copy[copied_key] = copied_val
|
|
||||||
end
|
|
||||||
|
|
||||||
return copy
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.hasKey(tabl, query)
|
|
||||||
for i,v in pairs(tabl) do
|
|
||||||
if i==query then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.hasVal(tabl, query)
|
|
||||||
for i,v in pairs(tabl) do
|
|
||||||
if v==query then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.proxy(tbl)
|
|
||||||
local proxies = setmetatable({}, {__mode = "k"}) -- Weak table to avoid cycles
|
|
||||||
|
|
||||||
local function createProxy(t)
|
|
||||||
if type(t) ~= "table" then return t end
|
|
||||||
if proxies[t] then return proxies[t] end -- reuse proxy for the same table (handle cycles)
|
|
||||||
|
|
||||||
local proxy = {}
|
|
||||||
proxies[t] = proxy
|
|
||||||
|
|
||||||
local mt
|
|
||||||
mt = {
|
|
||||||
__index = function(_, k)
|
|
||||||
local value = t[k]
|
|
||||||
if type(value) == "table" then
|
|
||||||
return createProxy(value) -- recursively proxy subtables
|
|
||||||
else
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
__newindex = function()
|
|
||||||
error("Attempt to modify table proxy", 2)
|
|
||||||
end,
|
|
||||||
__pairs = function()
|
|
||||||
return function(_, k)
|
|
||||||
local nextKey, nextValue = next(t, k)
|
|
||||||
if type(nextValue) == "table" then
|
|
||||||
nextValue = createProxy(nextValue)
|
|
||||||
end
|
|
||||||
return nextKey, nextValue
|
|
||||||
end, nil, nil
|
|
||||||
end,
|
|
||||||
__ipairs = function()
|
|
||||||
local i = 0
|
|
||||||
local n = #t
|
|
||||||
return function()
|
|
||||||
i = i + 1
|
|
||||||
if i <= n then
|
|
||||||
local v = t[i]
|
|
||||||
if type(v) == "table" then
|
|
||||||
v = createProxy(v)
|
|
||||||
end
|
|
||||||
return i, v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
__metatable = false
|
|
||||||
}
|
|
||||||
|
|
||||||
setmetatable(proxy, mt)
|
|
||||||
return proxy
|
|
||||||
end
|
|
||||||
|
|
||||||
return createProxy(tbl)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function serialize(table)
|
|
||||||
local output = "{"
|
|
||||||
for i,v in pairs(table) do
|
|
||||||
local coma=true
|
|
||||||
if type(i) == "string" then
|
|
||||||
output=output.."[\""..i.."\"]="
|
|
||||||
elseif type(i) == "number" then
|
|
||||||
output=output.."["..tostring(i).."]="
|
|
||||||
end
|
|
||||||
if type(v) == "table" then
|
|
||||||
if v == table then
|
|
||||||
output=string.sub(output,1,#output-(#i+1))
|
|
||||||
coma=false
|
|
||||||
else
|
|
||||||
output=output..serialize(v)
|
|
||||||
end
|
|
||||||
elseif type(v) == "string" then
|
|
||||||
output=output.."[=["..v.."]=]"
|
|
||||||
elseif type(v) == "number" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
elseif type(v) == "boolean" then
|
|
||||||
if v == true then
|
|
||||||
output=output.."true"
|
|
||||||
else
|
|
||||||
output=output.."false"
|
|
||||||
end
|
|
||||||
elseif type(v) == "function" then
|
|
||||||
output=output..tostring(v)
|
|
||||||
else
|
|
||||||
error("serialization of type \""..type(v).."\" is not supported")
|
|
||||||
end
|
|
||||||
if coma then
|
|
||||||
output=output..","
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #table>0 or string.sub(output,#output,#output) == "," then
|
|
||||||
output=string.sub(output,1,#output-1)
|
|
||||||
end
|
|
||||||
output=output.."}"
|
|
||||||
return output
|
|
||||||
end
|
|
||||||
|
|
||||||
local oldtype=type
|
|
||||||
local oldgetmetatable=getmetatable
|
|
||||||
function type(object, trueType)
|
|
||||||
if trueType then
|
|
||||||
return oldtype(object)
|
|
||||||
end
|
|
||||||
if oldtype(object)~="table" then
|
|
||||||
return oldtype(object)
|
|
||||||
else
|
|
||||||
if oldtype(oldgetmetatable(object))=="table" then
|
|
||||||
local metatable = oldgetmetatable(object)
|
|
||||||
if metatable.__type then return metatable.__type end
|
|
||||||
else
|
|
||||||
return "table"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function getmetatable(object)
|
|
||||||
if oldtype(object)~="table" then return end
|
|
||||||
if oldtype(oldgetmetatable(object))=="table" then
|
|
||||||
if oldgetmetatable(object).__isuserdata then
|
|
||||||
if oldtype(oldgetmetatable(object).__usermeta)=="function" then
|
|
||||||
return oldgetmetatable(object).__usermeta()
|
|
||||||
else
|
|
||||||
return oldgetmetatable(object).__usermeta
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return oldgetmetatable(object)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return oldgetmetatable(object)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function isEqualToAny(a, ...)
|
|
||||||
local args={...}
|
|
||||||
for i=0, #args do
|
|
||||||
if a==args[i] then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function isEqualToAll(a, ...)
|
|
||||||
local args={...}
|
|
||||||
for i=0, #args do
|
|
||||||
if a~=args[i] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.keys(t)
|
|
||||||
local a = {}
|
|
||||||
for n in pairs(t) do table.insert(a, n) end
|
|
||||||
return a
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.values(t)
|
|
||||||
local a = {}
|
|
||||||
for _, n in pairs(t) do table.insert(a, n) end
|
|
||||||
return a
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.indexOf(t, value)
|
|
||||||
for i,v in ipairs(t) do
|
|
||||||
if v==value then
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return -1
|
|
||||||
end
|
|
||||||
|
|
||||||
syscall = setmetatable({}, {
|
|
||||||
__index = function(self, name)
|
|
||||||
return function(...)
|
|
||||||
local res = table.pack(coroutine.yield("syscall", name, ...))
|
|
||||||
if res[1] then
|
|
||||||
return table.unpack(res, 2, res.n)
|
|
||||||
else
|
|
||||||
error(res[2], 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
table.serialize=serialize
|
|
||||||
@@ -1,277 +1 @@
|
|||||||
local kernel = ...
|
local a=...local b={}b.mounts={["$"]="/"}local c=a.disks;local function d(e)local f={}for g in e:gmatch("[^/]+")do if g==".."then if#f>0 then table.remove(f)end elseif g~="."and g~=""then table.insert(f,g)end end;return"/"..table.concat(f,"/")..(e:sub(-1)=="/"and"/"or"")end;local function h(e)local i=a.currentTask;local j=i.cwd or"/"if e:sub(1,1)~="/"then e=j..e end;e=d(e)local k="/"local l="$"for m,n in pairs(b.mounts)do if e:sub(1,#n)==n and#n>#k then k=n;l=m end end;local o=e:sub(#k+1)return c[l],o end;local function p(q,r,s,e)return{disk=q,handle=r,mode=s,path=e,refcount=1}end;local function t(i)local u=0;while i.fd[u]do u=u+1 end;return u end;local function t(i)local v=0;for w in pairs(i.fd)do v=v+1 end;if v>=a.config.maxFilesPerTask then error("EMFILE")end;local u=0;while i.fd[u]do u=u+1 end;return u end;local function x()local y=0;for w,i in pairs(a.tasks or{})do for w in pairs(i.fd)do y=y+1 end end;if y>=a.config.maxOpenFiles then error("ENFILE")end end;function b.open(e,s)local i=a.currentTask;x()local q,o=h(e)if not q then error("No disk mounted for path '"..e.."'")end;local r=q:open(o,s)if not r then return nil end;local z=p(q.address,r,s,e)local u=t(i)i.fd[u]=z;return u end;function b.close(u)local i=a.currentTask;local z=i.fd[u]if not z then error("EBADF")end;i.fd[u]=nil;z.refcount=z.refcount-1;if z.refcount==0 then z.handle.close()end;return true end;function b.read(u,v)local z=a.currentTask.fd[u]if not z then error("EBADF")end;if not z.mode:find("r")then error("File not open for reading")end;return z.handle.read(v)end;function b.write(u,A)local z=a.currentTask.fd[u]if not z then error("EBADF")end;if not z.mode:find("w")then error("File not open for writing")end;return z.handle.write(A)end;function b.whereis(u)local z=a.currentTask.fd[u]if not z then error("EBADF")end;return z.path end;function b.mkdir(e)local q,o=h(e)if not q then error("No disk mounted")end;return q:makeDirectory(o)end;function b.remove(e)local q,o=h(e)if not q then error("No disk mounted")end;return q:remove(o)end;function b.attributes(e)if type(e)=="number"then local z=a.currentTask.fd[e]if not z then error("EBADF")end;return c[z.disk]:attributes(z.path)end;local q,o=h(e)if not q then error("No disk mounted")end;return q:attributes(o)end;function b.list(e)local q,o=h(e)if not q then error("No disk mounted")end;return q:list(o)end;function b.exists(e)local q,o=h(e)if not q then return false end;return q:directoryExists(o)or q:fileExists(o)end;function b.type(e)if type(e)=="number"then local z=a.currentTask.fd[e]if not z then error("EBADF")end;return c[z.disk]:type(z.path)end;local q,o=h(e)if not q then error("No disk mounted")end;return q:type(o)end;function b.getcwd()return a.currentTask.cwd end;function b.setcwd(e)if e:sub(-1)~="/"then e=e.."/"end;if e:sub(1,1)~="/"then e="/"..e end;a.currentTask.cwd=d(e)end;function b.mount(B,e)if a.uid~=0 then error("Permission denied")end;if not c[B]then error("Unknown disk '"..B.."'")end;if e:sub(-1)~="/"then e=e.."/"end;for w,n in pairs(b.mounts)do if n==e then error("Mount point already used")end end;b.mounts[B]=e end;function b.unmount(e)if a.uid~=0 then error("Permission denied")end;for m,n in pairs(b.mounts)do if n==e then b.mounts[m]=nil;return true end end;return false end;function b.getMounts()return b.mounts end;function b.virtdisk(C)a.disks[C.address]=C;a.log("Registered virtual disk at "..C.address)end;function b.dup(D)local i=a.currentTask;local z=i.fd[D]if not z then error("EBADF")end;local E=t(i)i.fd[E]=z;z.refcount=z.refcount+1;return E end;function b.dup2(D,E)local i=a.currentTask;local z=i.fd[D]if not z then error("EBADF")end;if D==E then return E end;if i.fd[E]then b.close(E)end;i.fd[E]=z;z.refcount=z.refcount+1;return E end;a.vfs=b;a.syscalls["VFS_open"]=b.open;a.syscalls["VFS_read"]=b.read;a.syscalls["VFS_write"]=b.write;a.syscalls["VFS_close"]=b.close;a.syscalls["VFS_list"]=b.list;a.syscalls["VFS_type"]=b.type;a.syscalls["VFS_attributes"]=b.attributes;a.syscalls["VFS_mkdir"]=b.mkdir;a.syscalls["VFS_remove"]=b.remove;a.syscalls["VFS_exists"]=b.exists;a.syscalls["VFS_mount"]=b.mount;a.syscalls["VFS_unmount"]=b.unmount;a.syscalls["VFS_getcwd"]=b.getcwd;a.syscalls["VFS_setcwd"]=b.setcwd;a.syscalls["VFS_whereis"]=b.whereis;a.syscalls["VFS_dup"]=b.dup;a.syscalls["VFS_dup2"]=b.dup2;a.log("VFS module loaded")
|
||||||
local vfs = {}
|
|
||||||
vfs.mounts = { ["$"] = "/" }
|
|
||||||
local disks = kernel.disks
|
|
||||||
|
|
||||||
-- Path handling
|
|
||||||
local function normalizePath(path)
|
|
||||||
local parts = {}
|
|
||||||
for part in path:gmatch("[^/]+") do
|
|
||||||
if part == ".." then
|
|
||||||
if #parts > 0 then table.remove(parts) end
|
|
||||||
elseif part ~= "." and part ~= "" then
|
|
||||||
table.insert(parts, part)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return "/" .. table.concat(parts, "/") .. (path:sub(-1) == "/" and "/" or "")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function resolvePath(path)
|
|
||||||
local task = kernel.currentTask
|
|
||||||
local cwd = task.cwd or "/"
|
|
||||||
|
|
||||||
if path:sub(1,1) ~= "/" then
|
|
||||||
path = cwd .. path
|
|
||||||
end
|
|
||||||
|
|
||||||
path = normalizePath(path)
|
|
||||||
|
|
||||||
local mountPoint = "/"
|
|
||||||
local mountId = "$"
|
|
||||||
for k,v in pairs(vfs.mounts) do
|
|
||||||
if path:sub(1,#v) == v and #v > #mountPoint then
|
|
||||||
mountPoint = v
|
|
||||||
mountId = k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local diskPath = path:sub(#mountPoint + 1)
|
|
||||||
return disks[mountId], diskPath
|
|
||||||
end
|
|
||||||
|
|
||||||
-- File object creation
|
|
||||||
local function newFileObject(disk, handle, mode, path)
|
|
||||||
return {
|
|
||||||
disk = disk,
|
|
||||||
handle = handle,
|
|
||||||
mode = mode,
|
|
||||||
path = path,
|
|
||||||
refcount = 1
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function allocFD(task)
|
|
||||||
local fd = 0
|
|
||||||
while task.fd[fd] do fd = fd + 1 end
|
|
||||||
return fd
|
|
||||||
end
|
|
||||||
|
|
||||||
local function allocFD(task)
|
|
||||||
-- enforce per-task limit
|
|
||||||
local count = 0
|
|
||||||
for _ in pairs(task.fd) do count = count + 1 end
|
|
||||||
if count >= kernel.config.maxFilesPerTask then
|
|
||||||
error("EMFILE") -- Too many open files in this task
|
|
||||||
end
|
|
||||||
|
|
||||||
-- find first free FD
|
|
||||||
local fd = 0
|
|
||||||
while task.fd[fd] do fd = fd + 1 end
|
|
||||||
return fd
|
|
||||||
end
|
|
||||||
|
|
||||||
local function checkSystemLimit()
|
|
||||||
-- enforce system-wide limit
|
|
||||||
local total = 0
|
|
||||||
for _, task in pairs(kernel.tasks or {}) do
|
|
||||||
for _ in pairs(task.fd) do total = total + 1 end
|
|
||||||
end
|
|
||||||
if total >= kernel.config.maxOpenFiles then
|
|
||||||
error("ENFILE") -- Too many open files in the system
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- VFS syscalls
|
|
||||||
function vfs.open(path, mode)
|
|
||||||
local task = kernel.currentTask
|
|
||||||
|
|
||||||
-- check limits
|
|
||||||
checkSystemLimit()
|
|
||||||
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then
|
|
||||||
error("No disk mounted for path '"..path.."'")
|
|
||||||
end
|
|
||||||
|
|
||||||
local handle = disk:open(diskPath, mode)
|
|
||||||
if not handle then return nil end
|
|
||||||
|
|
||||||
local file = newFileObject(disk.address, handle, mode, path)
|
|
||||||
local fd = allocFD(task)
|
|
||||||
task.fd[fd] = file
|
|
||||||
|
|
||||||
return fd
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.close(fd)
|
|
||||||
local task = kernel.currentTask
|
|
||||||
local file = task.fd[fd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
|
|
||||||
task.fd[fd] = nil
|
|
||||||
file.refcount = file.refcount - 1
|
|
||||||
if file.refcount == 0 then
|
|
||||||
file.handle.close()
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.read(fd, count)
|
|
||||||
local file = kernel.currentTask.fd[fd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
if not file.mode:find("r") then error("File not open for reading") end
|
|
||||||
return file.handle.read(count)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.write(fd, data)
|
|
||||||
local file = kernel.currentTask.fd[fd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
if not file.mode:find("w") then error("File not open for writing") end
|
|
||||||
return file.handle.write(data)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.whereis(fd)
|
|
||||||
local file = kernel.currentTask.fd[fd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
return file.path
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Filesystem operations
|
|
||||||
function vfs.mkdir(path)
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then error("No disk mounted") end
|
|
||||||
return disk:makeDirectory(diskPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.remove(path)
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then error("No disk mounted") end
|
|
||||||
return disk:remove(diskPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.attributes(path)
|
|
||||||
if type(path) == "number" then
|
|
||||||
local file = kernel.currentTask.fd[path]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
return disks[file.disk]:attributes(file.path)
|
|
||||||
end
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then error("No disk mounted") end
|
|
||||||
return disk:attributes(diskPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.list(path)
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then error("No disk mounted") end
|
|
||||||
return disk:list(diskPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.exists(path)
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then return false end
|
|
||||||
return disk:directoryExists(diskPath) or disk:fileExists(diskPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.type(path)
|
|
||||||
if type(path) == "number" then
|
|
||||||
local file = kernel.currentTask.fd[path]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
return disks[file.disk]:type(file.path)
|
|
||||||
end
|
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then error("No disk mounted") end
|
|
||||||
return disk:type(diskPath)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- CWD
|
|
||||||
function vfs.getcwd()
|
|
||||||
return kernel.currentTask.cwd
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.setcwd(path)
|
|
||||||
if path:sub(-1) ~= "/" then path = path .. "/" end
|
|
||||||
if path:sub(1,1) ~= "/" then path = "/" .. path end
|
|
||||||
kernel.currentTask.cwd = normalizePath(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Mounting
|
|
||||||
function vfs.mount(diskId, path)
|
|
||||||
if kernel.uid ~= 0 then error("Permission denied") end
|
|
||||||
if not disks[diskId] then error("Unknown disk '"..diskId.."'") end
|
|
||||||
if path:sub(-1) ~= "/" then path = path .. "/" end
|
|
||||||
|
|
||||||
for _,v in pairs(vfs.mounts) do
|
|
||||||
if v == path then error("Mount point already used") end
|
|
||||||
end
|
|
||||||
vfs.mounts[diskId] = path
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.unmount(path)
|
|
||||||
if kernel.uid ~= 0 then error("Permission denied") end
|
|
||||||
for k,v in pairs(vfs.mounts) do
|
|
||||||
if v == path then
|
|
||||||
vfs.mounts[k] = nil
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.getMounts()
|
|
||||||
return vfs.mounts
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.virtdisk(obj)
|
|
||||||
kernel.disks[obj.address] = obj
|
|
||||||
kernel.log("Registered virtual disk at "..obj.address)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Redirect file operations to VFS
|
|
||||||
function vfs.dup(oldfd)
|
|
||||||
local task = kernel.currentTask
|
|
||||||
local file = task.fd[oldfd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
|
|
||||||
local newfd = allocFD(task)
|
|
||||||
task.fd[newfd] = file
|
|
||||||
file.refcount = file.refcount + 1
|
|
||||||
return newfd
|
|
||||||
end
|
|
||||||
|
|
||||||
function vfs.dup2(oldfd, newfd)
|
|
||||||
local task = kernel.currentTask
|
|
||||||
local file = task.fd[oldfd]
|
|
||||||
if not file then error("EBADF") end
|
|
||||||
|
|
||||||
if oldfd == newfd then return newfd end
|
|
||||||
|
|
||||||
if task.fd[newfd] then
|
|
||||||
vfs.close(newfd)
|
|
||||||
end
|
|
||||||
|
|
||||||
task.fd[newfd] = file
|
|
||||||
file.refcount = file.refcount + 1
|
|
||||||
return newfd
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Syscall registration
|
|
||||||
kernel.vfs = vfs
|
|
||||||
kernel.syscalls["VFS_open"] = vfs.open
|
|
||||||
kernel.syscalls["VFS_read"] = vfs.read
|
|
||||||
kernel.syscalls["VFS_write"] = vfs.write
|
|
||||||
kernel.syscalls["VFS_close"] = vfs.close
|
|
||||||
kernel.syscalls["VFS_list"] = vfs.list
|
|
||||||
kernel.syscalls["VFS_type"] = vfs.type
|
|
||||||
kernel.syscalls["VFS_attributes"] = vfs.attributes
|
|
||||||
kernel.syscalls["VFS_mkdir"] = vfs.mkdir
|
|
||||||
kernel.syscalls["VFS_remove"] = vfs.remove
|
|
||||||
kernel.syscalls["VFS_exists"] = vfs.exists
|
|
||||||
kernel.syscalls["VFS_mount"] = vfs.mount
|
|
||||||
kernel.syscalls["VFS_unmount"] = vfs.unmount
|
|
||||||
kernel.syscalls["VFS_getcwd"] = vfs.getcwd
|
|
||||||
kernel.syscalls["VFS_setcwd"] = vfs.setcwd
|
|
||||||
kernel.syscalls["VFS_whereis"] = vfs.whereis
|
|
||||||
kernel.syscalls["VFS_dup"] = vfs.dup
|
|
||||||
kernel.syscalls["VFS_dup2"] = vfs.dup2
|
|
||||||
|
|
||||||
kernel.log("VFS module loaded")
|
|
||||||
@@ -1,42 +1 @@
|
|||||||
local kernel = ...
|
local a=...local b={}local c={"/lib/?.lua","/lib/?","/usr/lib/?.lua","/usr/lib/?","/usr/local/lib/?.lua","/usr/local/lib/?","?.lua","?"}function require(d,...)if b[d]then return b[d]end;local e=d:gsub("%.","/")local f={}for g,h in ipairs(c)do local i=string.gsub(h,"%?",e)if i:sub(1,1)~="/"then i=a.currentTask.cwd..i end;if a.vfs.exists(i)then if a.vfs.type(i)=="directory"then i=i.."/init"end;if a.vfs.exists(i)then local j=a.vfs.open(i,"r")local k=a.vfs.read(j,1024*1024*4)a.vfs.close(j)return assert(load(k,i,"t",a._U))(...)else table.insert(f,i)end else table.insert(f,i)end end;error("Module not found: "..d.." (searched paths: "..table.concat(f,", ")..")")end
|
||||||
local cache = {}
|
|
||||||
local searchpaths = {
|
|
||||||
"/lib/?.lua",
|
|
||||||
"/lib/?",
|
|
||||||
"/usr/lib/?.lua",
|
|
||||||
"/usr/lib/?",
|
|
||||||
"/usr/local/lib/?.lua",
|
|
||||||
"/usr/local/lib/?",
|
|
||||||
"?.lua",
|
|
||||||
"?"
|
|
||||||
}
|
|
||||||
|
|
||||||
function require(module,...)
|
|
||||||
if cache[module] then
|
|
||||||
return cache[module]
|
|
||||||
end
|
|
||||||
local modpath = module:gsub("%.", "/")
|
|
||||||
local failed = {}
|
|
||||||
for _, path in ipairs(searchpaths) do
|
|
||||||
local full_path = string.gsub(path, "%?", modpath)
|
|
||||||
if full_path:sub(1,1)~="/" then
|
|
||||||
full_path=kernel.currentTask.cwd..full_path
|
|
||||||
end
|
|
||||||
if kernel.vfs.exists(full_path) then
|
|
||||||
if kernel.vfs.type(full_path)=="directory" then
|
|
||||||
full_path = full_path .. "/init"
|
|
||||||
end
|
|
||||||
if kernel.vfs.exists(full_path) then
|
|
||||||
local handle = kernel.vfs.open(full_path, "r")
|
|
||||||
local file_content = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
|
||||||
kernel.vfs.close(handle)
|
|
||||||
return assert(load(file_content, full_path, "t", kernel._U))(...)
|
|
||||||
else
|
|
||||||
table.insert(failed, full_path)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
table.insert(failed, full_path)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
error("Module not found: " .. module .. " (searched paths: " .. table.concat(failed, ", ") .. ")")
|
|
||||||
end
|
|
||||||
@@ -1,172 +1 @@
|
|||||||
local kernel = ...
|
local a=...local b={}local c={}b.address="devfs0000"b.isReadOnly=false;b.spaceUsed=function()return 0 end;b.spaceTotal=function()return 0 end;b.makeDirectory=function()error("Permission denied")end;b.remove=function()error("Permission denied")end;b.setLabel=function()error("Permission denied")end;b.getLabel=function()return"devfs"end;b.attributes=function(d)return{type=b.type(d),isReadOnly=false,size=0,lastModified=0,created=0,Permissions="666",owner="root",group="root"}end;local function e(d)local f=string.split(d,"/")if f[1]==""then table.remove(f,1)end;local g=c;for h,i in ipairs(f)do if g[i]then g=g[i]else return nil end end;return g end;b.type=function(d)local g=e(d)if g then return g.type else return nil end end;b.list=function(d)local g=e(d)if g and g.type=="directory"then local j=table.keys(g)table.remove(j,table.indexOf(j,"type"))return j else error("Not a directory")end end;b.open=function(d,k)local g=e(d)if g and(g.type=="file"or g.type=="character device")then if k=="r"then return{read=g.read,close=function()end}elseif k=="w"then return{write=g.write,close=function()end}else error("Invalid mode")end else error("Not a file"..type(g))end end;local function l(j)return{type="file",read=function()return j end,write=function(m)j=m end}end;local function n()return{type="directory"}end;c["random"]={type="character device",read=function(o)local p=""for h=1,o do p=p..string.char(math.random(0,255))end;return p end,write=function()error("Permission denied")end}c["null"]={type="character device",read=function()return""end,write=function()end}c["zero"]={type="character device",read=function(o)return string.rep("\0",o)end,write=function()error("Permission denied")end}c["rtc"]={type="character device",read=function()return a.computer:time()end,write=function()error("Permission denied")end}c["rtc0"]={type="character device",read=function()return a.computer:time()end,write=function()error("Permission denied")end}c["eeprom"]={type="character device",read=function()return a.computer:getEEPROM()end,write=function(c)if a.uid~=0 then error("Permission denied")end;a.computer:setEEPROM(c)end}local q=a.newFifo()local r=a.newFifo()c["input"]=n()c["input"]["keyboard"]={type="pipe",read=function(o)return q.pop()end,write=function()error("Permission denied")end}c["input"]["mouse"]={type="pipe",read=function(o)return r.pop()end,write=function()error("Permission denied")end}c["pts"]=n()a.devfs={}a.devfs.keyboard=q;a.devfs.mouse=r;a.devfs.proxy=b;a.devfs.data=c;a.vfs.virtdisk(b)
|
||||||
|
|
||||||
local proxy = {}
|
|
||||||
local data = {}
|
|
||||||
|
|
||||||
proxy.address = "devfs0000"
|
|
||||||
proxy.isReadOnly = false
|
|
||||||
proxy.spaceUsed = function() return 0 end
|
|
||||||
proxy.spaceTotal = function() return 0 end
|
|
||||||
proxy.makeDirectory = function() error("Permission denied") end
|
|
||||||
proxy.remove = function() error("Permission denied") end
|
|
||||||
proxy.setLabel = function() error("Permission denied") end
|
|
||||||
proxy.getLabel = function() return "devfs" end
|
|
||||||
proxy.attributes = function(path) return {
|
|
||||||
type = proxy.type(path),
|
|
||||||
isReadOnly = false,
|
|
||||||
size = 0,
|
|
||||||
lastModified = 0,
|
|
||||||
created = 0,
|
|
||||||
Permissions = "666",
|
|
||||||
owner = "root",
|
|
||||||
group = "root"
|
|
||||||
} end
|
|
||||||
|
|
||||||
local function getNode(path)
|
|
||||||
local parts = string.split(path, "/")
|
|
||||||
if parts[1] == "" then
|
|
||||||
table.remove(parts, 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
local node = data
|
|
||||||
for _, part in ipairs(parts) do
|
|
||||||
if node[part] then
|
|
||||||
node = node[part]
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return node
|
|
||||||
end
|
|
||||||
|
|
||||||
proxy.type = function(path)
|
|
||||||
local node = getNode(path)
|
|
||||||
if node then
|
|
||||||
return node.type
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
proxy.list = function(path)
|
|
||||||
local node = getNode(path)
|
|
||||||
if node and node.type == "directory" then
|
|
||||||
local content = table.keys(node)
|
|
||||||
table.remove(content, table.indexOf(content, "type"))
|
|
||||||
return content
|
|
||||||
else
|
|
||||||
error("Not a directory")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
proxy.open = function(path, mode)
|
|
||||||
local node = getNode(path)
|
|
||||||
if node and (node.type == "file" or node.type == "character device") then
|
|
||||||
if mode == "r" then
|
|
||||||
return {
|
|
||||||
read = node.read,
|
|
||||||
close = function() end
|
|
||||||
}
|
|
||||||
elseif mode == "w" then
|
|
||||||
return {
|
|
||||||
write = node.write,
|
|
||||||
close = function() end
|
|
||||||
}
|
|
||||||
else
|
|
||||||
error("Invalid mode")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
error("Not a file"..type(node))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function newStringFile(content)
|
|
||||||
return {
|
|
||||||
type = "file",
|
|
||||||
read = function() return content end,
|
|
||||||
write = function(newContent) content = newContent end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function newDirectory()
|
|
||||||
return {
|
|
||||||
type = "directory"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
data["random"] = {
|
|
||||||
type = "character device",
|
|
||||||
read = function(amount)
|
|
||||||
local result = ""
|
|
||||||
for _ = 1, amount do
|
|
||||||
result = result .. string.char(math.random(0, 255))
|
|
||||||
end
|
|
||||||
return result
|
|
||||||
end,
|
|
||||||
write = function() error("Permission denied") end
|
|
||||||
}
|
|
||||||
|
|
||||||
data["null"] = {
|
|
||||||
type = "character device",
|
|
||||||
read = function() return "" end,
|
|
||||||
write = function() end
|
|
||||||
}
|
|
||||||
|
|
||||||
data["zero"] = {
|
|
||||||
type = "character device",
|
|
||||||
read = function(amount)
|
|
||||||
return string.rep("\0", amount)
|
|
||||||
end,
|
|
||||||
write = function() error("Permission denied") end
|
|
||||||
}
|
|
||||||
|
|
||||||
data["rtc"] = {
|
|
||||||
type = "character device",
|
|
||||||
read = function() return kernel.computer:time() end,
|
|
||||||
write = function() error("Permission denied") end
|
|
||||||
}
|
|
||||||
|
|
||||||
data["rtc0"] = {
|
|
||||||
type = "character device",
|
|
||||||
read = function() return kernel.computer:time() end,
|
|
||||||
write = function() error("Permission denied") end
|
|
||||||
}
|
|
||||||
|
|
||||||
data["eeprom"] = {
|
|
||||||
type = "character device",
|
|
||||||
read = function() return kernel.computer:getEEPROM() end,
|
|
||||||
write = function(data)
|
|
||||||
if kernel.uid ~= 0 then
|
|
||||||
error("Permission denied")
|
|
||||||
end
|
|
||||||
kernel.computer:setEEPROM(data)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
local keyboard = kernel.newFifo()
|
|
||||||
local mouse = kernel.newFifo()
|
|
||||||
data["input"] = newDirectory()
|
|
||||||
data["input"]["keyboard"] = {
|
|
||||||
type = "pipe",
|
|
||||||
read = function(amount)
|
|
||||||
return keyboard.pop()
|
|
||||||
end,
|
|
||||||
write = function() error("Permission denied") end
|
|
||||||
}
|
|
||||||
data["input"]["mouse"] = {
|
|
||||||
type = "pipe",
|
|
||||||
read = function(amount)
|
|
||||||
return mouse.pop()
|
|
||||||
end,
|
|
||||||
write = function() error("Permission denied") end
|
|
||||||
}
|
|
||||||
|
|
||||||
data["pts"] = newDirectory()
|
|
||||||
|
|
||||||
kernel.devfs = {}
|
|
||||||
kernel.devfs.keyboard = keyboard
|
|
||||||
kernel.devfs.mouse = mouse
|
|
||||||
kernel.devfs.proxy = proxy
|
|
||||||
kernel.devfs.data = data
|
|
||||||
kernel.vfs.virtdisk(proxy)
|
|
||||||
@@ -1,12 +1 @@
|
|||||||
local kernel = ...
|
local a=...a.processes.keventd=function()while true do local b={a.computer:getMachineEvent()}if b[1]then if b[1]=="key"or b[1]=="keyPressed"or b[1]=="keyReleased"then a.devfs.keyboard.push(b)end end end end
|
||||||
|
|
||||||
kernel.processes.keventd = function()
|
|
||||||
while true do
|
|
||||||
local event = {kernel.computer:getMachineEvent()}
|
|
||||||
if event[1] then
|
|
||||||
if event[1] == "key" or event[1] == "keyPressed" or event[1] == "keyReleased" then
|
|
||||||
kernel.devfs.keyboard.push(event)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,17 +1 @@
|
|||||||
local kernel=...
|
local a=...for b,c in ipairs(string.split(a.fstab,"\n"))do if c:sub(1,1)=="U"then local d=""for b=3,#c do if c:sub(b,b)==";"then if b==3 then a.log("Invalid fstab line... Skipping.","WARN")goto e end;d=c:sub(3,b-1)end end;local f=c:sub(#d+4)if d~="$"then a.vfs.mount(d,f)end::e::end end
|
||||||
for i,v in ipairs(string.split(kernel.fstab,"\n")) do
|
|
||||||
if v:sub(1,1)=="U" then
|
|
||||||
local id=""
|
|
||||||
for i=3,#v do
|
|
||||||
if v:sub(i,i)==";" then
|
|
||||||
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN") goto endline end
|
|
||||||
id=v:sub(3,i-1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local path=v:sub(#id+4)
|
|
||||||
if id~="$" then
|
|
||||||
kernel.vfs.mount(id,path)
|
|
||||||
end
|
|
||||||
::endline::
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local kernel = ...
|
|
||||||
@@ -1,75 +1 @@
|
|||||||
local kernel = ...
|
local a=...local b={}local c={}local d={}function d.open(e)if not b[e]then local f=a.newUUID()b[e]={owner=a.currentProcess.pid,handle=f,messages={}}return b[e].handle end;error("Port already opened")end;function d.close(e)if b[e]then if b[e].owner==a.currentProcess.pid then b[e]=nil;return true else error("Cannot close port you do not own")end end;error("Port not opened")end;function d.send(e,g)if b[e]then table.insert(b[e].messages,{from=a.currentProcess.pid,message=g})if c[b[e].owner]then c[b[e].owner](e,g)end;return true end;error("Port not opened")end;function d.receive(e)if b[e]then if#b[e].messages>0 then return table.remove(b[e].messages,1)else return nil end end;error("Port not opened")end;function d.setSignalHandler(h,i)c[h]=i end;function d.clearSignalHandler(h)c[h]=nil end;function d.sendSignal(h,...)coroutine.resumeWithTimeout(coroutine.create(function(...)if c[h]then c[h](...)return true end end),100)return false end;a.ipc=d;a.syscalls["ipc_open"]=d.open;a.syscalls["ipc_close"]=d.close;a.syscalls["ipc_send"]=d.send;a.syscalls["ipc_receive"]=d.receive;a.syscalls["ipc_setSignalHandler"]=d.setSignalHandler;a.syscalls["ipc_clearSignalHandler"]=d.clearSignalHandler;a.syscalls["ipc_sendSignal"]=d.sendSignal;a.log("Loaded IPC module")
|
||||||
local ports = {}
|
|
||||||
local signals = {}
|
|
||||||
local ipc = {}
|
|
||||||
|
|
||||||
function ipc.open(port)
|
|
||||||
if not ports[port] then
|
|
||||||
local handle = kernel.newUUID()
|
|
||||||
ports[port] = {owner = kernel.currentProcess.pid, handle = handle, messages = {}}
|
|
||||||
return ports[port].handle
|
|
||||||
end
|
|
||||||
error("Port already opened")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.close(port)
|
|
||||||
if ports[port] then
|
|
||||||
if ports[port].owner == kernel.currentProcess.pid then
|
|
||||||
ports[port] = nil
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
error("Cannot close port you do not own")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
error("Port not opened")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.send(port, message)
|
|
||||||
if ports[port] then
|
|
||||||
table.insert(ports[port].messages, {from = kernel.currentProcess.pid, message = message})
|
|
||||||
if signals[ports[port].owner] then
|
|
||||||
signals[ports[port].owner](port, message)
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
error("Port not opened")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.receive(port)
|
|
||||||
if ports[port] then
|
|
||||||
if #ports[port].messages > 0 then
|
|
||||||
return table.remove(ports[port].messages, 1)
|
|
||||||
else
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
error("Port not opened")
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.setSignalHandler(pid, handler)
|
|
||||||
signals[pid] = handler
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.clearSignalHandler(pid)
|
|
||||||
signals[pid] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function ipc.sendSignal(pid, ...)
|
|
||||||
coroutine.resumeWithTimeout(coroutine.create(function(...)
|
|
||||||
if signals[pid] then
|
|
||||||
signals[pid](...)
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end), 100)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.ipc = ipc
|
|
||||||
kernel.syscalls["ipc_open"] = ipc.open
|
|
||||||
kernel.syscalls["ipc_close"] = ipc.close
|
|
||||||
kernel.syscalls["ipc_send"] = ipc.send
|
|
||||||
kernel.syscalls["ipc_receive"] = ipc.receive
|
|
||||||
kernel.syscalls["ipc_setSignalHandler"] = ipc.setSignalHandler
|
|
||||||
kernel.syscalls["ipc_clearSignalHandler"] = ipc.clearSignalHandler
|
|
||||||
kernel.syscalls["ipc_sendSignal"] = ipc.sendSignal
|
|
||||||
kernel.log("Loaded IPC module")
|
|
||||||
@@ -1,17 +1 @@
|
|||||||
local args={...}
|
local a={...}local b=a[1]b._G=_G;b._U=setmetatable({},{__index=b._G,__newindex=function(c,d,e)if b.config.allowGlobalOverwrites or b.allowGlobalOverwrites then rawset(c,d,e)return end;error("Attempt to modify global variable '"..d.."'",2)end,__metatable=false})b.allowGlobalOverwrites=true;b._U._G=b._U;b.allowGlobalOverwrites=false
|
||||||
local kernel=args[1]
|
|
||||||
kernel._G=_G
|
|
||||||
kernel._U=setmetatable({},{
|
|
||||||
__index = kernel._G,
|
|
||||||
__newindex = function(t,k,v)
|
|
||||||
if kernel.config.allowGlobalOverwrites or kernel.allowGlobalOverwrites then
|
|
||||||
rawset(t,k,v)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
error("Attempt to modify global variable '"..k.."'",2)
|
|
||||||
end,
|
|
||||||
__metatable = false
|
|
||||||
})
|
|
||||||
kernel.allowGlobalOverwrites=true
|
|
||||||
kernel._U._G=kernel._U
|
|
||||||
kernel.allowGlobalOverwrites=false
|
|
||||||
@@ -1,65 +1 @@
|
|||||||
local kernel = ...
|
local a=...local b={}a.pam=b;local c={}local function d(e)local f=a.vfs.open(e,"r")if not f then error("Failed to open file: "..e)end;local g=a.vfs.read(f,1024000)a.vfs.close(f)return g end;local h=require("crypto.blake2s")if not h then error("Failed to load blake2s")end;if not a.vfs.exists("/etc/pam.d/secret")then local i=""for j=1,256 do i=i..string.char(math.random(1,255))end;local k=a.vfs.open("/etc/pam.d/secret","w")a.vfs.write(k,i)a.vfs.close(k)end;local l=d("/etc/pam.d/secret")function b.authenticate(m,n)local o=d("/etc/passwd")local p=d("/etc/shadow")local q=string.split(o,"\n")local r=string.split(p,"\n")local s={}local t={}for u,v in ipairs(q)do local w=string.split(v,":")s[w[1]]=w end;for u,v in ipairs(r)do local w=string.split(v,":")t[w[1]]=w end;for x,w in pairs(s)do if x==m then local y=string.split(t[x][2],"$")local z=y[2]local A=h(n..z,l)if A==y[3]then c[m]=a.newUUID()return c[m]else return false end end end end;function b.authToken(m,B)return c[m]==B end
|
||||||
local pam = {}
|
|
||||||
kernel.pam = pam
|
|
||||||
local loggedIn = {}
|
|
||||||
|
|
||||||
local function getFile(path)
|
|
||||||
local file = kernel.vfs.open(path, "r")
|
|
||||||
if not file then error("Failed to open file: "..path) end
|
|
||||||
local content = kernel.vfs.read(file, 1024000)
|
|
||||||
kernel.vfs.close(file)
|
|
||||||
return content
|
|
||||||
end
|
|
||||||
|
|
||||||
local blake2s = require("crypto.blake2s")
|
|
||||||
if not blake2s then error("Failed to load blake2s") end
|
|
||||||
|
|
||||||
if not kernel.vfs.exists("/etc/pam.d/secret") then
|
|
||||||
local key = ""
|
|
||||||
for i=1, 256 do
|
|
||||||
key=key..string.char(math.random(1,255))
|
|
||||||
end
|
|
||||||
local handle = kernel.vfs.open("/etc/pam.d/secret", "w")
|
|
||||||
kernel.vfs.write(handle, key)
|
|
||||||
kernel.vfs.close(handle)
|
|
||||||
end
|
|
||||||
|
|
||||||
local pepper = getFile("/etc/pam.d/secret")
|
|
||||||
|
|
||||||
function pam.authenticate(username, password)
|
|
||||||
local fpasswd = getFile("/etc/passwd")
|
|
||||||
local fshadow = getFile("/etc/shadow")
|
|
||||||
|
|
||||||
local passwdLines = string.split(fpasswd, "\n")
|
|
||||||
local shadowLines = string.split(fshadow, "\n")
|
|
||||||
|
|
||||||
local passwd = {}
|
|
||||||
local shadow = {}
|
|
||||||
for _, line in ipairs(passwdLines) do
|
|
||||||
local fields = string.split(line, ":")
|
|
||||||
passwd[fields[1]] = fields
|
|
||||||
end
|
|
||||||
for _, line in ipairs(shadowLines) do
|
|
||||||
local fields = string.split(line, ":")
|
|
||||||
shadow[fields[1]] = fields
|
|
||||||
end
|
|
||||||
|
|
||||||
for user, fields in pairs(passwd) do
|
|
||||||
if user == username then
|
|
||||||
local shadowPasswd = string.split(shadow[user][2], "$")
|
|
||||||
local salt = shadowPasswd[2]
|
|
||||||
local hashedPassword = blake2s(password .. salt, pepper)
|
|
||||||
if hashedPassword == shadowPasswd[3] then
|
|
||||||
loggedIn[username] = kernel.newUUID()
|
|
||||||
return loggedIn[username]
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function pam.authToken(username, token)
|
|
||||||
return loggedIn[username] == token
|
|
||||||
end
|
|
||||||
|
|
||||||
@@ -1,211 +1 @@
|
|||||||
local kernel = ...
|
local a=...local b={}local c={}local d=2;a.exitMain=false;function c.spawn(e,f,g,h,i,j)local k=d;d=d+1;b[tostring(k)]={coro=coroutine.create(function()local l,m=xpcall(e,debug.traceback,table.unpack(h or{}))if not l then b[tostring(k)].status="Z"b[tostring(k)].exit=tostring(m)else b[tostring(k)].status="Z"b[tostring(k)].exit=m end end),name=f or"task"..tostring(k),envars=g or{},args=h or{},status="R",pid=k,tgid=i or a.currentTask.tgid,user=a.user,uid=a.uid,fd=j or{},exit="",sleep=0,ivs=0,vs=0,children={},parent=a.currentTask,siblings=a.currentTask.children,syscallReturn={},cwd=a.currentTask.cwd,term=a.currentTask.term,timeSlice=0,lastTime=0,totalTime=0,numRuns=0}table.insert(a.currentTask.children,b[tostring(k)])end;function c.sleep(n)a.currentTask.status="S"a.currentTask.sleep=a.computer:time()+n;coroutine.yield()end;a.syscalls["HPV_spawn"]=c.spawn;a.syscalls["HPV_sleep"]=c.sleep;a._G.sleep=function(...)coroutine.yield("syscall","HPV_sleep",...)end;local function o()for p,q in pairs(b)do if q.status=="Z"and not q.reapTime then q.coro=nil;q.ivs=nil;q.vs=nil;q.args=nil;q.envars=nil;q.cwd=nil;q.term=nil;q.numRuns=nil;q.totalTime=nil;q.lastTime=nil;q.timeSlice=nil;q.syscallReturn=nil;q.sleep=nil;for r,s in pairs(q.fd)do a.vfs.close(s)end;q.fd=nil;q.reapTime=a.computer:time()+30000 elseif q.reapTime and a.computer:time()>q.reapTime then for t,u in ipairs(q.children)do u.parent=b["1"]u.siblings=b["1"].children;table.insert(b["1"].children,u)end;for v,w in ipairs(q.siblings)do if w.pid==q.pid then table.remove(q.siblings,v)break end end;b[p]=nil end end end;local x=0.85;local y=0.01;local z=0.0005;local A=0.5;local B=0.08;local C=0.03;local D=0.02;local E=0.5;local F=0.5;local G=0.01;function a.main()while not a.exitMain do local H=0;local I=0;local J=0;local K=0;local L={}for p,q in pairs(b)do if q.status=="S"then if a.computer:time()>=q.sleep then q.status="R"q.sleep=0 end end;if q.status=="R"then a.currentTask=q;a.vfs.cwd=q.cwd;a.user=q.user;a.uid=q.uid;H=H+1;q.timeSlice=math.min(A,math.max(z,G/H^x))local M=a.computer:time()local N;if a.config.preempt then N={coroutine.resumeWithTimeout(q.coro,q.timeSlice,table.unpack(q.syscallReturn))}else N={coroutine.resume(q.coro,table.unpack(q.syscallReturn))}end;local O=a.computer:time()-M;q.lastTime=O;q.totalTime=(q.totalTime or 0)+O;q.numRuns=(q.numRuns or 0)+1;L[#L+1]=O;K=K+O;if O<=z then I=I+1 end;if O>=A then J=J+1 end;if N[1]=="error"then a.log("processHandlerException: "..N[2])q.status="Z"q.exit="processHandlerException: "..N[2]elseif N[1]=="timeout"then q.ivs=q.ivs+1;q.syscallReturn={}elseif N[1]=="success"then q.vs=q.vs+1;if N[2]=="syscall"then if a.syscalls[N[3]]then if a.config.debugSyscalls then a.log("Task "..q.pid.." invoking syscall: "..N[3],"DBUG")end;local P={xpcall(a.syscalls[N[3]],debug.traceback,table.unpack(N,4))}if a.config.debugSyscalls then if not P[1]then a.log("Task "..q.pid.." syscall "..N[3].." failed: "..tostring(P[2]))else a.log("Task "..q.pid.." syscall "..N[3].." completed returning "..tostring(#P-1).." values","DBUG")for v=2,#P do a.log(" retval["..tostring(v-1).."] = "..tostring(P[v]),"DBUG")end end end;if not P[1]then q.syscallReturn={false,P[2]}else q.syscallReturn={true,table.unpack(P,2)}end else q.syscallReturn={false,"Unknown syscall: "..tostring(N[3])}end end end end end;local Q=H>0 and K/H or 0;local R=0;for t,S in ipairs(L)do R=R+(S-Q)^2 end;if H>0 then R=R/H end;if H>0 then local T=E*I/H-F*J/H;local U=y*H^(x-1)/math.max(Q,1e-8)G=G+B*(U-G)+C*T-D*R end;o()end end;a.tasks=b;a.hpv=c
|
||||||
local tasks = {}
|
|
||||||
local sys = {}
|
|
||||||
local nextpid = 2
|
|
||||||
kernel.exitMain=false
|
|
||||||
|
|
||||||
function sys.spawn(func, name, envars, args, tgid, fshandles)
|
|
||||||
local id = nextpid
|
|
||||||
nextpid = nextpid + 1
|
|
||||||
tasks[tostring(id)] = {
|
|
||||||
coro=coroutine.create(function()
|
|
||||||
local ok, err = xpcall(func, debug.traceback, table.unpack(args or {}))
|
|
||||||
if not ok then
|
|
||||||
tasks[tostring(id)].status="Z"
|
|
||||||
tasks[tostring(id)].exit=tostring(err)
|
|
||||||
else
|
|
||||||
tasks[tostring(id)].status="Z"
|
|
||||||
tasks[tostring(id)].exit=err
|
|
||||||
end
|
|
||||||
end),
|
|
||||||
name=name or "task"..tostring(id),
|
|
||||||
envars=envars or {},
|
|
||||||
args=args or {},
|
|
||||||
status="R",
|
|
||||||
pid=id,
|
|
||||||
tgid=tgid or kernel.currentTask.tgid,
|
|
||||||
user=kernel.user,
|
|
||||||
uid=kernel.uid,
|
|
||||||
fd=fshandles or {},
|
|
||||||
exit="",
|
|
||||||
sleep=0,
|
|
||||||
ivs=0,
|
|
||||||
vs=0,
|
|
||||||
children={},
|
|
||||||
parent=kernel.currentTask,
|
|
||||||
siblings=kernel.currentTask.children,
|
|
||||||
syscallReturn={},
|
|
||||||
cwd=kernel.currentTask.cwd,
|
|
||||||
term=kernel.currentTask.term,
|
|
||||||
timeSlice=0,
|
|
||||||
lastTime=0,
|
|
||||||
totalTime=0,
|
|
||||||
numRuns=0
|
|
||||||
}
|
|
||||||
table.insert(kernel.currentTask.children, tasks[tostring(id)])
|
|
||||||
end
|
|
||||||
|
|
||||||
function sys.sleep(ms)
|
|
||||||
kernel.currentTask.status="S"
|
|
||||||
kernel.currentTask.sleep=kernel.computer:time()+ms
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.syscalls["HPV_spawn"]=sys.spawn
|
|
||||||
kernel.syscalls["HPV_sleep"]=sys.sleep
|
|
||||||
kernel._G.sleep=function(...)coroutine.yield("HPV_sleep",...)end
|
|
||||||
|
|
||||||
local function reapDeadTasks()
|
|
||||||
for pid, task in pairs(tasks) do
|
|
||||||
if task.status == "Z" and not task.reapTime then
|
|
||||||
task.coro = nil
|
|
||||||
task.ivs = nil
|
|
||||||
task.vs = nil
|
|
||||||
task.args = nil
|
|
||||||
task.envars = nil
|
|
||||||
task.cwd = nil
|
|
||||||
task.term = nil
|
|
||||||
task.numRuns = nil
|
|
||||||
task.totalTime = nil
|
|
||||||
task.lastTime = nil
|
|
||||||
task.timeSlice = nil
|
|
||||||
task.syscallReturn = nil
|
|
||||||
task.sleep = nil
|
|
||||||
for k,v in pairs(task.fd) do
|
|
||||||
kernel.vfs.close(v)
|
|
||||||
end
|
|
||||||
task.fd = nil
|
|
||||||
task.reapTime = kernel.computer:time() + 30000
|
|
||||||
elseif task.reapTime and kernel.computer:time() > task.reapTime then
|
|
||||||
for _,child in ipairs(task.children) do
|
|
||||||
child.parent = tasks["1"]
|
|
||||||
child.siblings = tasks["1"].children
|
|
||||||
table.insert(tasks["1"].children, child)
|
|
||||||
end
|
|
||||||
for i, sibling in ipairs(task.siblings) do
|
|
||||||
if sibling.pid == task.pid then
|
|
||||||
table.remove(task.siblings, i)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tasks[pid] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local alpha = 0.85
|
|
||||||
local C_target = 0.01
|
|
||||||
local Tmin = 0.0005
|
|
||||||
local Tmax = 0.5
|
|
||||||
local lambda_budget = 0.08
|
|
||||||
local lambda_clamp = 0.03
|
|
||||||
local lambda_var = 0.02
|
|
||||||
local k_min = 0.5
|
|
||||||
local k_max = 0.5
|
|
||||||
local B = 0.01
|
|
||||||
|
|
||||||
function kernel.main()
|
|
||||||
while not kernel.exitMain do
|
|
||||||
local N = 0
|
|
||||||
local Tmin_hit = 0
|
|
||||||
local Tmax_hit = 0
|
|
||||||
local totalTaskTime = 0
|
|
||||||
local taskTimes = {}
|
|
||||||
|
|
||||||
for pid, task in pairs(tasks) do
|
|
||||||
if task.status == "S" then
|
|
||||||
if kernel.computer:time() >= task.sleep then
|
|
||||||
task.status="R"
|
|
||||||
task.sleep=0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if task.status == "R" then
|
|
||||||
kernel.currentTask = task
|
|
||||||
kernel.vfs.cwd = task.cwd
|
|
||||||
kernel.user = task.user
|
|
||||||
kernel.uid = task.uid
|
|
||||||
N = N + 1
|
|
||||||
|
|
||||||
-- assign adaptive time slice
|
|
||||||
task.timeSlice = math.min(Tmax, math.max(Tmin, B / (N ^ alpha)))
|
|
||||||
|
|
||||||
-- measure execution time
|
|
||||||
local startTime = kernel.computer:time()
|
|
||||||
local ret
|
|
||||||
if kernel.config.preempt then
|
|
||||||
ret = {coroutine.resumeWithTimeout(task.coro, task.timeSlice, table.unpack(task.syscallReturn))}
|
|
||||||
else
|
|
||||||
ret = {coroutine.resume(task.coro, table.unpack(task.syscallReturn))}
|
|
||||||
end
|
|
||||||
local elapsed = kernel.computer:time() - startTime
|
|
||||||
task.lastTime = elapsed
|
|
||||||
task.totalTime = (task.totalTime or 0) + elapsed
|
|
||||||
task.numRuns = (task.numRuns or 0) + 1
|
|
||||||
|
|
||||||
taskTimes[#taskTimes + 1] = elapsed
|
|
||||||
totalTaskTime = totalTaskTime + elapsed
|
|
||||||
|
|
||||||
if elapsed <= Tmin then Tmin_hit = Tmin_hit + 1 end
|
|
||||||
if elapsed >= Tmax then Tmax_hit = Tmax_hit + 1 end
|
|
||||||
|
|
||||||
-- handle task results
|
|
||||||
if ret[1] == "error" then
|
|
||||||
kernel.log("processHandlerException: "..ret[2])
|
|
||||||
task.status = "Z"
|
|
||||||
task.exit = "processHandlerException: "..ret[2]
|
|
||||||
elseif ret[1] == "timeout" then
|
|
||||||
task.ivs=task.ivs+1
|
|
||||||
task.syscallReturn = {}
|
|
||||||
elseif ret[1] == "success" then
|
|
||||||
task.vs=task.vs+1
|
|
||||||
if ret[2]=="syscall" then
|
|
||||||
if kernel.syscalls[ret[3]] then
|
|
||||||
if kernel.config.debugSyscalls then
|
|
||||||
kernel.log("Task "..task.pid.." invoking syscall: "..ret[3])
|
|
||||||
end
|
|
||||||
local sysret = {xpcall(kernel.syscalls[ret[3]], debug.traceback, table.unpack(ret, 4))}
|
|
||||||
if kernel.config.debugSyscalls then
|
|
||||||
if not sysret[1] then
|
|
||||||
kernel.log("Task "..task.pid.." syscall "..ret[3].." failed: "..tostring(sysret[2]))
|
|
||||||
else
|
|
||||||
kernel.log("Task "..task.pid.." syscall "..ret[3].." completed returning "..tostring(#sysret-1).." values")
|
|
||||||
for i=2,#sysret do
|
|
||||||
kernel.log(" retval["..tostring(i-1).."] = "..tostring(sysret[i]))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not sysret[1] then
|
|
||||||
task.syscallReturn={false, sysret[2]}
|
|
||||||
else
|
|
||||||
task.syscallReturn={true, table.unpack(sysret,2)}
|
|
||||||
end
|
|
||||||
else
|
|
||||||
task.syscallReturn={false, "Unknown syscall: "..tostring(ret[3])}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local T_prev_avg = (N > 0) and (totalTaskTime / N) or 0
|
|
||||||
local T_prev_var = 0
|
|
||||||
for _, t in ipairs(taskTimes) do
|
|
||||||
T_prev_var = T_prev_var + (t - T_prev_avg)^2
|
|
||||||
end
|
|
||||||
if N > 0 then T_prev_var = T_prev_var / N end
|
|
||||||
|
|
||||||
if N > 0 then
|
|
||||||
local f_clamp = k_min*(Tmin_hit/N) - k_max*(Tmax_hit/N)
|
|
||||||
local B_budget = (C_target * (N^(alpha-1))) / math.max(T_prev_avg, 1e-8)
|
|
||||||
B = B + lambda_budget * (B_budget - B)
|
|
||||||
+ lambda_clamp * f_clamp
|
|
||||||
- lambda_var * T_prev_var
|
|
||||||
end
|
|
||||||
|
|
||||||
-- clean up dead tasks
|
|
||||||
reapDeadTasks()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.tasks=tasks
|
|
||||||
kernel.hpv=sys
|
|
||||||
@@ -1,6 +1 @@
|
|||||||
local kernel=...
|
local a=...local debug=debug;a._G.debug={getinfo=debug.getinfo,traceback=debug.traceback}
|
||||||
local debug=debug
|
|
||||||
kernel._G.debug={
|
|
||||||
getinfo=debug.getinfo,
|
|
||||||
traceback=debug.traceback
|
|
||||||
}
|
|
||||||
@@ -1,125 +1 @@
|
|||||||
local kernel=...
|
local a=...a.tty={}function a.tty.register(b,c)a.tty[b]=c end;function a.tty.print(d)local e=a.currentTask.term;if e and a.tty[e]then a.tty[e].print(d)end end;function a.tty.printInline(d)local e=a.currentTask.term;if e and a.tty[e]then a.tty[e].printInline(d)end end;function a.tty.size()local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].size()end end;function a.tty.setCursorPos(f,g)local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].setCursorPos(f,g)end end;function a.tty.getCursorPos()local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].getCursorPos()end end;function a.tty.clear()local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].clear()end end;function a.tty.setTextColor(h)local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].setTextColor(h)end end;function a.tty.setBackgroundColor(h)local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].setBackgroundColor(h)end end;function a.tty.scroll(i)local e=a.currentTask.term;if e and a.tty[e]then return a.tty[e].scroll(i)end end;function a.tty.getTextColor()local e=a.currentTask.term;if e and a.tty[e]and a.tty[e].getTextColor then return a.tty[e].getTextColor()end end;function a.tty.getBackgroundColor()local e=a.currentTask.term;if e and a.tty[e]and a.tty[e].getBackgroundColor then return a.tty[e].getBackgroundColor()end end;function a.tty.bind(j)if not j then return false,"No TTY ID specified"end;if not a.tty[j]then return false,"TTY "..tostring(j).." not registered"end;a.currentTask.term=j;return true end;function a.tty.unbind()a.currentTask.term=false end;function a.tty.isBound()return a.currentTask.term~=nil end;function a.tty.getBoundTTY()return a.currentTask.term end;a.syscalls["TTY_print"]=a.tty.print;a.syscalls["TTY_printInline"]=a.tty.printInline;a.syscalls["TTY_size"]=a.tty.size;a.syscalls["TTY_setCursorPos"]=a.tty.setCursorPos;a.syscalls["TTY_getCursorPos"]=a.tty.getCursorPos;a.syscalls["TTY_clear"]=a.tty.clear;a.syscalls["TTY_setTextColor"]=a.tty.setTextColor;a.syscalls["TTY_setBackgroundColor"]=a.tty.setBackgroundColor;a.syscalls["TTY_scroll"]=a.tty.scroll;a.syscalls["TTY_getTextColor"]=a.tty.getTextColor;a.syscalls["TTY_getBackgroundColor"]=a.tty.getBackgroundColor;a.syscalls["TTY_bind"]=a.tty.bind;a.syscalls["TTY_unbind"]=a.tty.unbind;a.syscalls["TTY_isBound"]=a.tty.isBound;a.syscalls["TTY_getBoundTTY"]=a.tty.getBoundTTY;a.log("TTY module loaded attempting to register console tty")a.status="init"
|
||||||
kernel.tty={}
|
|
||||||
|
|
||||||
function kernel.tty.register(tty, ttyo)
|
|
||||||
kernel.tty[tty]=ttyo
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.print(text)
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
kernel.tty[term].print(text)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.printInline(text)
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
kernel.tty[term].printInline(text)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.size()
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].size()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.setCursorPos(x,y)
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].setCursorPos(x,y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.getCursorPos()
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].getCursorPos()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.clear()
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].clear()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.setTextColor(color)
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].setTextColor(color)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.setBackgroundColor(color)
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].setBackgroundColor(color)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.scroll(n)
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] then
|
|
||||||
return kernel.tty[term].scroll(n)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.getTextColor()
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] and kernel.tty[term].getTextColor then
|
|
||||||
return kernel.tty[term].getTextColor()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.getBackgroundColor()
|
|
||||||
local term=kernel.currentTask.term
|
|
||||||
if term and kernel.tty[term] and kernel.tty[term].getBackgroundColor then
|
|
||||||
return kernel.tty[term].getBackgroundColor()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.bind(ttyid)
|
|
||||||
if not ttyid then
|
|
||||||
return false, "No TTY ID specified"
|
|
||||||
end
|
|
||||||
if not kernel.tty[ttyid] then
|
|
||||||
return false, "TTY "..tostring(ttyid).." not registered"
|
|
||||||
end
|
|
||||||
kernel.currentTask.term=ttyid
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.unbind()
|
|
||||||
kernel.currentTask.term=false
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.isBound()
|
|
||||||
return kernel.currentTask.term ~= nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function kernel.tty.getBoundTTY()
|
|
||||||
return kernel.currentTask.term
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.syscalls["TTY_print"]=kernel.tty.print
|
|
||||||
kernel.syscalls["TTY_printInline"]=kernel.tty.printInline
|
|
||||||
kernel.syscalls["TTY_size"]=kernel.tty.size
|
|
||||||
kernel.syscalls["TTY_setCursorPos"]=kernel.tty.setCursorPos
|
|
||||||
kernel.syscalls["TTY_getCursorPos"]=kernel.tty.getCursorPos
|
|
||||||
kernel.syscalls["TTY_clear"]=kernel.tty.clear
|
|
||||||
kernel.syscalls["TTY_setTextColor"]=kernel.tty.setTextColor
|
|
||||||
kernel.syscalls["TTY_setBackgroundColor"]=kernel.tty.setBackgroundColor
|
|
||||||
kernel.syscalls["TTY_scroll"]=kernel.tty.scroll
|
|
||||||
kernel.syscalls["TTY_getTextColor"]=kernel.tty.getTextColor
|
|
||||||
kernel.syscalls["TTY_getBackgroundColor"]=kernel.tty.getBackgroundColor
|
|
||||||
kernel.syscalls["TTY_bind"]=kernel.tty.bind
|
|
||||||
kernel.syscalls["TTY_unbind"]=kernel.tty.unbind
|
|
||||||
kernel.syscalls["TTY_isBound"]=kernel.tty.isBound
|
|
||||||
kernel.syscalls["TTY_getBoundTTY"]=kernel.tty.getBoundTTY
|
|
||||||
|
|
||||||
kernel.log("TTY module loaded attempting to register console tty")
|
|
||||||
kernel.status="init"
|
|
||||||
@@ -1,2 +1 @@
|
|||||||
local kernel=...
|
local a=...a.tty.bind("tty0")
|
||||||
kernel.tty.bind("tty0")
|
|
||||||
@@ -1,28 +1 @@
|
|||||||
local kernel=...
|
local a=...function print(...)coroutine.yield()local b={...}local c=""for d=1,#b do c=c..tostring(b[d]).."\t"end;c=c:sub(1,-2)a.tty.print(c)end;function printf(e,...)coroutine.yield()local c=string.format(e,...)a.tty.print(c)end;function printInline(...)coroutine.yield()local b={...}local c=""for d=1,#b do c=c..tostring(b[d]).."\t"end;c=c:sub(1,-2)a.tty.printInline(c)end
|
||||||
function print(...)
|
|
||||||
coroutine.yield()
|
|
||||||
local args={...}
|
|
||||||
local output=""
|
|
||||||
for i=1,#args do
|
|
||||||
output=output..tostring(args[i]).."\t"
|
|
||||||
end
|
|
||||||
output=output:sub(1,-2)
|
|
||||||
kernel.tty.print(output)
|
|
||||||
end
|
|
||||||
|
|
||||||
function printf(fmt, ...)
|
|
||||||
coroutine.yield()
|
|
||||||
local output=string.format(fmt,...)
|
|
||||||
kernel.tty.print(output)
|
|
||||||
end
|
|
||||||
|
|
||||||
function printInline(...)
|
|
||||||
coroutine.yield()
|
|
||||||
local args={...}
|
|
||||||
local output=""
|
|
||||||
for i=1,#args do
|
|
||||||
output=output..tostring(args[i]).."\t"
|
|
||||||
end
|
|
||||||
output=output:sub(1,-2)
|
|
||||||
kernel.tty.printInline(output)
|
|
||||||
end
|
|
||||||
@@ -1,44 +1 @@
|
|||||||
local kernel = ...
|
local a=...a.log("Loading init system...")a.log("InitPath: "..a.config.initPath)local b=a.vfs.open(a.config.initPath,"r")local c=a.vfs.read(b,1024*1024*4)a.vfs.close(b)local d,e=load(c,"@sysinit")if not d then error("Failed to load init system: "..e)end;a.tasks["1"]={coro=coroutine.create(function()local f,e=xpcall(d,debug.traceback,a)if not f then a.panic("Init system crashed: "..tostring(e))else a.panic("Init system exited: "..tostring(e))end end),name="sysinit",status="R",pid=1,tgid=1,user="root",uid=0,fd={},exit="",sleep=0,ivs=0,vs=0,parent=a.kernelTask,siblings=a.kernelTask.children,children={},syscallReturn={},cwd="/",timeSlice=0,lastTime=0,totalTime=0,numRuns=0}a.log("created init task with PID 1")a.log("Initializing init system...")
|
||||||
kernel.log("Loading init system...")
|
|
||||||
kernel.log("InitPath: "..kernel.config.initPath)
|
|
||||||
local handle = kernel.vfs.open(kernel.config.initPath, "r")
|
|
||||||
local data = kernel.vfs.read(handle, 1024 * 1024 * 4)
|
|
||||||
kernel.vfs.close(handle)
|
|
||||||
|
|
||||||
local initFunc, err = load(data, "@sysinit")
|
|
||||||
if not initFunc then
|
|
||||||
error("Failed to load init system: "..err)
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.tasks["1"] = {
|
|
||||||
coro=coroutine.create(function()
|
|
||||||
local ok, err = xpcall(initFunc, debug.traceback, kernel)
|
|
||||||
if not ok then
|
|
||||||
kernel.panic("Init system crashed: "..tostring(err))
|
|
||||||
else
|
|
||||||
kernel.panic("Init system exited: "..tostring(err))
|
|
||||||
end
|
|
||||||
end),
|
|
||||||
name="sysinit",
|
|
||||||
status="R",
|
|
||||||
pid=1,
|
|
||||||
tgid=1,
|
|
||||||
user="root",
|
|
||||||
uid=0,
|
|
||||||
fd={},
|
|
||||||
exit="",
|
|
||||||
sleep=0,
|
|
||||||
ivs=0,
|
|
||||||
vs=0,
|
|
||||||
parent=kernel.kernelTask,
|
|
||||||
siblings=kernel.kernelTask.children,
|
|
||||||
children={},
|
|
||||||
syscallReturn={},
|
|
||||||
cwd="/",
|
|
||||||
timeSlice=0,
|
|
||||||
lastTime=0,
|
|
||||||
totalTime=0,
|
|
||||||
numRuns=0
|
|
||||||
}
|
|
||||||
kernel.log("created init task with PID 1")
|
|
||||||
kernel.log("Initializing init system...")
|
|
||||||
+1
-1
@@ -76,7 +76,7 @@ local function serialize(table, seen)
|
|||||||
end
|
end
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
kernel.log(serialize(kernel.tasks))
|
--kernel.log(serialize(kernel.tasks))
|
||||||
kernel.saveLog()
|
kernel.saveLog()
|
||||||
sleep(1000)
|
sleep(1000)
|
||||||
end
|
end
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"Name": "Hyperion bash",
|
"Name": "Hyperion bash",
|
||||||
"Version": "1.0.0",
|
"Version": "1.0.0",
|
||||||
"Publishers": ["HyperionOS Dev Team"],
|
"Publishers": ["HyperionOS Dev Team"],
|
||||||
"Description": "basic bash shell",
|
"Description": "basic bash shell",
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-core-v1.0.0.pkg"
|
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-core-v1.0.0.pkg"
|
||||||
],
|
],
|
||||||
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-bash-v1.0.0.tar"
|
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-bash-v1.0.0.tar"
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,24 @@
|
|||||||
local args={...}
|
local args={...}
|
||||||
<<<<<<< HEAD
|
<<<<<<< HEAD
|
||||||
local sys = require("sys")
|
local sys = require("sys")
|
||||||
=======
|
=======
|
||||||
local os=require("os")
|
local os=require("os")
|
||||||
local io=require("io")
|
local io=require("io")
|
||||||
local text=""
|
local text=""
|
||||||
local blockKeyEvents=false
|
local blockKeyEvents=false
|
||||||
io.link(io.focas)
|
io.link(io.focas)
|
||||||
|
|
||||||
os.hookSignal("keyTyped", function(_, screen, key)
|
os.hookSignal("keyTyped", function(_, screen, key)
|
||||||
if blockKeyEvents then return end
|
if blockKeyEvents then return end
|
||||||
if key == "\n" then
|
if key == "\n" then
|
||||||
blockKeyEvents=true
|
blockKeyEvents=true
|
||||||
elseif key == "\b" then
|
elseif key == "\b" then
|
||||||
text=text:sub(1,#text-1)
|
text=text:sub(1,#text-1)
|
||||||
io.stdout.printInline("\b")
|
io.stdout.printInline("\b")
|
||||||
else
|
else
|
||||||
text=text..key
|
text=text..key
|
||||||
io.stdout.printInline(key)
|
io.stdout.printInline(key)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
>>>>>>> 9b268810a7ea44e586d5faf6e2717f1d02497c03
|
>>>>>>> 9b268810a7ea44e586d5faf6e2717f1d02497c03
|
||||||
File renamed without changes.
File renamed without changes.
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"Name": "Hyperion core",
|
"Name": "Hyperion core",
|
||||||
"Version": "1.0.0",
|
"Version": "1.0.0",
|
||||||
"Publishers": ["HyperionOS Dev Team"],
|
"Publishers": ["HyperionOS Dev Team"],
|
||||||
"Description": "Core system files and librarys for HyperionOS",
|
"Description": "Core system files and librarys for HyperionOS",
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.pkg"
|
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.pkg"
|
||||||
],
|
],
|
||||||
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-core-v1.0.0.tar"
|
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-core-v1.0.0.tar"
|
||||||
}
|
}
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"Name": "Hyperion CCT Firmware",
|
"Name": "Hyperion CCT Firmware",
|
||||||
"Version": "1.0.0",
|
"Version": "1.0.0",
|
||||||
"Publishers": ["HyperionOS Dev Team"],
|
"Publishers": ["HyperionOS Dev Team"],
|
||||||
"Description": "The ComputerCraftTweaked firmware package for HyperionOS.",
|
"Description": "The ComputerCraftTweaked firmware package for HyperionOS.",
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.pkg"
|
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.pkg"
|
||||||
],
|
],
|
||||||
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-firmware-cct-v1.0.0.tar",
|
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-firmware-cct-v1.0.0.tar",
|
||||||
"BuildCommand": "sudo cp boot/cct/eeprom /dev/eeprom"
|
"BuildCommand": "sudo cp boot/cct/eeprom /dev/eeprom"
|
||||||
}
|
}
|
||||||
+310
-310
@@ -1,311 +1,311 @@
|
|||||||
local BOOT_DRIVE_PATH="/$"
|
local BOOT_DRIVE_PATH="/$"
|
||||||
local term = term
|
local term = term
|
||||||
local os = os
|
local os = os
|
||||||
-- Function to write text to the terminal with special character handling
|
-- Function to write text to the terminal with special character handling
|
||||||
local function write(text)
|
local function write(text)
|
||||||
local x, y = term.getCursorPos()
|
local x, y = term.getCursorPos()
|
||||||
local w, h = term.getSize()
|
local w, h = term.getSize()
|
||||||
|
|
||||||
for i = 1, #text do
|
for i = 1, #text do
|
||||||
local c = text:sub(i, i)
|
local c = text:sub(i, i)
|
||||||
|
|
||||||
if c == "\n" then
|
if c == "\n" then
|
||||||
y = y + 1
|
y = y + 1
|
||||||
x = 1
|
x = 1
|
||||||
elseif c == "\t" then
|
elseif c == "\t" then
|
||||||
local tabSize = 4
|
local tabSize = 4
|
||||||
local spaces = tabSize - ((x - 1) % tabSize)
|
local spaces = tabSize - ((x - 1) % tabSize)
|
||||||
term.write(string.rep(" ", spaces))
|
term.write(string.rep(" ", spaces))
|
||||||
x = x + spaces
|
x = x + spaces
|
||||||
elseif c == "\b" then
|
elseif c == "\b" then
|
||||||
if x > 1 then
|
if x > 1 then
|
||||||
x = x - 1
|
x = x - 1
|
||||||
term.setCursorPos(x, y)
|
term.setCursorPos(x, y)
|
||||||
term.write(" ")
|
term.write(" ")
|
||||||
term.setCursorPos(x, y)
|
term.setCursorPos(x, y)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if x <= w and y <= h then
|
if x <= w and y <= h then
|
||||||
term.setCursorPos(x, y)
|
term.setCursorPos(x, y)
|
||||||
term.write(c)
|
term.write(c)
|
||||||
x = x + 1
|
x = x + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Handle wrapping if we go past right edge
|
-- Handle wrapping if we go past right edge
|
||||||
if x > w then
|
if x > w then
|
||||||
x = 1
|
x = 1
|
||||||
y = y + 1
|
y = y + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Handle scrolling if we go past bottom
|
-- Handle scrolling if we go past bottom
|
||||||
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)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
term.setCursorPos(x, y)
|
term.setCursorPos(x, y)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Function to display critical errors and halt the system
|
-- Function to display critical errors and halt the system
|
||||||
local function displaySuperBadError(err)
|
local function displaySuperBadError(err)
|
||||||
term.setBackgroundColor(0x1)
|
term.setBackgroundColor(0x1)
|
||||||
term.setTextColor(0x4)
|
term.setTextColor(0x4)
|
||||||
term.clear()
|
term.clear()
|
||||||
term.setCursorPos(1, 1)
|
term.setCursorPos(1, 1)
|
||||||
term.write("A critical error occurred while loading the system:")
|
term.write("A critical error occurred while loading the system:")
|
||||||
term.setCursorPos(1, 3)
|
term.setCursorPos(1, 3)
|
||||||
write(err)
|
write(err)
|
||||||
while true do end
|
while true do end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Wrap all in xpcall to catch errors
|
-- Wrap all in xpcall to catch errors
|
||||||
local ok, err = xpcall(function()
|
local ok, err = xpcall(function()
|
||||||
local apis={}
|
local apis={}
|
||||||
|
|
||||||
-- List of standard Lua globals
|
-- List of standard Lua globals
|
||||||
local lua = {
|
local lua = {
|
||||||
coroutine = true,
|
coroutine = true,
|
||||||
debug = true,
|
debug = true,
|
||||||
_HOST = true,
|
_HOST = true,
|
||||||
_VERSION = true,
|
_VERSION = true,
|
||||||
assert = true,
|
assert = true,
|
||||||
collectgarbage = true,
|
collectgarbage = true,
|
||||||
error = true,
|
error = true,
|
||||||
gcinfo = true,
|
gcinfo = true,
|
||||||
getfenv = true,
|
getfenv = true,
|
||||||
getmetatable = true,
|
getmetatable = true,
|
||||||
ipairs = true,
|
ipairs = true,
|
||||||
__inext = true,
|
__inext = true,
|
||||||
load = true,
|
load = true,
|
||||||
math = true,
|
math = true,
|
||||||
next = true,
|
next = true,
|
||||||
pairs = true,
|
pairs = true,
|
||||||
pcall = true,
|
pcall = true,
|
||||||
rawequal = true,
|
rawequal = true,
|
||||||
rawget = true,
|
rawget = true,
|
||||||
rawlen = true,
|
rawlen = true,
|
||||||
rawset = true,
|
rawset = true,
|
||||||
select = true,
|
select = true,
|
||||||
setfenv = true,
|
setfenv = true,
|
||||||
setmetatable = true,
|
setmetatable = true,
|
||||||
string = true,
|
string = true,
|
||||||
table = true,
|
table = true,
|
||||||
tonumber = true,
|
tonumber = true,
|
||||||
tostring = true,
|
tostring = true,
|
||||||
type = true,
|
type = true,
|
||||||
xpcall = true,
|
xpcall = true,
|
||||||
_G=true
|
_G=true
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Move all non-Lua standard library globals into the apis table
|
-- Move all non-Lua standard library globals into the apis table
|
||||||
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
|
||||||
|
|
||||||
function sleep(time)
|
function sleep(time)
|
||||||
local stoptime = apis.os.clock() + (time)
|
local stoptime = apis.os.clock() + (time)
|
||||||
while stoptime > apis.os.clock() do end
|
while stoptime > apis.os.clock() do end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set up terminal default colors
|
-- Set up terminal default colors
|
||||||
apis.term.setPaletteColor(0x1, 0x000000) -- #000000
|
apis.term.setPaletteColor(0x1, 0x000000) -- #000000
|
||||||
apis.term.setPaletteColor(0x2, 0xFFFFFF) -- #FFFFFF
|
apis.term.setPaletteColor(0x2, 0xFFFFFF) -- #FFFFFF
|
||||||
apis.term.setPaletteColor(0x4, 0xFF0000) -- #FF0000
|
apis.term.setPaletteColor(0x4, 0xFF0000) -- #FF0000
|
||||||
apis.term.setPaletteColor(0x8, 0x00FF00) -- #00FF00
|
apis.term.setPaletteColor(0x8, 0x00FF00) -- #00FF00
|
||||||
apis.term.setPaletteColor(0x10, 0x0000FF) -- #0000FF
|
apis.term.setPaletteColor(0x10, 0x0000FF) -- #0000FF
|
||||||
apis.term.setPaletteColor(0x20, 0x00FFFF) -- #00FFFF
|
apis.term.setPaletteColor(0x20, 0x00FFFF) -- #00FFFF
|
||||||
apis.term.setPaletteColor(0x40, 0xFF00FF) -- #FF00FF
|
apis.term.setPaletteColor(0x40, 0xFF00FF) -- #FF00FF
|
||||||
apis.term.setPaletteColor(0x80, 0xFFFF00) -- #FFFF00
|
apis.term.setPaletteColor(0x80, 0xFFFF00) -- #FFFF00
|
||||||
apis.term.setPaletteColor(0x100, 0xFF6D00) -- #FF6D00
|
apis.term.setPaletteColor(0x100, 0xFF6D00) -- #FF6D00
|
||||||
apis.term.setPaletteColor(0x200, 0x6DFF55) -- #6DFF55
|
apis.term.setPaletteColor(0x200, 0x6DFF55) -- #6DFF55
|
||||||
apis.term.setPaletteColor(0x400, 0x24FFFF) -- #24FFFF
|
apis.term.setPaletteColor(0x400, 0x24FFFF) -- #24FFFF
|
||||||
apis.term.setPaletteColor(0x800, 0x924900) -- #924900
|
apis.term.setPaletteColor(0x800, 0x924900) -- #924900
|
||||||
apis.term.setPaletteColor(0x1000, 0x6D6D55) -- #6D6D55
|
apis.term.setPaletteColor(0x1000, 0x6D6D55) -- #6D6D55
|
||||||
apis.term.setPaletteColor(0x2000, 0xDBDBAA) -- #DBDBAA
|
apis.term.setPaletteColor(0x2000, 0xDBDBAA) -- #DBDBAA
|
||||||
apis.term.setPaletteColor(0x4000, 0x6D00FF) -- #6D00FF
|
apis.term.setPaletteColor(0x4000, 0x6D00FF) -- #6D00FF
|
||||||
apis.term.setPaletteColor(0x8000, 0xB6FF00) -- #B6FF00
|
apis.term.setPaletteColor(0x8000, 0xB6FF00) -- #B6FF00
|
||||||
|
|
||||||
-- Wrapper to read files
|
-- Wrapper to read files
|
||||||
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
|
||||||
|
|
||||||
-- Load kernel first if it fails, we can't continue so we display an error
|
-- Load kernel first if it fails, we can't continue so we display an error
|
||||||
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")()
|
||||||
if not Kernel then
|
if not Kernel then
|
||||||
displaySuperBadError("Could not load kernel.")
|
displaySuperBadError("Could not load kernel.")
|
||||||
end
|
end
|
||||||
if not initFs then
|
if not initFs then
|
||||||
displaySuperBadError("Could not load initdisks.")
|
displaySuperBadError("Could not load initdisks.")
|
||||||
end
|
end
|
||||||
if not fs then
|
if not fs then
|
||||||
displaySuperBadError("Could not load initfs.")
|
displaySuperBadError("Could not load initfs.")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set up event queue
|
-- Set up event queue
|
||||||
local eventQueue = {}
|
local eventQueue = {}
|
||||||
local lkeys={}
|
local lkeys={}
|
||||||
lkeys[apis.keys.enter]="\n"
|
lkeys[apis.keys.enter]="\n"
|
||||||
lkeys[apis.keys.backspace]="\b"
|
lkeys[apis.keys.backspace]="\b"
|
||||||
lkeys[apis.keys.tab]="\t"
|
lkeys[apis.keys.tab]="\t"
|
||||||
|
|
||||||
-- Function to queue events
|
-- Function to queue events
|
||||||
local function queueEvent(event, ...)
|
local function queueEvent(event, ...)
|
||||||
table.insert(eventQueue, {event, ...})
|
table.insert(eventQueue, {event, ...})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set up computer api
|
-- Set up computer api
|
||||||
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()
|
||||||
if #eventQueue > 0 then
|
if #eventQueue > 0 then
|
||||||
return table.unpack(table.remove(eventQueue, 1))
|
return table.unpack(table.remove(eventQueue, 1))
|
||||||
else
|
else
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
getEEPROM = function()
|
getEEPROM = function()
|
||||||
return getFile("/startup.lua")
|
return getFile("/startup.lua")
|
||||||
end,
|
end,
|
||||||
setEEPROM = function(_,text)
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Set up terminal colors
|
-- Set up terminal colors
|
||||||
local icolors={
|
local icolors={
|
||||||
[0x1] =0, -- #000000
|
[0x1] =0, -- #000000
|
||||||
[0x2] =1, -- #FFFFFF
|
[0x2] =1, -- #FFFFFF
|
||||||
[0x4] =2, -- #FF0000
|
[0x4] =2, -- #FF0000
|
||||||
[0x8] =3, -- #00FF00
|
[0x8] =3, -- #00FF00
|
||||||
[0x10] =4, -- #0000FF
|
[0x10] =4, -- #0000FF
|
||||||
[0x20] =5, -- #00FFFF
|
[0x20] =5, -- #00FFFF
|
||||||
[0x40] =6, -- #FF00FF
|
[0x40] =6, -- #FF00FF
|
||||||
[0x80] =7, -- #FFFF00
|
[0x80] =7, -- #FFFF00
|
||||||
[0x100] =8, -- #FF6D00
|
[0x100] =8, -- #FF6D00
|
||||||
[0x200] =9, -- #6DFF55
|
[0x200] =9, -- #6DFF55
|
||||||
[0x400] =10, -- #24FFFF
|
[0x400] =10, -- #24FFFF
|
||||||
[0x800] =11, -- #924900
|
[0x800] =11, -- #924900
|
||||||
[0x1000] =12, -- #6D6D55
|
[0x1000] =12, -- #6D6D55
|
||||||
[0x2000] =13, -- #DBDBAA
|
[0x2000] =13, -- #DBDBAA
|
||||||
[0x4000] =14, -- #6D00FF
|
[0x4000] =14, -- #6D00FF
|
||||||
[0x8000] =15 -- #B6FF00
|
[0x8000] =15 -- #B6FF00
|
||||||
}
|
}
|
||||||
|
|
||||||
local colors={
|
local colors={
|
||||||
[0]=0x0001, -- #000000
|
[0]=0x0001, -- #000000
|
||||||
0x0002, -- #FFFFFF
|
0x0002, -- #FFFFFF
|
||||||
0x0004, -- #FF0000
|
0x0004, -- #FF0000
|
||||||
0x0008, -- #00FF00
|
0x0008, -- #00FF00
|
||||||
0x0010, -- #0000FF
|
0x0010, -- #0000FF
|
||||||
0x0020, -- #00FFFF
|
0x0020, -- #00FFFF
|
||||||
0x0040, -- #FF00FF
|
0x0040, -- #FF00FF
|
||||||
0x0080, -- #FFFF00
|
0x0080, -- #FFFF00
|
||||||
0x0100, -- #FF6D00
|
0x0100, -- #FF6D00
|
||||||
0x0200, -- #6DFF55
|
0x0200, -- #6DFF55
|
||||||
0x0400, -- #24FFFF
|
0x0400, -- #24FFFF
|
||||||
0x0800, -- #924900
|
0x0800, -- #924900
|
||||||
0x1000, -- #6D6D55
|
0x1000, -- #6D6D55
|
||||||
0x2000, -- #DBDBAA
|
0x2000, -- #DBDBAA
|
||||||
0x4000, -- #6D00FF
|
0x4000, -- #6D00FF
|
||||||
0x8000 -- #B6FF00
|
0x8000 -- #B6FF00
|
||||||
}
|
}
|
||||||
|
|
||||||
apis.term.setBackgroundColor(0x1)
|
apis.term.setBackgroundColor(0x1)
|
||||||
apis.term.setTextColor(0x1000)
|
apis.term.setTextColor(0x1000)
|
||||||
apis.term.clear()
|
apis.term.clear()
|
||||||
apis.term.setCursorPos(1, 1)
|
apis.term.setCursorPos(1, 1)
|
||||||
|
|
||||||
-- Make the kernel coroutine so we can hook its execution
|
-- Make the kernel coroutine so we can hook its execution
|
||||||
local kernelCoro = coroutine.create(function()
|
local kernelCoro = coroutine.create(function()
|
||||||
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,
|
print=function(_,text) write(text.."\n") end,
|
||||||
printInline=function(_,text) write(text) end,
|
printInline=function(_,text) write(text) end,
|
||||||
clear=function() apis.term.clear() apis.term.setCursorPos(1,1) end,
|
clear=function() apis.term.clear() apis.term.setCursorPos(1,1) end,
|
||||||
setCursorPos=function(_,x,y) apis.term.setCursorPos(x,y) end,
|
setCursorPos=function(_,x,y) apis.term.setCursorPos(x,y) end,
|
||||||
getCursorPos=function() return apis.term.getCursorPos() end,
|
getCursorPos=function() return apis.term.getCursorPos() end,
|
||||||
getSize=function() return apis.term.getSize() end,
|
getSize=function() return apis.term.getSize() end,
|
||||||
setBackgroundColor=function(_,color) apis.term.setBackgroundColor(colors[color]) end,
|
setBackgroundColor=function(_,color) apis.term.setBackgroundColor(colors[color]) end,
|
||||||
setTextColor=function(_,color) apis.term.setTextColor(colors[color]) end,
|
setTextColor=function(_,color) apis.term.setTextColor(colors[color]) end,
|
||||||
getBackgroundColor=function() return icolors[apis.term.getBackgroundColor()] end,
|
getBackgroundColor=function() return icolors[apis.term.getBackgroundColor()] end,
|
||||||
getTextColor=function() return icolors[apis.term.getTextColor()] end
|
getTextColor=function() return icolors[apis.term.getTextColor()] end
|
||||||
}, computer, fs, "$")
|
}, computer, fs, "$")
|
||||||
if not ok then
|
if not ok then
|
||||||
displaySuperBadError(err)
|
displaySuperBadError(err)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Diffine a coroutine.resumeWithTimeout function to avoid hanging the system, time is in milliseconds
|
-- Diffine a coroutine.resumeWithTimeout function to avoid hanging the system, time is in milliseconds
|
||||||
function coroutine.resumeWithTimeout(co, timeout, ...)
|
function coroutine.resumeWithTimeout(co, timeout, ...)
|
||||||
local startTime = computer.time()
|
local startTime = computer.time()
|
||||||
debug.sethook(co, function()
|
debug.sethook(co, function()
|
||||||
if computer.time() > startTime + timeout then
|
if computer.time() > startTime + timeout then
|
||||||
return coroutine.yield("timeout")
|
return coroutine.yield("timeout")
|
||||||
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)
|
||||||
return "success", table.unpack(ret, 2)
|
return "success", table.unpack(ret, 2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
write("Loaded in "..tostring(apis.os.clock()).." seconds.\n")
|
write("Loaded in "..tostring(apis.os.clock()).." seconds.\n")
|
||||||
|
|
||||||
-- Main loop to run the kernel coroutine
|
-- Main loop to run the kernel coroutine
|
||||||
while true do
|
while true do
|
||||||
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
|
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
|
||||||
apis.os.queueEvent("NoSleep")
|
apis.os.queueEvent("NoSleep")
|
||||||
local exit = false
|
local exit = false
|
||||||
while not exit do
|
while not exit do
|
||||||
local event = {coroutine.yield()}
|
local event = {coroutine.yield()}
|
||||||
if event[1] == "char" then
|
if event[1] == "char" then
|
||||||
queueEvent("keyTyped", 1, event[2])
|
queueEvent("keyTyped", 1, event[2])
|
||||||
elseif event[1] == "key" then
|
elseif event[1] == "key" then
|
||||||
queueEvent("keyPressed", 1, event[2])
|
queueEvent("keyPressed", 1, event[2])
|
||||||
if lkeys[event[2]] then
|
if lkeys[event[2]] then
|
||||||
queueEvent("keyTyped", 1, lkeys[event[2]])
|
queueEvent("keyTyped", 1, lkeys[event[2]])
|
||||||
end
|
end
|
||||||
elseif event[1] == "key_up" then
|
elseif event[1] == "key_up" then
|
||||||
queueEvent("keyReleased", 1, event[2])
|
queueEvent("keyReleased", 1, event[2])
|
||||||
elseif event[1] == "disk" then
|
elseif event[1] == "disk" then
|
||||||
queueEvent("componentAdded", "disk")
|
queueEvent("componentAdded", "disk")
|
||||||
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)
|
displaySuperBadError("Fatal error during boot: "..err)
|
||||||
end
|
end
|
||||||
while true do coroutine.yield() end
|
while true do coroutine.yield() end
|
||||||
+120
-120
@@ -1,121 +1,121 @@
|
|||||||
sleep(1)
|
sleep(1)
|
||||||
local BOOT_DRIVE_PATH="/$"
|
local BOOT_DRIVE_PATH="/$"
|
||||||
-- UnBIOS by JackMacWindows
|
-- UnBIOS by JackMacWindows
|
||||||
-- This will undo most of the changes/additions made in the BIOS, but some things may remain wrapped if `debug` is unavailable
|
-- This will undo most of the changes/additions made in the BIOS, but some things may remain wrapped if `debug` is unavailable
|
||||||
-- To use, just place a `bios.lua` in the root of the drive, and run this program
|
-- To use, just place a `bios.lua` in the root of the drive, and run this program
|
||||||
-- Here's a list of things that are irreversibly changed:
|
-- Here's a list of things that are irreversibly changed:
|
||||||
-- * both `bit` and `bit32` are kept for compatibility
|
-- * both `bit` and `bit32` are kept for compatibility
|
||||||
-- * string metatable blocking (on old versions of CC)
|
-- * string metatable blocking (on old versions of CC)
|
||||||
-- In addition, if `debug` is not available these things are also irreversibly changed:
|
-- In addition, if `debug` is not available these things are also irreversibly changed:
|
||||||
-- * old Lua 5.1 `load` function (for loading from a function)
|
-- * old Lua 5.1 `load` function (for loading from a function)
|
||||||
-- * `loadstring` prefixing (before CC:T 1.96.0)
|
-- * `loadstring` prefixing (before CC:T 1.96.0)
|
||||||
-- * `http.request`
|
-- * `http.request`
|
||||||
-- * `os.shutdown` and `os.reboot`
|
-- * `os.shutdown` and `os.reboot`
|
||||||
-- * `peripheral`
|
-- * `peripheral`
|
||||||
-- * `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
|
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
|
||||||
for _,k in ipairs(t) do _G[k] = nil end
|
for _,k in ipairs(t) do _G[k] = nil end
|
||||||
local native = _G.term.native()
|
local native = _G.term.native()
|
||||||
for _, method in ipairs {"nativePaletteColor", "nativePaletteColour", "screenshot"} do native[method] = _G.term[method] end
|
for _, method in ipairs {"nativePaletteColor", "nativePaletteColour", "screenshot"} do native[method] = _G.term[method] end
|
||||||
_G.term = native
|
_G.term = native
|
||||||
if _G.http then
|
if _G.http then
|
||||||
_G.http.checkURL = _G.http.checkURLAsync
|
_G.http.checkURL = _G.http.checkURLAsync
|
||||||
_G.http.websocket = _G.http.websocketAsync
|
_G.http.websocket = _G.http.websocketAsync
|
||||||
end
|
end
|
||||||
if _G.commands then _G.commands = _G.commands.native end
|
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)"
|
_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
|
||||||
-- empty placeholder to let it continue and return without throwing. This results
|
-- empty placeholder to let it continue and return without throwing. This results
|
||||||
-- in the `pcall` returning successfully, preventing the error-displaying code
|
-- in the `pcall` returning successfully, preventing the error-displaying code
|
||||||
-- from running - essentially making it so that `os.shutdown` is called immediately
|
-- from running - essentially making it so that `os.shutdown` is called immediately
|
||||||
-- after the new BIOS exits.
|
-- after the new BIOS exits.
|
||||||
--
|
--
|
||||||
-- From there, the setup code is placed in `term.native` since it's the first
|
-- From there, the setup code is placed in `term.native` since it's the first
|
||||||
-- thing called after `parallel` exits. This loads the new BIOS and prepares it
|
-- thing called after `parallel` exits. This loads the new BIOS and prepares it
|
||||||
-- for execution. Finally, it overwrites `os.shutdown` with the new function to
|
-- for execution. Finally, it overwrites `os.shutdown` with the new function to
|
||||||
-- allow it to be the last function called in the original BIOS, and returns.
|
-- allow it to be the last function called in the original BIOS, and returns.
|
||||||
-- From there execution continues, calling the `term.redirect` dummy, skipping
|
-- From there execution continues, calling the `term.redirect` dummy, skipping
|
||||||
-- over the error-handling code (since `pcall` returned ok), and calling
|
-- over the error-handling code (since `pcall` returned ok), and calling
|
||||||
-- `os.shutdown()`. The real `os.shutdown` is re-added, and the new BIOS is tail
|
-- `os.shutdown()`. The real `os.shutdown` is re-added, and the new BIOS is tail
|
||||||
-- called, which effectively makes it run as the main chunk.
|
-- called, which effectively makes it run as the main chunk.
|
||||||
local olderror = error
|
local olderror = error
|
||||||
_G.error = function() end
|
_G.error = function() end
|
||||||
_G.term.redirect = function() end
|
_G.term.redirect = function() end
|
||||||
function _G.term.native()
|
function _G.term.native()
|
||||||
_G.term.native = nil
|
_G.term.native = nil
|
||||||
_G.term.redirect = nil
|
_G.term.redirect = nil
|
||||||
_G.error = olderror
|
_G.error = olderror
|
||||||
term.setBackgroundColor(32768)
|
term.setBackgroundColor(32768)
|
||||||
term.setTextColor(1)
|
term.setTextColor(1)
|
||||||
term.setCursorPos(1, 1)
|
term.setCursorPos(1, 1)
|
||||||
term.setCursorBlink(true)
|
term.setCursorBlink(true)
|
||||||
term.clear()
|
term.clear()
|
||||||
local file = fs.open(BOOT_DRIVE_PATH.."/boot/cct/boot.lua", "r")
|
local file = fs.open(BOOT_DRIVE_PATH.."/boot/cct/boot.lua", "r")
|
||||||
if file == nil then
|
if file == nil then
|
||||||
term.setCursorBlink(false)
|
term.setCursorBlink(false)
|
||||||
term.setTextColor(16384)
|
term.setTextColor(16384)
|
||||||
term.write("Could not find /boot/cct/boot.lua. UnBIOS cannot continue.")
|
term.write("Could not find /boot/cct/boot.lua. UnBIOS cannot continue.")
|
||||||
term.setCursorPos(1, 2)
|
term.setCursorPos(1, 2)
|
||||||
term.write("Press any key to continue")
|
term.write("Press any key to continue")
|
||||||
coroutine.yield("key")
|
coroutine.yield("key")
|
||||||
os.shutdown()
|
os.shutdown()
|
||||||
end
|
end
|
||||||
local fn, err = loadstring(file.readAll(), "@bootloader")
|
local fn, err = loadstring(file.readAll(), "@bootloader")
|
||||||
file.close()
|
file.close()
|
||||||
if fn == nil then
|
if fn == nil then
|
||||||
term.setCursorBlink(false)
|
term.setCursorBlink(false)
|
||||||
term.setTextColor(16384)
|
term.setTextColor(16384)
|
||||||
term.write("Could not load /boot/cc/boot.lua. UnBIOS cannot continue.")
|
term.write("Could not load /boot/cc/boot.lua. UnBIOS cannot continue.")
|
||||||
term.setCursorPos(1, 2)
|
term.setCursorPos(1, 2)
|
||||||
term.write(err)
|
term.write(err)
|
||||||
term.setCursorPos(1, 3)
|
term.setCursorPos(1, 3)
|
||||||
term.write("Press any key to continue")
|
term.write("Press any key to continue")
|
||||||
coroutine.yield("key")
|
coroutine.yield("key")
|
||||||
os.shutdown()
|
os.shutdown()
|
||||||
end
|
end
|
||||||
setfenv(fn, _G)
|
setfenv(fn, _G)
|
||||||
local oldshutdown = os.shutdown
|
local oldshutdown = os.shutdown
|
||||||
os.shutdown = function()
|
os.shutdown = function()
|
||||||
os.shutdown = oldshutdown
|
os.shutdown = oldshutdown
|
||||||
return fn(table.unpack(args))
|
return fn(table.unpack(args))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if debug then
|
if debug then
|
||||||
-- Restore functions that were overwritten in the BIOS
|
-- Restore functions that were overwritten in the BIOS
|
||||||
-- Apparently this has to be done *after* redefining term.native
|
-- Apparently this has to be done *after* redefining term.native
|
||||||
local function restoreValue(tab, idx, name, hint)
|
local function restoreValue(tab, idx, name, hint)
|
||||||
local i, key, value = 1, debug.getupvalue(tab[idx], hint)
|
local i, key, value = 1, debug.getupvalue(tab[idx], hint)
|
||||||
while key ~= name and key ~= nil do
|
while key ~= name and key ~= nil do
|
||||||
key, value = debug.getupvalue(tab[idx], i)
|
key, value = debug.getupvalue(tab[idx], i)
|
||||||
i=i+1
|
i=i+1
|
||||||
end
|
end
|
||||||
tab[idx] = value or tab[idx]
|
tab[idx] = value or tab[idx]
|
||||||
end
|
end
|
||||||
restoreValue(_G, "loadstring", "nativeloadstring", 1)
|
restoreValue(_G, "loadstring", "nativeloadstring", 1)
|
||||||
restoreValue(_G, "load", "nativeload", 5)
|
restoreValue(_G, "load", "nativeload", 5)
|
||||||
if http then restoreValue(http, "request", "nativeHTTPRequest", 3) end
|
if http then restoreValue(http, "request", "nativeHTTPRequest", 3) end
|
||||||
restoreValue(os, "shutdown", "nativeShutdown", 1)
|
restoreValue(os, "shutdown", "nativeShutdown", 1)
|
||||||
restoreValue(os, "reboot", "nativeReboot", 1)
|
restoreValue(os, "reboot", "nativeReboot", 1)
|
||||||
if turtle then
|
if turtle then
|
||||||
restoreValue(turtle, "equipLeft", "v", 1)
|
restoreValue(turtle, "equipLeft", "v", 1)
|
||||||
restoreValue(turtle, "equipRight", "v", 1)
|
restoreValue(turtle, "equipRight", "v", 1)
|
||||||
end
|
end
|
||||||
do
|
do
|
||||||
local i, key, value = 1, debug.getupvalue(peripheral.isPresent, 2)
|
local i, key, value = 1, debug.getupvalue(peripheral.isPresent, 2)
|
||||||
while key ~= "native" and key ~= nil do
|
while key ~= "native" and key ~= nil do
|
||||||
key, value = debug.getupvalue(peripheral.isPresent, i)
|
key, value = debug.getupvalue(peripheral.isPresent, i)
|
||||||
i=i+1
|
i=i+1
|
||||||
end
|
end
|
||||||
_G.peripheral = value or peripheral
|
_G.peripheral = value or peripheral
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
+191
-191
@@ -1,191 +1,191 @@
|
|||||||
local apis = ({...})[1]
|
local apis = ({...})[1]
|
||||||
local BOOT_DRIVE_PATH="/$"
|
local BOOT_DRIVE_PATH="/$"
|
||||||
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)
|
return native.getType(name)
|
||||||
end
|
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
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function peripheral.getNames()
|
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)
|
table.insert(names, side)
|
||||||
end
|
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
|
||||||
table.insert(names, hubSide)
|
table.insert(names, hubSide)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return names
|
return names
|
||||||
end
|
end
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
-- STORAGE
|
-- STORAGE
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
local disks = {} -- real disks
|
local disks = {} -- real disks
|
||||||
local internal = {} -- "$" disk
|
local internal = {} -- "$" disk
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
-- HELPERS
|
-- 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
|
--- 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)
|
return fs.getCapacity(basePath)
|
||||||
end
|
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
|
||||||
|
|
||||||
function disk:fileExists(path)
|
function disk:fileExists(path)
|
||||||
local p = fs.combine(basePath, path)
|
local p = fs.combine(basePath, path)
|
||||||
return fs.exists(p) and not fs.isDir(p)
|
return fs.exists(p) and not fs.isDir(p)
|
||||||
end
|
end
|
||||||
|
|
||||||
function disk:directoryExists(path)
|
function disk:directoryExists(path)
|
||||||
local p = fs.combine(basePath, path)
|
local p = fs.combine(basePath, path)
|
||||||
return fs.exists(p) and fs.isDir(p)
|
return fs.exists(p) and fs.isDir(p)
|
||||||
end
|
end
|
||||||
|
|
||||||
function disk:type(path)
|
function disk:type(path)
|
||||||
local p = fs.combine(basePath, path)
|
local p = fs.combine(basePath, path)
|
||||||
if not fs.exists(p) then
|
if not fs.exists(p) then
|
||||||
return nil
|
return nil
|
||||||
elseif fs.isDir(p) then
|
elseif fs.isDir(p) then
|
||||||
return "directory"
|
return "directory"
|
||||||
else
|
else
|
||||||
return "file"
|
return "file"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function disk:makeDirectory(path)
|
function disk:makeDirectory(path)
|
||||||
local p = fs.combine(basePath, path)
|
local p = fs.combine(basePath, path)
|
||||||
fs.makeDir(p)
|
fs.makeDir(p)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function disk:remove(path)
|
function disk:remove(path)
|
||||||
local p = fs.combine(basePath, path)
|
local p = fs.combine(basePath, path)
|
||||||
if fs.exists(p) then fs.delete(p) end
|
if fs.exists(p) then fs.delete(p) end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function disk:setLabel(label)
|
function disk:setLabel(label)
|
||||||
periph.setLabel(label)
|
periph.setLabel(label)
|
||||||
end
|
end
|
||||||
|
|
||||||
function disk:getLabel(label)
|
function disk:getLabel(label)
|
||||||
return periph.getLabel()
|
return periph.getLabel()
|
||||||
end
|
end
|
||||||
|
|
||||||
function disk:attributes(path)
|
function disk:attributes(path)
|
||||||
local p = fs.combine(basePath, path)
|
local p = fs.combine(basePath, path)
|
||||||
return fs.attributes(p)
|
return fs.attributes(p)
|
||||||
end
|
end
|
||||||
|
|
||||||
function disk:open(path, mode)
|
function disk:open(path, mode)
|
||||||
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 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")
|
||||||
local label = h.readAll()
|
local label = h.readAll()
|
||||||
h.close()
|
h.close()
|
||||||
return label
|
return label
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
-- SCAN REAL DISK PERIPHERALS
|
-- SCAN REAL DISK PERIPHERALS
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
local function refresh()
|
local function refresh()
|
||||||
-- remove disks that no longer exist
|
-- 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
|
disks[id] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- detect new disks
|
-- 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
|
||||||
local mount = disk.getMountPath(name)
|
local mount = disk.getMountPath(name)
|
||||||
if mount then
|
if mount then
|
||||||
disks[name] = createDisk(name, mount, false, disk)
|
disks[name] = createDisk(name, mount, false, disk)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
-- ITERATOR
|
-- ITERATOR
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
local function iter()
|
local function iter()
|
||||||
refresh()
|
refresh()
|
||||||
-- first internal
|
-- first internal
|
||||||
local combined = {}
|
local combined = {}
|
||||||
|
|
||||||
for id, obj in pairs(internal) do
|
for id, obj in pairs(internal) do
|
||||||
combined[id] = obj
|
combined[id] = obj
|
||||||
end
|
end
|
||||||
for id, obj in pairs(disks) do
|
for id, obj in pairs(disks) do
|
||||||
combined[id] = obj
|
combined[id] = obj
|
||||||
end
|
end
|
||||||
|
|
||||||
return pairs(combined)
|
return pairs(combined)
|
||||||
end
|
end
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
-- MODULE RETURN
|
-- MODULE RETURN
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
return {
|
return {
|
||||||
refresh = refresh,
|
refresh = refresh,
|
||||||
list = iter
|
list = iter
|
||||||
}
|
}
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"Name": "Hyperion OC Firmware",
|
"Name": "Hyperion OC Firmware",
|
||||||
"Version": "1.0.0",
|
"Version": "1.0.0",
|
||||||
"Publishers": ["HyperionOS Dev Team"],
|
"Publishers": ["HyperionOS Dev Team"],
|
||||||
"Description": "The OpenComputers firmware package for HyperionOS.",
|
"Description": "The OpenComputers firmware package for HyperionOS.",
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.pkg"
|
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.pkg"
|
||||||
],
|
],
|
||||||
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-firmware-oc-v1.0.0.tar",
|
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-firmware-oc-v1.0.0.tar",
|
||||||
"BuildCommand": "cp boot/oc/eeprom /dev/eeprom"
|
"BuildCommand": "cp boot/oc/eeprom /dev/eeprom"
|
||||||
}
|
}
|
||||||
+39
-39
@@ -1,40 +1,40 @@
|
|||||||
local lua = {
|
local lua = {
|
||||||
coroutine = true,
|
coroutine = true,
|
||||||
debug = true,
|
debug = true,
|
||||||
_HOST = true,
|
_HOST = true,
|
||||||
_VERSION = true,
|
_VERSION = true,
|
||||||
assert = true,
|
assert = true,
|
||||||
collectgarbage = true,
|
collectgarbage = true,
|
||||||
error = true,
|
error = true,
|
||||||
gcinfo = true,
|
gcinfo = true,
|
||||||
getfenv = true,
|
getfenv = true,
|
||||||
getmetatable = true,
|
getmetatable = true,
|
||||||
ipairs = true,
|
ipairs = true,
|
||||||
__inext = true,
|
__inext = true,
|
||||||
load = true,
|
load = true,
|
||||||
math = true,
|
math = true,
|
||||||
next = true,
|
next = true,
|
||||||
pairs = true,
|
pairs = true,
|
||||||
pcall = true,
|
pcall = true,
|
||||||
rawequal = true,
|
rawequal = true,
|
||||||
rawget = true,
|
rawget = true,
|
||||||
rawlen = true,
|
rawlen = true,
|
||||||
rawset = true,
|
rawset = true,
|
||||||
select = true,
|
select = true,
|
||||||
setfenv = true,
|
setfenv = true,
|
||||||
setmetatable = true,
|
setmetatable = true,
|
||||||
string = true,
|
string = true,
|
||||||
table = true,
|
table = true,
|
||||||
tonumber = true,
|
tonumber = true,
|
||||||
tostring = true,
|
tostring = true,
|
||||||
type = true,
|
type = true,
|
||||||
xpcall = true,
|
xpcall = true,
|
||||||
_G=true
|
_G=true
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
+17
-17
@@ -1,18 +1,18 @@
|
|||||||
checkArg=nil
|
checkArg=nil
|
||||||
local oldcomputer=computer
|
local oldcomputer=computer
|
||||||
_G.computer=nil
|
_G.computer=nil
|
||||||
local os=os
|
local os=os
|
||||||
_G.os=nil
|
_G.os=nil
|
||||||
|
|
||||||
function component.wrap(address)
|
function component.wrap(address)
|
||||||
local methods=oldcomponent.methods(address)
|
local methods=oldcomponent.methods(address)
|
||||||
local object={}
|
local object={}
|
||||||
for _,method in ipairs(methods) do
|
for _,method in ipairs(methods) do
|
||||||
object[method]=function(_,...)
|
object[method]=function(_,...)
|
||||||
return oldcomponent.invoke(address,method,...)
|
return oldcomponent.invoke(address,method,...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return object
|
return object
|
||||||
end
|
end
|
||||||
|
|
||||||
local
|
local
|
||||||
File renamed without changes.
File renamed without changes.
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"Name": "Hyperion Kernel",
|
"Name": "Hyperion Kernel",
|
||||||
"Version": "1.0.0",
|
"Version": "1.0.0",
|
||||||
"Publishers": ["HyperionOS Dev Team"],
|
"Publishers": ["HyperionOS Dev Team"],
|
||||||
"Description": "The kernel package for HyperionOS.",
|
"Description": "The kernel package for HyperionOS.",
|
||||||
"Dependencies": [],
|
"Dependencies": [],
|
||||||
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.tar"
|
"Tar": "https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.tar"
|
||||||
}
|
}
|
||||||
File renamed without changes.
@@ -1,77 +1,78 @@
|
|||||||
local fs = {}
|
--:Minify:--
|
||||||
local disks = {}
|
local fs = {}
|
||||||
local mounts = {}
|
local disks = {}
|
||||||
|
local mounts = {}
|
||||||
local function resolve(path)
|
|
||||||
local mountPoint = "/"
|
local function resolve(path)
|
||||||
for mount, disk in pairs(mounts) do
|
local mountPoint = "/"
|
||||||
if path:sub(1, #mount) == mount then
|
for mount, disk in pairs(mounts) do
|
||||||
if not mountPoint or #mount > #mountPoint then
|
if path:sub(1, #mount) == mount then
|
||||||
mountPoint = mount
|
if not mountPoint or #mount > #mountPoint then
|
||||||
end
|
mountPoint = mount
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local newPath = path:sub(#mountPoint + 1)
|
end
|
||||||
return disks[mounts[mountPoint]], newPath
|
local newPath = path:sub(#mountPoint + 1)
|
||||||
end
|
return disks[mounts[mountPoint]], newPath
|
||||||
---------------------------------------------------------
|
end
|
||||||
|
---------------------------------------------------------
|
||||||
function fs.update(initdisks)
|
|
||||||
disks = {}
|
function fs.update(initdisks)
|
||||||
for k, v in initdisks.list() do
|
disks = {}
|
||||||
disks[k] = v
|
for k, v in initdisks.list() do
|
||||||
end
|
disks[k] = v
|
||||||
end
|
end
|
||||||
|
end
|
||||||
function fs.exists(path)
|
|
||||||
local disk, newPath = resolve(path)
|
function fs.exists(path)
|
||||||
return disk:directoryExists(newPath) or disk:fileExists(newPath)
|
local disk, newPath = resolve(path)
|
||||||
end
|
return disk:directoryExists(newPath) or disk:fileExists(newPath)
|
||||||
function fs.isFile(path)
|
end
|
||||||
local disk, newPath = resolve(path)
|
function fs.isFile(path)
|
||||||
return disk:fileExists(newPath)
|
local disk, newPath = resolve(path)
|
||||||
end
|
return disk:fileExists(newPath)
|
||||||
function fs.isDir(path)
|
end
|
||||||
local disk, newPath = resolve(path)
|
function fs.isDir(path)
|
||||||
return disk:directoryExists(newPath)
|
local disk, newPath = resolve(path)
|
||||||
end
|
return disk:directoryExists(newPath)
|
||||||
function fs.list(path)
|
end
|
||||||
local disk, newPath = resolve(path)
|
function fs.list(path)
|
||||||
return disk:list(newPath)
|
local disk, newPath = resolve(path)
|
||||||
end
|
return disk:list(newPath)
|
||||||
function fs.makeDir(path)
|
end
|
||||||
local disk, newPath = resolve(path)
|
function fs.makeDir(path)
|
||||||
return disk:makeDirectory(newPath)
|
local disk, newPath = resolve(path)
|
||||||
end
|
return disk:makeDirectory(newPath)
|
||||||
function fs.remove(path)
|
end
|
||||||
local disk, newPath = resolve(path)
|
function fs.remove(path)
|
||||||
return disk:remove(newPath)
|
local disk, newPath = resolve(path)
|
||||||
end
|
return disk:remove(newPath)
|
||||||
function fs.readAllText(path)
|
end
|
||||||
local disk, newPath = resolve(path)
|
function fs.readAllText(path)
|
||||||
local handle = disk:open(newPath, "r")
|
local disk, newPath = resolve(path)
|
||||||
if not handle then return nil end
|
local handle = disk:open(newPath, "r")
|
||||||
local content = handle.readAll()
|
if not handle then return nil end
|
||||||
handle.close()
|
local content = handle.readAll()
|
||||||
return content
|
handle.close()
|
||||||
end
|
return content
|
||||||
function fs.writeAllText(path, text)
|
end
|
||||||
local disk, newPath = resolve(path)
|
function fs.writeAllText(path, text)
|
||||||
local handle = disk:open(newPath, "w")
|
local disk, newPath = resolve(path)
|
||||||
handle.write(text)
|
local handle = disk:open(newPath, "w")
|
||||||
handle.close()
|
handle.write(text)
|
||||||
end
|
handle.close()
|
||||||
function fs.appendAllText(path, text)
|
end
|
||||||
local disk, newPath = resolve(path)
|
function fs.appendAllText(path, text)
|
||||||
local handle = disk:open(newPath, "a")
|
local disk, newPath = resolve(path)
|
||||||
handle.write(text)
|
local handle = disk:open(newPath, "a")
|
||||||
handle.close()
|
handle.write(text)
|
||||||
end
|
handle.close()
|
||||||
function fs.load(path)
|
end
|
||||||
return load(fs.readAllText(path), path)
|
function fs.load(path)
|
||||||
end
|
return load(fs.readAllText(path), path)
|
||||||
function fs.mount(disk, mountPoint)
|
end
|
||||||
if not disks[disk] then return end
|
function fs.mount(disk, mountPoint)
|
||||||
mounts[mountPoint] = disk
|
if not disks[disk] then return end
|
||||||
end
|
mounts[mountPoint] = disk
|
||||||
|
end
|
||||||
return fs
|
return fs
|
||||||
+242
-249
@@ -1,250 +1,243 @@
|
|||||||
local args = {...}
|
--:Minify:--
|
||||||
local apis = args[1]
|
local args = {...}
|
||||||
local disks = args[2]
|
local apis = args[1]
|
||||||
local arch = args[3]
|
local disks = args[2]
|
||||||
local screen = args[5]
|
local arch = args[3]
|
||||||
local computer = args[6]
|
local screen = args[5]
|
||||||
local ifs = args[7]
|
local computer = args[6]
|
||||||
local LOG_Text = ""
|
local ifs = args[7]
|
||||||
local kernel = {}
|
local LOG_Text = ""
|
||||||
kernel.process = "Kernel"
|
local kernel = {}
|
||||||
kernel.user = "root"
|
kernel.process = "Kernel"
|
||||||
kernel.group = "root"
|
kernel.user = "root"
|
||||||
kernel.groups = {0}
|
kernel.group = "root"
|
||||||
kernel.uid = 0
|
kernel.groups = {0}
|
||||||
kernel.gid = 0
|
kernel.uid = 0
|
||||||
kernel.status = "start"
|
kernel.gid = 0
|
||||||
kernel.key = {}
|
kernel.status = "start"
|
||||||
kernel.cache = {}
|
kernel.key = {}
|
||||||
kernel.cache.preload = {}
|
kernel.cache = {}
|
||||||
kernel._G=_G
|
kernel.cache.preload = {}
|
||||||
kernel.sleep=sleep
|
kernel._G=_G
|
||||||
kernel.debug=true
|
kernel.sleep=sleep
|
||||||
|
kernel.debug=true
|
||||||
_G.sleep=nil
|
|
||||||
local windowsExp = false
|
_G.sleep=nil
|
||||||
|
local windowsExp = false
|
||||||
function kernel.log(msg, level)
|
|
||||||
LOG_Text = LOG_Text..tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
|
function kernel.log(msg, level)
|
||||||
if kernel.status == "start" then
|
LOG_Text = LOG_Text..tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg.."\n"
|
||||||
screen:print(tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
if kernel.status == "start" then
|
||||||
elseif kernel.status == "init" then
|
screen:print(tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
||||||
kernel.standbyTask=kernel.currentTask
|
elseif kernel.status == "init" then
|
||||||
kernel.currentTask=kernel.kernelTask
|
kernel.standbyTask=kernel.currentTask
|
||||||
kernel.tty.print(tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
kernel.currentTask=kernel.kernelTask
|
||||||
kernel.currentTask=kernel.standbyTask
|
kernel.tty.print(tostring(computer:time()).." "..kernel.user.." "..kernel.process.."["..tostring(level or "INFO").."]: "..msg)
|
||||||
end
|
kernel.currentTask=kernel.standbyTask
|
||||||
end
|
end
|
||||||
|
end
|
||||||
function kernel.PANIC(msg)
|
|
||||||
if kernel.status~="Panic" then
|
function kernel.PANIC(msg)
|
||||||
kernel.log("PANIC: "..msg, "PANIC")
|
if kernel.status~="Panic" then
|
||||||
pcall(kernel["saveLog"])
|
kernel.log("PANIC: "..msg, "PANIC")
|
||||||
kernel.status="Panic"
|
pcall(kernel["saveLog"])
|
||||||
kernel.reason=msg
|
kernel.status="Panic"
|
||||||
screen:setTextColor(2)
|
kernel.reason=msg
|
||||||
screen:setBackgroundColor(0)
|
screen:setTextColor(2)
|
||||||
screen:clear()
|
screen:setBackgroundColor(0)
|
||||||
screen:setCursorPos(1,1)
|
screen:clear()
|
||||||
screen:print(LOG_Text)
|
screen:setCursorPos(1,1)
|
||||||
screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.")
|
screen:print(LOG_Text)
|
||||||
screen:print("Press any key to continue...")
|
screen:print("KERNEL PANIC!\n"..msg.."\nSystem halted.")
|
||||||
end
|
screen:print("Press any key to continue...")
|
||||||
while true do
|
end
|
||||||
local event={computer:getMachineEvent()}
|
while true do
|
||||||
if event[1]=="keyPressed" then
|
local event={computer:getMachineEvent()}
|
||||||
break
|
if event[1]=="keyPressed" then
|
||||||
end
|
break
|
||||||
end
|
end
|
||||||
computer:reboot()
|
end
|
||||||
end
|
computer:reboot()
|
||||||
kernel.panic=kernel.PANIC
|
end
|
||||||
|
kernel.panic=kernel.PANIC
|
||||||
if windowsExp then
|
|
||||||
screen:setTextColor(1)
|
if windowsExp then
|
||||||
screen:setBackgroundColor(4)
|
screen:setTextColor(1)
|
||||||
screen:clear()
|
screen:setBackgroundColor(4)
|
||||||
local w,h = screen:getSize()
|
screen:clear()
|
||||||
screen:setCursorPos(3,5)
|
local w,h = screen:getSize()
|
||||||
screen:print(":(")
|
screen:setCursorPos(3,5)
|
||||||
screen:setCursorPos(3,7)
|
screen:print(":(")
|
||||||
screen:print("Your PC ran into a problem and needs to restart. We're just collecting some error")
|
screen:setCursorPos(3,7)
|
||||||
screen:setCursorPos(3,8)
|
screen:print("Your PC ran into a problem and needs to restart. We're just collecting some error")
|
||||||
screen:print("info, and then we'll restart for you.\n")
|
screen:setCursorPos(3,8)
|
||||||
screen:setCursorPos(3,h-5)
|
screen:print("info, and then we'll restart for you.\n")
|
||||||
screen:print("Stop code: average windows experience")
|
screen:setCursorPos(3,h-5)
|
||||||
screen:setCursorPos(1,h)
|
screen:print("Stop code: average windows experience")
|
||||||
screen:print("Press any key to continue... jk reboot it yourself lazy")
|
screen:setCursorPos(1,h)
|
||||||
while true do end
|
screen:print("Press any key to continue... jk reboot it yourself lazy")
|
||||||
end
|
while true do end
|
||||||
|
end
|
||||||
kernel.log("Kernel loaded.")
|
|
||||||
kernel.log("Mounting init disks...")
|
kernel.log("Kernel loaded.")
|
||||||
disks.refresh()
|
kernel.log("Mounting init disks...")
|
||||||
ifs.update(disks)
|
disks.refresh()
|
||||||
kernel.disks={}
|
ifs.update(disks)
|
||||||
for _,v in disks.list() do
|
kernel.disks={}
|
||||||
kernel.disks[v.address] = v
|
for _,v in disks.list() do
|
||||||
end
|
kernel.disks[v.address] = v
|
||||||
ifs.mount("$", "/")
|
end
|
||||||
|
ifs.mount("$", "/")
|
||||||
local fstab=ifs.readAllText("/boot/fstab")
|
|
||||||
local split = function(str, delim, maxResultCountOrNil)
|
local fstab=ifs.readAllText("/boot/fstab")
|
||||||
assert(#delim == 1, "only delim len 1 supported for now")
|
local split = function(str, delim, maxResultCountOrNil)
|
||||||
maxResultCountOrNil = (maxResultCountOrNil or 0)-1
|
assert(#delim == 1, "only delim len 1 supported for now")
|
||||||
local rv = {}
|
maxResultCountOrNil = (maxResultCountOrNil or 0)-1
|
||||||
local buf = ""
|
local rv = {}
|
||||||
for i = 1, #str do
|
local buf = ""
|
||||||
local c = string.sub(str,i,i)
|
for i = 1, #str do
|
||||||
if #rv ~= maxResultCountOrNil and c == delim then
|
local c = string.sub(str,i,i)
|
||||||
table.insert(rv, buf)
|
if #rv ~= maxResultCountOrNil and c == delim then
|
||||||
buf = ""
|
table.insert(rv, buf)
|
||||||
else
|
buf = ""
|
||||||
buf = buf..c
|
else
|
||||||
end
|
buf = buf..c
|
||||||
end
|
end
|
||||||
table.insert(rv, buf)
|
end
|
||||||
return rv
|
table.insert(rv, buf)
|
||||||
end
|
return rv
|
||||||
|
end
|
||||||
if not ifs.isFile("/boot/boot.cfg") then
|
|
||||||
kernel.log("boot.cfg missing or corrupted!, Attempting to write recovery boot.cfg", "ERROR")
|
if not ifs.isFile("/boot/boot.cfg") then
|
||||||
ifs.writeAllText("/boot/boot.cfg",[[
|
kernel.log("boot.cfg missing or corrupted!, Attempting to write recovery boot.cfg", "ERROR")
|
||||||
-- DO NOT EDIT THIS FILE IF YOU DO NOT KNOW WHAT YOU ARE DOING!
|
ifs.writeAllText("/boot/boot.cfg",ifs.readAllText("/boot/safeboot.cfg"))
|
||||||
-- DOING SO MAY RENDER YOUR SYSTEM UNBOOTABLE!
|
end
|
||||||
|
local initCfgFunc, err = load(ifs.readAllText("/boot/boot.cfg"), "@boot.cfg")
|
||||||
-- This file is auto-generated during the build process.
|
if not initCfgFunc then
|
||||||
-- RECOVERY BOOT CONFIGURATION FILE
|
kernel.PANIC("Failed to load /boot/boot.cfg: "..tostring(err))
|
||||||
return {
|
end
|
||||||
initPath = "/sbin/init.lua",
|
|
||||||
maxOpenFiles = 128,
|
local initCfgStatus, config = pcall(initCfgFunc)
|
||||||
maxFilesPerTask = 16,
|
if not initCfgStatus then
|
||||||
preempt=true
|
kernel.PANIC("Error in /boot/boot.cfg: "..tostring(config))
|
||||||
}
|
end
|
||||||
]])
|
kernel.config = config
|
||||||
end
|
|
||||||
local initCfgFunc, err = load(ifs.readAllText("/boot/boot.cfg"), "@boot.cfg")
|
for i,v in ipairs(split(fstab,"\n")) do
|
||||||
if not initCfgFunc then
|
if v:sub(1,1)=="U" then
|
||||||
kernel.PANIC("Failed to load /boot/boot.cfg: "..tostring(err))
|
local id=""
|
||||||
end
|
for i=3,#v do
|
||||||
|
if v:sub(i,i)==";" then
|
||||||
local initCfgStatus, config = pcall(initCfgFunc)
|
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN") goto endline end
|
||||||
if not initCfgStatus then
|
id=v:sub(3,i-1)
|
||||||
kernel.PANIC("Error in /boot/boot.cfg: "..tostring(config))
|
end
|
||||||
end
|
end
|
||||||
kernel.config = config
|
local path=v:sub(#id+4)
|
||||||
|
ifs.mount(id,path)
|
||||||
for i,v in ipairs(split(fstab,"\n")) do
|
::endline::
|
||||||
if v:sub(1,1)=="U" then
|
end
|
||||||
local id=""
|
end
|
||||||
for i=3,#v do
|
kernel.log("Disks initialized")
|
||||||
if v:sub(i,i)==";" then
|
|
||||||
if i==3 then kernel.log("Invalid fstab line... Skipping.","WARN") goto endline end
|
function kernel.saveLog()
|
||||||
id=v:sub(3,i-1)
|
ifs.writeAllText("/var/log/syslog.log", LOG_Text)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
local path=v:sub(#id+4)
|
ifs.remove("/tmp")
|
||||||
ifs.mount(id,path)
|
ifs.makeDir("/tmp")
|
||||||
::endline::
|
|
||||||
end
|
function kernel.newFifo()
|
||||||
end
|
local fifo = {}
|
||||||
kernel.log("Disks initialized")
|
fifo.push=function(data)
|
||||||
|
table.insert(data)
|
||||||
function kernel.saveLog()
|
end
|
||||||
ifs.writeAllText("/var/log/syslog.log", LOG_Text)
|
fifo.pop=function()
|
||||||
end
|
return table.remove(fifo,1)
|
||||||
|
end
|
||||||
ifs.remove("/tmp")
|
return fifo
|
||||||
ifs.makeDir("/tmp")
|
end
|
||||||
|
|
||||||
function kernel.newFifo()
|
function kernel.newUUID()
|
||||||
local fifo = {}
|
local template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
|
||||||
fifo.push=function(data)
|
local uuid = ""
|
||||||
table.insert(data)
|
for i = 1, #template do
|
||||||
end
|
local c = template:sub(i,i)
|
||||||
fifo.pop=function()
|
if c == "x" then
|
||||||
return table.remove(fifo,1)
|
uuid = uuid .. string.format("%x", math.random(0, 15))
|
||||||
end
|
elseif c == "y" then
|
||||||
return fifo
|
uuid = uuid .. string.format("%x", math.random(8, 11))
|
||||||
end
|
else
|
||||||
|
uuid = uuid .. c
|
||||||
function kernel.newUUID()
|
end
|
||||||
local template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
|
end
|
||||||
local uuid = ""
|
return uuid
|
||||||
for i = 1, #template do
|
end
|
||||||
local c = template:sub(i,i)
|
|
||||||
if c == "x" then
|
kernel.syscalls={}
|
||||||
uuid = uuid .. string.format("%x", math.random(0, 15))
|
local modules={[0]={}}
|
||||||
elseif c == "y" then
|
for i=0, 100 do
|
||||||
uuid = uuid .. string.format("%x", math.random(8, 11))
|
modules[i]={}
|
||||||
else
|
end
|
||||||
uuid = uuid .. c
|
|
||||||
end
|
kernel.log("Gathering modules")
|
||||||
end
|
for _, i in ipairs(ifs.list("/lib/modules")) do
|
||||||
return uuid
|
for _,v in ipairs(ifs.list("/lib/modules/"..i)) do
|
||||||
end
|
local prior=tonumber(v:sub(1,2))
|
||||||
|
modules[prior+1][#modules[prior+1]+1]="/lib/modules/"..i.."/"..v
|
||||||
kernel.syscalls={}
|
end
|
||||||
local modules={[0]={}}
|
end
|
||||||
for i=0, 100 do
|
|
||||||
modules[i]={}
|
kernel.ifs=ifs
|
||||||
end
|
kernel.apis=apis
|
||||||
|
kernel.computer=computer
|
||||||
kernel.log("Gathering modules")
|
kernel.arch=arch
|
||||||
for _, i in ipairs(ifs.list("/lib/modules")) do
|
kernel.initdisks=disks
|
||||||
for _,v in ipairs(ifs.list("/lib/modules/"..i)) do
|
kernel.screen=screen
|
||||||
local prior=tonumber(v:sub(1,2))
|
kernel.processes={}
|
||||||
modules[prior+1][#modules[prior+1]+1]="/lib/modules/"..i.."/"..v
|
kernel.fstab=fstab
|
||||||
end
|
|
||||||
end
|
kernel.kernelTask = {
|
||||||
|
name="kernel",
|
||||||
kernel.ifs=ifs
|
status="R",
|
||||||
kernel.apis=apis
|
pid=0,
|
||||||
kernel.computer=computer
|
tgid=0,
|
||||||
kernel.arch=arch
|
user="root",
|
||||||
kernel.initdisks=disks
|
uid=0,
|
||||||
kernel.screen=screen
|
fd={},
|
||||||
kernel.processes={}
|
exit="",
|
||||||
kernel.fstab=fstab
|
sleep=0,
|
||||||
|
ivs=0,
|
||||||
kernel.kernelTask = {
|
vs=0,
|
||||||
name="kernel",
|
children={},
|
||||||
status="R",
|
syscallReturn={},
|
||||||
pid=0,
|
cwd="/",
|
||||||
tgid=0,
|
timeSlice=0,
|
||||||
user="root",
|
lastTime=0,
|
||||||
uid=0,
|
totalTime=0,
|
||||||
fd={},
|
numRuns=0
|
||||||
exit="",
|
}
|
||||||
sleep=0,
|
kernel.currentTask = kernel.kernelTask
|
||||||
ivs=0,
|
|
||||||
vs=0,
|
kernel.syscalls["OS_time"]=function() return kernel.computer:time() end
|
||||||
children={},
|
kernel.syscalls["OS_log"]=kernel.log
|
||||||
syscallReturn={},
|
|
||||||
cwd="/",
|
kernel.log("Running modules")
|
||||||
timeSlice=0,
|
for _,p in ipairs(modules) do
|
||||||
lastTime=0,
|
for _,v in ipairs(p) do
|
||||||
totalTime=0,
|
local code=ifs.readAllText(v)
|
||||||
numRuns=0
|
if not code then
|
||||||
}
|
kernel.log("ModuReadErr: "..v, "WARN")
|
||||||
kernel.currentTask = kernel.kernelTask
|
goto skip
|
||||||
|
end
|
||||||
kernel.log("Running modules")
|
local func,err=load(code,"@"..v)
|
||||||
for _,p in ipairs(modules) do
|
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) goto skip end
|
||||||
for _,v in ipairs(p) do
|
local status, err = xpcall(func,debug.traceback, kernel)
|
||||||
local code=ifs.readAllText(v)
|
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
||||||
if not code then
|
::skip::
|
||||||
kernel.log("ModuReadErr: "..v, "WARN")
|
end
|
||||||
goto skip
|
end
|
||||||
end
|
|
||||||
local func,err=load(code,"@"..v)
|
kernel.log("Kernel initialized successfully.")
|
||||||
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) goto skip end
|
kernel.status="running"
|
||||||
local status, err = xpcall(func,debug.traceback, kernel)
|
kernel.main()
|
||||||
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
|
||||||
::skip::
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
kernel.log("Kernel initialized successfully.")
|
|
||||||
kernel.main()
|
|
||||||
kernel.PANIC("Execution complete")
|
kernel.PANIC("Execution complete")
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
-- DO NOT EDIT THIS FILE IF YOU DO NOT KNOW WHAT YOU ARE DOING!
|
||||||
|
-- DOING SO MAY RENDER YOUR SYSTEM UNBOOTABLE!
|
||||||
|
|
||||||
|
-- This file is auto-generated during the build process.
|
||||||
|
-- RECOVERY BOOT CONFIGURATION FILE
|
||||||
|
return {
|
||||||
|
initPath = "/sbin/init.lua",
|
||||||
|
maxOpenFiles = 128,
|
||||||
|
maxFilesPerTask = 16,
|
||||||
|
preempt=true
|
||||||
|
}
|
||||||
+284
-283
@@ -1,284 +1,285 @@
|
|||||||
function string.hasSuffix(str, suffix)
|
--:Minify:--
|
||||||
return string.sub(str, #suffix+1) == suffix
|
function string.hasSuffix(str, suffix)
|
||||||
end
|
return string.sub(str, #suffix+1) == suffix
|
||||||
|
end
|
||||||
function string.hasPrefix(str, prefix)
|
|
||||||
return string.sub(str, 1, #prefix) == prefix
|
function string.hasPrefix(str, prefix)
|
||||||
end
|
return string.sub(str, 1, #prefix) == prefix
|
||||||
|
end
|
||||||
function string.getSuffix(str, prefix)
|
|
||||||
return string.sub(str, #prefix+1)
|
function string.getSuffix(str, prefix)
|
||||||
end
|
return string.sub(str, #prefix+1)
|
||||||
|
end
|
||||||
function string.getPrefix(str, suffix)
|
|
||||||
return string.sub(str, 1, #suffix)
|
function string.getPrefix(str, suffix)
|
||||||
end
|
return string.sub(str, 1, #suffix)
|
||||||
|
end
|
||||||
function string.join(str, ...)
|
|
||||||
return table.concat(table.pack(str, ...))
|
function string.join(str, ...)
|
||||||
end
|
return table.concat(table.pack(str, ...))
|
||||||
|
end
|
||||||
function string.delim(str, ...)
|
|
||||||
return table.concat(table.pack(...), str)
|
function string.delim(str, ...)
|
||||||
end
|
return table.concat(table.pack(...), str)
|
||||||
|
end
|
||||||
function string.split(str, delim, maxResultCountOrNil)
|
|
||||||
assert(#delim == 1, "only delim len 1 supported for now")
|
function string.split(str, delim, maxResultCountOrNil)
|
||||||
maxResultCountOrNil = (maxResultCountOrNil or 0)-1
|
assert(#delim == 1, "only delim len 1 supported for now")
|
||||||
local rv = {}
|
maxResultCountOrNil = (maxResultCountOrNil or 0)-1
|
||||||
local buf = ""
|
local rv = {}
|
||||||
for i = 1, #str do
|
local buf = ""
|
||||||
local c = string.sub(str,i,i)
|
for i = 1, #str do
|
||||||
if #rv ~= maxResultCountOrNil and c == delim then
|
local c = string.sub(str,i,i)
|
||||||
table.insert(rv, buf)
|
if #rv ~= maxResultCountOrNil and c == delim then
|
||||||
buf = ""
|
table.insert(rv, buf)
|
||||||
else
|
buf = ""
|
||||||
buf = buf..c
|
else
|
||||||
end
|
buf = buf..c
|
||||||
end
|
end
|
||||||
table.insert(rv, buf)
|
end
|
||||||
return rv
|
table.insert(rv, buf)
|
||||||
end
|
return rv
|
||||||
|
end
|
||||||
function string.replace(str, search, replacement)
|
|
||||||
local rv = ""
|
function string.replace(str, search, replacement)
|
||||||
local consumedLen = 1
|
local rv = ""
|
||||||
local i = 1
|
local consumedLen = 1
|
||||||
while i<#str do
|
local i = 1
|
||||||
if string.sub(str, i, i+#search-1) == search then
|
while i<#str do
|
||||||
rv = rv .. string.sub(str, consumedLen, i-1) .. replacement
|
if string.sub(str, i, i+#search-1) == search then
|
||||||
i=i+#search
|
rv = rv .. string.sub(str, consumedLen, i-1) .. replacement
|
||||||
consumedLen = i
|
i=i+#search
|
||||||
end
|
consumedLen = i
|
||||||
i=i+1
|
end
|
||||||
end
|
i=i+1
|
||||||
return rv .. string.sub(str, consumedLen)
|
end
|
||||||
end
|
return rv .. string.sub(str, consumedLen)
|
||||||
|
end
|
||||||
function table.deepcopy(orig, copies)
|
|
||||||
copies = copies or {}
|
function table.deepcopy(orig, copies)
|
||||||
|
copies = copies or {}
|
||||||
if type(orig) ~= 'table' then
|
|
||||||
return orig
|
if type(orig) ~= 'table' then
|
||||||
elseif copies[orig] then
|
return orig
|
||||||
return copies[orig]
|
elseif copies[orig] then
|
||||||
end
|
return copies[orig]
|
||||||
|
end
|
||||||
local copy = {}
|
|
||||||
copies[orig] = copy
|
local copy = {}
|
||||||
|
copies[orig] = copy
|
||||||
for k, v in next, orig, nil do
|
|
||||||
local copied_key = table.deepcopy(k, copies)
|
for k, v in next, orig, nil do
|
||||||
local copied_val = table.deepcopy(v, copies)
|
local copied_key = table.deepcopy(k, copies)
|
||||||
copy[copied_key] = copied_val
|
local copied_val = table.deepcopy(v, copies)
|
||||||
end
|
copy[copied_key] = copied_val
|
||||||
|
end
|
||||||
return copy
|
|
||||||
end
|
return copy
|
||||||
|
end
|
||||||
function table.hasKey(tabl, query)
|
|
||||||
for i,v in pairs(tabl) do
|
function table.hasKey(tabl, query)
|
||||||
if i==query then
|
for i,v in pairs(tabl) do
|
||||||
return true
|
if i==query then
|
||||||
end
|
return true
|
||||||
end
|
end
|
||||||
return false
|
end
|
||||||
end
|
return false
|
||||||
|
end
|
||||||
function table.hasVal(tabl, query)
|
|
||||||
for i,v in pairs(tabl) do
|
function table.hasVal(tabl, query)
|
||||||
if v==query then
|
for i,v in pairs(tabl) do
|
||||||
return true
|
if v==query then
|
||||||
end
|
return true
|
||||||
end
|
end
|
||||||
return false
|
end
|
||||||
end
|
return false
|
||||||
|
end
|
||||||
function table.proxy(tbl)
|
|
||||||
local proxies = setmetatable({}, {__mode = "k"}) -- Weak table to avoid cycles
|
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
|
local function createProxy(t)
|
||||||
if proxies[t] then return proxies[t] end -- reuse proxy for the same table (handle cycles)
|
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 proxy = {}
|
||||||
|
proxies[t] = proxy
|
||||||
local mt
|
|
||||||
mt = {
|
local mt
|
||||||
__index = function(_, k)
|
mt = {
|
||||||
local value = t[k]
|
__index = function(_, k)
|
||||||
if type(value) == "table" then
|
local value = t[k]
|
||||||
return createProxy(value) -- recursively proxy subtables
|
if type(value) == "table" then
|
||||||
else
|
return createProxy(value) -- recursively proxy subtables
|
||||||
return value
|
else
|
||||||
end
|
return value
|
||||||
end,
|
end
|
||||||
__newindex = function()
|
end,
|
||||||
error("Attempt to modify table proxy", 2)
|
__newindex = function()
|
||||||
end,
|
error("Attempt to modify table proxy", 2)
|
||||||
__pairs = function()
|
end,
|
||||||
return function(_, k)
|
__pairs = function()
|
||||||
local nextKey, nextValue = next(t, k)
|
return function(_, k)
|
||||||
if type(nextValue) == "table" then
|
local nextKey, nextValue = next(t, k)
|
||||||
nextValue = createProxy(nextValue)
|
if type(nextValue) == "table" then
|
||||||
end
|
nextValue = createProxy(nextValue)
|
||||||
return nextKey, nextValue
|
end
|
||||||
end, nil, nil
|
return nextKey, nextValue
|
||||||
end,
|
end, nil, nil
|
||||||
__ipairs = function()
|
end,
|
||||||
local i = 0
|
__ipairs = function()
|
||||||
local n = #t
|
local i = 0
|
||||||
return function()
|
local n = #t
|
||||||
i = i + 1
|
return function()
|
||||||
if i <= n then
|
i = i + 1
|
||||||
local v = t[i]
|
if i <= n then
|
||||||
if type(v) == "table" then
|
local v = t[i]
|
||||||
v = createProxy(v)
|
if type(v) == "table" then
|
||||||
end
|
v = createProxy(v)
|
||||||
return i, v
|
end
|
||||||
end
|
return i, v
|
||||||
end
|
end
|
||||||
end,
|
end
|
||||||
__metatable = false
|
end,
|
||||||
}
|
__metatable = false
|
||||||
|
}
|
||||||
setmetatable(proxy, mt)
|
|
||||||
return proxy
|
setmetatable(proxy, mt)
|
||||||
end
|
return proxy
|
||||||
|
end
|
||||||
return createProxy(tbl)
|
|
||||||
end
|
return createProxy(tbl)
|
||||||
|
end
|
||||||
local function serialize(table)
|
|
||||||
local output = "{"
|
local function serialize(table)
|
||||||
for i,v in pairs(table) do
|
local output = "{"
|
||||||
local coma=true
|
for i,v in pairs(table) do
|
||||||
if type(i) == "string" then
|
local coma=true
|
||||||
output=output.."[\""..i.."\"]="
|
if type(i) == "string" then
|
||||||
elseif type(i) == "number" then
|
output=output.."[\""..i.."\"]="
|
||||||
output=output.."["..tostring(i).."]="
|
elseif type(i) == "number" then
|
||||||
end
|
output=output.."["..tostring(i).."]="
|
||||||
if type(v) == "table" then
|
end
|
||||||
if v == table then
|
if type(v) == "table" then
|
||||||
output=string.sub(output,1,#output-(#i+1))
|
if v == table then
|
||||||
coma=false
|
output=string.sub(output,1,#output-(#i+1))
|
||||||
else
|
coma=false
|
||||||
output=output..serialize(v)
|
else
|
||||||
end
|
output=output..serialize(v)
|
||||||
elseif type(v) == "string" then
|
end
|
||||||
output=output.."[=["..v.."]=]"
|
elseif type(v) == "string" then
|
||||||
elseif type(v) == "number" then
|
output=output.."[=["..v.."]=]"
|
||||||
output=output..tostring(v)
|
elseif type(v) == "number" then
|
||||||
elseif type(v) == "boolean" then
|
output=output..tostring(v)
|
||||||
if v == true then
|
elseif type(v) == "boolean" then
|
||||||
output=output.."true"
|
if v == true then
|
||||||
else
|
output=output.."true"
|
||||||
output=output.."false"
|
else
|
||||||
end
|
output=output.."false"
|
||||||
elseif type(v) == "function" then
|
end
|
||||||
output=output..tostring(v)
|
elseif type(v) == "function" then
|
||||||
else
|
output=output..tostring(v)
|
||||||
error("serialization of type \""..type(v).."\" is not supported")
|
else
|
||||||
end
|
error("serialization of type \""..type(v).."\" is not supported")
|
||||||
if coma then
|
end
|
||||||
output=output..","
|
if coma then
|
||||||
end
|
output=output..","
|
||||||
end
|
end
|
||||||
if #table>0 or string.sub(output,#output,#output) == "," then
|
end
|
||||||
output=string.sub(output,1,#output-1)
|
if #table>0 or string.sub(output,#output,#output) == "," then
|
||||||
end
|
output=string.sub(output,1,#output-1)
|
||||||
output=output.."}"
|
end
|
||||||
return output
|
output=output.."}"
|
||||||
end
|
return output
|
||||||
|
end
|
||||||
local oldtype=type
|
|
||||||
local oldgetmetatable=getmetatable
|
local oldtype=type
|
||||||
function type(object, trueType)
|
local oldgetmetatable=getmetatable
|
||||||
if trueType then
|
function type(object, trueType)
|
||||||
return oldtype(object)
|
if trueType then
|
||||||
end
|
return oldtype(object)
|
||||||
if oldtype(object)~="table" then
|
end
|
||||||
return oldtype(object)
|
if oldtype(object)~="table" then
|
||||||
else
|
return oldtype(object)
|
||||||
if oldtype(oldgetmetatable(object))=="table" then
|
else
|
||||||
local metatable = oldgetmetatable(object)
|
if oldtype(oldgetmetatable(object))=="table" then
|
||||||
if metatable.__type then return metatable.__type end
|
local metatable = oldgetmetatable(object)
|
||||||
else
|
if metatable.__type then return metatable.__type end
|
||||||
return "table"
|
else
|
||||||
end
|
return "table"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
function getmetatable(object)
|
|
||||||
if oldtype(object)~="table" then return end
|
function getmetatable(object)
|
||||||
if oldtype(oldgetmetatable(object))=="table" then
|
if oldtype(object)~="table" then return end
|
||||||
if oldgetmetatable(object).__isuserdata then
|
if oldtype(oldgetmetatable(object))=="table" then
|
||||||
if oldtype(oldgetmetatable(object).__usermeta)=="function" then
|
if oldgetmetatable(object).__isuserdata then
|
||||||
return oldgetmetatable(object).__usermeta()
|
if oldtype(oldgetmetatable(object).__usermeta)=="function" then
|
||||||
else
|
return oldgetmetatable(object).__usermeta()
|
||||||
return oldgetmetatable(object).__usermeta
|
else
|
||||||
end
|
return oldgetmetatable(object).__usermeta
|
||||||
else
|
end
|
||||||
return oldgetmetatable(object)
|
else
|
||||||
end
|
return oldgetmetatable(object)
|
||||||
else
|
end
|
||||||
return oldgetmetatable(object)
|
else
|
||||||
end
|
return oldgetmetatable(object)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
function isEqualToAny(a, ...)
|
|
||||||
local args={...}
|
function isEqualToAny(a, ...)
|
||||||
for i=0, #args do
|
local args={...}
|
||||||
if a==args[i] then
|
for i=0, #args do
|
||||||
return true
|
if a==args[i] then
|
||||||
end
|
return true
|
||||||
end
|
end
|
||||||
return false
|
end
|
||||||
end
|
return false
|
||||||
|
end
|
||||||
function isEqualToAll(a, ...)
|
|
||||||
local args={...}
|
function isEqualToAll(a, ...)
|
||||||
for i=0, #args do
|
local args={...}
|
||||||
if a~=args[i] then
|
for i=0, #args do
|
||||||
return false
|
if a~=args[i] then
|
||||||
end
|
return false
|
||||||
end
|
end
|
||||||
return true
|
end
|
||||||
end
|
return true
|
||||||
|
end
|
||||||
function table.keys(t)
|
|
||||||
local a = {}
|
function table.keys(t)
|
||||||
for n in pairs(t) do table.insert(a, n) end
|
local a = {}
|
||||||
return a
|
for n in pairs(t) do table.insert(a, n) end
|
||||||
end
|
return a
|
||||||
|
end
|
||||||
function table.values(t)
|
|
||||||
local a = {}
|
function table.values(t)
|
||||||
for _, n in pairs(t) do table.insert(a, n) end
|
local a = {}
|
||||||
return a
|
for _, n in pairs(t) do table.insert(a, n) end
|
||||||
end
|
return a
|
||||||
|
end
|
||||||
function table.indexOf(t, value)
|
|
||||||
for i,v in ipairs(t) do
|
function table.indexOf(t, value)
|
||||||
if v==value then
|
for i,v in ipairs(t) do
|
||||||
return i
|
if v==value then
|
||||||
end
|
return i
|
||||||
end
|
end
|
||||||
return -1
|
end
|
||||||
end
|
return -1
|
||||||
|
end
|
||||||
syscall = setmetatable({}, {
|
|
||||||
__index = function(self, name)
|
syscall = setmetatable({}, {
|
||||||
return function(...)
|
__index = function(self, name)
|
||||||
local res = table.pack(coroutine.yield("syscall", name, ...))
|
return function(...)
|
||||||
if res[1] then
|
local res = table.pack(coroutine.yield("syscall", name, ...))
|
||||||
return table.unpack(res, 2, res.n)
|
if res[1] then
|
||||||
else
|
return table.unpack(res, 2, res.n)
|
||||||
error(res[2], 2)
|
else
|
||||||
end
|
error(res[2], 2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
end
|
||||||
|
})
|
||||||
|
|
||||||
table.serialize=serialize
|
table.serialize=serialize
|
||||||
+278
-277
@@ -1,277 +1,278 @@
|
|||||||
local kernel = ...
|
--:Minify:--
|
||||||
local vfs = {}
|
local kernel = ...
|
||||||
vfs.mounts = { ["$"] = "/" }
|
local vfs = {}
|
||||||
local disks = kernel.disks
|
vfs.mounts = { ["$"] = "/" }
|
||||||
|
local disks = kernel.disks
|
||||||
-- Path handling
|
|
||||||
local function normalizePath(path)
|
-- Path handling
|
||||||
local parts = {}
|
local function normalizePath(path)
|
||||||
for part in path:gmatch("[^/]+") do
|
local parts = {}
|
||||||
if part == ".." then
|
for part in path:gmatch("[^/]+") do
|
||||||
if #parts > 0 then table.remove(parts) end
|
if part == ".." then
|
||||||
elseif part ~= "." and part ~= "" then
|
if #parts > 0 then table.remove(parts) end
|
||||||
table.insert(parts, part)
|
elseif part ~= "." and part ~= "" then
|
||||||
end
|
table.insert(parts, part)
|
||||||
end
|
end
|
||||||
return "/" .. table.concat(parts, "/") .. (path:sub(-1) == "/" and "/" or "")
|
end
|
||||||
end
|
return "/" .. table.concat(parts, "/") .. (path:sub(-1) == "/" and "/" or "")
|
||||||
|
end
|
||||||
local function resolvePath(path)
|
|
||||||
local task = kernel.currentTask
|
local function resolvePath(path)
|
||||||
local cwd = task.cwd or "/"
|
local task = kernel.currentTask
|
||||||
|
local cwd = task.cwd or "/"
|
||||||
if path:sub(1,1) ~= "/" then
|
|
||||||
path = cwd .. path
|
if path:sub(1,1) ~= "/" then
|
||||||
end
|
path = cwd .. path
|
||||||
|
end
|
||||||
path = normalizePath(path)
|
|
||||||
|
path = normalizePath(path)
|
||||||
local mountPoint = "/"
|
|
||||||
local mountId = "$"
|
local mountPoint = "/"
|
||||||
for k,v in pairs(vfs.mounts) do
|
local mountId = "$"
|
||||||
if path:sub(1,#v) == v and #v > #mountPoint then
|
for k,v in pairs(vfs.mounts) do
|
||||||
mountPoint = v
|
if path:sub(1,#v) == v and #v > #mountPoint then
|
||||||
mountId = k
|
mountPoint = v
|
||||||
end
|
mountId = k
|
||||||
end
|
end
|
||||||
|
end
|
||||||
local diskPath = path:sub(#mountPoint + 1)
|
|
||||||
return disks[mountId], diskPath
|
local diskPath = path:sub(#mountPoint + 1)
|
||||||
end
|
return disks[mountId], diskPath
|
||||||
|
end
|
||||||
-- File object creation
|
|
||||||
local function newFileObject(disk, handle, mode, path)
|
-- File object creation
|
||||||
return {
|
local function newFileObject(disk, handle, mode, path)
|
||||||
disk = disk,
|
return {
|
||||||
handle = handle,
|
disk = disk,
|
||||||
mode = mode,
|
handle = handle,
|
||||||
path = path,
|
mode = mode,
|
||||||
refcount = 1
|
path = path,
|
||||||
}
|
refcount = 1
|
||||||
end
|
}
|
||||||
|
end
|
||||||
local function allocFD(task)
|
|
||||||
local fd = 0
|
local function allocFD(task)
|
||||||
while task.fd[fd] do fd = fd + 1 end
|
local fd = 0
|
||||||
return fd
|
while task.fd[fd] do fd = fd + 1 end
|
||||||
end
|
return fd
|
||||||
|
end
|
||||||
local function allocFD(task)
|
|
||||||
-- enforce per-task limit
|
local function allocFD(task)
|
||||||
local count = 0
|
-- enforce per-task limit
|
||||||
for _ in pairs(task.fd) do count = count + 1 end
|
local count = 0
|
||||||
if count >= kernel.config.maxFilesPerTask then
|
for _ in pairs(task.fd) do count = count + 1 end
|
||||||
error("EMFILE") -- Too many open files in this task
|
if count >= kernel.config.maxFilesPerTask then
|
||||||
end
|
error("EMFILE") -- Too many open files in this task
|
||||||
|
end
|
||||||
-- find first free FD
|
|
||||||
local fd = 0
|
-- find first free FD
|
||||||
while task.fd[fd] do fd = fd + 1 end
|
local fd = 0
|
||||||
return fd
|
while task.fd[fd] do fd = fd + 1 end
|
||||||
end
|
return fd
|
||||||
|
end
|
||||||
local function checkSystemLimit()
|
|
||||||
-- enforce system-wide limit
|
local function checkSystemLimit()
|
||||||
local total = 0
|
-- enforce system-wide limit
|
||||||
for _, task in pairs(kernel.tasks or {}) do
|
local total = 0
|
||||||
for _ in pairs(task.fd) do total = total + 1 end
|
for _, task in pairs(kernel.tasks or {}) do
|
||||||
end
|
for _ in pairs(task.fd) do total = total + 1 end
|
||||||
if total >= kernel.config.maxOpenFiles then
|
end
|
||||||
error("ENFILE") -- Too many open files in the system
|
if total >= kernel.config.maxOpenFiles then
|
||||||
end
|
error("ENFILE") -- Too many open files in the system
|
||||||
end
|
end
|
||||||
|
end
|
||||||
-- VFS syscalls
|
|
||||||
function vfs.open(path, mode)
|
-- VFS syscalls
|
||||||
local task = kernel.currentTask
|
function vfs.open(path, mode)
|
||||||
|
local task = kernel.currentTask
|
||||||
-- check limits
|
|
||||||
checkSystemLimit()
|
-- check limits
|
||||||
|
checkSystemLimit()
|
||||||
local disk, diskPath = resolvePath(path)
|
|
||||||
if not disk then
|
local disk, diskPath = resolvePath(path)
|
||||||
error("No disk mounted for path '"..path.."'")
|
if not disk then
|
||||||
end
|
error("No disk mounted for path '"..path.."'")
|
||||||
|
end
|
||||||
local handle = disk:open(diskPath, mode)
|
|
||||||
if not handle then return nil end
|
local handle = disk:open(diskPath, mode)
|
||||||
|
if not handle then return nil end
|
||||||
local file = newFileObject(disk.address, handle, mode, path)
|
|
||||||
local fd = allocFD(task)
|
local file = newFileObject(disk.address, handle, mode, path)
|
||||||
task.fd[fd] = file
|
local fd = allocFD(task)
|
||||||
|
task.fd[fd] = file
|
||||||
return fd
|
|
||||||
end
|
return fd
|
||||||
|
end
|
||||||
function vfs.close(fd)
|
|
||||||
local task = kernel.currentTask
|
function vfs.close(fd)
|
||||||
local file = task.fd[fd]
|
local task = kernel.currentTask
|
||||||
if not file then error("EBADF") end
|
local file = task.fd[fd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
task.fd[fd] = nil
|
|
||||||
file.refcount = file.refcount - 1
|
task.fd[fd] = nil
|
||||||
if file.refcount == 0 then
|
file.refcount = file.refcount - 1
|
||||||
file.handle.close()
|
if file.refcount == 0 then
|
||||||
end
|
file.handle.close()
|
||||||
return true
|
end
|
||||||
end
|
return true
|
||||||
|
end
|
||||||
function vfs.read(fd, count)
|
|
||||||
local file = kernel.currentTask.fd[fd]
|
function vfs.read(fd, count)
|
||||||
if not file then error("EBADF") end
|
local file = kernel.currentTask.fd[fd]
|
||||||
if not file.mode:find("r") then error("File not open for reading") end
|
if not file then error("EBADF") end
|
||||||
return file.handle.read(count)
|
if not file.mode:find("r") then error("File not open for reading") end
|
||||||
end
|
return file.handle.read(count)
|
||||||
|
end
|
||||||
function vfs.write(fd, data)
|
|
||||||
local file = kernel.currentTask.fd[fd]
|
function vfs.write(fd, data)
|
||||||
if not file then error("EBADF") end
|
local file = kernel.currentTask.fd[fd]
|
||||||
if not file.mode:find("w") then error("File not open for writing") end
|
if not file then error("EBADF") end
|
||||||
return file.handle.write(data)
|
if not file.mode:find("w") then error("File not open for writing") end
|
||||||
end
|
return file.handle.write(data)
|
||||||
|
end
|
||||||
function vfs.whereis(fd)
|
|
||||||
local file = kernel.currentTask.fd[fd]
|
function vfs.whereis(fd)
|
||||||
if not file then error("EBADF") end
|
local file = kernel.currentTask.fd[fd]
|
||||||
return file.path
|
if not file then error("EBADF") end
|
||||||
end
|
return file.path
|
||||||
|
end
|
||||||
-- Filesystem operations
|
|
||||||
function vfs.mkdir(path)
|
-- Filesystem operations
|
||||||
local disk, diskPath = resolvePath(path)
|
function vfs.mkdir(path)
|
||||||
if not disk then error("No disk mounted") end
|
local disk, diskPath = resolvePath(path)
|
||||||
return disk:makeDirectory(diskPath)
|
if not disk then error("No disk mounted") end
|
||||||
end
|
return disk:makeDirectory(diskPath)
|
||||||
|
end
|
||||||
function vfs.remove(path)
|
|
||||||
local disk, diskPath = resolvePath(path)
|
function vfs.remove(path)
|
||||||
if not disk then error("No disk mounted") end
|
local disk, diskPath = resolvePath(path)
|
||||||
return disk:remove(diskPath)
|
if not disk then error("No disk mounted") end
|
||||||
end
|
return disk:remove(diskPath)
|
||||||
|
end
|
||||||
function vfs.attributes(path)
|
|
||||||
if type(path) == "number" then
|
function vfs.attributes(path)
|
||||||
local file = kernel.currentTask.fd[path]
|
if type(path) == "number" then
|
||||||
if not file then error("EBADF") end
|
local file = kernel.currentTask.fd[path]
|
||||||
return disks[file.disk]:attributes(file.path)
|
if not file then error("EBADF") end
|
||||||
end
|
return disks[file.disk]:attributes(file.path)
|
||||||
local disk, diskPath = resolvePath(path)
|
end
|
||||||
if not disk then error("No disk mounted") end
|
local disk, diskPath = resolvePath(path)
|
||||||
return disk:attributes(diskPath)
|
if not disk then error("No disk mounted") end
|
||||||
end
|
return disk:attributes(diskPath)
|
||||||
|
end
|
||||||
function vfs.list(path)
|
|
||||||
local disk, diskPath = resolvePath(path)
|
function vfs.list(path)
|
||||||
if not disk then error("No disk mounted") end
|
local disk, diskPath = resolvePath(path)
|
||||||
return disk:list(diskPath)
|
if not disk then error("No disk mounted") end
|
||||||
end
|
return disk:list(diskPath)
|
||||||
|
end
|
||||||
function vfs.exists(path)
|
|
||||||
local disk, diskPath = resolvePath(path)
|
function vfs.exists(path)
|
||||||
if not disk then return false end
|
local disk, diskPath = resolvePath(path)
|
||||||
return disk:directoryExists(diskPath) or disk:fileExists(diskPath)
|
if not disk then return false end
|
||||||
end
|
return disk:directoryExists(diskPath) or disk:fileExists(diskPath)
|
||||||
|
end
|
||||||
function vfs.type(path)
|
|
||||||
if type(path) == "number" then
|
function vfs.type(path)
|
||||||
local file = kernel.currentTask.fd[path]
|
if type(path) == "number" then
|
||||||
if not file then error("EBADF") end
|
local file = kernel.currentTask.fd[path]
|
||||||
return disks[file.disk]:type(file.path)
|
if not file then error("EBADF") end
|
||||||
end
|
return disks[file.disk]:type(file.path)
|
||||||
local disk, diskPath = resolvePath(path)
|
end
|
||||||
if not disk then error("No disk mounted") end
|
local disk, diskPath = resolvePath(path)
|
||||||
return disk:type(diskPath)
|
if not disk then error("No disk mounted") end
|
||||||
end
|
return disk:type(diskPath)
|
||||||
|
end
|
||||||
-- CWD
|
|
||||||
function vfs.getcwd()
|
-- CWD
|
||||||
return kernel.currentTask.cwd
|
function vfs.getcwd()
|
||||||
end
|
return kernel.currentTask.cwd
|
||||||
|
end
|
||||||
function vfs.setcwd(path)
|
|
||||||
if path:sub(-1) ~= "/" then path = path .. "/" end
|
function vfs.setcwd(path)
|
||||||
if path:sub(1,1) ~= "/" then path = "/" .. path end
|
if path:sub(-1) ~= "/" then path = path .. "/" end
|
||||||
kernel.currentTask.cwd = normalizePath(path)
|
if path:sub(1,1) ~= "/" then path = "/" .. path end
|
||||||
end
|
kernel.currentTask.cwd = normalizePath(path)
|
||||||
|
end
|
||||||
-- Mounting
|
|
||||||
function vfs.mount(diskId, path)
|
-- Mounting
|
||||||
if kernel.uid ~= 0 then error("Permission denied") end
|
function vfs.mount(diskId, path)
|
||||||
if not disks[diskId] then error("Unknown disk '"..diskId.."'") end
|
if kernel.uid ~= 0 then error("Permission denied") end
|
||||||
if path:sub(-1) ~= "/" then path = path .. "/" end
|
if not disks[diskId] then error("Unknown disk '"..diskId.."'") end
|
||||||
|
if path:sub(-1) ~= "/" then path = path .. "/" end
|
||||||
for _,v in pairs(vfs.mounts) do
|
|
||||||
if v == path then error("Mount point already used") end
|
for _,v in pairs(vfs.mounts) do
|
||||||
end
|
if v == path then error("Mount point already used") end
|
||||||
vfs.mounts[diskId] = path
|
end
|
||||||
end
|
vfs.mounts[diskId] = path
|
||||||
|
end
|
||||||
function vfs.unmount(path)
|
|
||||||
if kernel.uid ~= 0 then error("Permission denied") end
|
function vfs.unmount(path)
|
||||||
for k,v in pairs(vfs.mounts) do
|
if kernel.uid ~= 0 then error("Permission denied") end
|
||||||
if v == path then
|
for k,v in pairs(vfs.mounts) do
|
||||||
vfs.mounts[k] = nil
|
if v == path then
|
||||||
return true
|
vfs.mounts[k] = nil
|
||||||
end
|
return true
|
||||||
end
|
end
|
||||||
return false
|
end
|
||||||
end
|
return false
|
||||||
|
end
|
||||||
function vfs.getMounts()
|
|
||||||
return vfs.mounts
|
function vfs.getMounts()
|
||||||
end
|
return vfs.mounts
|
||||||
|
end
|
||||||
function vfs.virtdisk(obj)
|
|
||||||
kernel.disks[obj.address] = obj
|
function vfs.virtdisk(obj)
|
||||||
kernel.log("Registered virtual disk at "..obj.address)
|
kernel.disks[obj.address] = obj
|
||||||
end
|
kernel.log("Registered virtual disk at "..obj.address)
|
||||||
|
end
|
||||||
-- Redirect file operations to VFS
|
|
||||||
function vfs.dup(oldfd)
|
-- Redirect file operations to VFS
|
||||||
local task = kernel.currentTask
|
function vfs.dup(oldfd)
|
||||||
local file = task.fd[oldfd]
|
local task = kernel.currentTask
|
||||||
if not file then error("EBADF") end
|
local file = task.fd[oldfd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
local newfd = allocFD(task)
|
|
||||||
task.fd[newfd] = file
|
local newfd = allocFD(task)
|
||||||
file.refcount = file.refcount + 1
|
task.fd[newfd] = file
|
||||||
return newfd
|
file.refcount = file.refcount + 1
|
||||||
end
|
return newfd
|
||||||
|
end
|
||||||
function vfs.dup2(oldfd, newfd)
|
|
||||||
local task = kernel.currentTask
|
function vfs.dup2(oldfd, newfd)
|
||||||
local file = task.fd[oldfd]
|
local task = kernel.currentTask
|
||||||
if not file then error("EBADF") end
|
local file = task.fd[oldfd]
|
||||||
|
if not file then error("EBADF") end
|
||||||
if oldfd == newfd then return newfd end
|
|
||||||
|
if oldfd == newfd then return newfd end
|
||||||
if task.fd[newfd] then
|
|
||||||
vfs.close(newfd)
|
if task.fd[newfd] then
|
||||||
end
|
vfs.close(newfd)
|
||||||
|
end
|
||||||
task.fd[newfd] = file
|
|
||||||
file.refcount = file.refcount + 1
|
task.fd[newfd] = file
|
||||||
return newfd
|
file.refcount = file.refcount + 1
|
||||||
end
|
return newfd
|
||||||
|
end
|
||||||
-- Syscall registration
|
|
||||||
kernel.vfs = vfs
|
-- Syscall registration
|
||||||
kernel.syscalls["VFS_open"] = vfs.open
|
kernel.vfs = vfs
|
||||||
kernel.syscalls["VFS_read"] = vfs.read
|
kernel.syscalls["VFS_open"] = vfs.open
|
||||||
kernel.syscalls["VFS_write"] = vfs.write
|
kernel.syscalls["VFS_read"] = vfs.read
|
||||||
kernel.syscalls["VFS_close"] = vfs.close
|
kernel.syscalls["VFS_write"] = vfs.write
|
||||||
kernel.syscalls["VFS_list"] = vfs.list
|
kernel.syscalls["VFS_close"] = vfs.close
|
||||||
kernel.syscalls["VFS_type"] = vfs.type
|
kernel.syscalls["VFS_list"] = vfs.list
|
||||||
kernel.syscalls["VFS_attributes"] = vfs.attributes
|
kernel.syscalls["VFS_type"] = vfs.type
|
||||||
kernel.syscalls["VFS_mkdir"] = vfs.mkdir
|
kernel.syscalls["VFS_attributes"] = vfs.attributes
|
||||||
kernel.syscalls["VFS_remove"] = vfs.remove
|
kernel.syscalls["VFS_mkdir"] = vfs.mkdir
|
||||||
kernel.syscalls["VFS_exists"] = vfs.exists
|
kernel.syscalls["VFS_remove"] = vfs.remove
|
||||||
kernel.syscalls["VFS_mount"] = vfs.mount
|
kernel.syscalls["VFS_exists"] = vfs.exists
|
||||||
kernel.syscalls["VFS_unmount"] = vfs.unmount
|
kernel.syscalls["VFS_mount"] = vfs.mount
|
||||||
kernel.syscalls["VFS_getcwd"] = vfs.getcwd
|
kernel.syscalls["VFS_unmount"] = vfs.unmount
|
||||||
kernel.syscalls["VFS_setcwd"] = vfs.setcwd
|
kernel.syscalls["VFS_getcwd"] = vfs.getcwd
|
||||||
kernel.syscalls["VFS_whereis"] = vfs.whereis
|
kernel.syscalls["VFS_setcwd"] = vfs.setcwd
|
||||||
kernel.syscalls["VFS_dup"] = vfs.dup
|
kernel.syscalls["VFS_whereis"] = vfs.whereis
|
||||||
kernel.syscalls["VFS_dup2"] = vfs.dup2
|
kernel.syscalls["VFS_dup"] = vfs.dup
|
||||||
|
kernel.syscalls["VFS_dup2"] = vfs.dup2
|
||||||
kernel.log("VFS module loaded")
|
|
||||||
|
kernel.log("VFS module loaded")
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
--:Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
local cache = {}
|
local cache = {}
|
||||||
local searchpaths = {
|
local searchpaths = {
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
--:Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
|
|
||||||
local proxy = {}
|
local proxy = {}
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
--:Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
|
|
||||||
kernel.processes.keventd = function()
|
kernel.processes.keventd = function()
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
--:Minify:--
|
||||||
local kernel=...
|
local kernel=...
|
||||||
for i,v in ipairs(string.split(kernel.fstab,"\n")) do
|
for i,v in ipairs(string.split(kernel.fstab,"\n")) do
|
||||||
if v:sub(1,1)=="U" then
|
if v:sub(1,1)=="U" then
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
--:Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
local ports = {}
|
local ports = {}
|
||||||
local signals = {}
|
local signals = {}
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
--:Minify:--
|
||||||
local args={...}
|
local args={...}
|
||||||
local kernel=args[1]
|
local kernel=args[1]
|
||||||
kernel._G=_G
|
kernel._G=_G
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
--:Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
local pam = {}
|
local pam = {}
|
||||||
kernel.pam = pam
|
kernel.pam = pam
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
--:Minify:--
|
||||||
local kernel = ...
|
local kernel = ...
|
||||||
local tasks = {}
|
local tasks = {}
|
||||||
local sys = {}
|
local sys = {}
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
--:Minify:--
|
||||||
local kernel=...
|
local kernel=...
|
||||||
local debug=debug
|
local debug=debug
|
||||||
kernel._G.debug={
|
kernel._G.debug={
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
--:Minify:--
|
||||||
local kernel=...
|
local kernel=...
|
||||||
kernel.tty={}
|
kernel.tty={}
|
||||||
|
|
||||||
+1
@@ -1,2 +1,3 @@
|
|||||||
|
--:Minify:--
|
||||||
local kernel=...
|
local kernel=...
|
||||||
kernel.tty.bind("tty0")
|
kernel.tty.bind("tty0")
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
--:Minify:--
|
||||||
local kernel=...
|
local kernel=...
|
||||||
function print(...)
|
function print(...)
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
--: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)
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"Name": "HyperionOS",
|
"Name": "HyperionOS",
|
||||||
"Version": "1.0.0",
|
"Version": "1.0.0",
|
||||||
"Publishers": ["HyperionOS Dev Team"],
|
"Publishers": ["HyperionOS Dev Team"],
|
||||||
"Description": "The install package for HyperionOS project.",
|
"Description": "The install package for HyperionOS project.",
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-core-v1.0.0.pkg",
|
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-core-v1.0.0.pkg",
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.pkg",
|
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-kernel-v1.0.0.pkg",
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-ui-v1.0.0.pkg",
|
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-ui-v1.0.0.pkg",
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-network-v1.0.0.pkg",
|
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-network-v1.0.0.pkg",
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-security-v1.0.0.pkg",
|
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-security-v1.0.0.pkg",
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-filesystem-v1.0.0.pkg",
|
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-filesystem-v1.0.0.pkg",
|
||||||
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-bash-v1.0.0.pkg"
|
"https://git.astronand.dev/Hyperion/HyperionOS/archive/Hyperion-bash-v1.0.0.pkg"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
-177
@@ -1,177 +0,0 @@
|
|||||||
-- Minimal ISO9660 parser
|
|
||||||
-- Provides: ISO.open(path) -> iso object
|
|
||||||
-- Methods: :close(), :readPVD(), :listRoot(), :readFile(path)
|
|
||||||
|
|
||||||
local M = {}
|
|
||||||
|
|
||||||
local SECTOR_SIZE = 2048
|
|
||||||
|
|
||||||
local function readBytes(f, pos, len)
|
|
||||||
f:seek("set", pos)
|
|
||||||
return f:read(len)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function u8(s, i)
|
|
||||||
return string.byte(s, i)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function u16le(s, i)
|
|
||||||
local b1 = string.byte(s, i)
|
|
||||||
local b2 = string.byte(s, i+1)
|
|
||||||
return b1 + b2 * 256
|
|
||||||
end
|
|
||||||
|
|
||||||
local function u32le(s, i)
|
|
||||||
local b1 = string.byte(s, i)
|
|
||||||
local b2 = string.byte(s, i+1)
|
|
||||||
local b3 = string.byte(s, i+2)
|
|
||||||
local b4 = string.byte(s, i+3)
|
|
||||||
return b1 + b2*256 + b3*65536 + b4*16777216
|
|
||||||
end
|
|
||||||
|
|
||||||
local function trimVersion(name)
|
|
||||||
-- remove ;1 version and trailing dots
|
|
||||||
local n = name:gsub(";1$", "")
|
|
||||||
n = n:gsub("%.$", "")
|
|
||||||
return n
|
|
||||||
end
|
|
||||||
|
|
||||||
local ISO = {}
|
|
||||||
ISO.__index = ISO
|
|
||||||
|
|
||||||
function M.open(path)
|
|
||||||
local f, err = io.open(path, "rb")
|
|
||||||
if not f then return nil, err end
|
|
||||||
local self = setmetatable({ f = f, path = path }, ISO)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
function ISO:close()
|
|
||||||
if self.f then self.f:close(); self.f = nil end
|
|
||||||
end
|
|
||||||
|
|
||||||
function ISO:readSector(n)
|
|
||||||
local pos = n * SECTOR_SIZE
|
|
||||||
return readBytes(self.f, pos, SECTOR_SIZE)
|
|
||||||
end
|
|
||||||
|
|
||||||
function ISO:readPVD()
|
|
||||||
-- Primary Volume Descriptor at sector 16 (index 16)
|
|
||||||
local pvd = self:readSector(16)
|
|
||||||
if not pvd or #pvd < SECTOR_SIZE then return nil, "cannot read PVD" end
|
|
||||||
local typecode = u8(pvd,1)
|
|
||||||
local id = pvd:sub(2,6)
|
|
||||||
if typecode ~= 1 or id ~= "CD001" then return nil, "no primary volume descriptor" end
|
|
||||||
|
|
||||||
local volumeIdentifier = pvd:sub(41,72):gsub('%z+$','')
|
|
||||||
-- root directory record starts at offset 157 (1-based index)
|
|
||||||
local rdOffset = 157
|
|
||||||
local rdLen = u8(pvd, rdOffset)
|
|
||||||
local extent = u32le(pvd, rdOffset + 2)
|
|
||||||
local dataLen = u32le(pvd, rdOffset + 10)
|
|
||||||
|
|
||||||
self.pvd = {
|
|
||||||
volumeIdentifier = volumeIdentifier,
|
|
||||||
root = { extent = extent, size = dataLen }
|
|
||||||
}
|
|
||||||
return self.pvd
|
|
||||||
end
|
|
||||||
|
|
||||||
local function parseDirRecords(buffer, bytesToRead)
|
|
||||||
local records = {}
|
|
||||||
local offset = 1
|
|
||||||
local total = bytesToRead or #buffer
|
|
||||||
while offset <= total do
|
|
||||||
local len = string.byte(buffer, offset)
|
|
||||||
if not len or len == 0 then
|
|
||||||
-- padding to sector boundary, move to next byte
|
|
||||||
offset = offset + 1
|
|
||||||
else
|
|
||||||
local rec = {}
|
|
||||||
rec.len = len
|
|
||||||
rec.extAttrLen = string.byte(buffer, offset+1)
|
|
||||||
rec.extent = u32le(buffer, offset+2)
|
|
||||||
rec.size = u32le(buffer, offset+10)
|
|
||||||
rec.recordingDate = buffer:sub(offset+18, offset+24)
|
|
||||||
rec.flags = string.byte(buffer, offset+25)
|
|
||||||
rec.fileUnitSize = string.byte(buffer, offset+26)
|
|
||||||
rec.interleaveGapSize = string.byte(buffer, offset+27)
|
|
||||||
rec.volumeSeq = u16le(buffer, offset+29)
|
|
||||||
local fiLen = string.byte(buffer, offset+32)
|
|
||||||
local idStart = offset + 33
|
|
||||||
local idEnd = idStart + fiLen - 1
|
|
||||||
local fileId = buffer:sub(idStart, idEnd)
|
|
||||||
-- strip trailing ;1 and dots
|
|
||||||
rec.fileIdentifier = fileId
|
|
||||||
rec.fileName = trimVersion(fileId)
|
|
||||||
rec.isDirectory = (rec.flags & 0x02) ~= 0
|
|
||||||
table.insert(records, rec)
|
|
||||||
offset = offset + len
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return records
|
|
||||||
end
|
|
||||||
|
|
||||||
function ISO:listRoot()
|
|
||||||
if not self.pvd then self:readPVD() end
|
|
||||||
local root = self.pvd.root
|
|
||||||
local extent = root.extent
|
|
||||||
local size = root.size
|
|
||||||
local pos = extent * SECTOR_SIZE
|
|
||||||
local buffer = readBytes(self.f, pos, size)
|
|
||||||
local records = parseDirRecords(buffer, size)
|
|
||||||
-- filter out '.' and '..' and entries with empty name
|
|
||||||
local out = {}
|
|
||||||
for _, r in ipairs(records) do
|
|
||||||
local name = r.fileName
|
|
||||||
if name and name ~= "" and name ~= "\0" and name ~= "\1" and name ~= "." and name ~= ".." then
|
|
||||||
table.insert(out, { name = name, isDirectory = r.isDirectory, extent = r.extent, size = r.size })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
|
|
||||||
local function splitPath(path)
|
|
||||||
local parts = {}
|
|
||||||
for part in path:gmatch('[^/\\]+') do parts[#parts+1]=part end
|
|
||||||
return parts
|
|
||||||
end
|
|
||||||
|
|
||||||
function ISO:findEntryByPath(path)
|
|
||||||
if not self.pvd then self:readPVD() end
|
|
||||||
local parts = splitPath(path)
|
|
||||||
local curExtent = self.pvd.root.extent
|
|
||||||
local curSize = self.pvd.root.size
|
|
||||||
for i, part in ipairs(parts) do
|
|
||||||
-- read directory entries for curExtent
|
|
||||||
local buffer = readBytes(self.f, curExtent * SECTOR_SIZE, curSize)
|
|
||||||
local records = parseDirRecords(buffer, curSize)
|
|
||||||
local found = nil
|
|
||||||
for _, r in ipairs(records) do
|
|
||||||
local name = trimVersion(r.fileIdentifier)
|
|
||||||
if name:lower() == part:lower() then
|
|
||||||
found = r; break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not found then return nil, "path not found: " .. part end
|
|
||||||
if i < #parts then
|
|
||||||
if not found.isDirectory then return nil, "not a directory: "..part end
|
|
||||||
curExtent = found.extent
|
|
||||||
curSize = found.size
|
|
||||||
else
|
|
||||||
return found
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil, "empty path"
|
|
||||||
end
|
|
||||||
|
|
||||||
function ISO:readFile(path)
|
|
||||||
local rec, err = self:findEntryByPath(path)
|
|
||||||
if not rec then return nil, err end
|
|
||||||
if rec.isDirectory then return nil, "path is a directory" end
|
|
||||||
local pos = rec.extent * SECTOR_SIZE
|
|
||||||
return readBytes(self.f, pos, rec.size)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- return module
|
|
||||||
return M
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
local kernel = ...
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
$testRoot = Join-Path $PSScriptRoot "..\src"
|
||||||
|
$buildRoot = Join-Path $PSScriptRoot "..\Build"
|
||||||
|
|
||||||
|
$testRoot = Resolve-Path $testRoot
|
||||||
|
|
||||||
|
# Clean Build folder
|
||||||
|
if (Test-Path $buildRoot) {
|
||||||
|
Remove-Item -LiteralPath $buildRoot -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
New-Item -ItemType Directory -Path $buildRoot | Out-Null
|
||||||
|
|
||||||
|
Write-Host "Building from $testRoot"
|
||||||
|
Write-Host "Output to $buildRoot"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# Each top-level folder in test/
|
||||||
|
Get-ChildItem -Path $testRoot -Directory | ForEach-Object {
|
||||||
|
|
||||||
|
$folderRoot = $_.FullName
|
||||||
|
Write-Host "== Package: $($_.Name) =="
|
||||||
|
|
||||||
|
# Walk files inside this folder
|
||||||
|
Get-ChildItem -Path $folderRoot -File -Recurse | ForEach-Object {
|
||||||
|
|
||||||
|
$src = $_.FullName
|
||||||
|
$rel = $src.Substring($folderRoot.Length).TrimStart("\")
|
||||||
|
$dst = Join-Path $buildRoot $rel
|
||||||
|
$dstDir = Split-Path $dst
|
||||||
|
|
||||||
|
if (-not (Test-Path $dstDir)) {
|
||||||
|
New-Item -ItemType Directory -Path $dstDir -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Processing: $rel"
|
||||||
|
Write-Host " > Copying"
|
||||||
|
Copy-Item -LiteralPath $src -Destination $dst -Force
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Build complete."
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
$testRoot = Join-Path $PSScriptRoot "..\src"
|
||||||
|
$buildRoot = Join-Path $PSScriptRoot "..\Build"
|
||||||
|
|
||||||
|
$testRoot = Resolve-Path $testRoot
|
||||||
|
|
||||||
|
# Clean Build folder
|
||||||
|
if (Test-Path $buildRoot) {
|
||||||
|
Remove-Item -LiteralPath $buildRoot -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
New-Item -ItemType Directory -Path $buildRoot | Out-Null
|
||||||
|
|
||||||
|
Write-Host "Building from $testRoot"
|
||||||
|
Write-Host "Output to $buildRoot"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# Each top-level folder in test/
|
||||||
|
Get-ChildItem -Path $testRoot -Directory | ForEach-Object {
|
||||||
|
|
||||||
|
$folderRoot = $_.FullName
|
||||||
|
Write-Host "== Package: $($_.Name) =="
|
||||||
|
|
||||||
|
# Walk files inside this folder
|
||||||
|
Get-ChildItem -Path $folderRoot -File -Recurse | ForEach-Object {
|
||||||
|
|
||||||
|
$src = $_.FullName
|
||||||
|
$rel = $src.Substring($folderRoot.Length).TrimStart("\")
|
||||||
|
$dst = Join-Path $buildRoot $rel
|
||||||
|
$dstDir = Split-Path $dst
|
||||||
|
|
||||||
|
if (-not (Test-Path $dstDir)) {
|
||||||
|
New-Item -ItemType Directory -Path $dstDir -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Processing: $rel"
|
||||||
|
|
||||||
|
# Read first 3 lines
|
||||||
|
$header = Get-Content $src -TotalCount 3 -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
if ($header -match "--:Minify:--") {
|
||||||
|
Write-Host " > Minifying"
|
||||||
|
$content = luamin -f "$src"
|
||||||
|
|
||||||
|
# UTF8 encoding without BOM because it breaks lua
|
||||||
|
$utf8NoBOM = New-Object System.Text.UTF8Encoding($false)
|
||||||
|
[System.IO.File]::WriteAllText($dst, $content, $utf8NoBOM)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host " > Copying"
|
||||||
|
Copy-Item -LiteralPath $src -Destination $dst -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Build complete."
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
$testRoot = Join-Path $PSScriptRoot "..\src"
|
||||||
|
$buildRoot = Join-Path $PSScriptRoot "..\Build"
|
||||||
|
|
||||||
|
$testRoot = Resolve-Path $testRoot
|
||||||
|
|
||||||
|
# Clean Build folder
|
||||||
|
if (Test-Path $buildRoot) {
|
||||||
|
Remove-Item -LiteralPath $buildRoot -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
New-Item -ItemType Directory -Path $buildRoot | Out-Null
|
||||||
|
|
||||||
|
Write-Host "Building from $testRoot"
|
||||||
|
Write-Host "Output to $buildRoot"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# Each top-level folder in test/
|
||||||
|
Get-ChildItem -Path $testRoot -Directory | ForEach-Object {
|
||||||
|
|
||||||
|
$folderRoot = $_.FullName
|
||||||
|
Write-Host "== Package: $($_.Name) =="
|
||||||
|
|
||||||
|
# Walk files inside this folder
|
||||||
|
Get-ChildItem -Path $folderRoot -File -Recurse | ForEach-Object {
|
||||||
|
|
||||||
|
$src = $_.FullName
|
||||||
|
$rel = $src.Substring($folderRoot.Length).TrimStart("\")
|
||||||
|
$dst = Join-Path $buildRoot $rel
|
||||||
|
$dstDir = Split-Path $dst
|
||||||
|
|
||||||
|
if (-not (Test-Path $dstDir)) {
|
||||||
|
New-Item -ItemType Directory -Path $dstDir -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Processing: $rel"
|
||||||
|
|
||||||
|
# Read first 3 lines
|
||||||
|
$header = Get-Content $src -TotalCount 3 -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
if ($header -match "--:Minify:--") {
|
||||||
|
Write-Host " > Minifying"
|
||||||
|
$content = luamin -f "$src"
|
||||||
|
|
||||||
|
# UTF8 encoding without BOM because it breaks lua
|
||||||
|
$utf8NoBOM = New-Object System.Text.UTF8Encoding($false)
|
||||||
|
[System.IO.File]::WriteAllText($dst, $content, $utf8NoBOM)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host " > Copying"
|
||||||
|
Copy-Item -LiteralPath $src -Destination $dst -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Build complete."
|
||||||
|
|
||||||
|
$testRoot = Join-Path $PSScriptRoot "..\test"
|
||||||
|
$buildRoot = Join-Path $PSScriptRoot "..\Build"
|
||||||
|
|
||||||
|
$testRoot = Resolve-Path $testRoot
|
||||||
|
|
||||||
|
Write-Host "Building from $testRoot"
|
||||||
|
Write-Host "Output to $buildRoot"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# Each top-level folder in test/
|
||||||
|
Get-ChildItem -Path $testRoot -Directory | ForEach-Object {
|
||||||
|
|
||||||
|
$folderRoot = $_.FullName
|
||||||
|
Write-Host "== Package: $($_.Name) =="
|
||||||
|
|
||||||
|
# Walk files inside this folder
|
||||||
|
Get-ChildItem -Path $folderRoot -File -Recurse | ForEach-Object {
|
||||||
|
|
||||||
|
$src = $_.FullName
|
||||||
|
$rel = $src.Substring($folderRoot.Length).TrimStart("\")
|
||||||
|
$dst = Join-Path $buildRoot $rel
|
||||||
|
$dstDir = Split-Path $dst
|
||||||
|
|
||||||
|
if (-not (Test-Path $dstDir)) {
|
||||||
|
New-Item -ItemType Directory -Path $dstDir -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Processing: $rel"
|
||||||
|
|
||||||
|
# Read first 3 lines
|
||||||
|
$header = Get-Content $src -TotalCount 3 -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
if ($header -match "--:Minify:--") {
|
||||||
|
Write-Host " > Minifying"
|
||||||
|
$content = luamin -f "$src"
|
||||||
|
|
||||||
|
# UTF8 encoding without BOM because it breaks lua
|
||||||
|
$utf8NoBOM = New-Object System.Text.UTF8Encoding($false)
|
||||||
|
[System.IO.File]::WriteAllText($dst, $content, $utf8NoBOM)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host " > Copying"
|
||||||
|
Copy-Item -LiteralPath $src -Destination $dst -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Build complete."
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
$testRoot = Join-Path $PSScriptRoot "..\src"
|
||||||
|
$buildRoot = Join-Path $PSScriptRoot "..\Build"
|
||||||
|
|
||||||
|
$testRoot = Resolve-Path $testRoot
|
||||||
|
|
||||||
|
# Clean Build folder
|
||||||
|
if (Test-Path $buildRoot) {
|
||||||
|
Remove-Item -LiteralPath $buildRoot -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
New-Item -ItemType Directory -Path $buildRoot | Out-Null
|
||||||
|
|
||||||
|
Write-Host "Building from $testRoot"
|
||||||
|
Write-Host "Output to $buildRoot"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# Each top-level folder in test/
|
||||||
|
Get-ChildItem -Path $testRoot -Directory | ForEach-Object {
|
||||||
|
|
||||||
|
$folderRoot = $_.FullName
|
||||||
|
Write-Host "== Package: $($_.Name) =="
|
||||||
|
|
||||||
|
# Walk files inside this folder
|
||||||
|
Get-ChildItem -Path $folderRoot -File -Recurse | ForEach-Object {
|
||||||
|
|
||||||
|
$src = $_.FullName
|
||||||
|
$rel = $src.Substring($folderRoot.Length).TrimStart("\")
|
||||||
|
$dst = Join-Path $buildRoot $rel
|
||||||
|
$dstDir = Split-Path $dst
|
||||||
|
|
||||||
|
if (-not (Test-Path $dstDir)) {
|
||||||
|
New-Item -ItemType Directory -Path $dstDir -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Processing: $rel"
|
||||||
|
Write-Host " > Copying"
|
||||||
|
Copy-Item -LiteralPath $src -Destination $dst -Force
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Build complete."
|
||||||
|
|
||||||
|
|
||||||
|
$testRoot = Join-Path $PSScriptRoot "..\test"
|
||||||
|
$buildRoot = Join-Path $PSScriptRoot "..\Build"
|
||||||
|
|
||||||
|
$testRoot = Resolve-Path $testRoot
|
||||||
|
|
||||||
|
Write-Host "Building from $testRoot"
|
||||||
|
Write-Host "Output to $buildRoot"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# Each top-level folder in test/
|
||||||
|
Get-ChildItem -Path $testRoot -Directory | ForEach-Object {
|
||||||
|
|
||||||
|
$folderRoot = $_.FullName
|
||||||
|
Write-Host "== Package: $($_.Name) =="
|
||||||
|
|
||||||
|
# Walk files inside this folder
|
||||||
|
Get-ChildItem -Path $folderRoot -File -Recurse | ForEach-Object {
|
||||||
|
|
||||||
|
$src = $_.FullName
|
||||||
|
$rel = $src.Substring($folderRoot.Length).TrimStart("\")
|
||||||
|
$dst = Join-Path $buildRoot $rel
|
||||||
|
$dstDir = Split-Path $dst
|
||||||
|
|
||||||
|
if (-not (Test-Path $dstDir)) {
|
||||||
|
New-Item -ItemType Directory -Path $dstDir -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Processing: $rel"
|
||||||
|
|
||||||
|
Write-Host " > Copying"
|
||||||
|
Copy-Item -LiteralPath $src -Destination $dst -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Build complete."
|
||||||
Whitespace-only changes.
@@ -1,47 +0,0 @@
|
|||||||
-- tar_list.lua
|
|
||||||
-- List all paths stored in a TAR file (no extraction)
|
|
||||||
|
|
||||||
local function octal_to_number(str)
|
|
||||||
str = str:gsub("%z", ""):match("^%s*(.-)%s*$")
|
|
||||||
return tonumber(str, 8) or 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local file = ({...})[1]
|
|
||||||
if not file then
|
|
||||||
print("Usage: tar_list <tarfile>")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local f = fs.open(file, "r")
|
|
||||||
local tar = f.readAll()
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
local i = 1
|
|
||||||
local len = #tar
|
|
||||||
|
|
||||||
while i + 512 <= len do
|
|
||||||
local header = tar:sub(i, i + 511)
|
|
||||||
|
|
||||||
if header:match("^\0+$") then break end
|
|
||||||
|
|
||||||
-- Extract raw name & prefix
|
|
||||||
local name = header:sub(1, 100):gsub("%z.*","")
|
|
||||||
local prefix = header:sub(346, 500):gsub("%z.*","")
|
|
||||||
|
|
||||||
local size = octal_to_number(header:sub(125, 136))
|
|
||||||
i = i + 512
|
|
||||||
|
|
||||||
-- Skip file contents
|
|
||||||
local pad = (512 - (size % 512)) % 512
|
|
||||||
i = i + size + pad
|
|
||||||
|
|
||||||
local full
|
|
||||||
if prefix ~= "" then
|
|
||||||
full = prefix .. "/" .. name
|
|
||||||
else
|
|
||||||
full = name
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Print exactly what Windows Explorer stored
|
|
||||||
print(full)
|
|
||||||
end
|
|
||||||
Reference in new issue
Block a user