mod error;
mod write;
use crate::{bail, ensure, err};
pub use write::GnuBuilder;
const GLOBAL_HEADER_LEN: usize = 8;
const GLOBAL_HEADER: &[u8; GLOBAL_HEADER_LEN] = b"!<arch>\n";
const GNU_NAME_TABLE_ID: &str = "//";
const GNU_SYMBOL_LOOKUP_TABLE_ID: &str = "/";
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Header {
identifier: Vec<u8>,
mtime: u64,
uid: u32,
gid: u32,
mode: u32,
size: u64,
}
impl Header {
pub fn new(identifier: Vec<u8>, size: u64) -> Header {
Header {
identifier,
mtime: 0,
uid: 0,
gid: 0,
mode: 0o644,
size,
}
}
pub fn identifier(&self) -> &[u8] {
&self.identifier
}
pub fn set_mode(&mut self, mode: u32) {
self.mode = mode;
}
pub fn size(&self) -> u64 {
self.size
}
pub fn validate(&self) -> std::io::Result<()> {
ensure!(
num_digits(self.mtime, 10) <= 12,
"MTime `{}` > 12 digits",
self.mtime
);
ensure!(
num_digits(self.uid, 10) <= 6,
"UID `{}` > 6 digits",
self.uid
);
ensure!(
num_digits(self.gid, 10) <= 6,
"GID `{}` > 6 digits",
self.gid
);
ensure!(
num_digits(self.mode, 8) <= 8,
"Mode `{:o}` > 8 octal digits",
self.mode
);
Ok(())
}
}
#[inline]
fn num_digits<N: Into<u64>>(val: N, radix: u64) -> u64 {
let mut val = val.into();
if val == 0 {
return 1;
}
let mut digits = 0;
while val != 0 {
val /= radix;
digits += 1;
}
digits
}