2018-12-30 12:47:27 +00:00
|
|
|
//! *catar* binary format definition
|
|
|
|
//!
|
|
|
|
//! Please note the all values are stored in little endian ordering.
|
|
|
|
//!
|
|
|
|
//! The Archive contains a list of items. Each item starts with a
|
|
|
|
//! `CaFormatHeader`, followed by the item data.
|
|
|
|
|
2018-12-27 08:22:23 +00:00
|
|
|
use failure::*;
|
2019-01-07 18:07:03 +00:00
|
|
|
use endian_trait::Endian;
|
2018-12-27 08:22:23 +00:00
|
|
|
|
2018-12-30 16:32:52 +00:00
|
|
|
use siphasher::sip::SipHasher24;
|
|
|
|
|
2018-12-28 08:55:26 +00:00
|
|
|
pub const CA_FORMAT_ENTRY: u64 = 0x1396fabcea5bbb51;
|
|
|
|
pub const CA_FORMAT_FILENAME: u64 = 0x6dbb6ebcb3161f0b;
|
|
|
|
pub const CA_FORMAT_SYMLINK: u64 = 0x664a6fb6830e0d6c;
|
2018-12-28 09:44:12 +00:00
|
|
|
pub const CA_FORMAT_PAYLOAD: u64 = 0x8b9e1d93d6dcffc9;
|
|
|
|
|
2018-12-28 08:55:26 +00:00
|
|
|
pub const CA_FORMAT_GOODBYE: u64 = 0xdfd35c5e8327c403;
|
2018-12-27 08:22:23 +00:00
|
|
|
/* The end marker used in the GOODBYE object */
|
2018-12-28 08:55:26 +00:00
|
|
|
pub const CA_FORMAT_GOODBYE_TAIL_MARKER: u64 = 0x57446fa533702943;
|
2018-12-27 08:22:23 +00:00
|
|
|
|
2018-12-28 13:26:05 +00:00
|
|
|
pub const CA_FORMAT_FEATURE_FLAGS_MAX: u64 = 0xb000_0001_ffef_fe26; // fixme: ?
|
|
|
|
|
2019-01-07 18:07:03 +00:00
|
|
|
#[derive(Endian)]
|
2018-12-27 08:22:23 +00:00
|
|
|
#[repr(C)]
|
|
|
|
pub struct CaFormatHeader {
|
2018-12-30 12:47:27 +00:00
|
|
|
/// The size of the item, including the size of `CaFormatHeader`.
|
2018-12-28 08:55:26 +00:00
|
|
|
pub size: u64,
|
2018-12-30 12:47:27 +00:00
|
|
|
/// The item type (see `CA_FORMAT_` constants).
|
2018-12-28 08:55:26 +00:00
|
|
|
pub htype: u64,
|
2018-12-27 08:22:23 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 18:07:03 +00:00
|
|
|
#[derive(Endian)]
|
2018-12-27 08:22:23 +00:00
|
|
|
#[repr(C)]
|
|
|
|
pub struct CaFormatEntry {
|
2018-12-28 08:55:26 +00:00
|
|
|
pub feature_flags: u64,
|
|
|
|
pub mode: u64,
|
|
|
|
pub flags: u64,
|
|
|
|
pub uid: u64,
|
|
|
|
pub gid: u64,
|
|
|
|
pub mtime: u64,
|
2018-12-27 08:22:23 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 18:07:03 +00:00
|
|
|
#[derive(Endian)]
|
2018-12-27 08:22:23 +00:00
|
|
|
#[repr(C)]
|
|
|
|
pub struct CaFormatGoodbyeItem {
|
2018-12-30 12:47:27 +00:00
|
|
|
/// The offset from the start of the GOODBYE object to the start
|
|
|
|
/// of the matching directory item (point to a FILENAME). The last
|
|
|
|
/// GOODBYE item points to the start of the matching ENTRY
|
2019-01-06 16:27:22 +00:00
|
|
|
/// object.
|
2018-12-28 08:55:26 +00:00
|
|
|
pub offset: u64,
|
2018-12-30 12:47:27 +00:00
|
|
|
/// The overall size of the directory item. The last GOODBYE item
|
|
|
|
/// repeats the size of the GOODBYE item.
|
2018-12-28 08:55:26 +00:00
|
|
|
pub size: u64,
|
2018-12-30 12:47:27 +00:00
|
|
|
/// SipHash24 of the directory item name. The last GOODBYE item
|
|
|
|
/// uses the special hash value `CA_FORMAT_GOODBYE_TAIL_MARKER`.
|
2018-12-28 08:55:26 +00:00
|
|
|
pub hash: u64,
|
2018-12-27 08:22:23 +00:00
|
|
|
}
|
|
|
|
|
2018-12-30 16:32:52 +00:00
|
|
|
|
|
|
|
/// Helper function to extract file names from binary archive.
|
|
|
|
pub fn read_os_string(buffer: &[u8]) -> std::ffi::OsString {
|
2018-12-27 08:22:23 +00:00
|
|
|
let len = buffer.len();
|
|
|
|
|
|
|
|
use std::os::unix::ffi::OsStrExt;
|
|
|
|
|
|
|
|
let name = if len > 0 && buffer[len-1] == 0 {
|
|
|
|
std::ffi::OsStr::from_bytes(&buffer[0..len-1])
|
|
|
|
} else {
|
|
|
|
std::ffi::OsStr::from_bytes(&buffer)
|
|
|
|
};
|
|
|
|
|
|
|
|
name.into()
|
|
|
|
}
|
2018-12-30 16:32:52 +00:00
|
|
|
|
|
|
|
/// Create SipHash values for goodby tables.
|
|
|
|
//pub fn compute_goodbye_hash(name: &std::ffi::CStr) -> u64 {
|
|
|
|
pub fn compute_goodbye_hash(name: &[u8]) -> u64 {
|
|
|
|
|
|
|
|
use std::hash::Hasher;
|
|
|
|
let mut hasher = SipHasher24::new_with_keys(0x8574442b0f1d84b3, 0x2736ed30d1c22ec1);
|
|
|
|
hasher.write(name);
|
|
|
|
hasher.finish()
|
|
|
|
}
|
2019-01-07 18:07:03 +00:00
|
|
|
|
|
|
|
pub fn check_ca_header<T>(head: &CaFormatHeader, htype: u64) -> Result<(), Error> {
|
|
|
|
if head.htype != htype {
|
|
|
|
bail!("got wrong header type ({:016x} != {:016x}", head.htype, htype);
|
|
|
|
}
|
|
|
|
if head.size != (std::mem::size_of::<T>() + std::mem::size_of::<CaFormatHeader>()) as u64 {
|
|
|
|
bail!("got wrong header size for type {:016x}", htype);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|