@@ -31,7 +31,10 @@ local function nbs(data)
3131 -- s = skip
3232 local function s (n ) p = p + n end
3333
34- return { r = rb , a = ab , p = p , s = s }
34+ -- TODO: inflate() currently expects bs.p() callable, change that
35+ local function gp () return p end
36+
37+ return { r = rb , a = ab , p = gp , s = s }
3538end
3639
3740-- rv = revbits
@@ -261,46 +264,90 @@ local function crc32(s)
261264 return c ~ x
262265end
263266
264- local function le16 (s , i ) local a ,b = s :byte (i ,i + 1 ) return a + b * 256 end
265- local function le32 (s , i ) local a ,b ,c ,d = s :byte (i , i + 3 ) return a + b * 256 + c * 65536 + d * 16777216 end
266-
267267local function unzip (path )
268268
269+ -- C = read chunk size
269270 -- f = file
270- -- d = data (or error string string if file can't be opened)
271- -- p = position
272- local f , d , p = io.open (path , " rb" )
273- if d then print (d ) os.exit (1 ) end
274- d , p = f :read (" *a" ), 1 f :close ()
271+ local C , f = 4096
272+
273+ f , E = io.open (path , " rb" )
274+ if E then print (E ) os.exit (1 ) end
275+
276+ -- R = read bytes
277+ local function R (n )
278+ local s , E = f :read (n )
279+ if E then print (E ) os.exit (1 ) end
280+ return s
281+ end
282+
283+ local function S (n ) f :seek (" cur" , n ) end
284+
285+ local function le16 () local a , b = R (2 ):byte (1 , 2 ) return a + b * 256 end
286+ local function le32 () local a , b , c , d = R (4 ):byte (1 , 4 ) return a + b * 256 + c * 65536 + d * 16777216 end
287+
288+ -- RB = read n bytes chunked
289+ local function RB (n )
290+
291+ -- p = parts
292+ -- g = got
293+ -- w = want
294+ -- d = data
295+ local p , g , w , d = {}, 0
296+
297+ while g < n do
298+ w = math.min (C , n - g )
299+ d , E = R (w )
300+ if E then return nil , E end
301+ p [# p + 1 ] = d
302+ g = g + # d
303+ end
304+
305+ return table.concat (p )
306+ end
275307
276308 while true do
277- if d :sub (p , p + 3 ) ~= " PK\3\4 " then break end
278309
279- -- _ = version needed
280- -- _ = flags
281- -- cm = cm
310+ -- s = signature
311+ -- v = version needed
312+ -- fl = flags
313+ -- cm = method
282314 -- cr = Expected crc32 checksum
283315 -- cs = Compressed size
284316 -- us = Uncompressed size
285317 -- nl = Length of file name
286318 -- el = Extra length in the file name
287- local _ , _ , cm , cr , cs , us , nl , el = le16 (d , p + 4 ), le16 (d , p + 6 ), le16 (d , p + 8 ), le32 (d , p + 14 ), le32 (d , p + 18 ), le32 (d , p + 22 ), le16 (d , p + 26 ), le16 (d , p + 28 )
288-
289- -- fn = The filename
290- -- st = The file Start offset
291- local fn , st = d :sub (p + 30 , p + 29 + nl ), p + 30 + nl + el
292-
293319 -- cd = A buffer of the files data
294320 -- os = The output stream
295- local cd , os = d :sub (st , st + cs - 1 )
321+ local s , v , fl , cm , ok , cr , cs , us , nl , el , fn , cd , os = f :read (4 )
322+ if not s or # s < 4 then break end
323+ if s ~= " PK\3\4 " then break end
324+
325+ v , E = le16 () if not v then break end -- version
326+ fl , E = le16 () if not fl then break end -- flags
327+ cm , E = le16 () if not cm then break end -- method
328+ S (4 ) -- modification time and date
329+ cr , E = le32 () if not cr then break end -- crc32
330+ cs , E = le32 () if not cs then break end -- compressed size
331+ us , E = le32 () if not us then break end -- uncompressed size
332+ nl , E = le16 () if not nl then break end -- name length
333+ el , E = le16 () if not el then break end -- extra name length
334+
335+ fn , E = R (nl ) if not fn then break end -- filename
336+ if el > 0 then S (el ) end
296337
297338 print (" Extracting: " .. fn )
298339
340+ cd , E = RB (cs )
341+ if not cd then
342+ print (e )
343+ break
344+ end
345+
299346 if cm == 0 then
300347 -- no compression
301348 os = cd
302349 elseif cm == 8 then
303- -- deflate
350+ -- deflate (still in-memory per entry)
304351 os = inflate (cd )
305352 else
306353 -- unsupported compression
@@ -325,16 +372,16 @@ local function unzip(path)
325372 end
326373 end
327374
328- of , di = io.open (fn , " wb" )
329- if di then
330- print (di )
375+ of , E = io.open (fn , " wb" )
376+ if not of then
377+ print (E )
331378 else
332379 of :write (os ) of :close ()
333380 end
334381 end
335-
336- p = st + cs
337382 end
383+
384+ f :close ()
338385end
339386
340387if # arg < 1 then
0 commit comments