util-tar.lua /size: 10 Kb    last modification: 2021-10-28 13:50
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
util-tar
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to luat-lib.mkiv
"
,
4
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
5
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
6
license
=
"
see context related readme files
"
7
}
8 9
local
type
,
tonumber
=
type
,
tonumber
10
local
gsub
,
escapedpattern
=
string
.
gsub
,
string
.
escapedpattern
11
local
nameonly
,
dirname
,
makedirs
=
file
.
nameonly
,
file
.
dirname
,
dir
.
makedirs
12
local
savedata
=
io
.
savedata
13
local
newreader
=
io
.
newreader
14 15
local
report
=
logs
.
reporter
(
"
tar
"
)
16 17
local
types
=
{
18
[
"
0
"
]
=
"
file
"
,
19
[
"
\0
"
]
=
"
regular
"
,
20
[
"
1
"
]
=
"
link
"
,
21
[
"
2
"
]
=
"
symbolic
"
,
-- reserved
22
[
"
3
"
]
=
"
character
"
,
23
[
"
4
"
]
=
"
block
"
,
24
[
"
5
"
]
=
"
directory
"
,
25
[
"
6
"
]
=
"
fifo
"
,
26
[
"
7
"
]
=
"
continuation
"
,
-- reserved
27
[
"
x
"
]
=
"
extended
"
,
-- header
28
}
29 30
local
function
asstring
(
str
)
31
return
str
and
gsub
(
str
,
"
[\0 ]+$
"
,
"
"
)
or
nil
32
end
33 34
local
function
asnumber
(
str
)
35
str
=
gsub
(
str
,
"
\0$
"
,
"
"
)
36
return
tonumber
(
str
,
8
)
37
end
38 39
local
function
opentar
(
whatever
,
filename
)
40
local
f
=
newreader
(
filename
,
whatever
)
41
if
f
then
42
f
.
metadata
=
{
43
nofpaths
=
0
,
44
noffiles
=
0
,
45
noflinks
=
0
,
46
nofbytes
=
0
,
47
}
48
return
f
49
end
50
end
51 52
local
function
readheader
(
t
)
53
-- checksum
54
local
p
=
t
:
getposition
(
)
55
local
h
=
t
:
readbytetable
(
512
)
56
t
:
setposition
(
p
)
57
for
i
=
149
,
156
do
-- nasty, one less
58
h
[
i
]
=
0
59
end
60
local
c
=
256
61
for
i
=
1
,
512
do
62
c
=
c
+
h
[
i
]
63
end
64
--
65
local
header
=
{
66
name
=
asstring
(
t
:
readstring
(
100
)
)
,
-- 0
67
mode
=
asnumber
(
t
:
readstring
(
8
)
)
,
-- 100 -- when we write: 0775 octal
68
uid
=
asnumber
(
t
:
readstring
(
8
)
)
,
-- 108
69
gid
=
asnumber
(
t
:
readstring
(
8
)
)
,
-- 116
70
size
=
asnumber
(
t
:
readstring
(
12
)
)
,
-- 124
71
mtime
=
asnumber
(
t
:
readstring
(
12
)
)
,
-- 136
72
checksum
=
asnumber
(
t
:
readstring
(
6
)
)
,
-- 148 -- actually 6 with space and \0
73
dummy
=
t
:
skip
(
2
)
,
74
typeflag
=
t
:
readstring
(
1
)
,
-- 156
75
linkname
=
asstring
(
t
:
readstring
(
100
)
)
,
-- 157
76
-- magic = asstring(t:readstring( 6)), -- 257 -- ustar\0
77
-- version = 2 -- 263
78
-- uname = 32 -- 265
79
-- gname = 32 -- 297
80
-- devmajor = 8 -- 329
81
-- devminor = 8 -- 337
82
-- prefix = 155 -- 345
83
padding
=
t
:
skip
(
255
)
,
-- 500
84
}
85
local
typeflag
=
header
.
typeflag
86
if
typeflag
then
87
header
.
filetype
=
types
[
typeflag
]
88
if
c
=
=
header
.
checksum
then
89
return
header
90
end
91
end
92
end
93 94
local
readers
=
{
95 96
directory
=
function
(
t
,
h
)
97
local
metadata
=
t
.
metadata
98
local
filename
=
h
.
name
99
if
metadata
.
verbose
then
100
report
(
"
%8s %s
"
,
"
"
,
filename
)
101
end
102
metadata
.
nofpaths
=
metadata
.
nofpaths
+
1
103
return
true
104
end
,
105 106
file
=
function
(
t
,
h
)
107
local
metadata
=
t
.
metadata
108
local
filename
=
h
.
name
109
local
filesize
=
h
.
size
110
local
pathname
=
dirname
(
filename
)
111
if
metadata
.
verbose
then
112
report
(
"
% 8i : %s
"
,
filesize
,
filename
)
113
end
114
if
makedirs
(
pathname
)
then
115
savedata
(
filename
,
t
:
readstring
(
filesize
)
)
116
else
117
t
.
skip
(
filesize
)
118
end
119
local
position
=
t
:
getposition
(
)
120
local
target
=
position
+
(
512
-
position
%
512
)
%
512
121
t
:
setposition
(
target
)
122
metadata
.
noffiles
=
metadata
.
noffiles
+
1
123
metadata
.
nofbytes
=
metadata
.
nofbytes
+
filesize
124
return
true
125
end
,
126 127
symbolic
=
function
(
t
,
h
)
128
local
metadata
=
t
.
metadata
129
local
filename
=
h
.
name
130
local
linkname
=
h
.
linkname
131
if
metadata
.
verbose
then
132
report
(
"
%8s %s => %s
"
,
"
"
,
linkname
,
filename
)
133
end
134
metadata
.
noflinks
=
metadata
.
noflinks
+
1
135
return
true
136
end
,
137 138
}
139 140
local
skippers
=
{
141 142
directory
=
function
(
t
,
h
)
143
return
true
144
end
,
145 146
file
=
function
(
t
,
h
)
147
local
filesize
=
h
.
size
148
local
fileoffset
=
t
:
getposition
(
)
149
local
position
=
filesize
+
fileoffset
150
local
target
=
position
+
(
512
-
position
%
512
)
%
512
151
t
:
setposition
(
target
)
152
return
fileoffset
153
end
,
154 155
symbolic
=
function
(
t
,
h
)
156
return
true
157
end
,
158 159
}
160 161
local
writers
=
{
162
-- nothing here (yet)
163
}
164 165
local
function
saveheader
(
t
,
h
)
166
local
filetype
=
h
.
filetype
167
local
reader
=
readers
[
filetype
]
168
if
reader
then
169
return
filetype
,
reader
(
t
,
h
)
170
else
171
report
(
"
no reader for %s
"
,
filetype
)
172
end
173
end
174 175
local
function
skipheader
(
t
,
h
)
176
local
filetype
=
h
.
filetype
177
local
skipper
=
skippers
[
filetype
]
178
if
skipper
then
179
return
filetype
,
skipper
(
t
,
h
)
180
else
181
report
(
"
no skipper for %s
"
,
filetype
)
182
end
183
end
184 185
local
function
unpacktar
(
whatever
,
filename
,
verbose
)
186
local
t
=
opentar
(
whatever
,
filename
)
187
if
t
then
188
local
metadata
=
t
.
metadata
189
statistics
.
starttiming
(
metadata
)
190
if
verbose
then
191
if
whatever
=
=
"
string
"
then
192
report
(
"
unpacking: %i bytes
"
,
#
filename
)
193
else
194
report
(
"
unpacking: %s
"
,
filename
)
195
end
196
report
(
"
"
)
197
metadata
.
verbose
=
verbose
198
end
199
while
true
do
200
local
h
=
readheader
(
t
)
201
if
not
h
then
202
break
203
else
204
local
filetype
,
saved
=
saveheader
(
t
,
h
)
205
if
not
saved
then
206
break
207
end
208
end
209
end
210
statistics
.
stoptiming
(
metadata
)
211
metadata
.
runtime
=
statistics
.
elapsed
(
metadata
)
212
if
verbose
then
213
report
(
"
"
)
214
report
(
"
number of paths : %i
"
,
metadata
.
nofpaths
)
215
report
(
"
number of files : %i
"
,
metadata
.
noffiles
)
216
report
(
"
number of links : %i
"
,
metadata
.
noflinks
)
217
report
(
"
number of bytes : %i
"
,
metadata
.
nofbytes
)
218
report
(
"
"
)
219
report
(
"
runtime needed : %s
"
,
statistics
.
elapsedseconds
(
metadata
)
)
220
report
(
"
"
)
221
end
222
t
.
close
(
)
223
return
metadata
224
end
225
end
226 227
local
function
listtar
(
whatever
,
filename
,
onlyfiles
)
228
local
t
=
opentar
(
whatever
,
filename
)
229
if
t
then
230
local
list
,
n
=
{
}
,
0
231
while
true
do
232
local
h
=
readheader
(
t
)
233
if
not
h
then
234
break
235
else
236
local
filetype
,
offset
=
skipheader
(
t
,
h
)
237
if
not
offset
then
238
break
239
elseif
filetype
=
=
"
file
"
then
240
n
=
n
+
1
;
list
[
n
]
=
{
filetype
,
h
.
name
,
h
.
size
}
241
elseif
filetype
=
=
"
link
"
then
242
n
=
n
+
1
;
list
[
n
]
=
{
filetype
,
h
.
name
,
h
.
linkfile
}
243
elseif
not
onlyfiles
then
244
n
=
n
+
1
;
list
[
n
]
=
{
filetype
,
h
.
name
}
245
end
246
end
247
end
248
t
.
close
(
)
249
-- can be an option
250
table
.
sort
(
list
,
function
(
a
,
b
)
return
a
[
2
]
<
b
[
2
]
end
)
251
return
list
252
end
253
end
254 255
local
function
hashtar
(
whatever
,
filename
,
strip
)
256
local
t
=
opentar
(
whatever
,
filename
)
257
if
t
then
258
local
list
=
{
}
259
if
strip
then
260
strip
=
"
^
"
.
.
escapedpattern
(
nameonly
(
nameonly
(
strip
)
)
)
.
.
"
/
"
261
end
262
while
true
do
263
local
h
=
readheader
(
t
)
264
if
not
h
then
265
break
266
else
267
local
filetype
,
offset
=
skipheader
(
t
,
h
)
268
if
not
offset
then
269
break
270
else
271
local
name
=
h
.
name
272
if
strip
then
273
name
=
gsub
(
name
,
strip
,
"
"
)
274
end
275
if
filetype
=
=
"
file
"
then
276
list
[
name
]
=
{
offset
,
h
.
size
}
277
elseif
filetype
=
=
"
link
"
then
278
list
[
name
]
=
h
.
linkname
279
end
280
end
281
end
282
end
283
t
.
close
(
)
284
return
list
285
end
286
end
287 288
-- weak table ?
289 290
local
function
fetchtar
(
whatever
,
archive
,
filename
,
list
)
291
if
not
list
then
292
list
=
hashtar
(
whatever
,
archive
)
293
end
294
if
list
then
295
local
what
=
list
[
filename
]
296
if
type
(
what
)
=
=
"
string
"
then
297
what
=
list
[
what
]
-- a link
298
end
299
if
what
then
300
local
t
=
opentar
(
whatever
,
archive
)
301
if
t
then
302
t
:
setposition
(
what
[
1
]
)
303
return
t
:
readstring
(
what
[
2
]
)
304
end
305
end
306
end
307
end
308 309
local
function
packtar
(
whatever
,
filename
,
verbose
)
310
report
(
"
packing will be implemented when we need it
"
)
311
end
312 313
local
tar
=
{
314
files
=
{
315
unpack
=
function
(
...
)
return
unpacktar
(
"
file
"
,
...
)
end
,
316
pack
=
function
(
...
)
return
packtar
(
"
file
"
,
...
)
end
,
317
list
=
function
(
...
)
return
listtar
(
"
file
"
,
...
)
end
,
318
hash
=
function
(
...
)
return
hashtar
(
"
file
"
,
...
)
end
,
319
fetch
=
function
(
...
)
return
fetchtar
(
"
file
"
,
...
)
end
,
320
}
,
321
strings
=
{
322
unpack
=
function
(
...
)
return
unpacktar
(
"
string
"
,
...
)
end
,
323
pack
=
function
(
...
)
return
packtar
(
"
string
"
,
...
)
end
,
324
list
=
function
(
...
)
return
listtar
(
"
string
"
,
...
)
end
,
325
hash
=
function
(
...
)
return
hashtar
(
"
string
"
,
...
)
end
,
326
fetch
=
function
(
...
)
return
fetchtar
(
"
string
"
,
...
)
end
,
327
}
,
328
streams
=
{
329
unpack
=
function
(
...
)
return
unpacktar
(
"
stream
"
,
...
)
end
,
330
pack
=
function
(
...
)
return
packtar
(
"
stream
"
,
...
)
end
,
331
list
=
function
(
...
)
return
listtar
(
"
stream
"
,
...
)
end
,
332
hash
=
function
(
...
)
return
hashtar
(
"
stream
"
,
...
)
end
,
333
fetch
=
function
(
...
)
return
fetchtar
(
"
stream
"
,
...
)
end
,
334
}
,
335
}
336 337
utilities
.
tar
=
tar
338 339
-- tar.files .unpack("e:/luatex/luametatex-source.tar",true)
340
-- tar.streams.unpack("e:/luatex/luametatex-source.tar",true)
341
-- tar.strings.unpack(io.loaddata("e:/luatex/luametatex-source.tar"),true)
342 343
-- inspect(tar.files .unpack("e:/luatex/luametatex-source.tar"))
344
-- inspect(tar.streams.unpack("e:/luatex/luametatex-source.tar"))
345
-- inspect(tar.strings.unpack(io.loaddata("e:/luatex/luametatex-source.tar")))
346 347
-- inspect(tar.files .list("e:/luatex/luametatex-source.tar",true))
348
-- inspect(tar.streams.list("e:/luatex/luametatex-source.tar",true))
349
-- inspect(tar.strings.list(io.loaddata("e:/luatex/luametatex-source.tar"),true))
350 351
-- local c = os.clock()
352
-- local l = tar.files.hash("e:/luatex/luametatex-source.tar")
353
-- for i=1,500 do
354
-- local s = tar.files.fetch("e:/luatex/luametatex-source.tar", "luametatex-source/source/tex/texbuildpage.c", l)
355
-- local s = tar.files.fetch( "e:/luatex/luametatex-source.tar","luametatex-source/source/lua/lmtlibrary.c", l)
356
-- end
357
-- print(os.clock()-c)
358 359
return
tar
360