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