77 lines
1.7 KiB
Rust
77 lines
1.7 KiB
Rust
|
//! Macintosh archived format header utilities.
|
||
|
|
||
|
use crate::durandal::bin::*;
|
||
|
|
||
|
/// Checks for an `AppleSingle` header. Returns offset to the resource fork.
|
||
|
pub fn check_apple_single(b: &[u8]) -> Option<usize>
|
||
|
{
|
||
|
// check magic numbers
|
||
|
if b.len() < 26 || *b.get(0..8)? != [0, 5, 22, 0, 0, 2, 0, 0] {
|
||
|
return None;
|
||
|
}
|
||
|
|
||
|
let num = u16b(&b[24..]) as usize;
|
||
|
|
||
|
if b.len() < 26 + 12 * num {
|
||
|
return None;
|
||
|
}
|
||
|
|
||
|
// get the resource fork (entity 1)
|
||
|
for i in 0..num {
|
||
|
let p = 26 + 12 * i;
|
||
|
let ent = u32b(&b[p..]);
|
||
|
let ofs = u32b(&b[p + 4..]) as usize;
|
||
|
let len = u32b(&b[p + 8..]) as usize;
|
||
|
|
||
|
if ent == 1 {
|
||
|
return if ofs + len > b.len() {None} else {Some(ofs)};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// no resource fork
|
||
|
None
|
||
|
}
|
||
|
|
||
|
/// Checks for a `MacBinary II` header. Returns offset to the resource fork.
|
||
|
pub fn check_macbin(b: &[u8]) -> Option<usize>
|
||
|
{
|
||
|
// check legacy version, length, zero fill, and macbin2 version
|
||
|
if b.len() < 128 || b[0] != 0 || b[1] > 63 || b[74] != 0 || b[123] > 129 {
|
||
|
return None;
|
||
|
}
|
||
|
|
||
|
let mut crc = 0;
|
||
|
|
||
|
// check header crc
|
||
|
for &byte in b.iter().take(124) {
|
||
|
for j in 8..16 {
|
||
|
let d = u16::from(byte) << j;
|
||
|
if (d ^ crc) & 0x8000 == 0 {
|
||
|
crc <<= 1;
|
||
|
} else {
|
||
|
crc = crc << 1 ^ 0x1021;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if ok, resource fork follows
|
||
|
if crc == u16b(&b[124..]) {
|
||
|
Some(128)
|
||
|
} else {
|
||
|
None
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Reads a `MacBin` or `AppleSingle` header if there is one and returns the
|
||
|
/// offset from the start of the header to the resource fork (if one is found.)
|
||
|
pub fn try_mac_header(b: &[u8]) -> usize
|
||
|
{
|
||
|
if let Some(ofs) = check_macbin(b) {
|
||
|
ofs
|
||
|
} else {
|
||
|
check_apple_single(b).unwrap_or(0)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// EOF
|