use bitflags::bitflags; const DIRECT_NUMBER: usize = 15; #[derive(Debug)] pub struct InodeMode(u16); bitflags! { impl InodeMode: u16 { const IXOTH = 0x0001; const IWOTH = 0x0002; const IROTH = 0x0004; const IXGRP = 0x0008; const IWGRP = 0x0010; const IRGRP = 0x0020; const IXUSR = 0x0040; const IWUSR = 0x0080; const IRUSR = 0x0100; const ISVTX = 0x0200; const ISGID = 0x0400; const ISUID = 0x0800; // These are mutually-exclusive: const IFIFO = 0x1000; const IFCHR = 0x2000; const IFDIR = 0x4000; const IFBLK = 0x6000; const IFREG = 0x8000; const IFLNK = 0xA000; const IFSOCK = 0xC000; } } /// Pretty much the same with ext2, with minor changes: /// - removed OS dependent attributes (osd1 & osd2) /// - removed i_faddr since fragmentation is not supported /// - changed uid and gid from u16 to u32 /// - added more direct blocks for a total size of 128 bytes /// TODO: do we need to extend time precision? #[repr(C)] #[derive(Debug)] pub struct Inode { mode: InodeMode, uid: u32, size: u32, atime: u32, // time in seconds ctime: u32, mtime: u32, dtime: u32, gid: u32, n_links: u16, n_blocks: u32, flags: u32, // TODO: do we actually need this? maybe just return 0 direct: [u32; DIRECT_NUMBER], single_indirect: u32, double_indirect: u32, triple_indirect: u32, generation: u32, file_acl: u32, dir_acl: u32, // TODO do we have to implement ACL......? } impl Inode { pub fn directory() -> Self { Self { mode: InodeMode::IFDIR | InodeMode::IRUSR | InodeMode::IWUSR | InodeMode::IXUSR | InodeMode::IRGRP | InodeMode::IXGRP | InodeMode::IROTH | InodeMode::IXOTH, // Directory, 755 permissions uid: 0, size: 0, atime: 0, ctime: 0, mtime: 0, dtime: 0, gid: 0, n_links: 0, n_blocks: 0, flags: 0, direct: [0; DIRECT_NUMBER], single_indirect: 0, double_indirect: 0, triple_indirect: 0, generation: 0, file_acl: 0, dir_acl: 0, } } pub fn file() -> Self { Self { mode: InodeMode::IFREG | InodeMode::IRUSR | InodeMode::IWUSR | InodeMode::IXUSR | InodeMode::IRGRP | InodeMode::IXGRP | InodeMode::IROTH | InodeMode::IXOTH, // RegularFile, 755 permissions uid: 0, size: 0, atime: 0, ctime: 0, mtime: 0, dtime: 0, gid: 0, n_links: 0, n_blocks: 0, flags: 0, direct: [0; DIRECT_NUMBER], single_indirect: 0, double_indirect: 0, triple_indirect: 0, generation: 0, file_acl: 0, dir_acl: 0, } } } // // #[repr(C)] // #[derive(Debug, Default)] // pub struct FileInode { // file_size: u32, // direct_blocks: [u32; DIRECT_NUMBER], // indirect_block: u32, // doubly_indirect_block: u32, // } // sizeof(FileInode) == 124 bytes // // #[repr(C)] // #[derive(Debug, Default)] // pub struct DirectoryInode { // child_number: u32, // direct_blocks: [u32; DIRECT_NUMBER], // indirect_block: u32, // doubly_indirect_block: u32, // } // sizeof(FileInode) == 124 bytes // // #[repr(C)] // #[derive(Debug)] // pub enum Inode { // File(FileInode), // Directory(DirectoryInode), // } // sizeof(Inode) == 128 bytes pub const INODE_SIZE: usize = std::mem::size_of::();