From 451fe6b192923b193609c8c7d877e3723ebe75b6 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Sat, 2 Mar 2019 21:25:36 +0800 Subject: [PATCH] impl sys_chdir, sys_rename, sys_mkdir --- kernel/src/syscall/fs.rs | 80 +++++++++++++++++++++++++++++++++++---- kernel/src/syscall/mod.rs | 10 +++-- 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index eb10ecd..58f5ad3 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -72,11 +72,8 @@ pub fn sys_open(path: *const u8, flags: usize, mode: usize) -> SysResult { let inode = if flags.contains(OpenFlags::CREATE) { - // FIXME: assume path start from root now - let mut split = path.as_str().rsplitn(2, '/'); - let file_name = split.next().unwrap(); - let dir_path = split.next().unwrap_or("."); - let dir_inode = ROOT_INODE.lookup(dir_path)?; + let (dir_path, file_name) = split_path(&path); + let dir_inode = proc.lookup_inode(dir_path)?; match dir_inode.find(file_name) { Ok(file_inode) => { if flags.contains(OpenFlags::EXCLUSIVE) { @@ -94,7 +91,7 @@ pub fn sys_open(path: *const u8, flags: usize, mode: usize) -> SysResult { match path.as_str() { "stdin:" => crate::fs::STDIN.clone() as Arc, "stdout:" => crate::fs::STDOUT.clone() as Arc, - _ => ROOT_INODE.lookup(path.as_str())?, + _ => proc.lookup_inode(&path)?, } }; @@ -157,7 +154,7 @@ pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult { } info!("lstat: path: {}", path); - let inode = ROOT_INODE.lookup(path.as_str())?; + let inode = proc.lookup_inode(&path)?; let stat = Stat::from(inode.metadata()?); unsafe { stat_ptr.write(stat); } Ok(0) @@ -195,7 +192,8 @@ pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> Sy Err(FsError::EntryNotFound) => break, r => r, }?; - let ok = writer.try_write(0, 0, name.as_str()); + // TODO: get ino from dirent + let ok = writer.try_write(0, 0, &name); if !ok { break; } } Ok(writer.written_size as isize) @@ -212,6 +210,59 @@ pub fn sys_dup2(fd1: usize, fd2: usize) -> SysResult { Ok(0) } +pub fn sys_chdir(path: *const u8) -> SysResult { + let mut proc = process(); + let path = unsafe { proc.memory_set.check_and_clone_cstr(path) } + .ok_or(SysError::EFAULT)?; + info!("chdir: path: {:?}", path); + + let inode = proc.lookup_inode(&path)?; + let info = inode.metadata()?; + if info.type_ != FileType::Dir { + return Err(SysError::ENOTDIR); + } + // FIXME: calculate absolute path of new cwd + proc.cwd += &path; + Ok(0) +} + +pub fn sys_rename(oldpath: *const u8, newpath: *const u8) -> SysResult { + let mut proc = process(); + let oldpath = unsafe { proc.memory_set.check_and_clone_cstr(oldpath) } + .ok_or(SysError::EFAULT)?; + let newpath = unsafe { proc.memory_set.check_and_clone_cstr(newpath) } + .ok_or(SysError::EFAULT)?; + info!("rename: oldpath: {:?}, newpath: {:?}", oldpath, newpath); + + let (old_dir_path, old_file_name) = split_path(&oldpath); + let (new_dir_path, new_file_name) = split_path(&newpath); + let old_dir_inode = proc.lookup_inode(old_dir_path)?; + let new_dir_inode = proc.lookup_inode(new_dir_path)?; + // TODO: merge `rename` and `move` in VFS + if Arc::ptr_eq(&old_dir_inode, &new_dir_inode) { + old_dir_inode.rename(old_file_name, new_file_name)?; + } else { + old_dir_inode.move_(old_file_name, &new_dir_inode, new_file_name)?; + } + Ok(0) +} + +pub fn sys_mkdir(path: *const u8, mode: usize) -> SysResult { + let mut proc = process(); + let path = unsafe { proc.memory_set.check_and_clone_cstr(path) } + .ok_or(SysError::EFAULT)?; + // TODO: check pathname + info!("mkdir: path: {:?}, mode: {:#o}", path, mode); + + let (dir_path, file_name) = split_path(&path); + let inode = proc.lookup_inode(dir_path)?; + if inode.find(file_name).is_ok() { + return Err(SysError::EEXIST); + } + inode.create(file_name, FileType::Dir, mode as u32)?; + Ok(0) +} + impl Process { fn get_file(&mut self, fd: usize) -> Result<&mut FileHandle, SysError> { @@ -222,6 +273,19 @@ impl Process { } }) } + fn lookup_inode(&self, path: &str) -> Result, SysError> { + let cwd = self.cwd.split_at(1).1; // skip start '/' + let inode = ROOT_INODE.lookup(cwd)?.lookup(path)?; + Ok(inode) + } +} + +/// Split a `path` str to `(base_path, file_name)` +fn split_path(path: &str) -> (&str, &str) { + let mut split = path.trim_end_matches('/').rsplitn(2, '/'); + let file_name = split.next().unwrap(); + let dir_path = split.next().unwrap_or("."); + (dir_path, file_name) } impl From for SysError { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 1bf6cc9..b082cc1 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -73,9 +73,9 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { // 076 => sys_trunc(), // 077 => sys_ftrunc(), 079 => sys_getcwd(args[0] as *mut u8, args[1]), -// 080 => sys_chdir(), -// 082 => sys_rename(), -// 083 => sys_mkdir(), + 080 => sys_chdir(args[0] as *const u8), + 082 => sys_rename(args[0] as *const u8, args[1] as *const u8), + 083 => sys_mkdir(args[0] as *const u8, args[1]), // 086 => sys_link(), // 087 => sys_unlink(), 096 => sys_get_time(), // TODO: sys_gettimeofday @@ -117,6 +117,10 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { warn!("sys_fcntl is unimplemented"); Ok(0) } + 095 => { + warn!("sys_umask is unimplemented"); + Ok(0o777) + } 102 => { warn!("sys_getuid is unimplemented"); Ok(0)