Added logging system, fixed filesystem read handle buffering and added read handle seeking.
This commit is contained in:
+15
-1
@@ -4,12 +4,16 @@ _G._OSVERSION = "HALYDE VERSION" -- TODO: Put this in a separate config file
|
|||||||
_G._OSLOGO = ""
|
_G._OSLOGO = ""
|
||||||
_G._PUBLIC = {}
|
_G._PUBLIC = {}
|
||||||
_G._PUBLIC.unicode = assert(loadfile("/lib/unicode.lua")(loadfile))
|
_G._PUBLIC.unicode = assert(loadfile("/lib/unicode.lua")(loadfile))
|
||||||
|
local log = assert(loadfile("/lib/log.lua")(loadfile))
|
||||||
|
|
||||||
local handle, tmpdata = filesystem.open("/halyde/config/oslogo.ans", "r"), nil
|
local handle, tmpdata = filesystem.open("/halyde/config/oslogo.ans", "r"), nil
|
||||||
repeat
|
repeat
|
||||||
tmpdata = handle:read(math.huge)
|
tmpdata = handle:read(math.huge)
|
||||||
_OSLOGO = _OSLOGO .. (tmpdata or "")
|
_OSLOGO = _OSLOGO .. (tmpdata or "")
|
||||||
until not tmpdata
|
until not tmpdata
|
||||||
|
handle:close()
|
||||||
|
|
||||||
|
log.kernel.info("Loaded OS logo")
|
||||||
|
|
||||||
_G.package = { ["preloaded"] = {} }
|
_G.package = { ["preloaded"] = {} }
|
||||||
|
|
||||||
@@ -26,7 +30,11 @@ function _G.reqgen(load)
|
|||||||
modulepath = module
|
modulepath = module
|
||||||
elseif filesystem.exists("/lib/" .. module .. ".lua") then
|
elseif filesystem.exists("/lib/" .. module .. ".lua") then
|
||||||
modulepath = "/lib/" .. module .. ".lua"
|
modulepath = "/lib/" .. module .. ".lua"
|
||||||
elseif shell and shell.workingDirectory and filesystem.exists(filesystem.concat(shell.workingDirectory, module .. ".lua")) then
|
elseif
|
||||||
|
shell
|
||||||
|
and shell.workingDirectory
|
||||||
|
and filesystem.exists(filesystem.concat(shell.workingDirectory, module .. ".lua"))
|
||||||
|
then
|
||||||
modulepath = shell.workingDirectory .. module .. ".lua"
|
modulepath = shell.workingDirectory .. module .. ".lua"
|
||||||
end
|
end
|
||||||
assert(modulepath, "Module not found\nPossible locations:\n/lib/" .. module .. ".lua")
|
assert(modulepath, "Module not found\nPossible locations:\n/lib/" .. module .. ".lua")
|
||||||
@@ -41,6 +49,7 @@ function _G.reqgen(load)
|
|||||||
end
|
end
|
||||||
|
|
||||||
_G.require = reqgen(_G.load)
|
_G.require = reqgen(_G.load)
|
||||||
|
log.kernel.info("Generated userland require function")
|
||||||
|
|
||||||
function _G.package.preload(module)
|
function _G.package.preload(module)
|
||||||
local handle, data, tmpdata = assert(filesystem.open("/lib/" .. module .. ".lua", "r")), "", nil
|
local handle, data, tmpdata = assert(filesystem.open("/lib/" .. module .. ".lua", "r")), "", nil
|
||||||
@@ -53,11 +62,14 @@ function _G.package.preload(module)
|
|||||||
_G[module] = nil
|
_G[module] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Datatools is imported twice??
|
||||||
require("/halyde/kernel/datatools.lua") -- If this is not imported BEFORE modload gets run, modload requires filesystem which requires computer which requires datatools. TODO: When VFS is implemented, make the pre-VFS loading of filesystem load a more basic version. And remove this.
|
require("/halyde/kernel/datatools.lua") -- If this is not imported BEFORE modload gets run, modload requires filesystem which requires computer which requires datatools. TODO: When VFS is implemented, make the pre-VFS loading of filesystem load a more basic version. And remove this.
|
||||||
|
log.kernel.info("Loading modules")
|
||||||
require("/halyde/kernel/modload.lua")
|
require("/halyde/kernel/modload.lua")
|
||||||
|
|
||||||
package.preload("component")
|
package.preload("component")
|
||||||
package.preload("computer")
|
package.preload("computer")
|
||||||
|
log.kernel.info("Pre-loaded low-level packages")
|
||||||
|
|
||||||
local component = require("component")
|
local component = require("component")
|
||||||
local gpu = component.gpu
|
local gpu = component.gpu
|
||||||
@@ -65,6 +77,7 @@ local screenAddress = component.list("screen")()
|
|||||||
|
|
||||||
gpu.bind(screenAddress)
|
gpu.bind(screenAddress)
|
||||||
gpu.setResolution(gpu.maxResolution())
|
gpu.setResolution(gpu.maxResolution())
|
||||||
|
log.kernel.info("Bound GPU to screen " .. tostring(screenAddress))
|
||||||
|
|
||||||
if not filesystem.exists("/halyde/config/shell.json") then -- Auto-generate configs
|
if not filesystem.exists("/halyde/config/shell.json") then -- Auto-generate configs
|
||||||
filesystem.copy("/halyde/config/generate/shell.json", "/halyde/config/shell.json")
|
filesystem.copy("/halyde/config/generate/shell.json", "/halyde/config/shell.json")
|
||||||
@@ -73,4 +86,5 @@ if not filesystem.exists("/halyde/config/startupapps.json") then
|
|||||||
filesystem.copy("/halyde/config/generate/startupapps.json", "/halyde/config/startupapps.json")
|
filesystem.copy("/halyde/config/generate/startupapps.json", "/halyde/config/startupapps.json")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
log.kernel.info("Starting tsched")
|
||||||
require("/halyde/kernel/tsched.lua")
|
require("/halyde/kernel/tsched.lua")
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
INFO [1.45] Loaded OS logo
|
||||||
|
INFO [1.5] Generated userland require function
|
||||||
|
INFO [1.5] Loading modules
|
||||||
|
INFO [2.2] Pre-loaded low-level packages
|
||||||
|
INFO [2.3] Bound GPU to screen d9443671-225d-4637-980f-fad46c9fb845
|
||||||
|
INFO [2.3] Starting tsched
|
||||||
+180
-57
@@ -1,6 +1,8 @@
|
|||||||
local loadfile = ... -- raw loadfile from boot.lua
|
local loadfile = ... -- raw loadfile from boot.lua
|
||||||
local unicode, component, computer
|
local unicode, component, computer
|
||||||
|
|
||||||
|
local bufferSize = math.huge or math.maxinteger
|
||||||
|
|
||||||
if loadfile then
|
if loadfile then
|
||||||
unicode = loadfile("/lib/unicode.lua")(loadfile)
|
unicode = loadfile("/lib/unicode.lua")(loadfile)
|
||||||
component = loadfile("/lib/component.lua")(loadfile)
|
component = loadfile("/lib/component.lua")(loadfile)
|
||||||
@@ -84,7 +86,9 @@ local function readBytes(self,n)
|
|||||||
n = n or 1
|
n = n or 1
|
||||||
if n == 1 then
|
if n == 1 then
|
||||||
local byte = self:read(1)
|
local byte = self:read(1)
|
||||||
if byte==nil then return nil end
|
if byte == nil then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
return string.byte(byte)
|
return string.byte(byte)
|
||||||
end
|
end
|
||||||
local bytes, res = { string.byte(self:read(n), 1, n) }, 0
|
local bytes, res = { string.byte(self:read(n), 1, n) }, 0
|
||||||
@@ -109,7 +113,9 @@ end
|
|||||||
local function iterateBytes(self)
|
local function iterateBytes(self)
|
||||||
return function()
|
return function()
|
||||||
local byte = readBytes(self, 1)
|
local byte = readBytes(self, 1)
|
||||||
if byte==nil then self:close() end
|
if byte == nil then
|
||||||
|
self:close()
|
||||||
|
end
|
||||||
return byte
|
return byte
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -120,19 +126,19 @@ end
|
|||||||
|
|
||||||
function filesystem.makeReadStream(content)
|
function filesystem.makeReadStream(content)
|
||||||
local properHandle = {}
|
local properHandle = {}
|
||||||
local readcursor = 1
|
local readCursor = 1
|
||||||
function properHandle.read(self, amount)
|
function properHandle.read(self, amount)
|
||||||
checkArg(2, amount, "number")
|
checkArg(2, amount, "number")
|
||||||
local limit = string.len(content) + 1
|
local limit = string.len(content) + 1
|
||||||
local out = nil
|
local out = nil
|
||||||
if readcursor<limit then
|
if readCursor < limit then
|
||||||
if amount == math.huge then
|
if amount == math.huge then
|
||||||
out = string.sub(content,math.min(readcursor,limit))
|
out = string.sub(content, math.min(readCursor, limit))
|
||||||
else
|
else
|
||||||
out = string.sub(content,math.min(readcursor,limit),math.min(readcursor+amount-1,limit))
|
out = string.sub(content, math.min(readCursor, limit), math.min(readCursor + amount - 1, limit))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
readcursor=readcursor+amount
|
readCursor = readCursor + amount
|
||||||
if out == "" then
|
if out == "" then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -186,41 +192,86 @@ function filesystem.open(path, mode, buffered) -- opens a file and returns its h
|
|||||||
properHandle.handle = handle
|
properHandle.handle = handle
|
||||||
properHandle.address = address
|
properHandle.address = address
|
||||||
local content = nil
|
local content = nil
|
||||||
local readcursor = 1
|
local bufferOffset = 0 -- Position in file where buffer starts
|
||||||
if buffered and mode:sub(1,1)=="r" then
|
local readCursor = 1 -- Position within buffer (1-based)
|
||||||
content=""
|
|
||||||
repeat
|
if buffered and mode == "r" then
|
||||||
tmpdata = component.invoke(address, "read", handle, math.huge or math.maxinteger)
|
content = component.invoke(address, "read", handle, bufferSize) or ""
|
||||||
content = content .. (tmpdata or "")
|
bufferOffset = 0
|
||||||
until not tmpdata
|
readCursor = 1
|
||||||
component.invoke(address, "close", handle)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function properHandle.read(self, amount)
|
function properHandle.read(self, amount)
|
||||||
checkArg(2, amount, "number")
|
checkArg(2, amount, "number")
|
||||||
if unmanagedDrive then
|
if unmanagedDrive then
|
||||||
local sectorIdx = ((readcursor-1)//sectorSize)+1
|
-- TODO: Test if this still works
|
||||||
if sectorIdx>sectorCount then return nil end
|
local sectorIdx = ((readCursor - 1) // sectorSize) + 1
|
||||||
|
if sectorIdx > sectorCount then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
local sector = unmanagedProxy.readSector(sectorIdx)
|
local sector = unmanagedProxy.readSector(sectorIdx)
|
||||||
local data = sector:sub(((readcursor-1)%sectorSize)+1,((readcursor+math.min(amount,sectorSize)-2)%sectorSize)+1)
|
local data = sector:sub(
|
||||||
readcursor=readcursor+#data
|
((readCursor - 1) % sectorSize) + 1,
|
||||||
if data=="" then return nil end
|
((readCursor + math.min(amount, sectorSize) - 2) % sectorSize) + 1
|
||||||
|
)
|
||||||
|
readCursor = readCursor + #data
|
||||||
|
if data == "" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
return data
|
return data
|
||||||
else
|
else
|
||||||
if buffered then
|
if buffered then
|
||||||
local limit = string.len(content)+1
|
if amount == math.huge or amount == math.maxinteger then
|
||||||
local out = nil
|
-- Read everything remaining
|
||||||
if readcursor<limit then
|
local result = ""
|
||||||
if amount==math.huge then
|
|
||||||
out = string.sub(content,math.min(readcursor,limit))
|
-- First, get what's left in current buffer
|
||||||
|
if content and readCursor <= #content then
|
||||||
|
result = content:sub(readCursor)
|
||||||
|
readCursor = #content + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Then read all remaining data from file
|
||||||
|
while true do
|
||||||
|
local newData = component.invoke(address, "read", handle, bufferSize)
|
||||||
|
if not newData or newData == "" then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
result = result .. newData
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update buffer state
|
||||||
|
content = nil
|
||||||
|
bufferOffset = bufferOffset + #(content or "")
|
||||||
|
|
||||||
|
return result ~= "" and result or nil
|
||||||
else
|
else
|
||||||
out = string.sub(content,math.min(readcursor,limit),math.min(readcursor+amount-1,limit))
|
local result = ""
|
||||||
|
local remaining = amount
|
||||||
|
|
||||||
|
while remaining > 0 do
|
||||||
|
-- If we need more data or buffer is empty
|
||||||
|
if not content or readCursor > #content then
|
||||||
|
content = component.invoke(address, "read", handle, bufferSize)
|
||||||
|
if not content or content == "" then
|
||||||
|
break
|
||||||
end
|
end
|
||||||
|
bufferOffset = bufferOffset + (readCursor - 1)
|
||||||
|
readCursor = 1
|
||||||
end
|
end
|
||||||
readcursor=readcursor+amount
|
|
||||||
if out=="" then
|
-- Extract data from current buffer
|
||||||
return nil
|
local available = #content - readCursor + 1
|
||||||
|
local toRead = math.min(remaining, available)
|
||||||
|
local chunk = content:sub(readCursor, readCursor + toRead - 1)
|
||||||
|
|
||||||
|
result = result .. chunk
|
||||||
|
readCursor = readCursor + toRead
|
||||||
|
remaining = remaining - toRead
|
||||||
|
end
|
||||||
|
|
||||||
|
return result ~= "" and result or nil
|
||||||
end
|
end
|
||||||
return out
|
|
||||||
else
|
else
|
||||||
return component.invoke(self.address, "read", self.handle, amount)
|
return component.invoke(self.address, "read", self.handle, amount)
|
||||||
end
|
end
|
||||||
@@ -233,16 +284,26 @@ function filesystem.open(path, mode, buffered) -- opens a file and returns its h
|
|||||||
function properHandle.write(self, data)
|
function properHandle.write(self, data)
|
||||||
checkArg(2, data, "string")
|
checkArg(2, data, "string")
|
||||||
if unmanagedDrive then
|
if unmanagedDrive then
|
||||||
local startSector = ((readcursor-1)//sectorSize)+1
|
local startSector = ((readCursor - 1) // sectorSize) + 1
|
||||||
if startSector>sectorCount then return nil, "not enough space" end
|
if startSector > sectorCount then
|
||||||
local startSByte = ((readcursor-1)%sectorSize)+1
|
return nil, "not enough space"
|
||||||
local sect = unmanagedProxy.readSector(startSector)
|
|
||||||
unmanagedProxy.writeSector(startSector,sect:sub(1,startSByte-1)..data:sub(1,sectorSize-startSByte+1))
|
|
||||||
for i=2,(#data+startSByte)//sectorSize do
|
|
||||||
if startSector+i-1>sectorCount then return nil, "not enough space" end
|
|
||||||
unmanagedProxy.writeSector(startSector+i-1,data:sub(startSByte+sectorSize*(i-1),startSByte+sectorSize*i-1))
|
|
||||||
end
|
end
|
||||||
readcursor=readcursor+#data
|
local startSByte = ((readCursor - 1) % sectorSize) + 1
|
||||||
|
local sect = unmanagedProxy.readSector(startSector)
|
||||||
|
unmanagedProxy.writeSector(
|
||||||
|
startSector,
|
||||||
|
sect:sub(1, startSByte - 1) .. data:sub(1, sectorSize - startSByte + 1)
|
||||||
|
)
|
||||||
|
for i = 2, (#data + startSByte) // sectorSize do
|
||||||
|
if startSector + i - 1 > sectorCount then
|
||||||
|
return nil, "not enough space"
|
||||||
|
end
|
||||||
|
unmanagedProxy.writeSector(
|
||||||
|
startSector + i - 1,
|
||||||
|
data:sub(startSByte + sectorSize * (i - 1), startSByte + sectorSize * i - 1)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
readCursor = readCursor + #data
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return component.invoke(self.address, "write", self.handle, data)
|
return component.invoke(self.address, "write", self.handle, data)
|
||||||
@@ -251,9 +312,8 @@ function filesystem.open(path, mode, buffered) -- opens a file and returns its h
|
|||||||
function properHandle.close(self)
|
function properHandle.close(self)
|
||||||
if buffered then
|
if buffered then
|
||||||
content = nil
|
content = nil
|
||||||
else
|
|
||||||
return component.invoke(self.address, "close", self.handle)
|
|
||||||
end
|
end
|
||||||
|
return component.invoke(self.address, "close", self.handle)
|
||||||
end
|
end
|
||||||
if address == computer.getBootAddress() then
|
if address == computer.getBootAddress() then
|
||||||
local eeprom
|
local eeprom
|
||||||
@@ -285,6 +345,39 @@ function filesystem.open(path, mode, buffered) -- opens a file and returns its h
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
function properHandle.seek(self, whence, offset)
|
||||||
|
checkArg(2, whence, "string", "number")
|
||||||
|
checkArg(3, offset, "number", "nil")
|
||||||
|
if not offset then
|
||||||
|
offset = 0
|
||||||
|
end
|
||||||
|
if type(whence) == "number" then
|
||||||
|
offset = whence
|
||||||
|
end
|
||||||
|
if not whence or type(whence) == "number" then
|
||||||
|
whence = "cur"
|
||||||
|
end
|
||||||
|
|
||||||
|
if buffered then
|
||||||
|
-- Calculate current absolute position in file
|
||||||
|
local currentAbsolutePos = bufferOffset + readCursor - 1
|
||||||
|
|
||||||
|
-- Seek the underlying file handle to the correct position
|
||||||
|
component.invoke(self.address, "seek", self.handle, "set", currentAbsolutePos)
|
||||||
|
|
||||||
|
-- Now perform the actual seek
|
||||||
|
local newPos = component.invoke(self.address, "seek", self.handle, whence, offset)
|
||||||
|
|
||||||
|
-- Invalidate the buffer and reset positions
|
||||||
|
content = nil
|
||||||
|
bufferOffset = newPos or 0
|
||||||
|
readCursor = 1
|
||||||
|
|
||||||
|
return newPos
|
||||||
|
else
|
||||||
|
return component.invoke(self.address, "seek", self.handle, whence, offset)
|
||||||
|
end
|
||||||
|
end
|
||||||
return properHandle
|
return properHandle
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -330,7 +423,9 @@ function filesystem.size(path)
|
|||||||
if address == computer.getBootAddress() then
|
if address == computer.getBootAddress() then
|
||||||
if absPath:find("^/special/drive") then
|
if absPath:find("^/special/drive") then
|
||||||
local drive = component.get(absPath:sub(16, 18))
|
local drive = component.get(absPath:sub(16, 18))
|
||||||
if not drive then return false end
|
if not drive then
|
||||||
|
return false
|
||||||
|
end
|
||||||
return component.invoke(drive, "getCapacity")
|
return component.invoke(drive, "getCapacity")
|
||||||
elseif absPath:find("^/special/eeprom") then
|
elseif absPath:find("^/special/eeprom") then
|
||||||
local eeprom
|
local eeprom
|
||||||
@@ -363,11 +458,15 @@ local function getRecursiveList(address,absPath)
|
|||||||
if component.invoke(address, "isDirectory", absPath .. "/" .. list[i]) then
|
if component.invoke(address, "isDirectory", absPath .. "/" .. list[i]) then
|
||||||
listChanged = true
|
listChanged = true
|
||||||
local dir = list[i]
|
local dir = list[i]
|
||||||
if dir:sub(-1)=="/" then dir=dir:sub(1,-2) end
|
if dir:sub(-1) == "/" then
|
||||||
|
dir = dir:sub(1, -2)
|
||||||
|
end
|
||||||
table.insert(dirList, dir)
|
table.insert(dirList, dir)
|
||||||
table.remove(list, i)
|
table.remove(list, i)
|
||||||
local subDir = component.invoke(address, "list", absPath .. "/" .. dir)
|
local subDir = component.invoke(address, "list", absPath .. "/" .. dir)
|
||||||
for j=1,#subDir do table.insert(list,dir.."/"..subDir[j]) end
|
for j = 1, #subDir do
|
||||||
|
table.insert(list, dir .. "/" .. subDir[j])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -375,14 +474,20 @@ local function getRecursiveList(address,absPath)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function copyContent(fromHandle, toHandle)
|
local function copyContent(fromHandle, toHandle)
|
||||||
if not (fromHandle and toHandle) then return end
|
if not (fromHandle and toHandle) then
|
||||||
|
return
|
||||||
|
end
|
||||||
local memory = math.floor(computer.freeMemory() * 0.8)
|
local memory = math.floor(computer.freeMemory() * 0.8)
|
||||||
local tmpdata
|
local tmpdata
|
||||||
while true do
|
while true do
|
||||||
tmpdata = fromHandle:read(memory)
|
tmpdata = fromHandle:read(memory)
|
||||||
if not tmpdata then break end
|
if not tmpdata then
|
||||||
|
break
|
||||||
|
end
|
||||||
local status, reason = toHandle:write(tmpdata)
|
local status, reason = toHandle:write(tmpdata)
|
||||||
if status~=true then break end
|
if status ~= true then
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
fromHandle:close()
|
fromHandle:close()
|
||||||
toHandle:close()
|
toHandle:close()
|
||||||
@@ -390,8 +495,12 @@ end
|
|||||||
|
|
||||||
local function copyRecursive(fromAddress, fromAbsPath, toAddress, toAbsPath)
|
local function copyRecursive(fromAddress, fromAbsPath, toAddress, toAbsPath)
|
||||||
-- TODO: make this use copyContent
|
-- TODO: make this use copyContent
|
||||||
if fromAbsPath:sub(-1)=="/" then fromAbsPath=fromAbsPath:sub(1,-2) end
|
if fromAbsPath:sub(-1) == "/" then
|
||||||
if toAbsPath:sub(-1)=="/" then toAbsPath=toAbsPath:sub(1,-2) end
|
fromAbsPath = fromAbsPath:sub(1, -2)
|
||||||
|
end
|
||||||
|
if toAbsPath:sub(-1) == "/" then
|
||||||
|
toAbsPath = toAbsPath:sub(1, -2)
|
||||||
|
end
|
||||||
component.invoke(toAddress, "makeDirectory", toAbsPath)
|
component.invoke(toAddress, "makeDirectory", toAbsPath)
|
||||||
local fileList, dirList = getRecursiveList(fromAddress, fromAbsPath)
|
local fileList, dirList = getRecursiveList(fromAddress, fromAbsPath)
|
||||||
for i = 1, #dirList do
|
for i = 1, #dirList do
|
||||||
@@ -412,11 +521,19 @@ local function copyRecursive(fromAddress,fromAbsPath,toAddress,toAbsPath)
|
|||||||
local fromHandle = component.invoke(fromAddress, "open", fromFile, "r")
|
local fromHandle = component.invoke(fromAddress, "open", fromFile, "r")
|
||||||
local toHandle = component.invoke(toAddress, "open", toFile, "w")
|
local toHandle = component.invoke(toAddress, "open", toFile, "w")
|
||||||
copyContent({
|
copyContent({
|
||||||
["read"]=function(...) return component.invoke(fromAddress, "read", handle, ...) end,
|
["read"] = function(...)
|
||||||
["close"]=function(...) return component.invoke(fromAddress, "close", handle, ...) end
|
return component.invoke(fromAddress, "read", handle, ...)
|
||||||
|
end,
|
||||||
|
["close"] = function(...)
|
||||||
|
return component.invoke(fromAddress, "close", handle, ...)
|
||||||
|
end,
|
||||||
}, {
|
}, {
|
||||||
["write"]=function(...) return component.invoke(fromAddress, "write", handle, ...) end,
|
["write"] = function(...)
|
||||||
["close"]=function(...) return component.invoke(fromAddress, "close", handle, ...) end
|
return component.invoke(fromAddress, "write", handle, ...)
|
||||||
|
end,
|
||||||
|
["close"] = function(...)
|
||||||
|
return component.invoke(fromAddress, "close", handle, ...)
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -488,9 +605,15 @@ function filesystem.remove(path)
|
|||||||
if not address then
|
if not address then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
if absPath:find("^/special") then return false end
|
if absPath:find("^/special") then
|
||||||
if absPath:find("^/tmp") then return false end
|
return false
|
||||||
if absPath:find("^/mnt") then return false end
|
end
|
||||||
|
if absPath:find("^/tmp") then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if absPath:find("^/mnt") then
|
||||||
|
return false
|
||||||
|
end
|
||||||
return component.invoke(address, "remove", absPath)
|
return component.invoke(address, "remove", absPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -503,4 +626,4 @@ function filesystem.makeDirectory(path)
|
|||||||
return component.invoke(address, "makeDirectory", absPath)
|
return component.invoke(address, "makeDirectory", absPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
return(filesystem)
|
return filesystem
|
||||||
|
|||||||
+66
-25
@@ -1,30 +1,71 @@
|
|||||||
local fs = require("filesystem")
|
local fs, computer
|
||||||
local computer = require("computer")
|
if require then
|
||||||
|
fs = require("filesystem")
|
||||||
|
computer = require("computer")
|
||||||
|
else
|
||||||
|
local loadfile = ...
|
||||||
|
fs = loadfile("/lib/filesystem.lua")(loadfile)
|
||||||
|
computer = _G.computer
|
||||||
|
end
|
||||||
|
|
||||||
|
logFileSizeLimit = 16384
|
||||||
|
|
||||||
|
local function writeToLog(path, text)
|
||||||
|
local handle
|
||||||
|
if fs.exists(path) then
|
||||||
|
handle = assert(fs.open(path, "a"))
|
||||||
|
else
|
||||||
|
handle = assert(fs.open(path, "w"))
|
||||||
|
end
|
||||||
|
handle:write(text .. "\n")
|
||||||
|
handle:close()
|
||||||
|
|
||||||
|
-- Log trimming if it gets too long
|
||||||
|
if fs.size(path) > logFileSizeLimit then
|
||||||
|
ocelot.log("Trimming log...")
|
||||||
|
local newlineCounter = 0
|
||||||
|
local sizeCounter = 0
|
||||||
|
local readHandle = fs.open(path, "r")
|
||||||
|
local chunkSize = 1024
|
||||||
|
readHandle:seek("end", -chunkSize)
|
||||||
|
repeat
|
||||||
|
local readText = readHandle:read(chunkSize)
|
||||||
|
readHandle:seek(-chunkSize * 2)
|
||||||
|
local _, newlineCount = readText:gsub("\n", "\n")
|
||||||
|
newlineCounter = newlineCounter + newlineCount
|
||||||
|
sizeCounter = sizeCounter + chunkSize
|
||||||
|
until sizeCounter >= logFileSizeLimit * 0.75
|
||||||
|
readHandle:seek(chunkSize)
|
||||||
|
local writeHandle = fs.open(path, "w")
|
||||||
|
while true do
|
||||||
|
local tmpdata = readHandle:read(math.huge or math.maxinteger)
|
||||||
|
if not tmpdata then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
writeHandle:write(tmpdata)
|
||||||
|
end
|
||||||
|
readHandle:close()
|
||||||
|
writeHandle:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local log = {}
|
local log = {}
|
||||||
|
|
||||||
function log.add(text, logType)
|
setmetatable(log, {
|
||||||
checkArg(1, text, "string")
|
["__index"] = function(tab, index)
|
||||||
checkArg(2, logType, "string", "nil")
|
return {
|
||||||
if logType ~= "debug" and logType ~= "info" and logType ~= "warning" and logType ~= "error" and logType then
|
["logpath"] = fs.concat("/halyde/logs/", index .. ".log"),
|
||||||
error("Log type must either be debug, info, warning or error.")
|
["info"] = function(text)
|
||||||
end
|
writeToLog(fs.concat("/halyde/logs/", index .. ".log"), "INFO [" .. computer.uptime() .. "] " .. text)
|
||||||
if not logType then
|
end,
|
||||||
logType = "debug"
|
["warn"] = function(text)
|
||||||
end
|
writeToLog(fs.concat("/halyde/logs/", index .. ".log"), "WARN [" .. computer.uptime() .. "] " .. text)
|
||||||
local handle = fs.open("/halyde/system.log", "a")
|
end,
|
||||||
local time = computer.uptime()
|
["error"] = function(text)
|
||||||
local logText = string.format("[%02d:%02d:%02d:%02d] " .. text, math.floor(time / 86400), math.floor(time / 3600 % 24), math.floor(time / 60 % 60), math.floor(time % 60)) .. "\n"
|
writeToLog(fs.concat("/halyde/logs/", index .. ".log"), "ERROR [" .. computer.uptime() .. "] " .. text)
|
||||||
if logType == "debug" then
|
end,
|
||||||
handle:write("\27[37m" .. logText)
|
}
|
||||||
elseif logType == "info" then
|
end,
|
||||||
handle:write("\27[97m" .. logText)
|
})
|
||||||
elseif logType == "warning" then
|
|
||||||
handle:write("\27[93m" .. logText)
|
|
||||||
else
|
|
||||||
handle:write("\27[91m" .. logText)
|
|
||||||
end
|
|
||||||
handle:close()
|
|
||||||
end
|
|
||||||
|
|
||||||
return log
|
return log
|
||||||
|
|||||||
Reference in New Issue
Block a user