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