OC-PsychOS/modules/util/tape.lua

162 lines
3.6 KiB
Lua

tape = {}
tape.types = {}
tape.types["!"] = "executable"
tape.types["t"] = "tar"
tape.types["d"] = "data"
tape.types["D"] = "directory"
tape.types["f"] = "file"
function tape.records(addr) -- { { type, start, end, length } }
local tp,ct = {},0
addr = addr or component.list("tape_drive")()
local t = component.proxy(addr)
local function read(n)
n=n or 1
ct=ct+n
return t.read(n)
end
local function seek(n)
n=n or 1
ct=ct+n
return t.seek(n)
end
while true do
local ty = read()
if not tape.types[ty] then break end
tp[#tp+1] = {ty,ct+8} -- type, start,
local ln = tonumber(read(8)) or 0
tp[#tp][#tp[#tp]+1] = ct+ln -- end
tp[#tp][#tp[#tp]+1] = ln -- length
seek(ln)
end
return tp
end
function tape.precords(addr)
tape.rewind(addr)
local pt = tape.records(addr)
for k,v in ipairs(pt) do
print(k.."\t"..v[1].."\t"..v[2].."\t"..v[3].."\t"..v[4])
end
end
function tape.drecord(n,addr)
addr = addr or component.list("tape_drive")()
tape.rewind(addr)
local pt = tape.records(addr)
tape.rewind(addr)
local t = component.proxy(addr)
print(pt[n][2]-9)
t.seek(pt[n][2]-9)
t.write("\0")
tape.rewind()
end
function tape.wrecord(c,ty,s,addr)
ty = ty or "!"
addr = addr or component.list("tape_drive")()
local t = component.proxy(addr)
if s then
t.seek(-math.huge)
t.seek(s)
end
local fh=ty:sub(1,1)..string.format("%8d",c:len())
print("Header: "..fh)
t.write(fh)
t.write(c)
end
function tape.rrecord(pn,addr)
addr = addr or component.list("tape_drive")()
pn = pn or 1
local t = component.proxy(addr)
local pP = t.seek(-math.huge)
local pt = tape.records(addr)
t.seek(-math.huge)
local pstart,plen = pt[pn][2],pt[pn][4]
t.seek(pstart)
C=t.read(plen)
t.seek(-math.huge)
t.seek(pP)
return C
end
function tape.nrecord(addr)
addr = addr or component.list("tape_drive")()
local t = component.proxy(addr)
local pP = t.seek(-math.huge)
local pt = tape.records(addr)
t.seek(-math.huge)
t.seek(pP)
return pt[#pt][3]
end
function tape.rewind(addr)
addr = addr or component.list("tape_drive")()
local t = component.proxy(addr)
t.seek(-math.huge)
end
function tape.parsefile(str)
return str:sub(1,64):gsub("\0",""), str:sub(65)
end
function tape.unparsefile(fname,str)
local nul = "\0"
nul=nul:rep(64-#fname)
fname=nul..fname
return fname..str
end
function tape.mkdir(str,addr)
tape.wrecord(str,"D",tape.nrecord(),addr)
end
function tape.wfile(fname,fcont,addr)
tape.wrecord(str,"f",tape.nrecord(),addr)
end
function tape.wtree(addr)
local ft = {""}
local rft = {}
addr = addr or component.list("tape_drive")()
local t = component.proxy(addr)
for _,d in ipairs(ft) do
local ls = fs.list(d)
for k,v in ipairs(ls) do
v=d..v
if fs.isdir(v) then
ft[#ft+1] = v
else
rft[#rft+1] = v
end
end
end
tape.rewind(addr)
t.seek(tape.nrecord(addr))
for k,v in ipairs(ft) do
if v ~= "" then
print(v)
local fh="D"..string.format("%8d",v:len())
t.write(fh)
t.write(v)
end
end
for k,v in ipairs(rft) do
print(v)
local f=io.open(v,"rb")
local fc = f:read("*a")
local fc = tape.unparsefile(v,fc)
f:close()
local fh="f"..string.format("%8d",fc:len())
t.write(fh)
t.write(fc)
end
end
function tape.rtree(pref,addr)
tape.rewind()
local pt = tape.records()
for k,v in ipairs(pt) do
if v[1] == "D" then
print(tostring(k).."\t"..v[1].."\t"..pref..tape.rrecord(k))
fs.mkdir(pref..tape.rrecord(k))
elseif v[1] == "f" then
local fn,fc = tape.parsefile(tape.rrecord(k))
print(tostring(k).."\t"..v[1].."\t"..pref..fn)
local f=io.open(pref..fn,"wb")
f:write(fc)
f:close()
end
computer.beep()
coroutine.yield()
end
end