//! use { core::{fmt::Debug, mem}, error::Error, sector::{Address, SectorSize}, volume::Volume, }; /// An inode is a structure on the disk that represents a file, directory, /// symbolic link, etc. Inodes do not contain the data of the file / directory / /// etc. that they represent. Instead, they link to the blocks that actually /// contain the data. This lets the inodes themselves have a well-defined size /// which lets them be placed in easily indexed arrays. Each block group has an /// array of inodes it is responsible for, and conversely every inode within a /// file system belongs to one of such tables (and one of such block groups). #[repr(C, packed)] #[derive(Clone, Debug, Copy)] pub struct Inode { /// Type and Permissions (see below) pub type_perm: TypePerm, /// User ID pub uid: u16, /// Lower 32 bits of size in bytes pub size_low: u32, /// Last Access Time (in POSIX time) pub atime: u32, /// Creation Time (in POSIX time) pub ctime: u32, /// Last Modification time (in POSIX time) pub mtime: u32, /// Deletion time (in POSIX time) pub dtime: u32, /// Group ID pub gid: u16, /// Count of hard links (directory entries) to this inode. When this /// reaches 0, the data blocks are marked as unallocated. pub hard_links: u16, /// Count of disk sectors (not Ext2 blocks) in use by this inode, not /// counting the actual inode structure nor directory entries linking /// to the inode. pub sectors_count: u32, /// Flags pub flags: Flags, /// Operating System Specific value #1 pub _os_specific_1: [u8; 4], /// Direct block pointers pub direct_pointer: [u32; 12], /// Singly Indirect Block Pointer (Points to a block that is a list of /// block pointers to data) pub indirect_pointer: u32, /// Doubly Indirect Block Pointer (Points to a block that is a list of /// block pointers to Singly Indirect Blocks) pub doubly_indirect: u32, /// Triply Indirect Block Pointer (Points to a block that is a list of /// block pointers to Doubly Indirect Blocks) pub triply_indirect: u32, /// Generation number (Primarily used for NFS) pub gen_number: u32, /// In Ext2 version 0, this field is reserved. In version >= 1, /// Extended attribute block (File ACL). pub ext_attribute_block: u32, /// In Ext2 version 0, this field is reserved. In version >= 1, Upper /// 32 bits of file size (if feature bit set) if it's a file, /// Directory ACL if it's a directory pub size_high: u32, /// Block address of fragment pub frag_block_addr: u32, /// Operating System Specific Value #2 pub _os_specific_2: [u8; 12], } impl Inode { /// Discover the inode location on the disk. pub unsafe fn find_inode>( haystack: &V, offset: Address, size: usize, ) -> Result<(Inode, Address), Error> { if size != mem::size_of::() { unimplemented!("inodes with a size != 128"); } let end = offset + Address::from(size); if haystack.size() < end { return Err(Error::AddressOutOfBounds { sector: end.sector(), offset: end.offset(), size: end.sector_size(), }); } let inode = haystack .slice_unchecked(offset..end) .dynamic_cast::(); Ok(inode) } } bitflags! { /// // #[derive(Copy)] pub struct TypePerm: u16 { /// FIFO const FIFO = 0x1000; /// Character device const CHAR_DEVICE = 0x2000; /// Directory const DIRECTORY = 0x4000; /// Block device const BLOCK_DEVICE = 0x6000; /// Regular file const FILE = 0x8000; /// Symbolic link const SYMLINK = 0xA000; /// Unix socket const SOCKET = 0xC000; /// Other—execute permission const O_EXEC = 0x001; /// Other—write permission const O_WRITE = 0x002; /// Other—read permission const O_READ = 0x004; /// Group—execute permission const G_EXEC = 0x008; /// Group—write permission const G_WRITE = 0x010; /// Group—read permission const G_READ = 0x020; /// User—execute permission const U_EXEC = 0x040; /// User—write permission const U_WRITE = 0x080; /// User—read permission const U_READ = 0x100; /// Sticky Bit const STICKY = 0x200; /// Set group ID const SET_GID = 0x400; /// Set user ID const SET_UID = 0x800; } } bitflags! { /// Flags pub struct Flags: u32 { /// Secure deletion (not used) const SECURE_DEL = 0x00000001; /// Keep a copy of data when deleted (not used) const KEEP_COPY = 0x00000002; /// File compression (not used) const COMPRESSION = 0x00000004; /// Synchronous updates—new data is written immediately to disk const SYNC_UPDATE = 0x00000008; /// Immutable file (content cannot be changed) const IMMUTABLE = 0x00000010; /// Append only const APPEND_ONLY = 0x00000020; /// File is not included in 'dump' command const NODUMP = 0x00000040; /// Last accessed time should not updated const DONT_ATIME = 0x00000080; /// Hash indexed directory const HASH_DIR = 0x00010000; /// AFS directory const AFS_DIR = 0x00020000; /// Journal file data const JOURNAL_DATA = 0x00040000; } } /// Unknown entry type pub const UNKNOWN: u8 = 0; /// FIFO entry type pub const FIFO: u8 = 1; /// Character device entry type pub const CHAR_DEVICE: u8 = 2; /// Directory entry type pub const DIRECTORY: u8 = 3; /// Block device entry type pub const BLOCK_DEVICE: u8 = 4; /// Regular file entry type pub const FILE: u8 = 5; /// Symbolic link entry type pub const SYMLINK: u8 = 6; /// Unix socket entry type pub const SOCKET: u8 = 7;