initial pkgfs work, seems functional
This commit is contained in:
parent
58c9a5492e
commit
0f1b324cc4
112
lib/libmtar.lua
Normal file
112
lib/libmtar.lua
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
local mtar = {}
|
||||||
|
|
||||||
|
-- detect OS hopefully
|
||||||
|
if _OSVERSION then
|
||||||
|
if _OSVERSION:sub(1,8) == "OpenOS" then
|
||||||
|
OPENOS = true
|
||||||
|
elseif _OSVERSION:sub(1,9) == "PsychOS" then
|
||||||
|
PSYCHOS = true
|
||||||
|
end
|
||||||
|
else
|
||||||
|
LINUX = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function mkdir(dir)
|
||||||
|
if OPENOS or LINUX then
|
||||||
|
os.execute("mkdir "..dest.."/"..dir.." &> /dev/null")
|
||||||
|
elseif PSYCHOS then
|
||||||
|
-- todo: write PsychOS support
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function toint(s)
|
||||||
|
local n = 0
|
||||||
|
local i = 1
|
||||||
|
for p in s:gmatch(".") do
|
||||||
|
n = n << 8
|
||||||
|
n = n | string.byte(p)
|
||||||
|
i=i+1
|
||||||
|
end
|
||||||
|
return n
|
||||||
|
end
|
||||||
|
|
||||||
|
local function cint(n,l)
|
||||||
|
local t={}
|
||||||
|
for i = 0, 7 do
|
||||||
|
t[i+1] = (n >> (i * 8)) & 0xFF
|
||||||
|
end
|
||||||
|
return string.reverse(string.char(table.unpack(t)):sub(1,l))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function cleanPath(path)
|
||||||
|
local pt = {}
|
||||||
|
for segment in path:gmatch("[^/]+") do
|
||||||
|
if segment == ".." then
|
||||||
|
pt[#pt] = nil
|
||||||
|
elseif segment ~= "." then
|
||||||
|
pt[#pt+1] = segment
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return table.concat(pt,"/")
|
||||||
|
end
|
||||||
|
|
||||||
|
function mtar.genHeader(fname,len) -- generate a header for file *fname* when provided with file length *len*
|
||||||
|
return string.format("%s%s%s",cint(fname:len(),2),fname,cint(len,2))
|
||||||
|
end
|
||||||
|
|
||||||
|
function mtar.iter(stream) -- table -- function -- Given buffer *stream*, returns an iterator suitable for use with *for* that returns, for each iteration, the file name, a function to read from the file, and the length of the file.
|
||||||
|
local remain = 0
|
||||||
|
local function read(n)
|
||||||
|
local rb = stream:read(math.min(n,remain))
|
||||||
|
remain = remain - rb:len()
|
||||||
|
return rb
|
||||||
|
end
|
||||||
|
return function()
|
||||||
|
stream:read(remain)
|
||||||
|
local nlen = toint(stream:read(2) or "\0\0")
|
||||||
|
if nlen == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local name = cleanPath(stream:read(nlen))
|
||||||
|
local fsize = toint(stream:read(2))
|
||||||
|
remain = fsize
|
||||||
|
return name, read, fsize
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function mtar.unarchive(stream,dest,verbose) -- Extract mtar archive read from *stream* to *dest*. If *verbose*, print status.
|
||||||
|
dest = dest or "."
|
||||||
|
while true do
|
||||||
|
local nlen = toint(stream:read(2) or "\0\0")
|
||||||
|
if nlen == 0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
local name = cleanPath(stream:read(nlen))
|
||||||
|
local fsize = toint(stream:read(2))
|
||||||
|
if verbose then
|
||||||
|
io.write(name.." "..tostring(fsize).."... ")
|
||||||
|
end
|
||||||
|
local dir = name:match("(.+)/.*%.?.+")
|
||||||
|
if (dir) then
|
||||||
|
mkdir(dir)
|
||||||
|
end
|
||||||
|
local f = io.open(dest.."/"..name,"wb")
|
||||||
|
local rsize,buf = fsize, ""
|
||||||
|
if f then
|
||||||
|
repeat
|
||||||
|
buf = stream:read(math.min(rsize,2048))
|
||||||
|
f:write(buf)
|
||||||
|
rsize = rsize - buf:len()
|
||||||
|
if verbose then
|
||||||
|
io.write(tostring(rsize).." ")
|
||||||
|
end
|
||||||
|
until rsize <= 1
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
if verbose then
|
||||||
|
print("done.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return mtar
|
109
lib/pkgfs.lua
Normal file
109
lib/pkgfs.lua
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
local mtar = require "libmtar"
|
||||||
|
local w, lz16 = pcall(require, "liblz16")
|
||||||
|
if not w then lz16 = nil end
|
||||||
|
|
||||||
|
pkgfs = {}
|
||||||
|
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}
|
||||||
|
|
||||||
|
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.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
|
||||||
|
|
||||||
|
function pkgfs.add(fname,comp)
|
||||||
|
local f = fopen(fname,comp)
|
||||||
|
for name, read, fsize in mtar.iter(f) do
|
||||||
|
findex[fnormalize(name)] = {fname,comp}
|
||||||
|
end
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
return pkgfs
|
Loading…
Reference in New Issue
Block a user