Skip to content

Commit 519ef00

Browse files
committed
Add output directory parameter to unzip function.
1 parent 4aa7772 commit 519ef00

1 file changed

Lines changed: 34 additions & 16 deletions

File tree

arch/UNZIP.LUA

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,21 @@ end
2727

2828
---Unzips a ZIP archive file, extracting its contents to the local directory.
2929
---Always supports store. Deflate is supported if the 'INFLATE' module can be found.
30-
---@param p string The path to the ZIP file to extract.
31-
function unzip(p)
32-
33-
-- C = read chunk size
34-
-- f = file
35-
local C, f = 4096
36-
f, E = io.open(p, "rb") D()
30+
---@param z string The path to the ZIP file to extract.
31+
---@param d string The path to extract files to.
32+
function unzip(z, d)
33+
34+
-- C = Read chunk size
35+
-- v = System path seperator/Version needed
36+
-- f = File
37+
local C, v, f = 4096, package.config:sub(1, 1)
38+
f, E = io.open(z, "rb") D()
39+
if not d then d = "." end
40+
if d:sub(-1) ~= v then d = d .. v end
3741

3842
while true do
3943

4044
-- s = Signature
41-
-- v = Version needed
4245
-- fl = Flags
4346
-- cm = Compression method
4447
-- cr = Calculated crc32 checksum
@@ -50,17 +53,34 @@ function unzip(p)
5053
-- of = Output file
5154
-- re = Remaining bytes
5255
-- ec = Expected crc32 checksum
53-
local s, v, fl, cm, cr, cs, us, nl, el, fn, di, of, re, ec = f:read(30)
56+
local s, fl, cm, cr, cs, us, nl, el, fn, di, of, re, ec = f:read(30)
5457
if not s or #s < 30 or not s:find("^PK\3\4") then break end
5558
v, fl, cm, _, _, ec, cs, us, nl, el = string.unpack("<HHHHHIIIHH", s, 5)
5659

5760
fn, E = f:read(nl) D() -- read the filename
5861
if el > 0 then f:seek("cur", el) end
5962

60-
print("Extracting: " .. fn)
61-
6263
re = cs
6364

65+
---Create all required directories in a path up to a file.
66+
---@param p string The path to a file to create directories for.
67+
---@return string The created directory.
68+
local function M(p)
69+
70+
-- e = path seperator
71+
-- c = current path
72+
local e, c, t = package.config:sub(1, 1), "", {}
73+
74+
p = p:gsub("[\\/]", e) -- Normalize separators to the current OS
75+
for i in p:gmatch("[^" .. e .. "]+") do table.insert(t, i) end
76+
77+
-- i = directory
78+
for i = 1, #t - 1 do
79+
c = c == "" and t[i] or c .. e .. t[i]
80+
os.execute('mkdir "' .. c .. '" ' .. (e == "\\" and '>nul 2>nul' or '>/dev/null 2>&1'))
81+
end
82+
end
83+
6484
---Read compressed data in chunks
6585
local function R()
6686
if re <= 0 then return nil end
@@ -72,13 +92,11 @@ function unzip(p)
7292
end
7393

7494
-- Setup output file
75-
di = fn:match("(.+)/")
76-
if di and os.execute then
77-
--TODO: DOS friendly version
78-
os.execute('mkdir -p "'.. di ..'"')
79-
end
95+
fn = d .. fn -- Prepend target directory
96+
M(fn) -- Create directory
8097

8198
of, E = io.open(fn, "wb") D()
99+
print("Extracting: " .. fn)
82100

83101
if of then
84102
---Write decompressed data and update CRC

0 commit comments

Comments
 (0)