OC-PsychOS2/lib/pkgfs.lua

147 lines
3.4 KiB
Lua

local mtar = require "libmtar"
local w, lz16 = pcall(require, "liblz16")
if not w then lz16 = nil end
pkgfs = {}
pkgfs.files = {}
local findex = {}
local handles = {}
local hc = 0
local function rfalse()
return false
end
local function rzero()
return 0
end
pkgfs.component = {seek = rfalse, makeDirectory = rfalse, write = rfalse, rename = rfalse, setlabel = rfalse, spaceUsed = rzero, spaceTotal = rzero, lastModified = rzero, address = "pkgfs"}
local function fopen(path,comp)
local f
if comp and lz16 then
f = lz16.open(path,"rb")
else
f = io.open(path,"rb")
end
return f
end
local function fnormalize(s)
return table.concat(fs.segments(s),"/")
end
function pkgfs.component.exists(path)
path = fnormalize(path)
return findex[path] and true
end
function pkgfs.component.list(path)
path = fnormalize(path).."/"
local ft,rt = {},{}
for k,v in pairs(findex) do
k="/"..k
if k:match(path.."([^/]+)/.+") then
ft[k:match(path.."([^/]+)/.+").."/"] = true
elseif k:match(path.."([^/]+)") then
ft[k:match(path.."([^/]+)")] = true
end
end
for k,v in pairs(ft) do
rt[#rt+1] = k
end
return rt
end
function pkgfs.component.isDirectory(path)
path = fnormalize(path).."/"
for k,v in pairs(findex) do
k="/"..k
if k:match(path.."([^/]+)/.+") then
return true
end
end
return false
end
function pkgfs.component.size(path)
path=fnormalize(path)
if not findex[path] then return false end
local f = fopen(findex[path][1], findex[path][2])
for fname, read, fsize in mtar.iter(f) do
if fname == path then
return fsize
end
end
return false
end
function pkgfs.component.open(path,mode)
path=fnormalize(path)
if mode:find("w") or mode:find("a") or not findex[path] then
return false
end
local f = fopen(findex[path][1],findex[path][2])
for fname,read,fsize in mtar.iter(f) do
if fname == path then
hc = hc + 1
handles[hc] = {read, f}
return hc
end
end
end
function pkgfs.component.read(handle, n)
if not handles[handle] then return false end
local rv = handles[handle][1](n)
if not rv then return nil end
if rv:len() < 1 then return nil end
return rv
end
function pkgfs.component.close(handle)
if not handles[handle] then return false end
handles[handle][2]:close()
handles[handle] = nil
return true
end
local function index()
findex = {}
for k,v in pairs(pkgfs.files) do
fname, comp = v[1], v[2]
if fname:sub(1,1) ~= "/" then
fname = "/"..fnormalize(os.getenv("PWD").."/"..fname)
end
local f = fopen(fname,comp)
if not f then error("unable to open file "..fname) end
for name, read, fsize in mtar.iter(f) do
findex[fnormalize(name)] = {fname,comp}
end
f:close()
end
return true
end
function pkgfs.add(fname,comp) -- string boolean -- boolean -- Add a package as specified in *fname* to the pkgfs component. If *comp* is true, read it as a LZ16-compressed package.
pkgfs.files[#pkgfs.files+1] = {fname,comp}
return index()
end
function pkgfs.remove(fname) -- string -- boolean -- Removes the package specified by *fname* from the pkgfs index.
for k,v in pairs(pkgfs.files) do
if v[1] == fname then
table.remove(pkgfs.files,k)
end
end
return index()
end
fs.makeDirectory("/pkg")
fs.mount("/pkg",pkgfs.component)
for _,file in ipairs(fs.list("/boot/pkg/")) do
if file:sub(-5) == ".mtar" then
pcall(pkgfs.add,"/boot/pkg/"..file)
elseif file:sub(-9) == ".mtar.lss" then
pcall(pkgfs.add,"/boot/pkg/"..file,true)
end
end
return pkgfs