Skip to content

Commit

Permalink
FEAT: improved ar codec to be able decode also System V (or GNU) va…
Browse files Browse the repository at this point in the history
…riant files
  • Loading branch information
Oldes committed Oct 7, 2021
1 parent 31b0832 commit 2ee6c0a
Showing 1 changed file with 50 additions and 19 deletions.
69 changes: 50 additions & 19 deletions src/mezz/codec-ar.reb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ REBOL [
title: "REBOL 3 codec for AR files"
name: 'codec-ar
author: rights: "Oldes"
version: 0.0.1
version: 0.0.2
specification: https://en.wikipedia.org/wiki/Ar_(Unix)
history: [7-Oct-2021 "Oldes" {Initial version of the AR decoder}]
todo: {AR encoder}
Expand All @@ -13,41 +13,72 @@ register-codec [
name: 'ar
type: 'compression
title: "Unix archive file"
suffixes: [%.ar %.a]
suffixes: [%.ar %.a %.lib]

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

long-names: none
numbers: system/catalog/bitsets/numeric

while [58 <= length? bin/buffer][
binary/read bin [
file: STRING-BYTES 16
info: STRING-BYTES 42
end: UI16LE ;#{600A}
info: binary/read bin [
STRING-BYTES 16 ; File identifier
STRING-BYTES 12 ; File modification timestamp
STRING-BYTES 6 ; Owner ID
STRING-BYTES 6 ; Group ID
STRING-BYTES 8 ; File mode (type and permission)
STRING-BYTES 10 ; File size in bytes
]
unless all [
try [info: load info]
end = 2656
info/1: to date! info/1
][ return none]

data: binary/read bin take/last info
if parse file ["#1/" copy len to end ][
; BSD variant
if 2656 <> binary/read bin 'UI16LE [ ;= #{600A}
sys/log/error 'AR "Invalid file header!"
return none
]
file: trim/tail take info
real: none
forall info [
; it may be an empty string in Windows' lib file!
try/except [info/1: to integer! info/1][info/1: 0]
]
; convert timestamp to Rebol value (it may be -1 in *.lib files)
info/1: either info/1 <= 0 [none][to date! info/1]
size: take/last info
data: binary/read bin size
if odd? size [
if 10 <> binary/read bin 'UI8 [
sys/log/error 'AR "Invalid padding!"
]
]
if parse file [opt ["#1" (bsd?: true)] #"/" copy len some numbers to end ][
len: to integer! to string! len
file: take/part data len ; real file name in front of the data section
file: binary/read file 'string ; removes null padding
case [
bsd? [
;- BSD variant
real: take/part data len ; real file name in front of the data section
real: binary/read real-name 'string ; removes null padding
]
long-names [
;- System V (or GNU) variant
binary/read long-names [ATZ :len real: STRING]
]
]
if real [append info as file! real]
]
sys/log/info 'AR ["File:^[[33m" pad copy file 20 mold info]
append info data
append/only append out as file! file info

if file = "//" [
long-names: data
]
]
new-line/all out true
out
Expand Down

0 comments on commit 2ee6c0a

Please # to comment.