OC-misc/mtar/OpenOS/usr/bin/mtar.lua

158 lines
3.2 KiB
Lua

local shell = require "shell"
local mtar = require "libmtar"
local fs = require "filesystem"
local args, opts = shell.parse(...)
local w, lz16 = pcall(require, "liblz16")
if not w then lz16 = nil 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
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(fn, mode)
if mode == "w" and tonumber(opts.csize) then
f.bufferSize = tonumber(opts.csize)
end
else
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 = unarchive(f,args[2] or ".",opts.v)
f:close()
elseif opts.t then
local f = open(args[1],"rb")
if not f then error("unable to open file") end
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 = open(args[1],mode)
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
inputf:close()
vp(c)
else
vp("failed to open.")
end
end
end
f:close()
else
print([[Usage:
mtar -[crtxvz] <archivefile> [otherfile] [otherfile] [--csize=blocksize]
Operations:
x: extract archive
c: create archive
t: list contents of archive
Flags:
v: be verbose
z: use LZSS compression (requires liblz16)
r: append rather than overwrite
Extended options:
csize: compression input block size]])
end