summaryrefslogtreecommitdiff
path: root/ayafs/src/disk/inode.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ayafs/src/disk/inode.rs')
-rw-r--r--ayafs/src/disk/inode.rs312
1 files changed, 312 insertions, 0 deletions
diff --git a/ayafs/src/disk/inode.rs b/ayafs/src/disk/inode.rs
new file mode 100644
index 0000000..0c801ad
--- /dev/null
+++ b/ayafs/src/disk/inode.rs
@@ -0,0 +1,312 @@
+use crate::utils;
+use bitflags::bitflags;
+use fuser::FileType;
+use crate::block_device::BLOCK_SIZE;
+
+pub const DIRECT_NUMBER: usize = 15;
+
+#[derive(Debug, Clone, Copy)]
+pub struct InodeMode(pub 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;
+ }
+}
+
+impl InodeMode {
+ #[allow(unused)]
+ pub(crate) fn exec_other(&self) -> bool {
+ self.0 & Self::IXOTH.0 != 0
+ }
+ #[allow(unused)]
+ pub(crate) fn write_other(&self) -> bool {
+ self.0 & Self::IWOTH.0 != 0
+ }
+ #[allow(unused)]
+ pub(crate) fn read_other(&self) -> bool {
+ self.0 & Self::IROTH.0 != 0
+ }
+ #[allow(unused)]
+ pub(crate) fn exec_group(&self) -> bool {
+ self.0 & Self::IXGRP.0 != 0
+ }
+ #[allow(unused)]
+ pub(crate) fn write_group(&self) -> bool {
+ self.0 & Self::IWGRP.0 != 0
+ }
+ #[allow(unused)]
+ pub(crate) fn read_group(&self) -> bool {
+ self.0 & Self::IRGRP.0 != 0
+ }
+ #[allow(unused)]
+ pub(crate) fn exec_user(&self) -> bool {
+ self.0 & Self::IXUSR.0 != 0
+ }
+ #[allow(unused)]
+ pub(crate) fn write_user(&self) -> bool {
+ self.0 & Self::IWUSR.0 != 0
+ }
+ #[allow(unused)]
+ pub(crate) fn read_user(&self) -> bool {
+ self.0 & Self::IRUSR.0 != 0
+ }
+
+ pub(crate) fn perm(&self) -> u16 {
+ self.0 & 0x0FFF
+ }
+
+ pub(crate) fn is_file(&self) -> bool {
+ (self.0 & 0xF000) == Self::IFREG.0
+ }
+
+ pub(crate) fn is_dir(&self) -> bool {
+ (self.0 & 0xF000) == Self::IFDIR.0
+ }
+
+ pub(crate) fn is_symlink(&self) -> bool {
+ self.0 & 0xF000 == Self::IFLNK.0
+ }
+
+ pub(crate) fn validate(mode_value: u16) -> Option<Self> {
+ let valid_flags: [u16; 7] = [0x1000, 0x2000, 0x4000, 0x6000, 0x8000, 0xA000, 0xC000];
+ valid_flags
+ .contains(&(mode_value & 0xF000))
+ .then(|| Self(mode_value))
+ }
+}
+
+impl From<InodeMode> for FileType {
+ fn from(value: InodeMode) -> Self {
+ let type_flag = value.0 & 0xF000;
+ match type_flag {
+ 0x1000 => FileType::NamedPipe,
+ 0x2000 => FileType::CharDevice,
+ 0x4000 => FileType::Directory,
+ 0x6000 => FileType::BlockDevice,
+ 0x8000 => FileType::RegularFile,
+ 0xA000 => FileType::Symlink,
+ 0xC000 => FileType::Socket,
+ _ => panic!("Invalid inode mode {:x}", type_flag),
+ }
+ }
+}
+
+impl From<InodeMode> for u8 {
+ fn from(value: InodeMode) -> Self {
+ utils::from_filetype(value.into())
+ }
+}
+
+/// 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, Clone)]
+pub struct Inode {
+ pub mode: InodeMode,
+ pub uid: u32,
+ pub size: u32,
+ pub atime: u32, // access time, in seconds
+ pub ctime: u32, // change time, in seconds
+ pub mtime: u32, // modify time, in seconds
+ pub crtime: u32, // create time, in seconds
+ pub gid: u32,
+ pub n_links: u16,
+ pub n_blocks: u32,
+ pub 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,
+ pub generation: u32,
+ pub file_acl: u32,
+ pub 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: 1,
+ n_blocks: 0,
+ flags,
+ direct: [0; DIRECT_NUMBER],
+ single_indirect: 0,
+ double_indirect: 0,
+ triple_indirect: 0,
+ generation,
+ file_acl,
+ dir_acl,
+ }
+ }
+
+ #[allow(unused)]
+ 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 symlink(
+ permissions: u16,
+ uid: u32,
+ gid: u32,
+ time: u32,
+ flags: u32,
+ generation: u32,
+ file_acl: u32,
+ dir_acl: u32,
+ ) -> Self {
+ Self::new(
+ InodeMode(permissions) | InodeMode::IFLNK,
+ uid,
+ gid,
+ time,
+ flags,
+ generation,
+ file_acl,
+ dir_acl,
+ )
+ }
+
+ pub(crate) fn is_file(&self) -> bool {
+ self.mode.is_file()
+ }
+
+ pub(crate) fn is_dir(&self) -> bool {
+ self.mode.is_dir()
+ }
+
+ pub(crate) fn is_symlink(&self) -> bool {
+ self.mode.is_symlink()
+ }
+
+ pub(crate) fn file_type(&self) -> FileType {
+ self.mode.into()
+ }
+
+ pub fn empty() -> Self {
+ Self {
+ mode: InodeMode(0),
+ uid: 0,
+ size: 0,
+ atime: 0,
+ ctime: 0,
+ mtime: 0,
+ crtime: 0,
+ gid: 0,
+ n_links: 0,
+ n_blocks: 0,
+ flags: 0,
+ direct: [0; 15],
+ single_indirect: 0,
+ double_indirect: 0,
+ triple_indirect: 0,
+ generation: 0,
+ file_acl: 0,
+ dir_acl: 0,
+ }
+ }
+}
+pub const INODE_SIZE: usize = std::mem::size_of::<Inode>();
+pub const ENTRY_PER_BLOCK: usize = BLOCK_SIZE / 4; \ No newline at end of file