diff --git a/mtar/libmtar.lua b/mtar/libmtar.lua new file mode 100644 index 0000000..0b54e04 --- /dev/null +++ b/mtar/libmtar.lua @@ -0,0 +1,89 @@ +local mtar = {} + +-- detect OS hopefully +if _OSVERSION then + if _OSVERSION:sub(1,8) == "OpenOS" then + OPENOS = true + elseif _OSVERSION:sub(1,9) == "PsychOS" then + PSYCHOS = true + end +else + LINUX = true +end + +local function mkdir(dir) + if OPENOS or LINUX then + os.execute("mkdir "..dest.."/"..dir.." &> /dev/null") + elseif PSYCHOS then + -- todo: write PsychOS support + end +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) + n = n << 8 + n = n | b + i=i+1 + end + return n +end + +local function cint(n,l) + local t={} + for i = 0, 7 do + t[i+1] = (n >> (i * 8)) & 0xFF + end + return string.reverse(string.char(table.unpack(t)):sub(1,l)) +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 mtar.genHeader(fname,len) -- generate a header for file *fname* when provided with file length *len* + return string.format("%s%s%s",cint(fname:len(),2),fname,cint(len,2)) +end + +function mtar.unarchive(stream,dest) + dest = dest or "." + mkdir(dest) + while true do + local nlen = toint(stream:read(2)) + if nlen == 0 then + break + end + local name = cleanPath(stream:read(nlen)) + local fsize = toint(stream:read(2)) + print(name,fsize) + local dir = name:match("(.+)/.*%.?.+") + if (dir) then + mkdir(dir) + end + local f = io.open(dest.."/"..name,"wb") + local rsize,buf = fsize, "" + if f then + repeat + buf = stream:read(math.min(rsize,1024)) + f:write(buf) + rsize = rsize - buf:len() + until rsize <= 1 + f:close() + end + end +end + +return mtar