Skip to content

Commit 2ee6c0a

Browse files
committed
FEAT: improved ar codec to be able decode also System V (or GNU) variant files
1 parent 31b0832 commit 2ee6c0a

File tree

1 file changed

+50
-19
lines changed

1 file changed

+50
-19
lines changed

src/mezz/codec-ar.reb

+50-19
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ REBOL [
22
title: "REBOL 3 codec for AR files"
33
name: 'codec-ar
44
author: rights: "Oldes"
5-
version: 0.0.1
5+
version: 0.0.2
66
specification: https://en.wikipedia.org/wiki/Ar_(Unix)
77
history: [7-Oct-2021 "Oldes" {Initial version of the AR decoder}]
88
todo: {AR encoder}
@@ -13,41 +13,72 @@ register-codec [
1313
name: 'ar
1414
type: 'compression
1515
title: "Unix archive file"
16-
suffixes: [%.ar %.a]
16+
suffixes: [%.ar %.a %.lib]
1717

1818
decode: function [
19-
{Extract content of the AR file}
19+
{Extract content of the AR/LIB file}
2020
data [binary! file! url!]
2121
return: [block!] "Result is in format: [NAME [DATE UID GID MODE DATA] ...]"
2222
] [
2323
unless binary? data [data: read data]
24-
sys/log/info 'AR ["^[[1;32mDecode AR data^[[m (^[[1m" length? data "^[[mbytes )"]
24+
sys/log/info 'AR ["^[[1;32mDecode AR/LIB data^[[m (^[[1m" length? data "^[[mbytes )"]
2525
unless parse data ["!<arch>^/" data: to end][return none]
2626
bin: binary data
2727
out: make block! 32
2828

29+
long-names: none
30+
numbers: system/catalog/bitsets/numeric
31+
2932
while [58 <= length? bin/buffer][
30-
binary/read bin [
31-
file: STRING-BYTES 16
32-
info: STRING-BYTES 42
33-
end: UI16LE ;#{600A}
33+
info: binary/read bin [
34+
STRING-BYTES 16 ; File identifier
35+
STRING-BYTES 12 ; File modification timestamp
36+
STRING-BYTES 6 ; Owner ID
37+
STRING-BYTES 6 ; Group ID
38+
STRING-BYTES 8 ; File mode (type and permission)
39+
STRING-BYTES 10 ; File size in bytes
3440
]
35-
unless all [
36-
try [info: load info]
37-
end = 2656
38-
info/1: to date! info/1
39-
][ return none]
40-
41-
data: binary/read bin take/last info
42-
if parse file ["#1/" copy len to end ][
43-
; BSD variant
41+
if 2656 <> binary/read bin 'UI16LE [ ;= #{600A}
42+
sys/log/error 'AR "Invalid file header!"
43+
return none
44+
]
45+
file: trim/tail take info
46+
real: none
47+
forall info [
48+
; it may be an empty string in Windows' lib file!
49+
try/except [info/1: to integer! info/1][info/1: 0]
50+
]
51+
; convert timestamp to Rebol value (it may be -1 in *.lib files)
52+
info/1: either info/1 <= 0 [none][to date! info/1]
53+
size: take/last info
54+
data: binary/read bin size
55+
if odd? size [
56+
if 10 <> binary/read bin 'UI8 [
57+
sys/log/error 'AR "Invalid padding!"
58+
]
59+
]
60+
if parse file [opt ["#1" (bsd?: true)] #"/" copy len some numbers to end ][
4461
len: to integer! to string! len
45-
file: take/part data len ; real file name in front of the data section
46-
file: binary/read file 'string ; removes null padding
62+
case [
63+
bsd? [
64+
;- BSD variant
65+
real: take/part data len ; real file name in front of the data section
66+
real: binary/read real-name 'string ; removes null padding
67+
]
68+
long-names [
69+
;- System V (or GNU) variant
70+
binary/read long-names [ATZ :len real: STRING]
71+
]
72+
]
73+
if real [append info as file! real]
4774
]
4875
sys/log/info 'AR ["File:^[[33m" pad copy file 20 mold info]
4976
append info data
5077
append/only append out as file! file info
78+
79+
if file = "//" [
80+
long-names: data
81+
]
5182
]
5283
new-line/all out true
5384
out

0 commit comments

Comments
 (0)