Files
RedBear-OS/src/types.rs
T
Kamil Koczurek f0dec135b9 Add symlink support
* Implement symlinks
  * Initfs only has links with absolute paths.
  * Relative links are assumed to be relative to link location.
  * Absolute paths must point into the archived location. E.g. if we
    archive /home/foo/data and wish the resultant link to point to
    /scheme/rand, then the absolute link must be
    /home/foo/data/scheme/rand.
* Move archive_common to a crate within the workspace -- Rust doesn't
  seem to accept #[path(..)] attributes with `..` segments anymore so
  tests wouldn't build on my machine.
* Improve the test to assert complete filesystem structure.
* Bump to edition 2021
* cargo fmt & clippy
2024-09-14 12:17:44 +02:00

119 lines
2.9 KiB
Rust

use core::mem::offset_of;
pub const MAGIC_LEN: usize = 8;
pub const MAGIC: [u8; 8] = *b"RedoxFtw";
macro_rules! primitive(
($wrapper:ident, $bits:expr, $primitive:ident) => {
#[repr(transparent)]
#[derive(Clone, Copy, Default)]
pub struct $wrapper([u8; $bits / 8]);
impl $wrapper {
#[inline]
pub const fn get(&self) -> $primitive {
<$primitive>::from_le_bytes(self.0)
}
#[inline]
pub fn set(&mut self, primitive: $primitive) {
*self = Self::new(primitive);
}
#[inline]
pub const fn new(primitive: $primitive) -> Self {
Self(<$primitive>::to_le_bytes(primitive))
}
}
impl From<$primitive> for $wrapper {
fn from(primitive: $primitive) -> Self {
Self::new(primitive)
}
}
impl From<$wrapper> for $primitive {
fn from(wrapper: $wrapper) -> Self {
wrapper.get()
}
}
impl core::fmt::Debug for $wrapper {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#0width$x}", self.get(), width = 2 * core::mem::size_of::<$primitive>())
}
}
}
);
primitive!(U16, 16, u16);
primitive!(U32, 32, u32);
primitive!(U64, 64, u64);
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Magic(pub [u8; MAGIC_LEN]);
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct Offset(pub U32);
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct Length(pub U32);
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct Timespec {
pub sec: U64,
pub nsec: U32,
}
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct Header {
pub magic: Magic,
pub inode_table_offset: Offset,
pub creation_time: Timespec,
pub inode_count: U16,
pub bootstrap_entry: U64,
pub initfs_size: U64,
}
const _: () = {
// Ensure the offsets of field used by the bootloader stay stable.
assert!(offset_of!(Header, bootstrap_entry) == 0x1a);
};
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct InodeHeader {
pub type_and_mode: U32,
pub length: U32,
pub offset: Offset,
pub uid: U32,
pub gid: U32,
}
pub const MODE_MASK: u32 = 0xFFF;
pub const MODE_SHIFT: u8 = 0;
pub const TYPE_SHIFT: u8 = 28;
pub const TYPE_MASK: u32 = 0xF000_0000;
#[derive(Clone, Copy, Debug)]
#[repr(u8)]
pub enum InodeType {
RegularFile = 0x0,
Dir = 0x1,
Link = 0x2,
// All other bit patterns are reserved... for now.
}
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct DirEntry {
pub inode: U16,
pub name_len: U16,
pub name_offset: Offset,
}
unsafe impl plain::Plain for Header {}
unsafe impl plain::Plain for InodeHeader {}
unsafe impl plain::Plain for DirEntry {}