summaryrefslogtreecommitdiff
path: root/src/filesystem
diff options
context:
space:
mode:
authorChuyan Zhang <me@zcy.moe>2023-11-26 02:33:01 -0800
committerChuyan Zhang <me@zcy.moe>2023-11-26 02:33:01 -0800
commit9d1368b0ea380a9446b4697af668d1685464b6c7 (patch)
tree2103af418264cc70addc9cfc6ed7acac640f5151 /src/filesystem
parent777d5e01a34b8ebe6f1a5751b593266f93e88499 (diff)
downloadmyfs-9d1368b0ea380a9446b4697af668d1685464b6c7.tar.gz
myfs-9d1368b0ea380a9446b4697af668d1685464b6c7.zip
more code idk what they are im so tired ohno
Diffstat (limited to 'src/filesystem')
-rw-r--r--src/filesystem/trait_impl.rs347
1 files changed, 232 insertions, 115 deletions
diff --git a/src/filesystem/trait_impl.rs b/src/filesystem/trait_impl.rs
index 73ae878..636bae7 100644
--- a/src/filesystem/trait_impl.rs
+++ b/src/filesystem/trait_impl.rs
@@ -1,21 +1,22 @@
-
use crate::disk::inode::InodeMode;
-use crate::utils::{from_systime, time_now, to_fileattr, to_filetype};
use crate::utils::permissions::get_groups;
+use crate::utils::permissions::{check_access, clear_suid_sgid};
+use crate::utils::{from_systime, time_now, to_fileattr, to_filetype};
use crate::{AyaFS, TTL};
-use fuser::{Filesystem, KernelConfig, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty,
- ReplyEntry, ReplyLseek, ReplyOpen, Request, TimeOrNow,
+use fuser::TimeOrNow::{Now, SpecificTime};
+use fuser::{
+ Filesystem, KernelConfig, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry,
+ ReplyLseek, ReplyOpen, Request, TimeOrNow,
+};
+use libc::{
+ c_int, EACCES, EEXIST, EISDIR, ENAMETOOLONG, ENOENT, ENOSPC, ENOSYS, ENOTDIR, EPERM, R_OK,
+ S_ISGID, S_ISUID, S_IXGRP, S_IXOTH, S_IXUSR, W_OK,
};
-use libc::{c_int, EACCES, EEXIST, ENAMETOOLONG, ENOENT, ENOSPC, ENOSYS, ENOTDIR, EPERM, R_OK, S_ISGID, S_ISUID, S_IXGRP, S_IXOTH, S_IXUSR, W_OK};
use log::debug;
use std::ffi::OsStr;
use std::time::SystemTime;
-use fuser::TimeOrNow::{Now, SpecificTime};
-use crate::utils::permissions::{check_access, clear_suid_sgid};
-impl AyaFS {
-
-}
+impl AyaFS {}
impl Filesystem for AyaFS {
fn init(&mut self, _req: &Request<'_>, _config: &mut KernelConfig) -> Result<(), c_int> {
@@ -42,15 +43,15 @@ impl Filesystem for AyaFS {
parent_inode.uid,
parent_inode.gid,
parent_inode.mode,
- R_OK
+ R_OK,
) {
let parent_inode = parent_inode.clone();
match self.lookup_name(&parent_inode, name) {
Ok((inode_index, _, inode)) => {
let attr = to_fileattr(inode_index as usize, &inode);
reply.entry(&TTL, &attr, 0);
- },
- Err(err_code) => reply.error(err_code)
+ }
+ Err(err_code) => reply.error(err_code),
};
} else {
reply.error(EACCES);
@@ -96,7 +97,10 @@ impl Filesystem for AyaFS {
return;
} // uid == 0 (root) or uid == inode.uid (user itself)
- if req.uid() != 0 && req.gid() != inode.gid && !get_groups(req.pid()).contains(&inode.gid) {
+ if req.uid() != 0
+ && req.gid() != inode.gid
+ && !get_groups(req.pid()).contains(&inode.gid)
+ {
inode.mode = InodeMode((mode & !S_ISGID) as u16);
} else {
inode.mode = InodeMode(mode as u16);
@@ -175,14 +179,17 @@ impl Filesystem for AyaFS {
return;
}
- if req.uid() != 0 && req.uid() != inode.uid && check_access(
- req.uid(),
- req.gid(),
- inode.uid,
- inode.gid,
- inode.mode,
- R_OK, // atime 来说是 read TODO 对吗
- ) {
+ if req.uid() != 0
+ && req.uid() != inode.uid
+ && check_access(
+ req.uid(),
+ req.gid(),
+ inode.uid,
+ inode.gid,
+ inode.mode,
+ R_OK, // atime 来说是 read TODO 对吗
+ )
+ {
reply.error(EACCES);
return;
}
@@ -201,14 +208,17 @@ impl Filesystem for AyaFS {
return;
}
- if req.uid() != 0 && req.uid() != inode.uid && check_access(
- req.uid(),
- req.gid(),
- inode.uid,
- inode.gid,
- inode.mode,
- W_OK, // mtime 来说是 write
- ) {
+ if req.uid() != 0
+ && req.uid() != inode.uid
+ && check_access(
+ req.uid(),
+ req.gid(),
+ inode.uid,
+ inode.gid,
+ inode.mode,
+ W_OK, // mtime 来说是 write
+ )
+ {
reply.error(EACCES);
return;
}
@@ -248,49 +258,54 @@ impl Filesystem for AyaFS {
);
if let Some(parent_inode) = self.get_inode(parent as usize) {
- if check_access(
+ if !check_access(
req.uid(),
req.gid(),
parent_inode.uid,
parent_inode.gid,
parent_inode.mode,
- W_OK
+ W_OK,
) {
- if parent_inode.is_dir() {
- let parent_inode = parent_inode.clone();
- // 如果已经存在, 返回 already exists
- if self.lookup_name(&parent_inode, name).is_ok() {
- reply.error(EEXIST);
- return;
- }
- // 文件名长度超过 255, 返回 filename too long
- if name.len() > 255 {
- reply.error(ENAMETOOLONG);
- return;
- }
+ reply.error(EACCES);
+ return;
+ }
- let mode = mode as u16;
- if let Some((inode_index, inode)) = self.create_file(
- mode,
- req.uid(),
- req.gid(),
- 0,
- ) {
- let file_attr = to_fileattr(inode_index, inode);
- // TODO 把 inode 挂到 parent 下
- self.update_inode(parent as usize, parent_inode);
- // 前面 clone 了, 这里写回
- reply.entry(&TTL, &file_attr, 0);
- } else {
- // create_inode 失败 -> no enough space
- reply.error(ENOSPC);
- }
- } else {
- // parent 不是 IFDIR -> Not a directory
- reply.error(ENOTDIR);
+ // parent 不是 IFDIR -> Not a directory
+ if !parent_inode.is_dir() {
+ reply.error(ENOTDIR);
+ return;
+ }
+
+ // 文件名长度超过 255, 返回 filename too long
+ if name.len() > 255 {
+ reply.error(ENAMETOOLONG);
+ return;
+ }
+
+ let mut parent_inode = parent_inode.clone();
+ // 如果已经存在, 返回 already exists
+ if self.lookup_name(&parent_inode, name).is_ok() {
+ reply.error(EEXIST);
+ return;
+ }
+
+ let mode = mode as u16;
+ if let Some((child_inode_index, child_inode)) =
+ self.create_file(mode, req.uid(), req.gid(), 0)
+ {
+ let child_inode = child_inode.clone();
+ let file_attr = to_fileattr(child_inode_index, &child_inode);
+ if let Err(err_code) =
+ self.add_direntry(&mut parent_inode, child_inode_index, name, &child_inode)
+ {
+ reply.error(err_code);
+ return;
}
+ self.update_inode(parent as usize, parent_inode); // 前面 clone 了, 这里写回
+ reply.entry(&TTL, &file_attr, 0);
} else {
- reply.error(EACCES);
+ // create_inode 失败 -> no enough space
+ reply.error(ENOSPC);
}
} else {
// parent 不存在 -> No such file or directory
@@ -308,49 +323,55 @@ impl Filesystem for AyaFS {
reply: ReplyEntry,
) {
if let Some(parent_inode) = self.get_inode(parent as usize) {
- if check_access(
+ // 无权限创建 -> EACCES
+ if !check_access(
req.uid(),
req.gid(),
parent_inode.uid,
parent_inode.gid,
parent_inode.mode,
- W_OK
+ W_OK,
) {
- if parent_inode.is_dir() {
- let parent_inode = parent_inode.clone();
- // 如果已经存在, 返回 already exists
- if self.lookup_name(&parent_inode, name).is_ok() {
- reply.error(EEXIST);
- return;
- }
- // 文件名长度超过 255, 返回 filename too long
- if name.len() > 255 {
- reply.error(ENAMETOOLONG);
- return;
- }
+ reply.error(EACCES);
+ return;
+ }
- let mode = mode as u16;
- if let Some((inode_index, inode)) = self.create_directory(
- mode,
- req.uid(),
- req.gid(),
- 0,
- ) {
- let file_attr = to_fileattr(inode_index, inode);
- // TODO 把 inode 挂到 parent 下
- self.update_inode(parent as usize, parent_inode);
- // 前面 clone 了, 这里写回
- reply.entry(&TTL, &file_attr, 0);
- } else {
- // create_inode 失败 -> no enough space
- reply.error(ENOSPC);
- }
- } else {
- // parent 不是 IFDIR -> Not a directory
- reply.error(ENOTDIR);
+ // parent 不是 IFDIR -> Not a directory
+ if !parent_inode.is_dir() {
+ reply.error(ENOTDIR);
+ return;
+ }
+
+ // 文件名长度超过 255 -> filename too long
+ if name.len() > 255 {
+ reply.error(ENAMETOOLONG);
+ return;
+ }
+
+ let mut parent_inode = parent_inode.clone();
+ // 已经存在 -> File exists
+ if self.lookup_name(&parent_inode, name).is_ok() {
+ reply.error(EEXIST);
+ return;
+ }
+
+ let mode = mode as u16;
+ if let Some((child_inode_index, child_inode)) =
+ self.create_directory(mode, req.uid(), req.gid(), 0, Some(parent as u32))
+ {
+ let child_inode = child_inode.clone();
+ let file_attr = to_fileattr(child_inode_index, &child_inode);
+ if let Err(err_code) =
+ self.add_direntry(&mut parent_inode, child_inode_index, name, &child_inode)
+ {
+ reply.error(err_code);
+ return;
}
+ self.update_inode(parent as usize, parent_inode); // 前面 clone 了, 这里写回
+ reply.entry(&TTL, &file_attr, 0);
} else {
- reply.error(EACCES);
+ // create_inode 失败 -> no enough space
+ reply.error(ENOSPC);
}
} else {
// parent 不存在 -> No such file or directory
@@ -358,11 +379,63 @@ impl Filesystem for AyaFS {
}
}
- fn unlink(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEmpty) {
+ fn unlink(&mut self, req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEmpty) {
debug!("unlink(parent: {:#x?}, name: {:?})", parent, name,);
- if let Some(inode) = self.get_inode_mut(parent as usize) {
- if inode.is_file() {
- // TODO 找到这个 inode 并且删掉
+ if let Some(parent_inode) = self.get_inode(parent as usize) {
+ // 无权限删除 -> EACCES
+ if !check_access(
+ req.uid(),
+ req.gid(),
+ parent_inode.uid,
+ parent_inode.gid,
+ parent_inode.mode,
+ W_OK,
+ ) {
+ reply.error(EACCES);
+ return;
+ }
+
+ // parent 不是 dir -> ENOTDIR
+ if !parent_inode.is_dir() {
+ reply.error(ENOTDIR);
+ return;
+ }
+
+ // 文件名长度超过 255 -> filename too long
+ if name.len() > 255 {
+ reply.error(ENAMETOOLONG);
+ return;
+ }
+
+ let mut parent_inode = parent_inode.clone();
+ // 不存在 -> No such file or directory
+ if let Ok((inode_index, entry_index, mut inode)) = self.lookup_name(&parent_inode, name)
+ {
+ let inode_index = inode_index as usize;
+ // 要删除的 entry 是目录, 不能用 unlink
+ if inode.is_dir() {
+ reply.error(EISDIR);
+ return;
+ }
+ // 删除 dir entry
+ if let Err(err_code) = self.remove_direntry(&mut parent_inode, entry_index) {
+ reply.error(err_code);
+ return;
+ }
+ // inode 的 n_links 减 1
+ inode.n_links -= 1;
+ if inode.n_links == 0 {
+ // 释放块的操作在 remove file 里实现了
+ match self.remove_file(inode_index) {
+ Ok(flag) => debug!(" unlink {}", flag),
+ Err(err_code) => {
+ reply.error(err_code);
+ return;
+ }
+ }
+ } else {
+ self.update_inode(inode_index, inode);
+ }
reply.ok();
} else {
reply.error(ENOENT);
@@ -372,14 +445,65 @@ impl Filesystem for AyaFS {
}
}
- fn rmdir(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEmpty) {
+ fn rmdir(&mut self, req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEmpty) {
debug!("rmdir(parent: {:#x?}, name: {:?}", parent, name,);
- if let Some(inode) = self.get_inode_mut(parent as usize) {
- if inode.is_file() {
- // TODO 找到这个 inode 并且删掉
+ if let Some(parent_inode) = self.get_inode(parent as usize) {
+ // 无权限删除 -> EACCES
+ if !check_access(
+ req.uid(),
+ req.gid(),
+ parent_inode.uid,
+ parent_inode.gid,
+ parent_inode.mode,
+ W_OK,
+ ) {
+ reply.error(EACCES);
+ return;
+ }
+
+ // parent 不是 dir -> ENOTDIR
+ if !parent_inode.is_dir() {
+ reply.error(ENOTDIR);
+ return;
+ }
+
+ // 文件名长度超过 255 -> filename too long
+ if name.len() > 255 {
+ reply.error(ENAMETOOLONG);
+ return;
+ }
+
+ let mut parent_inode = parent_inode.clone();
+ // 不存在 -> No such file or directory
+ if let Ok((inode_index, entry_index, mut inode)) = self.lookup_name(&parent_inode, name)
+ {
+ let inode_index = inode_index as usize;
+ // 要删除的 entry 是一般文件, 不用 rmdir
+ if inode.is_file() {
+ reply.error(ENOTDIR);
+ return;
+ }
+
+ // TODO 检查待删除的 dir 是 empty 的
+
+ // 删除 dir entry
+ if let Err(err_code) = self.remove_direntry(&mut parent_inode, entry_index) {
+ reply.error(err_code);
+ return;
+ }
+
+ // directory 没有 hard link, 删了就是删了
+ match self.remove_dir(inode_index) {
+ Ok(flag) => debug!(" rmdir {}", flag),
+ Err(err_code) => {
+ reply.error(err_code);
+ return;
+ }
+ }
+
reply.ok();
} else {
- reply.error(ENOTDIR);
+ reply.error(ENOENT);
}
} else {
reply.error(ENOENT);
@@ -415,14 +539,7 @@ impl Filesystem for AyaFS {
) {
if let Some(inode) = self.get_inode(ino as usize) {
if inode.is_dir() {
- if check_access(
- req.uid(),
- req.gid(),
- inode.uid,
- inode.gid,
- inode.mode,
- R_OK,
- ) {
+ if check_access(req.uid(), req.gid(), inode.uid, inode.gid, inode.mode, R_OK) {
let inode = inode.clone();
let mut entry_index = offset as u32;