1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
--[[
File l3build-zip.lua Copyright (C) 2021 The LaTeX Project
It may be distributed and/or modified under the conditions of the
LaTeX Project Public License (LPPL), either version 1.3c of this
license or (at your option) any later version. The latest version
of this license is in the file
http://www.latex-project.org/lppl.txt
This file is part of the "l3build bundle" (The Work in LPPL)
and all files in that bundle must be distributed together.
-----------------------------------------------------------------------
The development version of the bundle can be found at
https://github.com/latex3/l3build
for those people who are interested.
--]]
local concat = table.concat
local open = io.open
local osdate = os.date
local pack = string.pack
local setmetatable = setmetatable
local iotype = io.type
local compress = zlib.compress
local crc32 = zlib.crc32
local function encode_time(unix)
local t = osdate('*t', unix)
local date = t.day | (t.month << 5) | ((t.year-1980) << 9)
local time = (t.sec//2) | (t.min << 5) | (t.hour << 11)
return date, time
end
local function extra_timestamp(mod, access, creation)
local flags = 0
local local_extra, central_extra = '', ''
if mod then
flags = flags | 0x1
local_extra = pack('<I4', mod)
central_extra = local_extra
end
if access then
flags = flags | 0x2
local_extra = local_extra .. pack('<I4', access)
end
if creation then
flags = flags | 0x4
local_extra = local_extra .. pack('<I4', creation)
end
if flags == 0 then return '', '' end
return pack('<c2I2B', 'UT', #central_extra + 1, flags) .. central_extra, pack('<c2I2B', 'UT', #local_extra + 1, flags) .. local_extra
end
local meta = {__index = {
add = function(z, filename, innername, binary, executable)
innername = innername or filename
local offset = z.f:seek'cur'
local content do
local f = iotype(filename) and filename or assert(open(filename, binary and 'rb' or 'r'))
content = f:read'*a'
f:close()
end
local crc32 = crc32(crc32(), content)
local compressed = compress(content, nil, nil, -15)
if #compressed >= #content then
compressed = nil
end
local timestamp = os.time()
local date, time = encode_time(timestamp)
local central_extra, local_extra = extra_timestamp(timestamp, nil, nil)
z.f:write(pack("<c4I2I2I2I2I2I4I4I4I2I2",
'PK\3\4',
compressed and 20 or 10, -- ZIP 2.0 to allow deflate
0, -- We never set flags
compressed and 8 or 0, -- Always use deflate
time,
date,
crc32,
compressed and #compressed or #content,
#content,
#innername,
#local_extra),
innername,
local_extra,
compressed or content)
local central = pack("<c4I2I2I2I2I2I2I4I4I4I2I2I2I2I2I4I4",
'PK\1\2',
(3 << 8) | 63, -- Use UNIX attributes, written against ZIP 6.3
compressed and 20 or 10, -- ZIP 2.0 to allow deflate
0, -- We never set flags
compressed and 8 or 0, -- Always use deflate
time,
date,
crc32,
compressed and #compressed or #content,
#content,
#innername,
#central_extra,
0, -- no comment
0, -- Disc 0
binary and 0 or 1,
(executable and 0x81ED--[[0100755]] or 0x81A4--[[0100644]]) << 16,
offset)
z.central[#z.central+1] = central .. innername .. central_extra
end,
close = function(z, comment)
comment = comment or ''
local offset = z.f:seek'cur'
local central = concat(z.central)
z.f:write(central, pack("<c4I2I2I2I2I4I4I2",
'PK\5\6',
0, -- This is disc 0
0, -- central dictionary started on disc 0
#z.central, -- Central disctionary entries on this disc
#z.central, -- Central disctionary entries on all discs
#central,
offset,
#comment), comment)
return z.f:close()
end,
}}
return function(filename)
local f, msg = open(filename, 'wb')
if not f then return f, msg end
return setmetatable({
f = f,
offset = 1,
central = {},
}, meta)
end
|