From 9e7d778e211148788b01a375505e80ebbd3b8da2 Mon Sep 17 00:00:00 2001 From: XeonSquared Date: Fri, 6 Mar 2020 22:10:16 +1100 Subject: [PATCH] added an mtar utility for OpenOS --- mtar/OpenOS/usr/bin/mtar.lua | 126 +++++++++++++++++++++++++++++++++++ mtar/OpenOS/usr/man/mtar | 30 +++++++++ mtar/libmtar.lua | 25 ++++--- 3 files changed, 170 insertions(+), 11 deletions(-) create mode 100644 mtar/OpenOS/usr/bin/mtar.lua create mode 100644 mtar/OpenOS/usr/man/mtar diff --git a/mtar/OpenOS/usr/bin/mtar.lua b/mtar/OpenOS/usr/bin/mtar.lua new file mode 100644 index 0000000..791da33 --- /dev/null +++ b/mtar/OpenOS/usr/bin/mtar.lua @@ -0,0 +1,126 @@ +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] [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 diff --git a/mtar/OpenOS/usr/man/mtar b/mtar/OpenOS/usr/man/mtar new file mode 100644 index 0000000..1e9132b --- /dev/null +++ b/mtar/OpenOS/usr/man/mtar @@ -0,0 +1,30 @@ +# mtar - Minitel Archiver +## Usage + + mtar -[crtxvz] [otherfile] [otherfile] + +## Operations + + x: extract archive + c: create archive + t: list contents of archive + +## Flags + + v: be verbose + z: use LZSS compression (requires liblz16)]]) + +## Examples + +Extract archive *example.mtar* + + mtar -x example.mtar + +Show the files in compressed archive *example.mtar.lss* + + mtar -tz example.mtar.lss + +Create a compressed archive *example.mtar.lss* from file *fun* and folder *junk* + + mtar -cz example.mtar.lss fun junk/ + diff --git a/mtar/libmtar.lua b/mtar/libmtar.lua index 0b54e04..fe77f82 100644 --- a/mtar/libmtar.lua +++ b/mtar/libmtar.lua @@ -20,15 +20,11 @@ local function mkdir(dir) end local function toint(s) - s=s or "" local n = 0 local i = 1 - while true do - local p = s:sub(i,i) - if p == "" then break end - local b = string.byte(p) + for p in s:gmatch(".") do n = n << 8 - n = n | b + n = n | string.byte(p) i=i+1 end return n @@ -58,17 +54,18 @@ function mtar.genHeader(fname,len) -- generate a header for file *fname* when pr return string.format("%s%s%s",cint(fname:len(),2),fname,cint(len,2)) end -function mtar.unarchive(stream,dest) +function mtar.unarchive(stream,dest,verbose) -- Extract mtar archive read from *stream* to *dest*. If *verbose*, print status. dest = dest or "." - mkdir(dest) while true do - local nlen = toint(stream:read(2)) + local nlen = toint(stream:read(2) or "\0\0") if nlen == 0 then break end local name = cleanPath(stream:read(nlen)) local fsize = toint(stream:read(2)) - print(name,fsize) + if verbose then + io.write(name.." "..tostring(fsize).."... ") + end local dir = name:match("(.+)/.*%.?.+") if (dir) then mkdir(dir) @@ -77,12 +74,18 @@ function mtar.unarchive(stream,dest) local rsize,buf = fsize, "" if f then repeat - buf = stream:read(math.min(rsize,1024)) + buf = stream:read(math.min(rsize,2048)) f:write(buf) rsize = rsize - buf:len() + if verbose then + io.write(tostring(rsize).." ") + end until rsize <= 1 f:close() end + if verbose then + print("done.") + end end end