spm works maybe?
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
|
||||
local kbs = {kernel.cct.peripheral.find("tm_keyboard")}
|
||||
|
||||
|
||||
kernel.cct.eventhooks["tm_keyboard_char"]=function(...)
|
||||
|
||||
end
|
||||
@@ -1,394 +1,6 @@
|
||||
--:Minify:--
|
||||
local kernel = ...
|
||||
local apis = kernel.apis
|
||||
local native = apis.peripheral
|
||||
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
||||
local peripheral={}
|
||||
local kernel=...
|
||||
|
||||
function peripheral.getNames()
|
||||
local results = {}
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
if native.isPresent(side) then
|
||||
table.insert(results, side)
|
||||
if native.hasType(side, "peripheral_hub") then
|
||||
local remote = native.call(side, "getNamesRemote")
|
||||
for _, name in ipairs(remote) do
|
||||
table.insert(results, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
function peripheral.isPresent(name)
|
||||
if native.isPresent(name) then
|
||||
return true
|
||||
end
|
||||
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function peripheral.getType(peripheral)
|
||||
if type(peripheral) == "string" then
|
||||
if native.isPresent(peripheral) then
|
||||
return native.getType(peripheral)
|
||||
end
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
|
||||
return native.call(side, "getTypeRemote", peripheral)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
else
|
||||
local mt = getmetatable(peripheral)
|
||||
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
|
||||
error("bad argument #1 (table is not a peripheral)", 2)
|
||||
end
|
||||
return table.unpack(mt.types)
|
||||
end
|
||||
end
|
||||
|
||||
function peripheral.hasType(peripheral, peripheral_type)
|
||||
if type(peripheral) == "string" then
|
||||
if native.isPresent(peripheral) then
|
||||
return native.hasType(peripheral, peripheral_type)
|
||||
end
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then
|
||||
return native.call(side, "hasTypeRemote", peripheral, peripheral_type)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
else
|
||||
local mt = getmetatable(peripheral)
|
||||
if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then
|
||||
error("bad argument #1 (table is not a peripheral)", 2)
|
||||
end
|
||||
return mt.types[peripheral_type] ~= nil
|
||||
end
|
||||
end
|
||||
|
||||
function peripheral.getMethods(name)
|
||||
if native.isPresent(name) then
|
||||
return native.getMethods(name)
|
||||
end
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
|
||||
return native.call(side, "getMethodsRemote", name)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function peripheral.getName(peripheral)
|
||||
local mt = getmetatable(peripheral)
|
||||
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
|
||||
error("bad argument #1 (table is not a peripheral)", 2)
|
||||
end
|
||||
return mt.name
|
||||
end
|
||||
|
||||
function peripheral.call(name, method, ...)
|
||||
if native.isPresent(name) then
|
||||
return native.call(name, method, ...)
|
||||
end
|
||||
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
|
||||
return native.call(side, "callRemote", name, method, ...)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function peripheral.wrap(name)
|
||||
local methods = peripheral.getMethods(name)
|
||||
if not methods then
|
||||
return nil
|
||||
end
|
||||
|
||||
local types = { peripheral.getType(name) }
|
||||
for i = 1, #types do types[types[i]] = true end
|
||||
local result = setmetatable({}, {
|
||||
__name = "peripheral",
|
||||
name = name,
|
||||
type = types[1],
|
||||
types = types,
|
||||
})
|
||||
for _, method in ipairs(methods) do
|
||||
result[method] = function(...)
|
||||
return peripheral.call(name, method, ...)
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function peripheral.find(ty, filter)
|
||||
local results = {}
|
||||
for _, name in ipairs(peripheral.getNames()) do
|
||||
if peripheral.hasType(name, ty) then
|
||||
local wrapped = peripheral.wrap(name)
|
||||
if filter == nil or filter(name, wrapped) then
|
||||
table.insert(results, wrapped)
|
||||
end
|
||||
end
|
||||
end
|
||||
return table.unpack(results)
|
||||
end
|
||||
|
||||
local icolors = {
|
||||
[0x1] = 1, -- #000000
|
||||
[0x2] = 2, -- #FFFFFF
|
||||
[0x4] = 3, -- #FF0000
|
||||
[0x8] = 4, -- #00FF00
|
||||
[0x10] = 5, -- #0000FF
|
||||
[0x20] = 6, -- #00FFFF
|
||||
[0x40] = 7, -- #FF00FF
|
||||
[0x80] = 8, -- #FFFF00
|
||||
[0x100] = 9, -- #FF6D00
|
||||
[0x200] = 10, -- #6DFF55
|
||||
[0x400] = 11, -- #24FFFF
|
||||
[0x800] = 12, -- #924900
|
||||
[0x1000] = 13, -- #6D6D55
|
||||
[0x2000] = 14, -- #DBDBAA
|
||||
[0x4000] = 15, -- #6D00FF
|
||||
[0x8000] = 16 -- #B6FF00
|
||||
}
|
||||
|
||||
local colors = {
|
||||
0x0001, -- #000000
|
||||
0x0002, -- #FFFFFF
|
||||
0x0004, -- #FF0000
|
||||
0x0008, -- #00FF00
|
||||
0x0010, -- #0000FF
|
||||
0x0020, -- #00FFFF
|
||||
0x0040, -- #FF00FF
|
||||
0x0080, -- #FFFF00
|
||||
0x0100, -- #FF6D00
|
||||
0x0200, -- #6DFF55
|
||||
0x0400, -- #24FFFF
|
||||
0x0800, -- #924900
|
||||
0x1000, -- #6D6D55
|
||||
0x2000, -- #DBDBAA
|
||||
0x4000, -- #6D00FF
|
||||
0x8000 -- #B6FF00
|
||||
}
|
||||
|
||||
local function write(text, term)
|
||||
local x, y = term.getCursorPos()
|
||||
local w, h = term.getSize()
|
||||
|
||||
for i = 1, #text do
|
||||
local c = text:sub(i, i)
|
||||
|
||||
if c == "\n" then
|
||||
y = y + 1
|
||||
x = 1
|
||||
elseif c == "\t" then
|
||||
local tabSize = 4
|
||||
local spaces = tabSize - ((x - 1) % tabSize)
|
||||
term.write(string.rep(" ", spaces))
|
||||
x = x + spaces
|
||||
elseif c == "\b" then
|
||||
if x > 1 then
|
||||
x = x - 1
|
||||
term.setCursorPos(x, y)
|
||||
term.write(" ")
|
||||
term.setCursorPos(x, y)
|
||||
end
|
||||
else
|
||||
if x <= w and y <= h then
|
||||
term.setCursorPos(x, y)
|
||||
term.write(c)
|
||||
x = x + 1
|
||||
end
|
||||
end
|
||||
|
||||
if x > w then
|
||||
x = 1
|
||||
y = y + 1
|
||||
end
|
||||
|
||||
if y - 1 >= h then
|
||||
term.scroll(1)
|
||||
y = h
|
||||
term.setCursorPos(x, y)
|
||||
end
|
||||
end
|
||||
|
||||
term.setCursorPos(x, y)
|
||||
end
|
||||
|
||||
kernel.devfs.data.tty={}
|
||||
local ctrl,alt = false, false
|
||||
|
||||
local function serializeBool(bool)
|
||||
if bool then
|
||||
return "T"
|
||||
else
|
||||
return "F"
|
||||
end
|
||||
end
|
||||
|
||||
local function newtty(obj, id, ev)
|
||||
kernel.devfs.data["tty"][id] = function(op, mode)
|
||||
if op=="type" then
|
||||
return "character device"
|
||||
elseif op=="open" then
|
||||
local h = {
|
||||
read=function(amount)
|
||||
local rv=""
|
||||
for i=1, amount or 1 do
|
||||
local event = {ev()}
|
||||
if event[1] then
|
||||
rv=rv..event[1]
|
||||
end
|
||||
end
|
||||
if rv=="" then rv=nil end
|
||||
return rv
|
||||
end,
|
||||
write=function(content)
|
||||
write(content, obj)
|
||||
end,
|
||||
size=function()
|
||||
local s={obj.getSize()}
|
||||
return table.concat(s,";")
|
||||
end,
|
||||
clear=function()
|
||||
obj.clear()
|
||||
obj.setCursorPos(1,1)
|
||||
end,
|
||||
gpos=function()
|
||||
local s={obj.getCursorPos()}
|
||||
return table.concat(s,";")
|
||||
end,
|
||||
spos=function(x,y)
|
||||
return obj.setCursorPos(x,y)
|
||||
end,
|
||||
sfgc=function(c)
|
||||
return obj.setTextColor(colors[c])
|
||||
end,
|
||||
sbgc=function(c)
|
||||
return obj.setBackgroundColor(colors[c])
|
||||
end,
|
||||
gfgc=function()
|
||||
return icolors[obj.getTextColor()]
|
||||
end,
|
||||
gbgc=function()
|
||||
return icolors[obj.getBackgroundColor()]
|
||||
end,
|
||||
gctrl=function()
|
||||
return serializeBool(ctrl)..";"..serializeBool(alt)
|
||||
end
|
||||
}
|
||||
if mode=="rw" then
|
||||
return h
|
||||
elseif mode=="r" then
|
||||
h["write"]=nil
|
||||
return h
|
||||
elseif mode=="w" then
|
||||
h["read"]=nil
|
||||
return h
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local fifo = kernel.newFifo()
|
||||
|
||||
kernel.processes.cctmond = function()
|
||||
local timeout = false
|
||||
while true do
|
||||
local event = {kernel.EFI:getMachineEvent()}
|
||||
|
||||
if event[1] then
|
||||
local eventType = event[1]
|
||||
local charOrKey = event[3]
|
||||
|
||||
local ctrlKeyMap = {
|
||||
[apis.keys.a]=1, [apis.keys.b]=2, [apis.keys.c]=3,
|
||||
[apis.keys.d]=4, [apis.keys.e]=5, [apis.keys.f]=6,
|
||||
[apis.keys.g]=7, [apis.keys.h]=8, [apis.keys.i]=9,
|
||||
[apis.keys.j]=10, [apis.keys.k]=11, [apis.keys.l]=12,
|
||||
[apis.keys.m]=13, [apis.keys.n]=14, [apis.keys.o]=15,
|
||||
[apis.keys.p]=16, [apis.keys.q]=17, [apis.keys.r]=18,
|
||||
[apis.keys.s]=19, [apis.keys.t]=20, [apis.keys.u]=21,
|
||||
[apis.keys.v]=22, [apis.keys.w]=23, [apis.keys.x]=24,
|
||||
[apis.keys.y]=25, [apis.keys.z]=26,
|
||||
}
|
||||
|
||||
if eventType == "keyPressed" then
|
||||
if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then
|
||||
ctrl = true
|
||||
elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then
|
||||
alt = true
|
||||
end
|
||||
|
||||
if ctrl then
|
||||
local ctrlByte = ctrlKeyMap[charOrKey]
|
||||
if ctrlByte then
|
||||
if ctrlByte == 3 then
|
||||
for _, task in ipairs(syscall.getTasks()) do
|
||||
syscall.sigsend(task, 1)
|
||||
end
|
||||
else
|
||||
fifo.push(string.char(ctrlByte))
|
||||
end
|
||||
end
|
||||
else
|
||||
local specialKeyMap = {
|
||||
[apis.keys.up] = "[A",
|
||||
[apis.keys.down] = "[B",
|
||||
[apis.keys.right] = "[C",
|
||||
[apis.keys.left] = "[D",
|
||||
[apis.keys.home] = "[H",
|
||||
[apis.keys["end"]] = "[F",
|
||||
[apis.keys.pageUp] = "[5~",
|
||||
[apis.keys.pageDown] = "[6~",
|
||||
[apis.keys.delete] = "[3~",
|
||||
}
|
||||
local special = specialKeyMap[charOrKey]
|
||||
if special then fifo.push(special) end
|
||||
end
|
||||
|
||||
elseif eventType == "keyReleased" then
|
||||
if charOrKey == apis.keys.leftCtrl or charOrKey == apis.keys.rightCtrl then
|
||||
ctrl = false
|
||||
elseif charOrKey == apis.keys.leftAlt or charOrKey == apis.keys.rightAlt then
|
||||
alt = false
|
||||
end
|
||||
|
||||
elseif eventType == "keyTyped" then
|
||||
if charOrKey then fifo.push(charOrKey) end
|
||||
end
|
||||
|
||||
timeout = false
|
||||
else
|
||||
timeout = true
|
||||
end
|
||||
|
||||
if timeout then
|
||||
sleep(0.05)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newtty(apis.term, "1", fifo.pop)
|
||||
|
||||
for i,v in ipairs({peripheral.find("monitor")}) do
|
||||
v.setTextScale(.5)
|
||||
v.write("Initializing...")
|
||||
newtty(v,tostring(i+1),function () end)
|
||||
if kernel.gfx then
|
||||
|
||||
end
|
||||
@@ -55,11 +55,12 @@ local function displaySuperBadError(err)
|
||||
lterm.write("A critical error occurred while loading the system:")
|
||||
lterm.setCursorPos(1, 3)
|
||||
write(err, lterm)
|
||||
while true do end
|
||||
coroutine.yield("key")
|
||||
end
|
||||
|
||||
term.setCursorBlink(false)
|
||||
local ok, err = xpcall(function()
|
||||
--p
|
||||
local apis = {BOOT_DRIVE_PATH = BOOT_DRIVE_PATH}
|
||||
|
||||
local lua = {
|
||||
@@ -100,6 +101,7 @@ local ok, err = xpcall(function()
|
||||
_G[i] = nil
|
||||
end
|
||||
end
|
||||
--p
|
||||
|
||||
local acekeys={
|
||||
[apis.keys.enter]="\n",
|
||||
@@ -248,11 +250,12 @@ local ok, err = xpcall(function()
|
||||
return value
|
||||
end
|
||||
|
||||
local peripheral={}
|
||||
--p
|
||||
local p={}
|
||||
local native = apis.peripheral
|
||||
local sides = {"top", "bottom", "left", "right", "front", "back"}
|
||||
|
||||
function peripheral.getNames()
|
||||
function p.getNames()
|
||||
local results = {}
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
@@ -269,7 +272,7 @@ local ok, err = xpcall(function()
|
||||
return results
|
||||
end
|
||||
|
||||
function peripheral.isPresent(name)
|
||||
function p.isPresent(name)
|
||||
if native.isPresent(name) then
|
||||
return true
|
||||
end
|
||||
@@ -283,7 +286,7 @@ local ok, err = xpcall(function()
|
||||
return false
|
||||
end
|
||||
|
||||
function peripheral.getType(peripheral)
|
||||
function p.getType(peripheral)
|
||||
if type(peripheral) == "string" then
|
||||
if native.isPresent(peripheral) then
|
||||
return native.getType(peripheral)
|
||||
@@ -304,7 +307,7 @@ local ok, err = xpcall(function()
|
||||
end
|
||||
end
|
||||
|
||||
function peripheral.hasType(peripheral, peripheral_type)
|
||||
function p.hasType(peripheral, peripheral_type)
|
||||
if type(peripheral) == "string" then
|
||||
if native.isPresent(peripheral) then
|
||||
return native.hasType(peripheral, peripheral_type)
|
||||
@@ -325,7 +328,7 @@ local ok, err = xpcall(function()
|
||||
end
|
||||
end
|
||||
|
||||
function peripheral.getMethods(name)
|
||||
function p.getMethods(name)
|
||||
if native.isPresent(name) then
|
||||
return native.getMethods(name)
|
||||
end
|
||||
@@ -338,7 +341,7 @@ local ok, err = xpcall(function()
|
||||
return nil
|
||||
end
|
||||
|
||||
function peripheral.getName(peripheral)
|
||||
function p.getName(peripheral)
|
||||
local mt = getmetatable(peripheral)
|
||||
if not mt or mt.__name ~= "peripheral" or type(mt.name) ~= "string" then
|
||||
error("bad argument #1 (table is not a peripheral)", 2)
|
||||
@@ -346,7 +349,7 @@ local ok, err = xpcall(function()
|
||||
return mt.name
|
||||
end
|
||||
|
||||
function peripheral.call(name, method, ...)
|
||||
function p.call(name, method, ...)
|
||||
if native.isPresent(name) then
|
||||
return native.call(name, method, ...)
|
||||
end
|
||||
@@ -360,13 +363,13 @@ local ok, err = xpcall(function()
|
||||
return nil
|
||||
end
|
||||
|
||||
function peripheral.wrap(name)
|
||||
local methods = peripheral.getMethods(name)
|
||||
function p.wrap(name)
|
||||
local methods = p.getMethods(name)
|
||||
if not methods then
|
||||
return nil
|
||||
end
|
||||
|
||||
local types = { peripheral.getType(name) }
|
||||
local types = { p.getType(name) }
|
||||
for i = 1, #types do types[types[i]] = true end
|
||||
local result = setmetatable({}, {
|
||||
__name = "peripheral",
|
||||
@@ -376,17 +379,17 @@ local ok, err = xpcall(function()
|
||||
})
|
||||
for _, method in ipairs(methods) do
|
||||
result[method] = function(...)
|
||||
return peripheral.call(name, method, ...)
|
||||
return p.call(name, method, ...)
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function peripheral.find(ty, filter)
|
||||
function p.find(ty, filter)
|
||||
local results = {}
|
||||
for _, name in ipairs(peripheral.getNames()) do
|
||||
if peripheral.hasType(name, ty) then
|
||||
local wrapped = peripheral.wrap(name)
|
||||
for _, name in ipairs(p.getNames()) do
|
||||
if p.hasType(name, ty) then
|
||||
local wrapped = p.wrap(name)
|
||||
if filter == nil or filter(name, wrapped) then
|
||||
table.insert(results, wrapped)
|
||||
end
|
||||
@@ -394,8 +397,8 @@ local ok, err = xpcall(function()
|
||||
end
|
||||
return table.unpack(results)
|
||||
end
|
||||
|
||||
local allscreens = {peripheral.find("monitor")}
|
||||
--p
|
||||
local allscreens = {p.find("monitor")}
|
||||
for i=1, #allscreens do
|
||||
allscreens[i].setTextScale(.5)
|
||||
allscreens[i].clear()
|
||||
@@ -404,6 +407,17 @@ local ok, err = xpcall(function()
|
||||
|
||||
allscreens[#allscreens+1] = apis.term
|
||||
|
||||
local callAsyncQueue = {}
|
||||
local callAsyncReturn = {}
|
||||
apis.callAsyncReturn = callAsyncReturn
|
||||
local callidx=0
|
||||
|
||||
function apis.callAsync(func, ...)
|
||||
callidx=callidx+1
|
||||
callAsyncQueue[#callAsyncQueue+1] = {callidx, func, ...}
|
||||
return callidx
|
||||
end
|
||||
|
||||
local EFI = {
|
||||
getEpochMs = function() return apis.os.epoch("utc") end,
|
||||
getUptime = function() return apis.os.clock() * 1000 end,
|
||||
@@ -489,7 +503,8 @@ local ok, err = xpcall(function()
|
||||
apis.term.setCursorPos(1, 1)
|
||||
|
||||
local kernelCoro = coroutine.create(function()
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
--pf
|
||||
---@diagnostic disable-next-line: param-type-mismatch-
|
||||
local ok, err = xpcall(Kernel, debug.traceback, EFI)
|
||||
if not ok and not EFI.reboot then displaySuperBadError(err) end
|
||||
if err then
|
||||
@@ -518,6 +533,7 @@ local ok, err = xpcall(function()
|
||||
end
|
||||
|
||||
EFI.screenCtl:print("Loaded in " .. tostring(apis.os.clock()) .. " seconds.\n")
|
||||
--p
|
||||
|
||||
while true do
|
||||
local status, err = coroutine.resumeWithTimeout(kernelCoro, 50)
|
||||
@@ -526,28 +542,30 @@ local ok, err = xpcall(function()
|
||||
while not exit do
|
||||
local event = {coroutine.yield()}
|
||||
if event[1] == "key" then
|
||||
queueEvent(table.unpack(event))
|
||||
queueEvent("keyPressed", 1, event[2])
|
||||
if acekeys[event[2]] then
|
||||
queueEvent("keyTyped", 1, acekeys[event[2]])
|
||||
end
|
||||
elseif event[1] == "char" then
|
||||
queueEvent(table.unpack(event))
|
||||
queueEvent("keyTyped", 1, event[2])
|
||||
elseif event[1] == "key_up" then
|
||||
queueEvent(table.unpack(event))
|
||||
queueEvent("keyReleased", 1, event[2])
|
||||
elseif event[1] == "disk" then
|
||||
queueEvent("componentAdded", "disk")
|
||||
elseif event[1] == "disk_eject" then
|
||||
queueEvent("componentRemoved", "disk")
|
||||
elseif event[1] == "modem_message" then
|
||||
queueEvent("modem_message", table.unpack(event, 2))
|
||||
elseif event[1] == "rednet_message" then
|
||||
queueEvent("rednet_message", table.unpack(event, 2))
|
||||
elseif event[1] == "http_success" then
|
||||
queueEvent("http_success", table.unpack(event, 2))
|
||||
elseif event[1] == "http_failure" then
|
||||
queueEvent("http_failure", table.unpack(event, 2))
|
||||
elseif event[1] == "NoSleep" then
|
||||
exit = true
|
||||
else
|
||||
queueEvent(table.unpack(event))
|
||||
end
|
||||
end
|
||||
while #callAsyncQueue>0 do
|
||||
local bundle = table.remove(callAsyncQueue, 1)
|
||||
local ret = {xpcall(bundle[2], debug.traceback, table.unpack(bundle, 3))}
|
||||
if not ret[1] then
|
||||
callAsyncReturn[bundle[1]]={false, ret[2]}
|
||||
else
|
||||
callAsyncReturn[bundle[1]]={true, table.unpack(ret,2)}
|
||||
end
|
||||
end
|
||||
if status == "error" or coroutine.status(kernelCoro) == "dead" then
|
||||
@@ -556,6 +574,12 @@ local ok, err = xpcall(function()
|
||||
end
|
||||
displaySuperBadError("Kernel error: " .. tostring(err))
|
||||
coroutine.yield("key")
|
||||
elseif status == "success" then
|
||||
if EFI.reboot then
|
||||
apis.os.reboot()
|
||||
end
|
||||
displaySuperBadError("Kernel error: Attempted to yield main thread\n"..debug.traceback(kernelCoro, "Attempted to yield main thread"))
|
||||
coroutine.yield("key")
|
||||
end
|
||||
initFs:refresh()
|
||||
end
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
local kernel=...
|
||||
kernel.cct={}
|
||||
kernel.cct.peripheral={}
|
||||
kernel.cct.callAsync=kernel.apis.callAsync
|
||||
local peripheral=kernel.cct.peripheral
|
||||
local apis = kernel.apis
|
||||
local native = apis.peripheral
|
||||
@@ -103,6 +104,40 @@ function peripheral.getName(peripheral)
|
||||
end
|
||||
|
||||
function peripheral.call(name, method, ...)
|
||||
if native.isPresent(name) then
|
||||
local id = kernel.cct.callAsync(native.call, name, method, ...)
|
||||
kernel.currentTask.io=function()
|
||||
if kernel.apis.callAsyncReturn[id] then
|
||||
local r=kernel.apis.callAsyncReturn[id]
|
||||
if not r[1] then error(r[2]) end
|
||||
kernel.apis.callAsyncReturn[id]=nil
|
||||
return table.unpack(r,2)
|
||||
end
|
||||
end
|
||||
kernel.currentTask.status="D"
|
||||
return
|
||||
end
|
||||
|
||||
for n = 1, #sides do
|
||||
local side = sides[n]
|
||||
if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then
|
||||
local id = kernel.cct.callAsync(native.call, side, "callRemote", name, method, ...)
|
||||
kernel.currentTask.io=function()
|
||||
if kernel.apis.callAsyncReturn[id] then
|
||||
local r=kernel.apis.callAsyncReturn[id]
|
||||
if not r[1] then error(r[2]) end
|
||||
kernel.apis.callAsyncReturn[id]=nil
|
||||
return table.unpack(r,2)
|
||||
end
|
||||
end
|
||||
kernel.currentTask.status="D"
|
||||
return
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function peripheral.callnative(name, method, ...)
|
||||
if native.isPresent(name) then
|
||||
return native.call(name, method, ...)
|
||||
end
|
||||
@@ -116,7 +151,7 @@ function peripheral.call(name, method, ...)
|
||||
return nil
|
||||
end
|
||||
|
||||
function peripheral.wrap(name)
|
||||
function peripheral.wrap(name, wrap)
|
||||
local methods = peripheral.getMethods(name)
|
||||
if not methods then
|
||||
return nil
|
||||
@@ -130,9 +165,17 @@ function peripheral.wrap(name)
|
||||
type = types[1],
|
||||
types = types,
|
||||
})
|
||||
for _, method in ipairs(methods) do
|
||||
result[method] = function(...)
|
||||
return peripheral.call(name, method, ...)
|
||||
if wrap then
|
||||
for _, method in ipairs(methods) do
|
||||
result[method] = function(...)
|
||||
return peripheral.call(name, method, ...)
|
||||
end
|
||||
end
|
||||
else
|
||||
for _, method in ipairs(methods) do
|
||||
result[method] = function(...)
|
||||
return peripheral.callnative(name, method, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
return result
|
||||
@@ -149,4 +192,4 @@ function peripheral.find(ty, filter)
|
||||
end
|
||||
end
|
||||
return table.unpack(results)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
local peripheral=kernel.cct.peripheral
|
||||
|
||||
local function wrap(p)
|
||||
return function(op, mode)
|
||||
if op=="type" then
|
||||
return "device"
|
||||
elseif op=="open" then
|
||||
if kernel.uid~=0 then error("EACCES") end
|
||||
return peripheral.wrap(p, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local peripherals=peripheral.getNames()
|
||||
for i=1, #peripherals do
|
||||
local p=peripherals[i]
|
||||
local typ=peripheral.getType(p)
|
||||
local file=wrap(p)
|
||||
kernel.devfs.data["raw"][p]=file
|
||||
local typefolder=kernel.devfs.data["raw"]["by-type"][typ]
|
||||
if not typefolder then typefolder={} end
|
||||
typefolder[tostring(#table.keys(typefolder)+1)] = file
|
||||
kernel.devfs.data["raw"]["by-type"][typ]=typefolder
|
||||
end
|
||||
@@ -120,6 +120,7 @@ function handler.connect(fd, address)
|
||||
end
|
||||
fdo.socket.active=true
|
||||
fdo.socket.url=url
|
||||
fdo.socket.loaded=false
|
||||
|
||||
return true
|
||||
end
|
||||
@@ -129,10 +130,11 @@ function handler.connect(fd, address)
|
||||
return
|
||||
end
|
||||
|
||||
if not kernel.cct.httpqueue[fdo.socket.url] then
|
||||
if not kernel.cct.httpqueue[fdo.socket.url] and not fdo.socket.loaded then
|
||||
fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url]))
|
||||
kernel.cct.httpqueue[fdo.socket.url]=nil
|
||||
kernel.cct.httpresponse[fdo.socket.url]=nil
|
||||
fdo.socket.loaded=true
|
||||
end
|
||||
|
||||
if not fdo.socket.file then
|
||||
@@ -141,6 +143,7 @@ function handler.connect(fd, address)
|
||||
fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url]))
|
||||
kernel.cct.httpqueue[fdo.socket.url]=nil
|
||||
kernel.cct.httpresponse[fdo.socket.url]=nil
|
||||
fdo.socket.loaded=true
|
||||
return fdo.socket.file.read(count)
|
||||
end
|
||||
end
|
||||
@@ -156,10 +159,11 @@ function handler.connect(fd, address)
|
||||
return
|
||||
end
|
||||
|
||||
if not kernel.cct.httpqueue[fdo.socket.url] then
|
||||
if not kernel.cct.httpqueue[fdo.socket.url] and not fdo.socket.loaded then
|
||||
fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url]))
|
||||
kernel.cct.httpqueue[fdo.socket.url]=nil
|
||||
kernel.cct.httpresponse[fdo.socket.url]=nil
|
||||
fdo.socket.loaded=true
|
||||
end
|
||||
|
||||
if not fdo.socket.file then
|
||||
@@ -168,6 +172,7 @@ function handler.connect(fd, address)
|
||||
fdo.socket.file=kernel.sfile(buildResponse(kernel.cct.httpresponse[fdo.socket.url]))
|
||||
kernel.cct.httpqueue[fdo.socket.url]=nil
|
||||
kernel.cct.httpresponse[fdo.socket.url]=nil
|
||||
fdo.socket.loaded=true
|
||||
return fdo.socket.file.seek(whence, offset)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -144,7 +144,6 @@ local function write(text, term)
|
||||
term.setCursorPos(x, y)
|
||||
end
|
||||
|
||||
kernel.devfs.data.tty={}
|
||||
kernel.cct.ctrl,kernel.cct.alt = false, false
|
||||
|
||||
local function serializeBool(bool)
|
||||
|
||||
+11
-3
@@ -1,10 +1,11 @@
|
||||
--:Minify:--
|
||||
local kernel=...
|
||||
local keys=kernel.apis.keys
|
||||
kernel.cct.eventhooks={}
|
||||
|
||||
kernel.processes.cctdeamon = function()
|
||||
kernel.processes.cctdaemon = function()
|
||||
local timeout = false
|
||||
kernel.log("CCT deamon started")
|
||||
kernel.log("CCT daemon started")
|
||||
while true do
|
||||
local event = {kernel.EFI:getMachineEvent()}
|
||||
|
||||
@@ -84,6 +85,13 @@ kernel.processes.cctdeamon = function()
|
||||
kernel.cct.httperror[event[2]]=event[3]
|
||||
kernel.cct.httpresponse[event[2]]=event[4]
|
||||
end
|
||||
else
|
||||
if kernel.cct.eventhooks[eventType] then
|
||||
local ok,err = xpcall(kernel.cct.eventhooks[eventType], debug.traceback, table.unpack(event))
|
||||
if not ok then
|
||||
kernel.log("Error on eventhook "..eventType.."\n"..err)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
timeout = false
|
||||
@@ -97,4 +105,4 @@ kernel.processes.cctdeamon = function()
|
||||
end
|
||||
end
|
||||
|
||||
kernel.log("CCT deamon queued for execution")
|
||||
kernel.log("CCT daemon queued for execution")
|
||||
@@ -1,5 +1,6 @@
|
||||
--:Minify:--
|
||||
local EFI=...
|
||||
--pf
|
||||
EFI.beep(440, 500)
|
||||
local screen=EFI.screenCtl
|
||||
local ifs=EFI.initfs
|
||||
@@ -302,20 +303,24 @@ for _, i in ipairs(ifs.list("/lib/modules")) do
|
||||
for _,v in ipairs(modlist) do
|
||||
local prior=tonumber(v:sub(1,2))
|
||||
if prior then
|
||||
modules[prior+1][#modules[prior+1]+1]="/lib/modules/"..i.."/"..v
|
||||
modules[prior+1][#modules[prior+1]+1]=i.."/"..v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
kernel.ifs=ifs
|
||||
--pf
|
||||
kernel.apis=EFI.firmware
|
||||
--pf
|
||||
kernel.EFI=EFI
|
||||
kernel.arch=arch
|
||||
kernel.initdisks=disks
|
||||
kernel.screen=screen
|
||||
kernel.processes={}
|
||||
kernel.fstab=fstab
|
||||
kernel.denied={}
|
||||
kernel.loadingModule="kernel"
|
||||
|
||||
kernel.kernelTask = {
|
||||
name="kernel",
|
||||
@@ -357,6 +362,11 @@ function kernel.asyncReturn(...)
|
||||
kernel.currentTask.syscallReturn = {...}
|
||||
end
|
||||
|
||||
function kernel.deny(moduleid)
|
||||
kernel.denied[moduleid]=true
|
||||
if kernel.config.showModLoad then kernel.log("Module "..kernel.loadingModule.." denied "..moduleid, "DBUG", 0xFF0000) end
|
||||
end
|
||||
|
||||
kernel.syscalls["time"]=function() return kernel.EFI:getEpochMs() end
|
||||
kernel.syscalls["date"]=function() return kernel.EFI:date() end
|
||||
kernel.syscalls["log"]=kernel.log
|
||||
@@ -390,28 +400,39 @@ kernel.syscalls["halt"]=function()
|
||||
kernel.halt()
|
||||
end
|
||||
end
|
||||
kernel.syscalls["saveLog"]=function()
|
||||
if kernel.uid==0 or kernel.groups.wheel then
|
||||
kernel.saveLog()
|
||||
end
|
||||
end
|
||||
|
||||
kernel.saveLog()
|
||||
kernel.log("Running modules")
|
||||
for _,p in ipairs(modules) do
|
||||
for _,v in ipairs(p) do
|
||||
if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG", 0x00FFFF) end
|
||||
local code=ifs.readAllText(v)
|
||||
if not code then
|
||||
kernel.panic("Failed to read module "..v)
|
||||
kernel.loadingModule=v
|
||||
if not kernel.denied[v] then
|
||||
if kernel.config.showModLoad then kernel.log("Loading module "..v, "DBUG", 0x00FFFF) end
|
||||
local code=ifs.readAllText("/lib/modules/"..v)
|
||||
if not code then
|
||||
kernel.panic("Failed to read module "..v)
|
||||
end
|
||||
local func,err=load(code,"@"..v)
|
||||
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) end
|
||||
local status, err = xpcall(func,debug.traceback, kernel)
|
||||
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
||||
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 0x00FFFF) end
|
||||
if kernel.config.moreLogsaves then kernel.saveLog() end
|
||||
else
|
||||
if kernel.config.showModLoad then kernel.log("Denied module "..v, "DBUG", 0xFF0000) end
|
||||
end
|
||||
local func,err=load(code,"@"..v)
|
||||
if not func then kernel.panic("ModuLoadErr: "..tostring(err)) end
|
||||
local status, err = xpcall(func,debug.traceback, kernel)
|
||||
if not status then kernel.panic("ModuRunErr: "..tostring(err)) end
|
||||
if kernel.config.showModLoad then kernel.log("Loaded module "..v, "DBUG", 0x00FFFF) end
|
||||
if kernel.config.moreLogsaves then kernel.saveLog() end
|
||||
end
|
||||
end
|
||||
|
||||
kernel.log("Kernel initialized successfully.")
|
||||
kernel.saveLog()
|
||||
kernel.status="running"
|
||||
kernel.loadingModule=nil
|
||||
screen:disable()
|
||||
local ok,err = xpcall(kernel.main, debug.traceback)
|
||||
if not ok then
|
||||
|
||||
@@ -690,7 +690,9 @@ function vfs.open(path, mode)
|
||||
local handle
|
||||
if disk:type(diskPath) ~= "directory" then
|
||||
handle = disk:open(diskPath, mode)
|
||||
if type(handle) ~= "table" then error("ENFILE") end
|
||||
if type(handle, true) ~= "table" then
|
||||
error("ENFILE")
|
||||
end
|
||||
end
|
||||
|
||||
if isNew then
|
||||
@@ -761,7 +763,7 @@ function vfs.close(fd)
|
||||
local task = kernel.currentTask
|
||||
local file = task.fd[fd]
|
||||
if not file then error("EBADF") end
|
||||
if not task.fd[fd].isvirt then
|
||||
if not task.fd[fd].isvirt then
|
||||
total = total - 1
|
||||
end
|
||||
task.fd[fd] = nil
|
||||
@@ -1147,6 +1149,12 @@ function vfs.devctl(fd, method, ...)
|
||||
return kernel.currentTask.fd[fd].handle[method](...)
|
||||
end
|
||||
|
||||
function vfs.devlst(fd)
|
||||
if not kernel.currentTask.fd[fd] then error("EBADF") end
|
||||
if not kernel.currentTask.fd[fd] then error("EINVAL") end
|
||||
return table.keys(kernel.currentTask.fd[fd].handle)
|
||||
end
|
||||
|
||||
vfs.resolveMount = resolveMount
|
||||
|
||||
local sys = kernel.syscalls
|
||||
@@ -1179,6 +1187,7 @@ sys["chroot"] = vfs.chroot
|
||||
sys["dup"] = vfs.dup
|
||||
sys["dup2"] = vfs.dup2
|
||||
sys["devctl"] = vfs.devctl
|
||||
sys["devlst"] = vfs.devlst
|
||||
sys["symlink"] = vfs.symlink
|
||||
sys["readlink"] = vfs.readlink
|
||||
sys["access"] = vfs.access
|
||||
|
||||
@@ -214,6 +214,8 @@ end
|
||||
data[".meta"]=strFile(buildMeta({
|
||||
stdin="/proc/self/fd/0",
|
||||
stdout="/proc/self/fd/1",
|
||||
stderr="/proc/self/2",
|
||||
fd="/proc/self/fd",
|
||||
log="/var/log/syslog.log"
|
||||
}))
|
||||
|
||||
@@ -222,6 +224,7 @@ if kernel.EFI.getEEPROM then
|
||||
if op=="type" then
|
||||
return "character device"
|
||||
elseif op=="open" then
|
||||
if kernel.uid~=0 then error("EACCES") end
|
||||
if mode=="r" then
|
||||
local ptr,eeprom=1,kernel.EFI:getEEPROM()
|
||||
return {
|
||||
@@ -231,7 +234,6 @@ if kernel.EFI.getEEPROM then
|
||||
end
|
||||
}
|
||||
elseif mode=="w" then
|
||||
if kernel.uid~=0 then error("EACCES") end
|
||||
local firstwrite=true
|
||||
return {
|
||||
write=function(data)
|
||||
@@ -243,7 +245,6 @@ if kernel.EFI.getEEPROM then
|
||||
end
|
||||
}
|
||||
elseif mode=="a" then
|
||||
if kernel.uid~=0 then error("EACCES") end
|
||||
return {
|
||||
write=function(data)
|
||||
kernel.EFI:setEEPROM(kernel.EFI:getEEPROM()..data)
|
||||
@@ -260,6 +261,7 @@ if kernel.EFI.getNvram then
|
||||
if op=="type" then
|
||||
return "character device"
|
||||
elseif op=="open" then
|
||||
if kernel.uid~=0 then error("EACCES") end
|
||||
if mode=="r" then
|
||||
local ptr,nvram=1,kernel.EFI:getNvram()
|
||||
return {
|
||||
@@ -269,7 +271,6 @@ if kernel.EFI.getNvram then
|
||||
end
|
||||
}
|
||||
elseif mode=="w" then
|
||||
if kernel.uid~=0 then error("EACCES") end
|
||||
local firstwrite=true
|
||||
return {
|
||||
write=function(data)
|
||||
@@ -281,7 +282,6 @@ if kernel.EFI.getNvram then
|
||||
end
|
||||
}
|
||||
elseif mode=="a" then
|
||||
if kernel.uid~=0 then error("EACCES") end
|
||||
return {
|
||||
write=function(data)
|
||||
kernel.EFI:setNvram(kernel.EFI:getNvram()..data)
|
||||
@@ -294,7 +294,15 @@ if kernel.EFI.getNvram then
|
||||
end
|
||||
|
||||
data["disk"]={["by-id"]={}, ["by-path"]={}, ["by-label"]={}}
|
||||
-- disks
|
||||
for i,v in pairs(kernel.vfs.mounts) do
|
||||
|
||||
end
|
||||
|
||||
data["raw"]={["by-type"]={}}
|
||||
data["gfx"]={}
|
||||
data["input"]={}
|
||||
data["tty"]={}
|
||||
kernel.devfs={}
|
||||
kernel.devfs.data=data
|
||||
kernel.devfs.proxy=proxy
|
||||
|
||||
@@ -150,7 +150,6 @@ function sys.exec(path, args, envars)
|
||||
tasks[tostring(task.pid)].status = "Z"
|
||||
end)
|
||||
task.syscallReturn = {}
|
||||
coroutine.yield()
|
||||
end
|
||||
|
||||
function sys.sleep(s)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
--:Minify:--
|
||||
local kernel = ...
|
||||
kernel.processes.kgc = function()
|
||||
while true do
|
||||
@@ -6,6 +7,6 @@ kernel.processes.kgc = function()
|
||||
kernel.reqcache[i] = nil
|
||||
end
|
||||
end
|
||||
kernel.sleep(5000)
|
||||
sleep(5)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,84 @@
|
||||
--:Minify:--
|
||||
local lib = {}
|
||||
|
||||
--[[
|
||||
Example framebuffer object
|
||||
|
||||
fb = {
|
||||
r={
|
||||
"","" -- repeat for # of rows length of string is the # of collums
|
||||
},
|
||||
g = {
|
||||
"",""
|
||||
},
|
||||
b = {
|
||||
"",""
|
||||
}
|
||||
}
|
||||
|
||||
Example font object
|
||||
|
||||
font = {
|
||||
width=int,
|
||||
hight=int,
|
||||
data={
|
||||
A={
|
||||
"Ga","gs","Gk" -- length of string is byte alligned with the string being a binary bitmap
|
||||
}
|
||||
}
|
||||
}
|
||||
]]
|
||||
|
||||
function lib.newFbObj(fb)
|
||||
local handle = {}
|
||||
|
||||
function handle.setPixel(x,y,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.line(x1,y1,x2,y2,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.box(x1,y1,x2,y2,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.filledBox(x1,y1,x2,y2,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.tri(x1,y1,x2,y2,x3,y3,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.filledTri(x1,y1,x2,y2,x3,y3,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.window(id,x,y,w,h,writeonly)
|
||||
|
||||
end
|
||||
|
||||
function handle.editWindow(id,x,y,w,h)
|
||||
|
||||
end
|
||||
|
||||
function handle.text(x,y,font,color24)
|
||||
|
||||
end
|
||||
|
||||
function handle.draw()
|
||||
|
||||
end
|
||||
|
||||
function handle.getPixel(x,y)
|
||||
|
||||
end
|
||||
|
||||
function handle.getPixels(x1y1,x2,y2)
|
||||
|
||||
end
|
||||
|
||||
return handle
|
||||
end
|
||||
@@ -0,0 +1,232 @@
|
||||
-- psf.lua
|
||||
-- NeetComputers PSF1 & PSF2 font renderer
|
||||
|
||||
-- Copyright 2026 SpartanSoftware
|
||||
--
|
||||
-- Licensed under the Apache License, Version 2.0 (the "License");
|
||||
-- you may not use this file except in compliance with the License.
|
||||
-- You may obtain a copy of the License at
|
||||
--
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
--
|
||||
-- Unless required by applicable law or agreed to in writing, software
|
||||
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
-- See the License for the specific language governing permissions and
|
||||
-- limitations under the License.
|
||||
|
||||
-- MODULE API
|
||||
-- psf.open(path, disk = 0) Returns a Font object, or nil + errmsg
|
||||
--
|
||||
-- FONT OBJECT API
|
||||
-- font:print(x, y, text) Draw text in white
|
||||
-- font:print(x, y, text, r, g, b) Draw text in given color
|
||||
-- font:measure(text) Width of string in pixels
|
||||
-- font:lineHeight() Font height in pixels
|
||||
-- font:setSpacing(w) Set px width of glyph spacing
|
||||
-- font:close() Free all layers
|
||||
|
||||
local psf = {}
|
||||
|
||||
local function readUInt(header, n)
|
||||
local bytes = header.read(n)
|
||||
if not bytes or #bytes < n then return nil end
|
||||
local value = 0
|
||||
for i = 1, n do
|
||||
value = value + string.byte(bytes, i) * (256 ^ (i - 1))
|
||||
end
|
||||
return math.floor(value)
|
||||
end
|
||||
|
||||
local function parseGlyph(bytes, w, h)
|
||||
local bytesPerRow = math.floor((w + 7) / 8)
|
||||
local pixels = {}
|
||||
for y = 1, h do
|
||||
pixels[y] = {}
|
||||
for x = 1, w do
|
||||
local byteIdx = (y - 1) * bytesPerRow + math.floor((x - 1) / 8) + 1
|
||||
local bitPos = 7 - ((x - 1) % 8)
|
||||
local b = string.byte(bytes, byteIdx) or 0
|
||||
pixels[y][x] = (math.floor(b / (2 ^ bitPos)) % 2 == 1)
|
||||
end
|
||||
end
|
||||
return pixels
|
||||
end
|
||||
|
||||
local OFF_PIXEL = "\0\0\0\0"
|
||||
|
||||
local function getGlyphBuffer(glyph, r, g, b)
|
||||
local cache = glyph._bufCache
|
||||
if not cache then
|
||||
cache = {}
|
||||
glyph._bufCache = cache
|
||||
end
|
||||
|
||||
local key = r * 65536 + g * 256 + b
|
||||
local buf = cache[key]
|
||||
if buf then return buf end
|
||||
|
||||
local onPixel = string.char(r, g, b, 255)
|
||||
local pixels = glyph.pixels
|
||||
local chunks = {}
|
||||
local n = 0
|
||||
|
||||
for y = 1, glyph.height do
|
||||
local row = pixels[y]
|
||||
for x = 1, glyph.width do
|
||||
n = n + 1
|
||||
chunks[n] = row[x] and onPixel or OFF_PIXEL
|
||||
end
|
||||
end
|
||||
|
||||
buf = table.concat(chunks)
|
||||
cache[key] = buf
|
||||
return buf
|
||||
end
|
||||
|
||||
local function parsePSF1(header, glyphs)
|
||||
local mode = readUInt(header, 1)
|
||||
local charsize = readUInt(header, 1)
|
||||
if not charsize then return false, "truncated PSF1 header" end
|
||||
|
||||
local count = (mode and (mode % 4 >= 2)) and 512 or 256
|
||||
for i = 0, count - 1 do
|
||||
local raw = header.read(charsize)
|
||||
if not raw or #raw < charsize then break end
|
||||
glyphs[i] = { width = 8, height = charsize,
|
||||
pixels = parseGlyph(raw, 8, charsize) }
|
||||
end
|
||||
return true, 8, charsize
|
||||
end
|
||||
|
||||
local function parsePSF2(header, glyphs)
|
||||
readUInt(header, 4)
|
||||
local headersize = readUInt(header, 4)
|
||||
readUInt(header, 4)
|
||||
local numglyph = readUInt(header, 4)
|
||||
local bytesperglyph = readUInt(header, 4)
|
||||
local h = readUInt(header, 4)
|
||||
local w = readUInt(header, 4)
|
||||
if not w or not h then return false, "truncated PSF2 header" end
|
||||
|
||||
local consumed = 32
|
||||
if headersize > consumed then
|
||||
header.seek('cur', headersize - consumed)
|
||||
end
|
||||
|
||||
for i = 0, numglyph - 1 do
|
||||
local raw = header.read(bytesperglyph)
|
||||
if not raw or #raw < bytesperglyph then break end
|
||||
glyphs[i] = { width = w, height = h,
|
||||
pixels = parseGlyph(raw, w, h) }
|
||||
end
|
||||
return true, w, h
|
||||
end
|
||||
|
||||
local Font = {}
|
||||
Font.__index = Font
|
||||
|
||||
function Font:print(x, y, text, r, g, b)
|
||||
assert(not self._closed, "psf: font has been closed")
|
||||
|
||||
r = r or 255
|
||||
g = g or 255
|
||||
b = b or 255
|
||||
|
||||
local sw = screen.getSize()
|
||||
local cur = x
|
||||
local spacing = self._spacing
|
||||
|
||||
for i = 1, #text do
|
||||
if cur >= sw then break end
|
||||
local code = string.byte(text, i)
|
||||
local glyph = self._glyphs[code]
|
||||
if glyph then
|
||||
local buf = getGlyphBuffer(glyph, r, g, b)
|
||||
screen.drawPixels(cur, y, buf, glyph.width, glyph.height)
|
||||
cur = cur + glyph.width + spacing
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Font:measure(text)
|
||||
local w = 0
|
||||
local count = 0
|
||||
for i = 1, #text do
|
||||
local g = self._glyphs[string.byte(text, i)]
|
||||
if g then
|
||||
w = w + g.width
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
if count > 1 then
|
||||
w = w + self._spacing * (count - 1)
|
||||
end
|
||||
return w
|
||||
end
|
||||
|
||||
function Font:lineHeight()
|
||||
return self._height
|
||||
end
|
||||
|
||||
function Font:close()
|
||||
if self._closed then return end
|
||||
for _, glyph in pairs(self._glyphs) do
|
||||
glyph._bufCache = nil
|
||||
end
|
||||
self._glyphs = {}
|
||||
self._closed = true
|
||||
end
|
||||
|
||||
function Font:setSpacing(px)
|
||||
self._spacing = px
|
||||
end
|
||||
|
||||
function psf.open(path, disk)
|
||||
disk = disk or 0
|
||||
|
||||
if not files.exists(path, disk) then
|
||||
return nil, "file not found: " .. path
|
||||
end
|
||||
|
||||
local ok, header = pcall(files.open, path, 'rb', disk)
|
||||
if not ok or not header then
|
||||
return nil, "could not open: " .. path
|
||||
end
|
||||
|
||||
local magic = header.read(2)
|
||||
if not magic or #magic < 2 then
|
||||
header.close()
|
||||
return nil, "could not read magic bytes"
|
||||
end
|
||||
|
||||
local b1, b2 = string.byte(magic, 1), string.byte(magic, 2)
|
||||
local glyphs = {}
|
||||
local ok, w, h
|
||||
|
||||
if b1 == 0x36 and b2 == 0x04 then
|
||||
ok, w, h = parsePSF1(header, glyphs)
|
||||
elseif b1 == 0x72 and b2 == 0xb5 then
|
||||
header.read(2)
|
||||
ok, w, h = parsePSF2(header, glyphs)
|
||||
else
|
||||
header.close()
|
||||
return nil, string.format("not a PSF file (magic: %02x %02x)", b1, b2)
|
||||
end
|
||||
|
||||
header.close()
|
||||
|
||||
if not ok then
|
||||
return nil, w
|
||||
end
|
||||
|
||||
return setmetatable({
|
||||
_glyphs = glyphs,
|
||||
_width = w,
|
||||
_height = h,
|
||||
_spacing = 0,
|
||||
_closed = false,
|
||||
}, Font)
|
||||
end
|
||||
|
||||
return psf
|
||||
@@ -833,14 +833,18 @@ builtinCmds.ops = function()
|
||||
end
|
||||
end
|
||||
|
||||
builtinCmds.reboot = function ()
|
||||
builtinCmds.reboot = function()
|
||||
syscall.reboot()
|
||||
end
|
||||
|
||||
builtinCmds.shutdown = function ()
|
||||
builtinCmds.shutdown = function()
|
||||
syscall.shutdown()
|
||||
end
|
||||
|
||||
builtinCmds.kill = function(id)
|
||||
syscall.kill(tonumber(id))
|
||||
end
|
||||
|
||||
local function listDir(dir, prefix)
|
||||
local ok, entries = pcall(syscall.listdir, dir)
|
||||
if not ok or not entries then return {} end
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
--:Minify:--
|
||||
local args = {...}
|
||||
local list = syscall.listdir("/proc/self/fd")
|
||||
for i=1, #list do
|
||||
syscall.close(tonumber(list[i]))
|
||||
end
|
||||
|
||||
if #args>=2 then
|
||||
for i=2, #args do
|
||||
syscall.open(args[i], "rw")
|
||||
end
|
||||
end
|
||||
|
||||
syscall.exec(args[1])
|
||||
@@ -1,3 +1,4 @@
|
||||
--:Minify:--
|
||||
--[[
|
||||
MIT License
|
||||
|
||||
@@ -89,7 +90,11 @@ local WhiteChars = lookupify { ' ', '\n', '\t', '\r' }
|
||||
|
||||
local EscapeForCharacter = { ['\r'] = '\\r', ['\n'] = '\\n', ['\t'] = '\\t', ['"'] = '\\"', ["'"] = "\\'", ['\\'] = '\\' }
|
||||
|
||||
local CharacterForEscape = { ['r'] = '\r', ['n'] = '\n', ['t'] = '\t', ['"'] = '"', ["'"] = "'", ['\\'] = '\\' }
|
||||
local CharacterForEscape = { ['r'] = '\r', ['n'] = '\n', ['t'] = '\t', ['"'] = '"', ["'"] = "'", ['\\'] = '\\', ['b'] = '\b', ['f'] = '\f' }
|
||||
|
||||
for i=0,255 do
|
||||
CharacterForEscape[tostring(i)]=string.char(i)
|
||||
end
|
||||
|
||||
local AllIdentStartChars = lookupify { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
|
||||
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
|
||||
@@ -201,9 +206,9 @@ local function CreateLuaTokenStream(text)
|
||||
end
|
||||
q = q + 1
|
||||
end
|
||||
for _, token in pairs(tokenBuffer) do
|
||||
print(token.Type .. "<" .. token.Source .. ">")
|
||||
end
|
||||
--for _, token in pairs(tokenBuffer) do
|
||||
-- print(token.Type .. "<" .. token.Source .. ">")
|
||||
--end
|
||||
olderr("file<" .. line .. ":" .. char .. ">: " .. str)
|
||||
end
|
||||
|
||||
@@ -485,9 +490,9 @@ local function CreateLuaParser(text)
|
||||
if tk.Type == type and (source == nil or tk.Source == source) then
|
||||
return get()
|
||||
else
|
||||
for i = -3, 3 do
|
||||
print("Tokens[" .. i .. "] = `" .. peek(i).Source .. "`")
|
||||
end
|
||||
--for i = -3, 3 do
|
||||
-- print("Tokens[" .. i .. "] = `" .. peek(i).Source .. "`")
|
||||
--end
|
||||
if source then
|
||||
error(getTokenStartPosition(tk) .. ": `" .. source .. "` expected.")
|
||||
else
|
||||
@@ -666,7 +671,7 @@ local function CreateLuaParser(text)
|
||||
get()
|
||||
return body, after
|
||||
else
|
||||
print(after.Type, after.Source)
|
||||
--print(after.Type, after.Source)
|
||||
error(getTokenStartPosition(after) .. ": " .. terminator .. " expected.")
|
||||
end
|
||||
end
|
||||
@@ -2802,6 +2807,7 @@ local function StripAst(ast)
|
||||
stript(sep)
|
||||
end
|
||||
end
|
||||
|
||||
stript(stat.Token_OpenParen)
|
||||
for index, arg in pairs(stat.ArgList) do
|
||||
stript(arg)
|
||||
@@ -3074,7 +3080,7 @@ end
|
||||
|
||||
local function validateCode(code, validate)
|
||||
if validate then
|
||||
local func,err = load(code, "@minifyvalidation", "t", {})
|
||||
local func,err = load(code, "@minifyvalidation", "t", _G)
|
||||
if not func then
|
||||
error(err)
|
||||
end
|
||||
|
||||
+426
-22
@@ -16,10 +16,11 @@ local spm = function(...)
|
||||
i = false,
|
||||
e = false,
|
||||
t = false,
|
||||
s = false,
|
||||
sysroot = "",
|
||||
init = false,
|
||||
help = false,
|
||||
source = false
|
||||
overwrite = false
|
||||
}
|
||||
|
||||
local i = 1
|
||||
@@ -27,7 +28,9 @@ local spm = function(...)
|
||||
local http = require("http")
|
||||
local json = require("json")
|
||||
local tar = require("tar")
|
||||
local minify = require("minify")
|
||||
local deflate = require("deflate")
|
||||
local bit32 = require("bit32")
|
||||
local httpcache = {}
|
||||
|
||||
local function get(url)
|
||||
@@ -93,6 +96,82 @@ local spm = function(...)
|
||||
|
||||
i = i + 1
|
||||
end
|
||||
i=nil
|
||||
|
||||
if cloptions.help or cloptions.h then
|
||||
if cloptions.S then
|
||||
print("spm -S - Synchronize Packages")
|
||||
print("")
|
||||
print("Usage:")
|
||||
print(" spm -S [options] <packages>")
|
||||
print("")
|
||||
print("Options:")
|
||||
print(" -y Refresh package databases")
|
||||
print(" -u Upgrade installed packages")
|
||||
print(" -i Show remote package information")
|
||||
print(" -s Download source")
|
||||
print("")
|
||||
print("Examples:")
|
||||
print(" spm -Sy")
|
||||
print(" spm -S package")
|
||||
print(" spm -Syu")
|
||||
return
|
||||
|
||||
elseif cloptions.Q then
|
||||
print("spm -Q - Query Package Database")
|
||||
print("")
|
||||
print("Usage:")
|
||||
print(" spm -Q [options] [package]")
|
||||
print("")
|
||||
print("Options:")
|
||||
print(" -i Show installed package information")
|
||||
print(" -l List files owned by a package")
|
||||
print(" -o Find which package owns a file")
|
||||
print(" -e List explicitly installed packages")
|
||||
print(" -t List orphan packages")
|
||||
print("")
|
||||
print("Examples:")
|
||||
print(" spm -Q")
|
||||
print(" spm -Qi lua")
|
||||
print(" spm -Ql lua")
|
||||
print(" spm -Qo /bin/lua")
|
||||
return
|
||||
|
||||
elseif cloptions.R then
|
||||
print("spm -R - Remove Packages")
|
||||
print("")
|
||||
print("Usage:")
|
||||
print(" spm -R [options] <packages>")
|
||||
print("")
|
||||
print("Currently no remove-specific options are implemented.")
|
||||
print("")
|
||||
print("Example:")
|
||||
print(" spm -R package")
|
||||
return
|
||||
|
||||
else
|
||||
print("spm - HyperionOS Package Manager")
|
||||
print("")
|
||||
print("Usage:")
|
||||
print(" spm <operation> [options] [targets]")
|
||||
print("")
|
||||
print("Operations:")
|
||||
print(" -S Synchronize packages")
|
||||
print(" -Q Query package database")
|
||||
print(" -R Remove packages")
|
||||
print("")
|
||||
print("General Options:")
|
||||
print(" -h, --help Show help")
|
||||
print(" --init Initialize spm")
|
||||
print(" --sysroot DIR Operate on alternate root")
|
||||
print("")
|
||||
print("For operation-specific help:")
|
||||
print(" spm -Sh")
|
||||
print(" spm -Qh")
|
||||
print(" spm -Rh")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if cloptions.sysroot=="" then
|
||||
syscall.chdir("/")
|
||||
@@ -113,6 +192,17 @@ local spm = function(...)
|
||||
print("spm not initialized run \"spm --init\"")
|
||||
return
|
||||
end
|
||||
local log = fs.open("var/log/spm.log", "w")
|
||||
|
||||
local function w(...)
|
||||
local args = {...}
|
||||
local output = ""
|
||||
for i = 1, #args do output = output .. tostring(args[i]) .. "\t" end
|
||||
output = output:sub(1, -2)
|
||||
syscall.write(1, output.."\n")
|
||||
log.write(output.."\n")
|
||||
log.flush()
|
||||
end
|
||||
|
||||
local repodb = string.split(fs.readAllText("var/spm/db/repos.list"), "\n")
|
||||
local sourcelist = string.split(fs.readAllText("etc/spm/sources.list"), "\n")
|
||||
@@ -192,29 +282,29 @@ local spm = function(...)
|
||||
for _, url in ipairs(repodb) do
|
||||
local ok, repo = checkRepo(url)
|
||||
if not ok then
|
||||
print("Failed to contact repository:")
|
||||
print(url)
|
||||
print("Consider running 'spm -Sy' to remove broken repositories.")
|
||||
w("Failed to contact repository:")
|
||||
w(url)
|
||||
w("Consider running 'spm -Sy' to remove broken repositories.")
|
||||
else
|
||||
if repo.packages then
|
||||
if repo.packages[name] then
|
||||
local pkgurl = repo.packages[name]
|
||||
local resp = get(pkgurl)
|
||||
if not resp then
|
||||
print("Repository: "..url)
|
||||
print("Has broken package: "..name)
|
||||
print("Ignoring")
|
||||
w("Repository: "..url)
|
||||
w("Has broken package: "..name)
|
||||
w("Ignoring")
|
||||
else
|
||||
if resp.code ~= 200 then
|
||||
print("Repository: "..url)
|
||||
print("Has broken package: "..name)
|
||||
print("Ignoring")
|
||||
w("Repository: "..url)
|
||||
w("Has broken package: "..name)
|
||||
w("Ignoring")
|
||||
else
|
||||
local pkgjson = json.decode(resp.body)
|
||||
if not pkgjson then
|
||||
print("Repository: "..url)
|
||||
print("Has broken package: "..name)
|
||||
print("Ignoring")
|
||||
w("Repository: "..url)
|
||||
w("Has broken package: "..name)
|
||||
w("Ignoring")
|
||||
else
|
||||
return {
|
||||
url=pkgurl,
|
||||
@@ -236,14 +326,207 @@ local spm = function(...)
|
||||
return false, "target not found: "..name
|
||||
end
|
||||
|
||||
local function flatten(t)
|
||||
local ret={}
|
||||
for _,v in ipairs(t.content) do
|
||||
if v.type == "dir" then
|
||||
local f=flatten(v)
|
||||
for i,c in pairs(f) do
|
||||
ret[i]=c
|
||||
end
|
||||
elseif v.type == "file" then
|
||||
ret[v.name]=v.content
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local function ptar(t, pkg)
|
||||
t=t.content[1]
|
||||
if t.name~=pkg.id then w("Tar contains "..t.name.." not "..pkg.id) return false end
|
||||
local ret={}
|
||||
for i=1, #t.content do
|
||||
if t.content[i].name == "data" then
|
||||
local data=flatten(t.content[i])
|
||||
local new={}
|
||||
for p,v in pairs(data) do
|
||||
new[p:sub(#pkg.id+7)]=v
|
||||
end
|
||||
ret.data=new
|
||||
elseif t.content[i].name == "control" then
|
||||
local data=flatten(t.content[i])
|
||||
local new={}
|
||||
for p,v in pairs(data) do
|
||||
new[p:sub(#pkg.id+10)]=v
|
||||
end
|
||||
ret.control=new
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local function mini(tabl)
|
||||
local ret={}
|
||||
for i,v in pairs(tabl) do
|
||||
if v:sub(1,12)=="--:Minify:--" then
|
||||
local ok, code = pcall(minify.minify,v)
|
||||
if not ok then w("Failed to minify "..i..":\n"..code) ret[i]=v
|
||||
else ret[i]=code end
|
||||
else
|
||||
ret[i]=v
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local function md5(msg)
|
||||
local bit = bit32
|
||||
|
||||
local function rol(x, n)
|
||||
return bit.lrotate(x, n)
|
||||
end
|
||||
|
||||
local function F(x, y, z)
|
||||
return bit.bor(bit.band(x, y), bit.band(bit.bnot(x), z))
|
||||
end
|
||||
|
||||
local function G(x, y, z)
|
||||
return bit.bor(bit.band(x, z), bit.band(y, bit.bnot(z)))
|
||||
end
|
||||
|
||||
local function H(x, y, z)
|
||||
return bit.bxor(x, y, z)
|
||||
end
|
||||
|
||||
local function I(x, y, z)
|
||||
return bit.bxor(y, bit.bor(x, bit.bnot(z)))
|
||||
end
|
||||
|
||||
local function u32le(s, i)
|
||||
return s:byte(i)
|
||||
+ s:byte(i + 1) * 0x100
|
||||
+ s:byte(i + 2) * 0x10000
|
||||
+ s:byte(i + 3) * 0x1000000
|
||||
end
|
||||
|
||||
local function le32(x)
|
||||
return string.char(
|
||||
bit.band(x, 0xff),
|
||||
bit.band(bit.rshift(x, 8), 0xff),
|
||||
bit.band(bit.rshift(x, 16), 0xff),
|
||||
bit.band(bit.rshift(x, 24), 0xff)
|
||||
)
|
||||
end
|
||||
|
||||
-- MD5 padding
|
||||
local bitlen = #msg * 8
|
||||
|
||||
msg = msg .. "\128"
|
||||
|
||||
while #msg % 64 ~= 56 do
|
||||
msg = msg .. "\0"
|
||||
end
|
||||
|
||||
-- Append 64-bit little-endian length
|
||||
local lo = bitlen % 0x100000000
|
||||
local hi = math.floor(bitlen / 0x100000000)
|
||||
|
||||
msg = msg .. le32(lo) .. le32(hi)
|
||||
|
||||
local a0 = 0x67452301
|
||||
local b0 = 0xefcdab89
|
||||
local c0 = 0x98badcfe
|
||||
local d0 = 0x10325476
|
||||
|
||||
local S = {
|
||||
7,12,17,22, 7,12,17,22, 7,12,17,22, 7,12,17,22,
|
||||
5, 9,14,20, 5, 9,14,20, 5, 9,14,20, 5, 9,14,20,
|
||||
4,11,16,23, 4,11,16,23, 4,11,16,23, 4,11,16,23,
|
||||
6,10,15,21, 6,10,15,21, 6,10,15,21, 6,10,15,21
|
||||
}
|
||||
|
||||
local K = {
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
|
||||
}
|
||||
|
||||
for chunk = 1, #msg, 64 do
|
||||
local M = {}
|
||||
|
||||
for i = 0, 15 do
|
||||
M[i] = u32le(msg, chunk + i * 4)
|
||||
end
|
||||
|
||||
local A = a0
|
||||
local B = b0
|
||||
local C = c0
|
||||
local D = d0
|
||||
|
||||
for i = 0, 63 do
|
||||
local f
|
||||
local g
|
||||
|
||||
if i < 16 then
|
||||
f = F(B, C, D)
|
||||
g = i
|
||||
elseif i < 32 then
|
||||
f = G(B, C, D)
|
||||
g = (5 * i + 1) % 16
|
||||
elseif i < 48 then
|
||||
f = H(B, C, D)
|
||||
g = (3 * i + 5) % 16
|
||||
else
|
||||
f = I(B, C, D)
|
||||
g = (7 * i) % 16
|
||||
end
|
||||
|
||||
local tmp = D
|
||||
D = C
|
||||
C = B
|
||||
|
||||
local x = A + f + K[i + 1] + M[g]
|
||||
x = x % 0x100000000
|
||||
|
||||
B = (B + rol(x, S[i + 1])) % 0x100000000
|
||||
|
||||
A = tmp
|
||||
end
|
||||
|
||||
a0 = (a0 + A) % 0x100000000
|
||||
b0 = (b0 + B) % 0x100000000
|
||||
c0 = (c0 + C) % 0x100000000
|
||||
d0 = (d0 + D) % 0x100000000
|
||||
end
|
||||
|
||||
local digest = le32(a0) .. le32(b0) .. le32(c0) .. le32(d0)
|
||||
|
||||
return (digest:gsub(".", function(c)
|
||||
return string.format("%02x", c:byte())
|
||||
end))
|
||||
end
|
||||
|
||||
if cloptions.S then
|
||||
if cloptions.y then
|
||||
print("Updating repositories...")
|
||||
w("Updating repositories...")
|
||||
repodb={}
|
||||
for _,v in ipairs(getRepos(sourcelist)) do
|
||||
repodb[#repodb+1]=v
|
||||
end
|
||||
print("Writing new data...")
|
||||
w("Writing new data...")
|
||||
local str = ""
|
||||
for _,v in ipairs(repodb) do
|
||||
str=str..v.."\n"
|
||||
@@ -257,7 +540,7 @@ local spm = function(...)
|
||||
local found = {}
|
||||
for i,v in ipairs(args) do
|
||||
local pkg, err = getPkg(v)
|
||||
if not pkg then print(err) syscall.exit(1) end
|
||||
if not pkg then w(err) syscall.exit(1) end
|
||||
needed[#needed+1] = pkg
|
||||
found[v]=true
|
||||
end
|
||||
@@ -286,10 +569,10 @@ local spm = function(...)
|
||||
if #needed==0 then
|
||||
syscall.exit()
|
||||
end
|
||||
print("")
|
||||
print("Packages("..tostring(#needed).."):")
|
||||
w("")
|
||||
w("Packages("..tostring(#needed).."):")
|
||||
printpkgs(needed)
|
||||
print("")
|
||||
w("")
|
||||
while true do
|
||||
local text = userinput(0, "Proceed with download [Y/n]", nil, 1)
|
||||
if text=="" then
|
||||
@@ -303,10 +586,131 @@ local spm = function(...)
|
||||
|
||||
local files = {}
|
||||
for _,v in ipairs(needed) do
|
||||
local file = http.get(v.tar)
|
||||
|
||||
if not pkgdb[v.id] or not pkgdb[v.id].hash==v.hash then
|
||||
w("Downloading "..v.id)
|
||||
local resp = get(v.tar)
|
||||
if not resp then
|
||||
w("Package "..v.id.." failed GET")
|
||||
syscall.exit()
|
||||
end
|
||||
if resp.code ~= 200 then
|
||||
w("Package "..v.id.." returned code "..tostring(resp.code))
|
||||
syscall.exit()
|
||||
end
|
||||
local ok, repotar = pcall(tar.unpack, resp.body)
|
||||
if not ok or not repotar then
|
||||
w("Package "..v.id.." failed tar parsing")
|
||||
syscall.exit()
|
||||
end
|
||||
local f=ptar(repotar, v)
|
||||
if not f or not f.data then syscall.exit() end
|
||||
if not cloptions.s then
|
||||
f.data=mini(f.data)
|
||||
end
|
||||
f.hash=v.hash
|
||||
files[v.id]=f
|
||||
else
|
||||
w("Package "..v.id.." hash already installed")
|
||||
end
|
||||
end
|
||||
|
||||
w("Checking for conflicts...")
|
||||
local seen={}
|
||||
for i,v in pairs(files) do
|
||||
for f,c in pairs(v.data) do
|
||||
if seen[f] then
|
||||
w(i.." and "..seen[f].." have conflicting file "..f)
|
||||
v.data[f]=nil
|
||||
else
|
||||
seen[f]=i
|
||||
end
|
||||
end
|
||||
end
|
||||
seen=nil
|
||||
w("Checking for modified files...")
|
||||
local block={}
|
||||
for i, v in pairs(files) do
|
||||
if pkgdb[i] then
|
||||
if not cloptions.overwrite then
|
||||
for f,h in pairs(v.data) do
|
||||
if pkgdb[i].files[f]~=md5(fs.readAllText(f)) then
|
||||
w(f.." was modified on disk, specify --overwrite to overwrite")
|
||||
block[f]=true
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if not cloptions.overwrite then
|
||||
for f,h in pairs(v.data) do
|
||||
if fs.exists(f) then
|
||||
w(f.." already exists, specify --overwrite to overwrite or remove the file")
|
||||
syscall.exit()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
w("Adding delete calls...")
|
||||
local delete={}
|
||||
for i,v in pairs(files) do
|
||||
if pkgdb[i] then
|
||||
for f,c in pairs(pkgdb[i].files) do
|
||||
if not v.data[f] then
|
||||
if c~=md5(fs.readAllText(f)) then
|
||||
w(f.." was modified on disk, specify --overwrite to overwrite")
|
||||
else
|
||||
delete[f]=true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
w("Calculating useage...")
|
||||
local net=0
|
||||
for i,v in pairs(files) do
|
||||
for f,c in pairs(v.data) do
|
||||
if not block[f] then
|
||||
net=net+#c
|
||||
end
|
||||
end
|
||||
for f,c in pairs(delete) do
|
||||
net=net-#fs.readAllText(f)
|
||||
end
|
||||
end
|
||||
w("")
|
||||
w("Net Upgrade Size: "..tostring(net))
|
||||
w("")
|
||||
while true do
|
||||
local text = userinput(0, "Proceed with Installation [Y/n]", nil, 1)
|
||||
if text=="" then
|
||||
break
|
||||
elseif text:lower()=="y" then
|
||||
break
|
||||
elseif text:lower()=="n" then
|
||||
syscall.exit()
|
||||
end
|
||||
end
|
||||
w("Updatating db...")
|
||||
for i,v in pairs(files) do
|
||||
local content={}
|
||||
content.files={}
|
||||
for f,c in pairs(v.data) do
|
||||
content.files[f]=md5(c)
|
||||
end
|
||||
content.hash=v.hash
|
||||
fs.writeAllText("var/spm/db/installed/"..i, json.encode(content))
|
||||
end
|
||||
w("Writing changes...")
|
||||
for i,v in pairs(files) do
|
||||
w("Writing "..i)
|
||||
for f,c in pairs(v.data) do
|
||||
if not block[f] then
|
||||
fs.writeAllText(f,c)
|
||||
end
|
||||
end
|
||||
end
|
||||
w("Install complete")
|
||||
log.close()
|
||||
|
||||
elseif cloptions.R then
|
||||
-- remove tree
|
||||
elseif cloptions.Q then
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
tar
|
||||
deflate
|
||||
json
|
||||
minify
|
||||
minify
|
||||
bit32
|
||||
Hyperion-core
|
||||
@@ -1,3 +1,4 @@
|
||||
--:Minify:--
|
||||
local LibDeflate = require("LibDeflate")
|
||||
local tar = {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user