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