|
|
@@ -1,5 +1,6 @@ |
|
|
|
local shell = require "shell" |
|
|
|
local mtar = require "libmtar" |
|
|
|
local fs = require "filesystem" |
|
|
|
|
|
|
|
local args, opts = shell.parse(...) |
|
|
|
|
|
|
@@ -30,43 +31,78 @@ local function vp(...) |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
if opts.x then |
|
|
|
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 unarchive(stream,dest,verbose,csize) |
|
|
|
csize = csize or 2048 |
|
|
|
function vwrite(...) |
|
|
|
if verbose then |
|
|
|
io.write(...) |
|
|
|
end |
|
|
|
end |
|
|
|
for fname, read, len in mtar.iter(stream) do |
|
|
|
local written = 0 |
|
|
|
fname = cleanPath(fname) |
|
|
|
vwrite(string.format("%s %i... ",fname,len)) |
|
|
|
local dir = fname:match("(.+)/.*%.?.+") |
|
|
|
if dir then |
|
|
|
if dir:sub(1,1) ~= "/" then |
|
|
|
dir = os.getenv("PWD").."/"..dir |
|
|
|
end |
|
|
|
fs.makeDirectory(dest.."/"..dir) |
|
|
|
end |
|
|
|
local f = io.open(dest.."/"..fname,"wb") |
|
|
|
if f then |
|
|
|
repeat |
|
|
|
local rb = read(csize) |
|
|
|
written = written + rb:len() |
|
|
|
f:write(rb) |
|
|
|
vwrite(written) |
|
|
|
vwrite(" ") |
|
|
|
until written == len |
|
|
|
f:close() |
|
|
|
vwrite("done\n") |
|
|
|
else |
|
|
|
vwrite("failed to open "..fname.."\n") |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
function open(fn,mode) |
|
|
|
local f |
|
|
|
if opts.z then |
|
|
|
f = lz16.open(args[1],"rb") |
|
|
|
f = lz16.open(fn, mode) |
|
|
|
else |
|
|
|
f = io.open(args[1],"rb") |
|
|
|
f = io.open(fn, mode) |
|
|
|
end |
|
|
|
return f |
|
|
|
end |
|
|
|
|
|
|
|
if opts.x then |
|
|
|
local f = open(args[1],"rb") |
|
|
|
if not f then error("unable to open file") end |
|
|
|
local w, r = mtar.unarchive(f,args[2] or ".",opts.v) |
|
|
|
local w, r = unarchive(f,args[2] or ".",opts.v) |
|
|
|
f:close() |
|
|
|
elseif opts.t then |
|
|
|
local f |
|
|
|
if opts.z then |
|
|
|
f = lz16.open(args[1],"rb") |
|
|
|
else |
|
|
|
f = io.open(args[1],"rb") |
|
|
|
end |
|
|
|
local f = open(args[1],"rb") |
|
|
|
if not f then error("unable to open file") end |
|
|
|
while true do |
|
|
|
local nlen = toint(f:read(2)) |
|
|
|
if nlen == 0 then |
|
|
|
break |
|
|
|
end |
|
|
|
local name = f:read(nlen) |
|
|
|
local fsize = toint(f:read(2) or "\0\0") |
|
|
|
f:read(fsize) |
|
|
|
for name, _, fsize in mtar.iter(f) do |
|
|
|
print(name..": "..tostring(fsize)) |
|
|
|
end |
|
|
|
f:close() |
|
|
|
elseif opts.c then |
|
|
|
local mode = (opts.r and "ab") or "wb" |
|
|
|
local f |
|
|
|
if opts.z then |
|
|
|
f = lz16.open(args[1],mode) |
|
|
|
else |
|
|
|
f = io.open(args[1],mode) |
|
|
|
end |
|
|
|
local f = open(args[1],mode) |
|
|
|
if not f then error("unable to open file") end |
|
|
|
table.remove(args,1) |
|
|
|
local fs = require "filesystem" |
|
|
@@ -122,5 +158,6 @@ Operations: |
|
|
|
t: list contents of archive |
|
|
|
Flags: |
|
|
|
v: be verbose |
|
|
|
z: use LZSS compression (requires liblz16)]]) |
|
|
|
z: use LZSS compression (requires liblz16) |
|
|
|
r: append rather than overwrite]]) |
|
|
|
end |