Zorya-NEO/lib/util_cpio/init.lua

118 lines
2.6 KiB
Lua

local comp = component
local cpio = {}
local arc = {}
local function read(f, h, n)
local d = f.read(h, n)
return d
end
local function readint(f, h, amt, rev)
local tmp = 0
for i=(rev and amt) or 1, (rev and 1) or amt, (rev and -1) or 1 do
tmp = tmp | (read(f, h, 1):byte() << ((i-1)*8))
end
return tmp
end
function cpio.read(drive, path)
local f = comp.proxy(drive)
local h = f.open(path)
local tbl = {}
while true do
local dent = {}
dent.magic = readint(f, h, 2)
local rev = false
if (dent.magic ~= tonumber("070707", 8)) then rev = true end
dent.dev = readint(f, h, 2)
dent.ino = readint(f, h, 2)
dent.mode = readint(f, h, 2)
dent.uid = readint(f, h, 2)
dent.gid = readint(f, h, 2)
dent.nlink = readint(f, h, 2)
dent.rdev = readint(f, h, 2)
dent.mtime = (readint(f, h, 2) << 16) | readint(f, h, 2)
dent.namesize = readint(f, h, 2)
dent.filesize = (readint(f, h, 2) << 16) | readint(f, h, 2)
local name = read(f, h, dent.namesize):sub(1, dent.namesize-1)
if (name == "TRAILER!!!") then break end
--for k, v in pairs(dent) do
-- print(k, v)
--end
dent.name = name
if (dent.namesize % 2 ~= 0) then
f.seek(h, "cur", 1)
end
if (dent.mode & 32768 ~= 0) then
--fwrite()
end
dent.pos = f.seek(h, "cur", 0)
f.seek(h, "cur", dent.filesize)
if (dent.filesize % 2 ~= 0) then
f.seek(h, "cur", 1)
end
tbl[#tbl+1] = dent
end
return setmetatable({
tbl = tbl,
fs = f,
handle = h
}, {__index=arc})
end
function arc:fetch(path)
for i=1, #self.tbl do
if (self.tbl[i].name == path and self.tbl[i].mode &32768 > 0) then
self.fs.seek(self.handle, "set", self.tbl[i].pos)
return self.fs.read(self.handle, self.tbl[i].filesize)
end
end
return nil, "file not found"
end
function arc:exists(path)
for i=1, #self.tbl do
if (self.tbl[i].name == path) then
return true
end
end
return false
end
function arc:close()
self.fs.close(self.handle)
self.tbl = {}
end
function arc:list_dir(path)
if path:sub(#path) ~= "/" then path = path .. "/" end
local ent = {}
for i=1, #self.tbl do
if (self.tbl[i].name:sub(1, #path) == path and not self.tbl[i].name:find("/", #path+1, false)) then
ent[#ent+1] = self.tbl[i].name
end
end
return ent
end
function arc:stream()
for i=1, #self.tbl do
if (self.tbl[i].name == path and self.tbl[i].mode & 32768 > 0) then
local pos = 1
local function read(amt)
self.seek(self.tbl[i].pos-self.seek(0)+pos-1)
pos = pos + amt
return self.read(amt)
end
local function seek(amt)
pos = pos + amt
return pos
end
local function close()end
return read, seek, close
end
end
return nil, "file not found"
end
return cpio