2020-06-05 12:10:48 +10:00
local mtar = require " libmtar "
local w , lz16 = pcall ( require , " liblz16 " )
if not w then lz16 = nil end
pkgfs = { }
2020-06-06 13:35:59 +10:00
pkgfs.files = { }
2020-06-05 12:10:48 +10:00
local findex = { }
local handles = { }
local hc = 0
local function rfalse ( )
return false
end
local function rzero ( )
return 0
end
2020-06-06 19:45:40 +10:00
pkgfs.component = { seek = rfalse , makeDirectory = rfalse , write = rfalse , rename = rfalse , setlabel = rfalse , spaceUsed = rzero , spaceTotal = rzero , lastModified = rzero , address = " pkgfs " }
2020-06-05 12:10:48 +10:00
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
2020-06-06 19:45:40 +10:00
function pkgfs . component . exists ( path )
path = fnormalize ( path )
return findex [ path ] and true
end
2020-06-05 12:10:48 +10:00
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
2020-06-06 13:35:59 +10:00
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 )
2020-06-06 19:45:40 +10:00
if not f then error ( " unable to open file " .. fname ) end
2020-06-06 13:35:59 +10:00
for name , read , fsize in mtar.iter ( f ) do
findex [ fnormalize ( name ) ] = { fname , comp }
end
f : close ( )
2020-06-05 22:45:31 +10:00
end
2020-06-06 13:35:59 +10:00
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
2020-06-05 12:10:48 +10:00
end
2020-06-06 13:35:59 +10:00
return index ( )
2020-06-05 12:10:48 +10:00
end
2020-06-06 12:50:50 +10:00
fs.makeDirectory ( " /pkg " )
fs.mount ( " /pkg " , pkgfs.component )
2020-06-06 19:45:40 +10:00
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
2020-06-05 12:10:48 +10:00
return pkgfs