Added logging system, fixed filesystem read handle buffering and added read handle seeking.

This commit is contained in:
2025-09-15 08:10:50 +03:00
parent d3d5f21ab1
commit 099fbee8c6
4 changed files with 667 additions and 483 deletions
+18 -4
View File
@@ -4,14 +4,18 @@ _G._OSVERSION = "HALYDE VERSION" -- TODO: Put this in a separate config file
_G._OSLOGO = ""
_G._PUBLIC = {}
_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
repeat
tmpdata = handle:read(math.huge)
_OSLOGO = _OSLOGO .. (tmpdata or "")
until not tmpdata
handle:close()
_G.package = {["preloaded"] = {}}
log.kernel.info("Loaded OS logo")
_G.package = { ["preloaded"] = {} }
loadfile("/halyde/kernel/modules/datatools.lua")()
@@ -26,7 +30,11 @@ function _G.reqgen(load)
modulepath = module
elseif filesystem.exists("/lib/" .. module .. ".lua") then
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"
end
assert(modulepath, "Module not found\nPossible locations:\n/lib/" .. module .. ".lua")
@@ -36,11 +44,12 @@ function _G.reqgen(load)
data = data .. (tmpdata or "")
until not tmpdata
handle:close()
return(assert(load(data, "="..modulepath))(table.unpack(args)))
return (assert(load(data, "=" .. modulepath))(table.unpack(args)))
end
end
_G.require = reqgen(_G.load)
log.kernel.info("Generated userland require function")
function _G.package.preload(module)
local handle, data, tmpdata = assert(filesystem.open("/lib/" .. module .. ".lua", "r")), "", nil
@@ -49,15 +58,18 @@ function _G.package.preload(module)
data = data .. (tmpdata or "")
until not tmpdata
handle:close()
package.preloaded[module] = assert(load(data, "="..module))()
package.preloaded[module] = assert(load(data, "=" .. module))()
_G[module] = nil
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.
log.kernel.info("Loading modules")
require("/halyde/kernel/modload.lua")
package.preload("component")
package.preload("computer")
log.kernel.info("Pre-loaded low-level packages")
local component = require("component")
local gpu = component.gpu
@@ -65,6 +77,7 @@ local screenAddress = component.list("screen")()
gpu.bind(screenAddress)
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
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")
end
log.kernel.info("Starting tsched")
require("/halyde/kernel/tsched.lua")
+6
View File
@@ -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
+242 -119
View File
@@ -1,6 +1,8 @@
local loadfile = ... -- raw loadfile from boot.lua
local unicode, component, computer
local bufferSize = math.huge or math.maxinteger
if loadfile then
unicode = loadfile("/lib/unicode.lua")(loadfile)
component = loadfile("/lib/component.lua")(loadfile)
@@ -50,7 +52,7 @@ function filesystem.absolutePath(path) -- returns the address and absolute path
address = computer.tmpAddress()
path = path:sub(5)
elseif path:find("^/mnt/...") then
address = component.get(path:sub(6,8))
address = component.get(path:sub(6, 8))
if not address then
address = computer.getBootAddress()
else
@@ -72,29 +74,31 @@ function filesystem.exists(path) -- check if path exists
return false
end
if absPath:find("^/special/drive/...") then
return not not (computer.getBootAddress() and component.get(absPath:sub(16,18)))
return not not (computer.getBootAddress() and component.get(absPath:sub(16, 18)))
end
if absPath:find("^/special/eeprom/") then
return table.find({"init.lua","data.bin","label.txt"},absPath:sub(17))
return table.find({ "init.lua", "data.bin", "label.txt" }, absPath:sub(17))
end
return component.invoke(address, "exists", absPath)
end
local function readBytes(self,n)
local function readBytes(self, n)
n = n or 1
if n==1 then
if n == 1 then
local byte = self:read(1)
if byte==nil then return nil end
if byte == nil then
return nil
end
return string.byte(byte)
end
local bytes, res = {string.byte(self:read(n),1,n)}, 0
local bytes, res = { string.byte(self:read(n), 1, n) }, 0
if self.littleEndian then
for i=#bytes,1,-1 do
res = (res<<8)&0xFFFFFFFF | bytes[i]
for i = #bytes, 1, -1 do
res = (res << 8) & 0xFFFFFFFF | bytes[i]
end
else
for i=1,#bytes do
res = (res<<8)&0xFFFFFFFF | bytes[i]
for i = 1, #bytes do
res = (res << 8) & 0xFFFFFFFF | bytes[i]
end
end
return res
@@ -108,8 +112,10 @@ end
local function iterateBytes(self)
return function()
local byte = readBytes(self,1)
if byte==nil then self:close() end
local byte = readBytes(self, 1)
if byte == nil then
self:close()
end
return byte
end
end
@@ -120,20 +126,20 @@ end
function filesystem.makeReadStream(content)
local properHandle = {}
local readcursor = 1
local readCursor = 1
function properHandle.read(self, amount)
checkArg(2, amount, "number")
local limit = string.len(content)+1
local limit = string.len(content) + 1
local out = nil
if readcursor<limit then
if amount==math.huge then
out = string.sub(content,math.min(readcursor,limit))
if readCursor < limit then
if amount == math.huge then
out = string.sub(content, math.min(readCursor, limit))
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
readcursor=readcursor+amount
if out=="" then
readCursor = readCursor + amount
if out == "" then
return nil
end
return out
@@ -146,7 +152,7 @@ function filesystem.makeReadStream(content)
return nil
end
function properHandle.close()
content=nil
content = nil
end
return properHandle
end
@@ -168,14 +174,14 @@ function filesystem.open(path, mode, buffered) -- opens a file and returns its h
return nil, "/special does not allow creating files"
end
local address, absPath = filesystem.absolutePath(path)
local unmanagedDrive = address==computer.getBootAddress() and absPath:find("^/special/drive")
local unmanagedDrive = address == computer.getBootAddress() and absPath:find("^/special/drive")
local unmanagedProxy, sectorSize, sectorCount, handle
if unmanagedDrive then
unmanagedProxy = component.proxy(component.get(absPath:sub(16,18)))
unmanagedProxy = component.proxy(component.get(absPath:sub(16, 18)))
sectorSize = unmanagedProxy.getSectorSize()
sectorCount = math.ceil(unmanagedProxy.getCapacity()/sectorSize)
elseif not (address==computer.getBootAddress() and absPath:find("^/special/")) then
local handleArgs = {component.invoke(address, "open", absPath, mode)}
sectorCount = math.ceil(unmanagedProxy.getCapacity() / sectorSize)
elseif not (address == computer.getBootAddress() and absPath:find("^/special/")) then
local handleArgs = { component.invoke(address, "open", absPath, mode) }
handle = handleArgs[1]
if not handle then
return table.unpack(handleArgs)
@@ -186,41 +192,86 @@ function filesystem.open(path, mode, buffered) -- opens a file and returns its h
properHandle.handle = handle
properHandle.address = address
local content = nil
local readcursor = 1
if buffered and mode:sub(1,1)=="r" then
content=""
repeat
tmpdata = component.invoke(address, "read", handle, math.huge or math.maxinteger)
content = content .. (tmpdata or "")
until not tmpdata
component.invoke(address, "close", handle)
local bufferOffset = 0 -- Position in file where buffer starts
local readCursor = 1 -- Position within buffer (1-based)
if buffered and mode == "r" then
content = component.invoke(address, "read", handle, bufferSize) or ""
bufferOffset = 0
readCursor = 1
end
function properHandle.read(self, amount)
checkArg(2, amount, "number")
if unmanagedDrive then
local sectorIdx = ((readcursor-1)//sectorSize)+1
if sectorIdx>sectorCount then return nil end
-- TODO: Test if this still works
local sectorIdx = ((readCursor - 1) // sectorSize) + 1
if sectorIdx > sectorCount then
return nil
end
local sector = unmanagedProxy.readSector(sectorIdx)
local data = sector:sub(((readcursor-1)%sectorSize)+1,((readcursor+math.min(amount,sectorSize)-2)%sectorSize)+1)
readcursor=readcursor+#data
if data=="" then return nil end
local data = sector:sub(
((readCursor - 1) % sectorSize) + 1,
((readCursor + math.min(amount, sectorSize) - 2) % sectorSize) + 1
)
readCursor = readCursor + #data
if data == "" then
return nil
end
return data
else
if buffered then
local limit = string.len(content)+1
local out = nil
if readcursor<limit then
if amount==math.huge then
out = string.sub(content,math.min(readcursor,limit))
if amount == math.huge or amount == math.maxinteger then
-- Read everything remaining
local result = ""
-- 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
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
bufferOffset = bufferOffset + (readCursor - 1)
readCursor = 1
end
readcursor=readcursor+amount
if out=="" then
return nil
-- Extract data from current buffer
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
return out
else
return component.invoke(self.address, "read", self.handle, amount)
end
@@ -233,16 +284,26 @@ function filesystem.open(path, mode, buffered) -- opens a file and returns its h
function properHandle.write(self, data)
checkArg(2, data, "string")
if unmanagedDrive then
local startSector = ((readcursor-1)//sectorSize)+1
if startSector>sectorCount then return nil, "not enough space" end
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))
local startSector = ((readCursor - 1) // sectorSize) + 1
if startSector > sectorCount then
return nil, "not enough space"
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
else
return component.invoke(self.address, "write", self.handle, data)
@@ -251,33 +312,32 @@ function filesystem.open(path, mode, buffered) -- opens a file and returns its h
function properHandle.close(self)
if buffered then
content = nil
else
end
return component.invoke(self.address, "close", self.handle)
end
end
if address==computer.getBootAddress() then
if address == computer.getBootAddress() then
local eeprom
pcall(function()
eeprom = component.eeprom
end)
if eeprom then
local getFunc, setFunc
if absPath=="/special/eeprom/init.lua" then
getFunc,setFunc = "get","set"
elseif absPath=="/special/eeprom/data.bin" then
getFunc,setFunc = "getData","setData"
elseif absPath=="/special/eeprom/label.txt" then
getFunc,setFunc = "getLabel","setLabel"
if absPath == "/special/eeprom/init.lua" then
getFunc, setFunc = "get", "set"
elseif absPath == "/special/eeprom/data.bin" then
getFunc, setFunc = "getData", "setData"
elseif absPath == "/special/eeprom/label.txt" then
getFunc, setFunc = "getLabel", "setLabel"
end
if mode:sub(1,1)=="r" and getFunc then
if mode:sub(1, 1) == "r" and getFunc then
local stream = filesystem.makeReadStream(eeprom[getFunc]() or "")
properHandle.read = stream.read
properHandle.close = stream.close
elseif mode:sub(1,1)=="w" and setFunc then
elseif mode:sub(1, 1) == "w" and setFunc then
local content = ""
function properHandle.write(self, data)
checkArg(2, data, "string")
content=content..data
content = content .. data
end
function properHandle.close(self)
return eeprom[setFunc](content)
@@ -285,6 +345,39 @@ function filesystem.open(path, mode, buffered) -- opens a file and returns its h
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
end
@@ -296,7 +389,7 @@ function filesystem.list(path)
local returnTable = {}
local tmpAddress = computer.tmpAddress()
for address, _ in component.list("filesystem") do
if address~=tmpAddress then
if address ~= tmpAddress then
table.insert(returnTable, address:sub(1, 3) .. "/")
end
end
@@ -305,13 +398,13 @@ function filesystem.list(path)
local returnTable = {}
local tmpAddress = computer.tmpAddress()
for address, type in component.list("drive") do
if address~=tmpAddress and type=="drive" then
if address ~= tmpAddress and type == "drive" then
table.insert(returnTable, address:sub(1, 3))
end
end
return returnTable
elseif path=="/special/eeprom" then
return {"init.lua","data.bin","label.txt"}
elseif path == "/special/eeprom" then
return { "init.lua", "data.bin", "label.txt" }
else
local address, absPath = filesystem.absolutePath(path)
if not address then
@@ -327,11 +420,13 @@ function filesystem.size(path)
if not address then
return false
end
if address==computer.getBootAddress() then
if address == computer.getBootAddress() then
if absPath:find("^/special/drive") then
local drive = component.get(absPath:sub(16,18))
if not drive then return false end
return component.invoke(drive,"getCapacity")
local drive = component.get(absPath:sub(16, 18))
if not drive then
return false
end
return component.invoke(drive, "getCapacity")
elseif absPath:find("^/special/eeprom") then
local eeprom
pcall(function()
@@ -339,11 +434,11 @@ function filesystem.size(path)
end)
if eeprom then
local getFunc
if absPath=="/special/eeprom/init.lua" then
if absPath == "/special/eeprom/init.lua" then
getFunc = "get"
elseif absPath=="/special/eeprom/data.bin" then
elseif absPath == "/special/eeprom/data.bin" then
getFunc = "getData"
elseif absPath=="/special/eeprom/label.txt" then
elseif absPath == "/special/eeprom/label.txt" then
getFunc = "getLabel"
end
return #(eeprom[getFunc]())
@@ -353,52 +448,66 @@ function filesystem.size(path)
return component.invoke(address, "size", absPath)
end
local function getRecursiveList(address,absPath)
local list = component.invoke(address,"list",absPath)
local function getRecursiveList(address, absPath)
local list = component.invoke(address, "list", absPath)
local dirList = {}
local listChanged = true
while listChanged do
listChanged = false
for i=1,#list do
if component.invoke(address, "isDirectory", absPath.."/"..list[i]) then
for i = 1, #list do
if component.invoke(address, "isDirectory", absPath .. "/" .. list[i]) then
listChanged = true
local dir = list[i]
if dir:sub(-1)=="/" then dir=dir:sub(1,-2) end
table.insert(dirList,dir)
table.remove(list,i)
local subDir = component.invoke(address,"list",absPath.."/"..dir)
for j=1,#subDir do table.insert(list,dir.."/"..subDir[j]) end
if dir:sub(-1) == "/" then
dir = dir:sub(1, -2)
end
table.insert(dirList, dir)
table.remove(list, i)
local subDir = component.invoke(address, "list", absPath .. "/" .. dir)
for j = 1, #subDir do
table.insert(list, dir .. "/" .. subDir[j])
end
end
end
return list,dirList
end
return list, dirList
end
local function copyContent(fromHandle,toHandle)
if not (fromHandle and toHandle) then return end
local memory = math.floor(computer.freeMemory()*0.8)
local function copyContent(fromHandle, toHandle)
if not (fromHandle and toHandle) then
return
end
local memory = math.floor(computer.freeMemory() * 0.8)
local tmpdata
while true do
tmpdata = fromHandle:read(memory)
if not tmpdata then break end
local status,reason = toHandle:write(tmpdata)
if status~=true then break end
if not tmpdata then
break
end
local status, reason = toHandle:write(tmpdata)
if status ~= true then
break
end
end
fromHandle:close()
toHandle:close()
end
local function copyRecursive(fromAddress,fromAbsPath,toAddress,toAbsPath)
local function copyRecursive(fromAddress, fromAbsPath, toAddress, toAbsPath)
-- TODO: make this use copyContent
if fromAbsPath:sub(-1)=="/" then fromAbsPath=fromAbsPath:sub(1,-2) end
if toAbsPath:sub(-1)=="/" then toAbsPath=toAbsPath:sub(1,-2) end
component.invoke(toAddress,"makeDirectory",toAbsPath)
local fileList,dirList = getRecursiveList(fromAddress,fromAbsPath)
for i=1,#dirList do
component.invoke(toAddress,"makeDirectory",toAbsPath.."/"..dirList[i])
if fromAbsPath:sub(-1) == "/" then
fromAbsPath = fromAbsPath:sub(1, -2)
end
for i=1,#fileList do
local fromFile, toFile = fromAbsPath.."/"..fileList[i], toAbsPath.."/"..fileList[i]
if toAbsPath:sub(-1) == "/" then
toAbsPath = toAbsPath:sub(1, -2)
end
component.invoke(toAddress, "makeDirectory", toAbsPath)
local fileList, dirList = getRecursiveList(fromAddress, fromAbsPath)
for i = 1, #dirList do
component.invoke(toAddress, "makeDirectory", toAbsPath .. "/" .. dirList[i])
end
for i = 1, #fileList do
local fromFile, toFile = fromAbsPath .. "/" .. fileList[i], toAbsPath .. "/" .. fileList[i]
--[[ local handle = component.invoke(fromAddress, "open", fromFile, "r")
local data, tmpdata = "", nil
repeat
@@ -412,11 +521,19 @@ local function copyRecursive(fromAddress,fromAbsPath,toAddress,toAbsPath)
local fromHandle = component.invoke(fromAddress, "open", fromFile, "r")
local toHandle = component.invoke(toAddress, "open", toFile, "w")
copyContent({
["read"]=function(...) 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,
["close"]=function(...) return component.invoke(fromAddress, "close", handle, ...) end
["read"] = function(...)
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,
["close"] = function(...)
return component.invoke(fromAddress, "close", handle, ...)
end,
})
end
end
@@ -441,7 +558,7 @@ function filesystem.rename(fromPath, toPath)
if fromAddress == toAddress then
return component.invoke(fromAddress, "rename", fromAbsPath, toAbsPath)
elseif filesystem.isDirectory(fromPath) then -- component.invoke(fromAddress, "isDirectory", fromAbsPath) then
copyRecursive(fromAddress,fromAbsPath,toAddress,toAbsPath)
copyRecursive(fromAddress, fromAbsPath, toAddress, toAbsPath)
filesystem.remove(fromPath) -- component.invoke(fromAddress,"remove", fromAbsPath)
else
local handle, data, tmpdata = filesystem.open(fromPath), "", nil -- component.invoke(fromAddress, "open", fromAbsPath, "r"), "", nil
@@ -466,7 +583,7 @@ function filesystem.copy(fromPath, toPath)
return false
end
if filesystem.isDirectory(fromPath) then -- component.invoke(fromAddress, "isDirectory", fromAbsPath)
copyRecursive(fromAddress,fromAbsPath,toAddress,toAbsPath)
copyRecursive(fromAddress, fromAbsPath, toAddress, toAbsPath)
else
--[[ local handle = filesystem.open(fromPath,"r")
local data, tmpdata = "", nil
@@ -478,7 +595,7 @@ function filesystem.copy(fromPath, toPath)
local handle = filesystem.open(toPath,"w")
handle:write(data)
handle:close() ]]
copyContent(filesystem.open(fromPath,"r"),filesystem.open(toPath,"w"))
copyContent(filesystem.open(fromPath, "r"), filesystem.open(toPath, "w"))
end
end
@@ -488,9 +605,15 @@ function filesystem.remove(path)
if not address then
return false
end
if absPath:find("^/special") then return false end
if absPath:find("^/tmp") then return false end
if absPath:find("^/mnt") then return false end
if absPath:find("^/special") then
return false
end
if absPath:find("^/tmp") then
return false
end
if absPath:find("^/mnt") then
return false
end
return component.invoke(address, "remove", absPath)
end
@@ -503,4 +626,4 @@ function filesystem.makeDirectory(path)
return component.invoke(address, "makeDirectory", absPath)
end
return(filesystem)
return filesystem
+66 -25
View File
@@ -1,30 +1,71 @@
local fs = require("filesystem")
local computer = require("computer")
local fs, 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 = {}
function log.add(text, logType)
checkArg(1, text, "string")
checkArg(2, logType, "string", "nil")
if logType ~= "debug" and logType ~= "info" and logType ~= "warning" and logType ~= "error" and logType then
error("Log type must either be debug, info, warning or error.")
end
if not logType then
logType = "debug"
end
local handle = fs.open("/halyde/system.log", "a")
local time = computer.uptime()
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"
if logType == "debug" then
handle:write("\27[37m" .. logText)
elseif logType == "info" then
handle:write("\27[97m" .. logText)
elseif logType == "warning" then
handle:write("\27[93m" .. logText)
else
handle:write("\27[91m" .. logText)
end
handle:close()
end
setmetatable(log, {
["__index"] = function(tab, index)
return {
["logpath"] = fs.concat("/halyde/logs/", index .. ".log"),
["info"] = function(text)
writeToLog(fs.concat("/halyde/logs/", index .. ".log"), "INFO [" .. computer.uptime() .. "] " .. text)
end,
["warn"] = function(text)
writeToLog(fs.concat("/halyde/logs/", index .. ".log"), "WARN [" .. computer.uptime() .. "] " .. text)
end,
["error"] = function(text)
writeToLog(fs.concat("/halyde/logs/", index .. ".log"), "ERROR [" .. computer.uptime() .. "] " .. text)
end,
}
end,
})
return log