From 76ac602c3d79bb39c133c81a38425a77bc0b8b1f Mon Sep 17 00:00:00 2001 From: Chuyan Zhang Date: Sat, 25 Nov 2023 02:13:22 -0800 Subject: Some FUSE callbacks, some POSIX interface implementation --- src/utils/constants.rs | 1 + src/utils/mod.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++- src/utils/permissions.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 src/utils/constants.rs create mode 100644 src/utils/permissions.rs (limited to 'src/utils') diff --git a/src/utils/constants.rs b/src/utils/constants.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/utils/constants.rs @@ -0,0 +1 @@ + diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 60b09f2..0a9b825 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,7 +1,10 @@ +mod constants; +pub mod permissions; + use crate::block_device::BLOCK_SIZE; use crate::disk::inode::{Inode, INODE_SIZE}; use crate::{AyaFS, INODE_PER_BLOCK}; -use fuser::FileAttr; +use fuser::{FileAttr, FileType}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; pub(crate) fn time_now() -> u32 { @@ -42,6 +45,62 @@ pub(crate) fn to_systime(time: u32) -> SystemTime { UNIX_EPOCH + Duration::from_secs(time as u64) } +// File type code, one of: +// 0x0 Unknown. +// 0x1 Regular file. +// 0x2 Directory. +// 0x3 Character device file. +// 0x4 Block device file. +// 0x5 FIFO. +// 0x6 Socket. +// 0x7 Symbolic link. + +pub(crate) fn from_filetype(file_type: FileType) -> u8 { + match file_type { + FileType::NamedPipe => 0x5, + FileType::CharDevice => 0x3, + FileType::BlockDevice => 0x4, + FileType::Directory => 0x2, + FileType::RegularFile => 0x1, + FileType::Symlink => 0x7, + FileType::Socket => 0x6, + } +} + +pub(crate) fn to_filetype(file_type: u8) -> Option { + match file_type { + 0x0 => None, + 0x1 => Some(FileType::RegularFile), + 0x2 => Some(FileType::Directory), + 0x3 => Some(FileType::CharDevice), + 0x4 => Some(FileType::BlockDevice), + 0x5 => Some(FileType::NamedPipe), + 0x6 => Some(FileType::Socket), + 0x7 => Some(FileType::Symlink), + _ => panic!("bad filetype"), + } +} + +pub(crate) fn to_fileattr(inode_index: usize, inode: &Inode) -> FileAttr { + FileAttr { + ino: inode_index as u64, + size: inode.size as u64, + blocks: inode.n_blocks as u64, + atime: to_systime(inode.atime), + mtime: to_systime(inode.mtime), + ctime: to_systime(inode.ctime), + crtime: to_systime(inode.crtime), + kind: inode.mode.into(), + perm: inode.mode.perm(), + nlink: inode.n_links as u32, + uid: inode.uid, + gid: inode.gid, + rdev: 0, + blksize: BLOCK_SIZE as u32, + flags: inode.flags, + } +} + impl AyaFS { /// 输入 inode 编号, 返回它对应的 block number 和 block 内 offset pub(crate) fn locate_inode(&self, inode_index: usize) -> (usize, usize) { diff --git a/src/utils/permissions.rs b/src/utils/permissions.rs new file mode 100644 index 0000000..a3afe77 --- /dev/null +++ b/src/utils/permissions.rs @@ -0,0 +1,62 @@ +use std::fs::File; +use std::io::BufRead; +use libc::{F_OK, S_ISGID, S_ISUID, S_IXGRP, X_OK}; +use crate::disk::inode::InodeMode; + +pub(crate) fn get_groups(pid: u32) -> Vec { + let file = File::open(format!("/proc/{pid}/task/{pid}/status")) + .expect(format!("pid {pid} incorrect!").as_str()); + for line in std::io::BufReader::new(file).lines() { + let line = line.unwrap(); + if line.starts_with("Groups:") { + return line["Groups: ".len()..] + .split(' ') + .filter(|x| !x.trim().is_empty()) + .map(|x| x.parse::().unwrap()) + .collect(); + } + } + + Vec::new() +} + +pub(crate) fn clear_suid_sgid(mut mode: InodeMode) -> InodeMode { + mode.0 &= !S_ISUID as u16; + if mode.0 & S_IXGRP as u16 != 0 { + mode.0 &= !S_ISGID as u16; + } + mode +} + +pub(crate) fn check_access( + incoming_uid: u32, + incoming_gid: u32, + uid: u32, + gid: u32, + perm: InodeMode, + mut mask: i32, +) -> bool { + if mask == F_OK { + return true; + } + + let perm = i32::from(perm.0); + // root + if incoming_uid == 0 { + // 读写任何东西都是可以的, 执行只有 IXOTH/IXGRP/IXUSR 之一设置才可以 + mask &= X_OK; + mask -= mask & (perm >> 6); + mask -= mask & (perm >> 3); + mask -= mask & perm; + return mask == 0; + } + + if incoming_uid == uid { + mask -= mask & (perm >> 6); + } else if incoming_gid == gid { + mask -= mask & (perm >> 3); + } else { + mask -= mask & perm; + } + mask == 0 +} \ No newline at end of file -- cgit v1.2.3-70-g09d2