127 lines
2.4 KiB
Lua
127 lines
2.4 KiB
Lua
|
local shell = require "shell"
|
||
|
local mtar = require "libmtar"
|
||
|
|
||
|
local args, opts = shell.parse(...)
|
||
|
|
||
|
local w, lz16 = pcall(require, "liblz16")
|
||
|
if not w then lz16 = nil end
|
||
|
|
||
|
local function toint(s)
|
||
|
s = s or "\0"
|
||
|
local n = 0
|
||
|
local i = 1
|
||
|
for p in s:gmatch(".") do
|
||
|
n = n << 8
|
||
|
n = n | string.byte(p)
|
||
|
i=i+1
|
||
|
end
|
||
|
return n
|
||
|
end
|
||
|
|
||
|
local function vw(s)
|
||
|
if opts.v and s then
|
||
|
io.write(tostring(s))
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function vp(...)
|
||
|
for k,v in ipairs({...}) do
|
||
|
vw(tostring(v).."\n")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if opts.x then
|
||
|
local f
|
||
|
if opts.z then
|
||
|
f = lz16.open(args[1],"rb")
|
||
|
else
|
||
|
f = io.open(args[1],"rb")
|
||
|
end
|
||
|
if not f then error("unable to open file") end
|
||
|
local w, r = mtar.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
|
||
|
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)
|
||
|
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
|
||
|
if not f then error("unable to open file") end
|
||
|
table.remove(args,1)
|
||
|
local fs = require "filesystem"
|
||
|
for k,v in pairs(args) do
|
||
|
local ap = true
|
||
|
if v:sub(1,1) ~= "/" then
|
||
|
ap = false
|
||
|
v = os.getenv("PWD") .. "/" .. v
|
||
|
end
|
||
|
v=fs.canonical(v)
|
||
|
vw(v.."... ")
|
||
|
if fs.isDirectory(v) then
|
||
|
vp("directory.")
|
||
|
for file in fs.list(v) do
|
||
|
if ap then
|
||
|
args[#args+1] = v.."/"..file
|
||
|
else
|
||
|
args[#args+1] = v:sub(os.getenv("PWD"):len()+2).."/"..file
|
||
|
end
|
||
|
end
|
||
|
else
|
||
|
local fsize = fs.size(v)
|
||
|
local inputf = io.open(v,"rb")
|
||
|
if fsize and inputf then
|
||
|
local c = 0
|
||
|
if ap then
|
||
|
f:write(mtar.genHeader(v,fsize))
|
||
|
else
|
||
|
f:write(mtar.genHeader(v:sub(os.getenv("PWD"):len()+2),fsize))
|
||
|
end
|
||
|
while true do
|
||
|
local ib = inputf:read(4096)
|
||
|
if ib then
|
||
|
c=c+ib:len()
|
||
|
f:write(ib)
|
||
|
else
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
vp(c)
|
||
|
else
|
||
|
vp("failed to open.")
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
f:close()
|
||
|
else
|
||
|
print([[Usage:
|
||
|
mtar -[crtxvz] <archivefile> [otherfile] [otherfile]
|
||
|
Operations:
|
||
|
x: extract archive
|
||
|
c: create archive
|
||
|
t: list contents of archive
|
||
|
Flags:
|
||
|
v: be verbose
|
||
|
z: use LZSS compression (requires liblz16)]])
|
||
|
end
|