Maraiah/maraiah/machdr.rs

79 lines
1.8 KiB
Rust
Raw Normal View History

2018-09-06 09:01:52 -07:00
//! Macintosh archived format header utilities.
2019-06-13 18:09:07 -07:00
use crate::bin::*;
2018-09-06 09:01:52 -07:00
2019-02-24 20:34:59 -08:00
/// Checks for an `AppleSingle` header. Returns offset to the resource fork.
2018-09-11 12:07:42 -07:00
pub fn check_apple_single(b: &[u8]) -> Option<usize>
2018-09-06 09:01:52 -07:00
{
2019-02-04 21:12:10 -08:00
// check magic numbers
2019-02-18 20:06:34 -08:00
if b.len() < 26 || *b.get(0..8)? != [0, 5, 22, 0, 0, 2, 0, 0] {
return None;
}
2019-03-02 18:31:00 -08:00
let num = usize::from(u16b(&b[24..]));
2019-02-18 20:06:34 -08:00
if b.len() < 26 + 12 * num {
2019-02-08 21:53:27 -08:00
return None;
}
2018-09-06 09:01:52 -07:00
2019-02-04 21:12:10 -08:00
// get the resource fork (entity 1)
2018-12-10 23:32:59 -08:00
for i in 0..num {
2019-02-04 21:12:10 -08:00
let p = 26 + 12 * i;
2019-02-18 20:06:34 -08:00
let ent = u32b(&b[p..]);
2019-03-02 18:31:00 -08:00
let ofs = usize_from_u32(u32b(&b[p + 4..]));
let len = usize_from_u32(u32b(&b[p + 8..]));
2018-09-06 09:01:52 -07:00
2019-02-08 21:53:27 -08:00
if ent == 1 {
return if ofs + len > b.len() {None} else {Some(ofs)};
}
2018-09-06 09:01:52 -07:00
}
2019-02-04 21:12:10 -08:00
// no resource fork
2018-09-11 12:07:42 -07:00
None
2018-09-06 09:01:52 -07:00
}
2019-02-24 20:34:59 -08:00
/// Checks for a `MacBinary II` header. Returns offset to the resource fork.
2019-02-04 21:12:10 -08:00
pub fn check_macbin(b: &[u8]) -> Option<usize>
2018-09-06 09:01:52 -07:00
{
2019-02-04 21:12:10 -08:00
// check legacy version, length, zero fill, and macbin2 version
2019-03-04 02:18:57 -08:00
// I swear this isn't *completely* magic
2019-02-10 02:31:57 -08:00
if b.len() < 128 || b[0] != 0 || b[1] > 63 || b[74] != 0 || b[123] > 129 {
2019-02-08 21:53:27 -08:00
return None;
}
2018-09-06 09:01:52 -07:00
let mut crc = 0;
2019-02-04 21:12:10 -08:00
// check header crc
2019-02-13 21:19:36 -08:00
for &byte in b.iter().take(124) {
2018-12-10 23:32:59 -08:00
for j in 8..16 {
2019-02-13 21:19:36 -08:00
let d = u16::from(byte) << j;
2019-03-04 02:18:57 -08:00
2019-02-24 20:34:59 -08:00
if (d ^ crc) & 0x8000 == 0 {
2019-02-08 21:53:27 -08:00
crc <<= 1;
2019-02-24 20:34:59 -08:00
} else {
crc = crc << 1 ^ 0x1021;
2019-02-08 21:53:27 -08:00
}
2018-09-06 09:01:52 -07:00
}
}
2019-02-04 21:12:10 -08:00
// if ok, resource fork follows
2019-04-01 06:05:06 -07:00
if crc == u16b(&b[124..]) {
Some(128)
} else {
None
}
2018-09-06 09:01:52 -07:00
}
2019-02-24 20:34:59 -08:00
/// Reads a `MacBin` or `AppleSingle` header if there is one and returns the
2018-09-06 09:01:52 -07:00
/// offset from the start of the header to the resource fork (if one is found.)
pub fn try_mac_header(b: &[u8]) -> usize
{
2019-02-08 21:53:27 -08:00
if let Some(ofs) = check_macbin(b) {
ofs
} else {
check_apple_single(b).unwrap_or(0)
}
2018-09-06 09:01:52 -07:00
}
// EOF