2
2
title: "REBOL 3 codec for AR files"
3
3
name: 'codec-ar
4
4
author: rights: "Oldes"
5
- version: 0.0.1
5
+ version: 0.0.2
6
6
specification: https://en.wikipedia.org/wiki/Ar_ (Unix)
7
7
history: [7-Oct-2021 "Oldes" {Initial version of the AR decoder} ]
8
8
todo: {AR encoder}
@@ -13,41 +13,72 @@ register-codec [
13
13
name: 'ar
14
14
type: 'compression
15
15
title: "Unix archive file"
16
- suffixes: [%.ar %.a ]
16
+ suffixes: [%.ar %.a %.lib ]
17
17
18
18
decode : function [
19
- {Extract content of the AR file}
19
+ {Extract content of the AR/LIB file}
20
20
data [binary! file! url! ]
21
21
return: [block! ] "Result is in format: [NAME [DATE UID GID MODE DATA] ...]"
22
22
] [
23
23
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 )" ]
25
25
unless parse data ["!<arch>^/ " data: to end][return none]
26
26
bin: binary data
27
27
out: make block! 32
28
28
29
+ long-names: none
30
+ numbers: system/catalog/bitsets/numeric
31
+
29
32
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
34
40
]
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 ][
44
61
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]
47
74
]
48
75
sys/log/info 'AR ["File:^[ [33m" pad copy file 20 mold info]
49
76
append info data
50
77
append /only append out as file! file info
78
+
79
+ if file = "//" [
80
+ long-names: data
81
+ ]
51
82
]
52
83
new-line /all out true
53
84
out
0 commit comments