Maraiah/maraiah/machdr.rs

117 lines
3.0 KiB
Rust
Raw Normal View History

2018-09-06 09:01:52 -07:00
//! Macintosh archived format header utilities.
use crate::file::SeekBackToStart;
use std::io::{SeekFrom, prelude::*};
2018-09-06 09:01:52 -07:00
2019-06-23 06:20:53 -07:00
/// Skips over an Apple Single header. Returns true if one was found.
pub fn skip_apple_single<R>(fp: &mut R) -> bool
where R: Read + Seek
2018-09-06 09:01:52 -07:00
{
let mut fp = SeekBackToStart::new(fp);
let mut magic = [0; 8];
let magic = if fp.read(&mut magic).is_ok() {magic} else {return false;};
2019-02-04 21:12:10 -08:00
// check magic numbers
if magic != [0, 5, 22, 0, 0, 2, 0, 0] {
return false;
2019-02-18 20:06:34 -08:00
}
let mut num = [0; 2];
let num = if fp.read(&mut num).is_ok() {num} else {return false;};
let num = u64::from(u16::from_be_bytes(num));
2019-02-18 20:06:34 -08:00
if fp.seek(SeekFrom::Start(26 + 12 * num)).is_err() |
fp.seek(SeekFrom::Start(26)).is_err() {
return false;
2019-02-08 21:53:27 -08:00
}
2018-09-06 09:01:52 -07:00
2019-02-04 21:12:10 -08:00
// get the resource fork (entity 1)
for _ in 0..num {
let mut ent = [0; 4];
let mut ofs = [0; 4];
let mut len = [0; 4];
let ent = if fp.read(&mut ent).is_ok() {ent} else {return false;};
let ofs = if fp.read(&mut ofs).is_ok() {ofs} else {return false;};
let len = if fp.read(&mut len).is_ok() {len} else {return false;};
let ent = u32::from_be_bytes(ent);
let ofs = u64::from(u32::from_be_bytes(ofs));
let len = u64::from(u32::from_be_bytes(len));
2018-09-06 09:01:52 -07:00
2019-02-08 21:53:27 -08:00
if ent == 1 {
if fp.seek(SeekFrom::Start(ofs + len)).is_ok() &
fp.seek(SeekFrom::Start(ofs)).is_ok() {
fp.set_seek(false);
return true;
} else {
return false;
}
2019-02-08 21:53:27 -08:00
}
2018-09-06 09:01:52 -07:00
}
2019-02-04 21:12:10 -08:00
// no resource fork
false
2018-09-06 09:01:52 -07:00
}
2019-06-23 06:20:53 -07:00
/// Skips over a Mac Binary II header. Returns true if one was found.
pub fn skip_macbin<R>(fp: &mut R) -> bool
where R: Read + Seek
2018-09-06 09:01:52 -07:00
{
let mut fp = SeekBackToStart::new(fp);
let mut head = [0; 128];
let head = if fp.read(&mut head).is_ok() {head} else {return false;};
// check legacy version, length, zero fill, and macbin2 version. I swear,
// this isn't *completely* magic
if head[0] != 0 || head[1] > 63 || head[74] != 0 || head[123] > 129 {
return false;
2019-02-08 21:53:27 -08:00
}
2018-09-06 09:01:52 -07:00
let mut crc = 0;
2019-02-04 21:12:10 -08:00
// check header crc
for &byte in head.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
if crc == u16::from_be_bytes([head[124], head[125]]) {
fp.set_seek(false);
true
2019-04-01 06:05:06 -07:00
} else {
false
2019-04-01 06:05:06 -07:00
}
2018-09-06 09:01:52 -07:00
}
2019-06-23 06:20:53 -07:00
/// Reads a `MacBin` or `AppleSingle` header if there is one and skips past it
/// from the start of the header to the resource fork (if one is found.) Returns
/// true if either one was found.
pub fn skip_mac_header<R>(fp: &mut R) -> bool
where R: Read + Seek
2018-09-06 09:01:52 -07:00
{
2019-06-23 06:20:53 -07:00
if skip_macbin(fp) {
return true;
}
let _ = fp.seek(SeekFrom::Start(0));
2019-06-23 06:20:53 -07:00
if skip_apple_single(fp) {
return true;
2019-02-08 21:53:27 -08:00
}
let _ = fp.seek(SeekFrom::Start(0));
false
2018-09-06 09:01:52 -07:00
}
// EOF