Browse Source

实现了sys_rename (#578)

* 基本实现了rename的系统调用

* 实现相对路径的mv

* confilct resolve

* make fmt

* 更改校验位置,
 增加了SYS_RENAMEAT与SYS_RENAMEAT2两个系统调用,其实现与SYS_RENAME基本一致

* 删除了fat中的link

* fix

* 修改注释格式,删除管道文件判断

* 1
TTaq 11 months ago
parent
commit
9e481b3bfe

+ 49 - 0
kernel/src/filesystem/fat/entry.rs

@@ -895,6 +895,55 @@ impl FATDir {
             return Err(SystemError::EPERM);
         }
     }
+
+    /// @brief 跨目录,重命名一个目录项
+    ///
+    pub fn rename_across(
+        &self,
+        fs: Arc<FATFileSystem>,
+        target: &FATDir,
+        old_name: &str,
+        new_name: &str,
+    ) -> Result<FATDirEntry, SystemError> {
+        // 判断源目录项是否存在
+        let old_dentry: FATDirEntry = if let FATDirEntryOrShortName::DirEntry(dentry) =
+            self.check_existence(old_name, None, fs.clone())?
+        {
+            dentry
+        } else {
+            // 如果目标目录项不存在,则返回错误
+            return Err(SystemError::ENOENT);
+        };
+
+        let short_name = if let FATDirEntryOrShortName::ShortName(s) =
+            target.check_existence(new_name, None, fs.clone())?
+        {
+            s
+        } else {
+            // 如果目标目录项存在,那么就返回错误
+            return Err(SystemError::EEXIST);
+        };
+
+        let old_short_dentry: Option<ShortDirEntry> = old_dentry.short_dir_entry();
+        if let Some(se) = old_short_dentry {
+            // 删除原来的目录项
+            self.remove(fs.clone(), old_dentry.name().as_str(), false)?;
+
+            // 创建新的目录项
+            let new_dentry: FATDirEntry = target.create_dir_entries(
+                new_name,
+                &short_name,
+                Some(se),
+                se.attributes,
+                fs.clone(),
+            )?;
+
+            return Ok(new_dentry);
+        } else {
+            // 不允许对根目录项进行重命名
+            return Err(SystemError::EPERM);
+        }
+    }
 }
 
 impl FileAttributes {

+ 72 - 0
kernel/src/filesystem/fat/fs.rs

@@ -1641,6 +1641,78 @@ impl IndexNode for LockedFATInode {
         }
     }
 
+    fn move_to(
+        &self,
+        old_name: &str,
+        target: &Arc<dyn IndexNode>,
+        new_name: &str,
+    ) -> Result<(), SystemError> {
+        let old_id = self.metadata().unwrap().inode_id;
+        let new_id = target.metadata().unwrap().inode_id;
+        // 若在同一父目录下
+        if old_id == new_id {
+            let mut guard = self.0.lock();
+            let old_inode: Arc<LockedFATInode> = guard.find(old_name)?;
+            // 对目标inode上锁,以防更改
+            let old_inode_guard: SpinLockGuard<FATInode> = old_inode.0.lock();
+            let fs = old_inode_guard.fs.upgrade().unwrap();
+            // 从缓存删除
+            let _nod = guard.children.remove(&old_name.to_uppercase());
+            let old_dir = match &guard.inode_type {
+                FATDirEntry::File(_) | FATDirEntry::VolId(_) => {
+                    return Err(SystemError::ENOTDIR);
+                }
+                FATDirEntry::Dir(d) => d,
+                FATDirEntry::UnInit => {
+                    kerror!("FATFS: param: Inode_type uninitialized.");
+                    return Err(SystemError::EROFS);
+                }
+            };
+            // 检查文件是否存在
+            // old_dir.check_existence(old_name, Some(false), guard.fs.upgrade().unwrap())?;
+
+            old_dir.rename(fs, old_name, new_name)?;
+        } else {
+            let mut old_guard = self.0.lock();
+            let other: &LockedFATInode = target
+                .downcast_ref::<LockedFATInode>()
+                .ok_or(SystemError::EPERM)?;
+
+            let new_guard = other.0.lock();
+            let old_inode: Arc<LockedFATInode> = old_guard.find(old_name)?;
+            // 对目标inode上锁,以防更改
+            let old_inode_guard: SpinLockGuard<FATInode> = old_inode.0.lock();
+            let fs = old_inode_guard.fs.upgrade().unwrap();
+            // 从缓存删除
+            let _nod = old_guard.children.remove(&old_name.to_uppercase());
+            let old_dir = match &old_guard.inode_type {
+                FATDirEntry::File(_) | FATDirEntry::VolId(_) => {
+                    return Err(SystemError::ENOTDIR);
+                }
+                FATDirEntry::Dir(d) => d,
+                FATDirEntry::UnInit => {
+                    kerror!("FATFS: param: Inode_type uninitialized.");
+                    return Err(SystemError::EROFS);
+                }
+            };
+            let new_dir = match &new_guard.inode_type {
+                FATDirEntry::File(_) | FATDirEntry::VolId(_) => {
+                    return Err(SystemError::ENOTDIR);
+                }
+                FATDirEntry::Dir(d) => d,
+                FATDirEntry::UnInit => {
+                    kerror!("FATFA: param: Inode_type uninitialized.");
+                    return Err(SystemError::EROFS);
+                }
+            };
+            // 检查文件是否存在
+            old_dir.check_existence(old_name, Some(false), old_guard.fs.upgrade().unwrap())?;
+            old_dir.rename_across(fs, new_dir, old_name, new_name)?;
+        }
+
+        return Ok(());
+    }
+
     fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> {
         let guard: SpinLockGuard<FATInode> = self.0.lock();
         if guard.metadata.file_type != FileType::Dir {

+ 6 - 1
kernel/src/filesystem/kernfs/mod.rs

@@ -195,7 +195,7 @@ impl IndexNode for KernFSInode {
         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
     }
 
-    fn move_(
+    fn move_to(
         &self,
         _old_name: &str,
         _target: &Arc<dyn IndexNode>,
@@ -366,6 +366,11 @@ impl IndexNode for KernFSInode {
             .unwrap()
             .write(callback_data, &buf[..len], offset);
     }
+
+    fn rename(&self, _old_name: &str, _new_name: &str) -> Result<(), SystemError> {
+        // 待实现
+        Err(SystemError::ENOSYS)
+    }
 }
 
 impl KernFSInode {

+ 5 - 1
kernel/src/filesystem/procfs/mod.rs

@@ -636,6 +636,7 @@ impl IndexNode for LockedProcFSInode {
         if inode.metadata.file_type != FileType::Dir {
             return Err(SystemError::ENOTDIR);
         }
+
         // 不允许删除当前文件夹,也不允许删除上一个目录
         if name == "." || name == ".." {
             return Err(SystemError::ENOTEMPTY);
@@ -643,14 +644,17 @@ impl IndexNode for LockedProcFSInode {
 
         // 获得要删除的文件的inode
         let to_delete = inode.children.get(name).ok_or(SystemError::ENOENT)?;
+
         // 减少硬链接计数
         to_delete.0.lock().metadata.nlinks -= 1;
+
         // 在当前目录中删除这个子目录项
         inode.children.remove(name);
+
         return Ok(());
     }
 
-    fn move_(
+    fn move_to(
         &self,
         _old_name: &str,
         _target: &Arc<dyn IndexNode>,

+ 17 - 1
kernel/src/filesystem/ramfs/mod.rs

@@ -374,7 +374,7 @@ impl IndexNode for LockedRamFSInode {
         return Ok(());
     }
 
-    fn move_(
+    fn move_to(
         &self,
         old_name: &str,
         target: &Arc<dyn IndexNode>,
@@ -539,4 +539,20 @@ impl IndexNode for LockedRamFSInode {
     fn special_node(&self) -> Option<super::vfs::SpecialNodeData> {
         return self.0.lock().special_node.clone();
     }
+
+    /// # 用于重命名内存中的文件或目录
+    fn rename(&self, _old_name: &str, _new_name: &str) -> Result<(), SystemError> {
+        let old_inode: Arc<dyn IndexNode> = self.find(_old_name)?;
+        // 在新的目录下创建一个硬链接
+        self.link(_new_name, &old_inode)?;
+
+        // 取消现有的目录下的这个硬链接
+        if let Err(err) = self.unlink(_old_name) {
+            // 如果取消失败,那就取消新的目录下的硬链接
+            self.unlink(_new_name)?;
+            return Err(err);
+        }
+
+        return Ok(());
+    }
 }

+ 0 - 1
kernel/src/filesystem/vfs/core.rs

@@ -255,7 +255,6 @@ pub fn do_unlink_at(dirfd: i32, path: &str) -> Result<u64, SystemError> {
     }
     let pcb = ProcessManager::current_pcb();
     let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path)?;
-
     let inode: Result<Arc<dyn IndexNode>, SystemError> =
         inode_begin.lookup_follow_symlink(&remain_path, VFS_MAX_FOLLOW_SYMLINK_TIMES);
 

+ 18 - 1
kernel/src/filesystem/vfs/mod.rs

@@ -287,7 +287,7 @@ pub trait IndexNode: Any + Sync + Send + Debug {
     ///
     /// @return 成功: Ok()
     ///         失败: Err(错误码)
-    fn move_(
+    fn move_to(
         &self,
         _old_name: &str,
         _target: &Arc<dyn IndexNode>,
@@ -297,6 +297,23 @@ pub trait IndexNode: Any + Sync + Send + Debug {
         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
     }
 
+    /// # 修改文件名
+    ///
+    ///
+    /// ## 参数
+    ///
+    /// - _old_name: 源文件路径
+    /// - _new_name: 目标文件路径
+    ///
+    /// ## 返回值
+    /// - Ok(返回值类型): 返回值的说明
+    /// - Err(错误值类型): 错误的说明
+    ///
+    fn rename(&self, _old_name: &str, _new_name: &str) -> Result<(), SystemError> {
+        // 若文件系统没有实现此方法,则返回“不支持”
+        return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
+    }
+
     /// @brief 寻找一个名为Name的inode
     ///
     /// @param name 要寻找的inode的名称

+ 2 - 2
kernel/src/filesystem/vfs/mount.rs

@@ -253,13 +253,13 @@ impl IndexNode for MountFSInode {
     }
 
     #[inline]
-    fn move_(
+    fn move_to(
         &self,
         old_name: &str,
         target: &Arc<dyn IndexNode>,
         new_name: &str,
     ) -> Result<(), SystemError> {
-        return self.inner_inode.move_(old_name, target, new_name);
+        return self.inner_inode.move_to(old_name, target, new_name);
     }
 
     fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {

+ 45 - 0
kernel/src/filesystem/vfs/syscall.rs

@@ -602,6 +602,51 @@ impl Syscall {
         return do_unlink_at(AtFlags::AT_FDCWD.bits(), pathname).map(|v| v as usize);
     }
 
+    /// # 修改文件名
+    ///
+    ///
+    /// ## 参数
+    ///
+    /// - oldfd: 源文件描述符
+    /// - filename_from: 源文件路径
+    /// - newfd: 目标文件描述符
+    /// - filename_to: 目标文件路径
+    /// - flags: 标志位
+    ///
+    ///
+    /// ## 返回值
+    /// - Ok(返回值类型): 返回值的说明
+    /// - Err(错误值类型): 错误的说明
+    ///
+    pub fn do_renameat2(
+        oldfd: i32,
+        filename_from: *const u8,
+        newfd: i32,
+        filename_to: *const u8,
+        _flags: u32,
+    ) -> Result<usize, SystemError> {
+        let filename_from = check_and_clone_cstr(filename_from, Some(MAX_PATHLEN)).unwrap();
+        let filename_to = check_and_clone_cstr(filename_to, Some(MAX_PATHLEN)).unwrap();
+        // 文件名过长
+        if filename_from.len() > MAX_PATHLEN as usize || filename_to.len() > MAX_PATHLEN as usize {
+            return Err(SystemError::ENAMETOOLONG);
+        }
+
+        //获取pcb,文件节点
+        let pcb = ProcessManager::current_pcb();
+        let (_old_inode_begin, old_remain_path) = user_path_at(&pcb, oldfd, &filename_from)?;
+        let (_new_inode_begin, new_remain_path) = user_path_at(&pcb, newfd, &filename_to)?;
+        //获取父目录
+        let (old_filename, old_parent_path) = rsplit_path(&old_remain_path);
+        let old_parent_inode = ROOT_INODE()
+            .lookup_follow_symlink(old_parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
+        let (new_filename, new_parent_path) = rsplit_path(&new_remain_path);
+        let new_parent_inode = ROOT_INODE()
+            .lookup_follow_symlink(new_parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
+        old_parent_inode.move_to(old_filename, &new_parent_inode, new_filename)?;
+        return Ok(0);
+    }
+
     /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd
     pub fn dup(oldfd: i32) -> Result<usize, SystemError> {
         let binding = ProcessManager::current_pcb().fd_table();

+ 41 - 1
kernel/src/syscall/mod.rs

@@ -24,7 +24,7 @@ use crate::{
     arch::{cpu::cpu_reset, interrupt::TrapFrame, MMArch},
     driver::base::block::SeekFrom,
     filesystem::vfs::{
-        fcntl::FcntlCommand,
+        fcntl::{AtFlags, FcntlCommand},
         file::FileMode,
         syscall::{ModeType, PosixKstat, SEEK_CUR, SEEK_END, SEEK_MAX, SEEK_SET},
         MAX_PATHLEN,
@@ -107,6 +107,35 @@ impl Syscall {
                 res
             }
 
+            SYS_RENAME => {
+                let oldname: *const u8 = args[0] as *const u8;
+                let newname: *const u8 = args[1] as *const u8;
+                Self::do_renameat2(
+                    AtFlags::AT_FDCWD.bits(),
+                    oldname,
+                    AtFlags::AT_FDCWD.bits(),
+                    newname,
+                    0,
+                )
+            }
+
+            SYS_RENAMEAT => {
+                let oldfd = args[0] as i32;
+                let oldname: *const u8 = args[1] as *const u8;
+                let newfd = args[2] as i32;
+                let newname: *const u8 = args[3] as *const u8;
+                Self::do_renameat2(oldfd, oldname, newfd, newname, 0)
+            }
+
+            SYS_RENAMEAT2 => {
+                let oldfd = args[0] as i32;
+                let oldname: *const u8 = args[1] as *const u8;
+                let newfd = args[2] as i32;
+                let newname: *const u8 = args[3] as *const u8;
+                let flags = args[4] as u32;
+                Self::do_renameat2(oldfd, oldname, newfd, newname, flags)
+            }
+
             SYS_OPENAT => {
                 let dirfd = args[0] as i32;
                 let path: &CStr = unsafe { CStr::from_ptr(args[1] as *const c_char) };
@@ -1030,6 +1059,17 @@ impl Syscall {
                 )
             }
 
+            SYS_FADVISE64 => {
+                // todo: 这个系统调用还没有实现
+
+                Err(SystemError::ENOSYS)
+            }
+            SYS_NEWFSTATAT => {
+                // todo: 这个系统调用还没有实现
+
+                Err(SystemError::ENOSYS)
+            }
+
             SYS_SCHED_YIELD => Self::sched_yield(),
 
             _ => panic!("Unsupported syscall ID: {}", syscall_num),