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, // access time, in seconds ctime: u32, // change time, in seconds mtime: u32, // modify time, in seconds crtime: u32, // create time, in seconds gid: u32, pub n_links: u16, pub n_blocks: u32, flags: u32, // TODO: do we actually need this? maybe just return 0 pub direct: [u32; DIRECT_NUMBER], pub single_indirect: u32, pub double_indirect: u32, pub triple_indirect: u32, generation: u32, file_acl: u32, dir_acl: u32, // TODO do we have to implement ACL......? } impl Inode { fn new( mode: InodeMode, uid: u32, gid: u32, time: u32, flags: u32, generation: u32, file_acl: u32, dir_acl: u32, ) -> Self { Self { mode, uid, size: 0, atime: time, ctime: time, mtime: time, crtime: time, gid, n_links: 0, n_blocks: 0, flags, direct: [0; DIRECT_NUMBER], single_indirect: 0, double_indirect: 0, triple_indirect: 0, generation, file_acl, dir_acl, } } pub fn make_inode( permissions: u16, mode: InodeMode, uid: u32, gid: u32, time: u32, flags: u32, generation: u32, file_acl: u32, dir_acl: u32, ) -> Self { Self::new( InodeMode(permissions) | mode, uid, gid, time, flags, generation, file_acl, dir_acl, ) } pub fn directory( permissions: u16, uid: u32, gid: u32, time: u32, flags: u32, generation: u32, file_acl: u32, dir_acl: u32, ) -> Self { Self::new( InodeMode(permissions) | InodeMode::IFDIR, uid, gid, time, flags, generation, file_acl, dir_acl, ) } pub fn file( permissions: u16, uid: u32, gid: u32, time: u32, flags: u32, generation: u32, file_acl: u32, dir_acl: u32, ) -> Self { Self::new( InodeMode(permissions) | InodeMode::IFREG, uid, gid, time, flags, generation, file_acl, dir_acl, ) } pub fn empty() -> Self { Self::new(InodeMode(0), 0, 0, 0, 0, 0, 0, 0) } } pub const INODE_SIZE: usize = std::mem::size_of::();