From 556d263d8e37f04ef179a4072356fc8e86a92250 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Sun, 24 Mar 2019 00:36:13 +0800 Subject: [PATCH] Implement sys_openat and sys_renameat --- crate/thread/src/thread_pool.rs | 2 +- kernel/src/drivers/bus/pci.rs | 6 +-- kernel/src/fs/file.rs | 4 ++ kernel/src/shell.rs | 2 +- kernel/src/syscall/fs.rs | 96 ++++++++++++++++++++++++--------- kernel/src/syscall/misc.rs | 4 +- kernel/src/syscall/mod.rs | 6 +-- kernel/src/syscall/net.rs | 8 +-- kernel/src/syscall/proc.rs | 4 +- 9 files changed, 90 insertions(+), 42 deletions(-) diff --git a/crate/thread/src/thread_pool.rs b/crate/thread/src/thread_pool.rs index ebf5572..441bc47 100644 --- a/crate/thread/src/thread_pool.rs +++ b/crate/thread/src/thread_pool.rs @@ -217,6 +217,6 @@ impl ThreadPool { fn new_vec_default(size: usize) -> Vec { let mut vec = Vec::new(); - vec.resize_default(size); + vec.resize_with(size, Default::default); vec } diff --git a/kernel/src/drivers/bus/pci.rs b/kernel/src/drivers/bus/pci.rs index cb3351b..e46c7d0 100644 --- a/kernel/src/drivers/bus/pci.rs +++ b/kernel/src/drivers/bus/pci.rs @@ -136,9 +136,9 @@ impl PciTag { let mut max_base_lo = self.read(bar, 4); self.write(bar, base_lo); - let mut base = 0usize; - let mut max_base = 0usize; - let mut address_mark = 0usize; + let mut base; + let mut max_base; + let mut address_mark; // memory instead of io assert!(base_lo & PCI_BASE_ADDRESS_SPACE == PCI_BASE_ADDRESS_SPACE_MEMORY); diff --git a/kernel/src/fs/file.rs b/kernel/src/fs/file.rs index fa6d837..76c55a8 100644 --- a/kernel/src/fs/file.rs +++ b/kernel/src/fs/file.rs @@ -96,6 +96,10 @@ impl FileHandle { self.inode.metadata() } + pub fn lookup_follow(&self, path: &str, max_follow: usize) -> Result> { + self.inode.lookup_follow(path, max_follow) + } + pub fn read_entry(&mut self) -> Result { if !self.options.read { return Err(FsError::InvalidParam); // FIXME: => EBADF diff --git a/kernel/src/shell.rs b/kernel/src/shell.rs index 77bf450..5a04e5f 100644 --- a/kernel/src/shell.rs +++ b/kernel/src/shell.rs @@ -28,7 +28,7 @@ pub extern fn shell(_arg: usize) -> ! { let name = cmd.trim().split(' ').next().unwrap(); if let Ok(file) = ROOT_INODE.lookup(name) { let data = file.read_as_vec().unwrap(); - let pid = processor().manager().add(Thread::new_user(data.as_slice(), cmd.split(' '))); + let _pid = processor().manager().add(Thread::new_user(data.as_slice(), cmd.split(' '))); // TODO: wait until process exits, or use user land shell completely //unsafe { thread::JoinHandle::<()>::_of(pid) }.join().unwrap(); } else { diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 055dd1d..99d042d 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -297,31 +297,63 @@ pub fn sys_writev(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResu } } +const AT_FDCWD: usize = -100isize as usize; + pub fn sys_open(path: *const u8, flags: usize, mode: usize) -> SysResult { + sys_openat(AT_FDCWD, path, flags, mode) +} + +pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) -> SysResult { let mut proc = process(); let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; let flags = OpenFlags::from_bits_truncate(flags); - info!("open: path: {:?}, flags: {:?}, mode: {:#o}", path, flags, mode); + info!("openat: dir_fd: {}, path: {:?}, flags: {:?}, mode: {:#o}", dir_fd as isize, path, flags, mode); let inode = - if flags.contains(OpenFlags::CREATE) { - 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) { - return Err(SysError::EEXIST); - } - file_inode - }, - Err(FsError::EntryNotFound) => { - dir_inode.create(file_name, FileType::File, mode as u32)? + if dir_fd == AT_FDCWD { + // from process cwd + if flags.contains(OpenFlags::CREATE) { + let (dir_path, file_name) = split_path(&path); + // relative to cwd + let dir_inode = proc.lookup_inode(dir_path)?; + match dir_inode.find(file_name) { + Ok(file_inode) => { + if flags.contains(OpenFlags::EXCLUSIVE) { + return Err(SysError::EEXIST); + } + file_inode + }, + Err(FsError::EntryNotFound) => { + dir_inode.create(file_name, FileType::File, mode as u32)? + } + Err(e) => return Err(SysError::from(e)), + } + } else { + proc.lookup_inode(&path)? } - Err(e) => return Err(SysError::from(e)), - } - } else { - proc.lookup_inode(&path)? - }; + } else { + // relative to dir_fd + let dir_file = proc.get_file(dir_fd)?; + if flags.contains(OpenFlags::CREATE) { + let (dir_path, file_name) = split_path(&path); + // relative to cwd + let dir_inode = dir_file.lookup_follow(dir_path, FOLLOW_MAX_DEPTH)?; + match dir_inode.find(file_name) { + Ok(file_inode) => { + if flags.contains(OpenFlags::EXCLUSIVE) { + return Err(SysError::EEXIST); + } + file_inode + }, + Err(FsError::EntryNotFound) => { + dir_inode.create(file_name, FileType::File, mode as u32)? + } + Err(e) => return Err(SysError::from(e)), + } + } else { + dir_file.lookup_follow(&path, FOLLOW_MAX_DEPTH)? + } + }; let fd = proc.get_free_fd(); @@ -506,15 +538,27 @@ pub fn sys_chdir(path: *const u8) -> SysResult { } pub fn sys_rename(oldpath: *const u8, newpath: *const u8) -> SysResult { - let proc = process(); + sys_renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath) +} + +pub fn sys_renameat(olddirfd: usize, oldpath: *const u8, newdirfd: usize, newpath: *const u8) -> SysResult { + let mut proc = process(); let oldpath = unsafe { proc.vm.check_and_clone_cstr(oldpath)? }; let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? }; - info!("rename: oldpath: {:?}, newpath: {:?}", oldpath, newpath); + info!("renameat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}", olddirfd, oldpath, newdirfd, 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)?; + let old_dir_inode = if olddirfd == AT_FDCWD { + proc.lookup_inode(old_dir_path)? + } else { + proc.get_file(olddirfd)?.lookup_follow(old_dir_path, FOLLOW_MAX_DEPTH)? + }; + let new_dir_inode = if newdirfd == AT_FDCWD { + proc.lookup_inode(new_dir_path)? + } else { + proc.get_file(newdirfd)?.lookup_follow(new_dir_path, FOLLOW_MAX_DEPTH)? + }; old_dir_inode.move_(old_file_name, &new_dir_inode, new_file_name)?; Ok(0) } @@ -622,7 +666,7 @@ pub fn sys_sendfile(out_fd: usize, in_fd: usize, offset: *mut usize, count: usiz let mut bytes_read = 0; while bytes_read < count { let len = min(buffer.len(), count - bytes_read); - let read_len = in_file.read(&mut buffer)?; + let read_len = in_file.read(&mut buffer[..len])?; if read_len == 0 { break; } @@ -638,16 +682,16 @@ pub fn sys_sendfile(out_fd: usize, in_fd: usize, offset: *mut usize, count: usiz } return Ok(bytes_read); } else { - let mut proc_mem = unsafe {&mut *proc_cell.get()}; + let proc_mem = unsafe {&mut *proc_cell.get()}; proc_mem.vm.check_read_ptr(offset)?; let mut read_offset = unsafe { *offset }; - // read from specified offset and write back + // read from specified offset and write new offset back let mut bytes_read = 0; while bytes_read < count { let len = min(buffer.len(), count - bytes_read); - let read_len = in_file.read_at(read_offset, &mut buffer)?; + let read_len = in_file.read_at(read_offset, &mut buffer[..len])?; if read_len == 0 { break; } diff --git a/kernel/src/syscall/misc.rs b/kernel/src/syscall/misc.rs index d422e0f..cb8df7d 100644 --- a/kernel/src/syscall/misc.rs +++ b/kernel/src/syscall/misc.rs @@ -79,7 +79,7 @@ pub fn sys_futex(uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> S .vm .check_write_ptr(uaddr as *mut AtomicI32)?; let atomic = unsafe { &mut *(uaddr as *mut AtomicI32) }; - let timeout = if timeout.is_null() { + let _timeout = if timeout.is_null() { None } else { process().vm.check_read_ptr(timeout)?; @@ -114,7 +114,7 @@ pub fn sys_futex(uaddr: usize, op: u32, val: i32, timeout: *const TimeSpec) -> S const LINUX_REBOOT_CMD_HALT: u32 = 0xcdef0123; -pub fn sys_reboot(magic: u32, magic2: u32, cmd: u32, arg: *const u8) -> SysResult { +pub fn sys_reboot(_magic: u32, magic2: u32, cmd: u32, _arg: *const u8) -> SysResult { // we will skip verifying magic if cmd == LINUX_REBOOT_CMD_HALT { unsafe { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index a7bc453..ce68f44 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -199,12 +199,12 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { } SYS_CLOCK_GETTIME => sys_clock_gettime(args[0], args[1] as *mut TimeSpec), SYS_EXIT_GROUP => sys_exit_group(args[0]), - SYS_OPENAT => sys_open(args[1] as *const u8, args[2], args[3]), // TODO: handle `dfd` + SYS_OPENAT => sys_openat(args[0], args[1] as *const u8, args[2], args[3]), // TODO: handle `dfd` SYS_MKDIRAT => sys_mkdir(args[1] as *const u8, args[2]), // TODO: handle `dfd` // SYS_MKNODAT => sys_mknod(), SYS_NEWFSTATAT => sys_stat(args[1] as *const u8, args[2] as *mut Stat), // TODO: handle `dfd`, `flag` SYS_UNLINKAT => sys_unlink(args[1] as *const u8), // TODO: handle `dfd`, `flag` - SYS_RENAMEAT => sys_rename(args[1] as *const u8, args[3] as *const u8), // TODO: handle `olddfd`, `newdfd` + SYS_RENAMEAT => sys_renameat(args[0], args[1] as *const u8, args[2], args[3] as *const u8), // TODO: handle `olddfd`, `newdfd` SYS_LINKAT => sys_link(args[1] as *const u8, args[3] as *const u8), // TODO: handle `olddfd`, `newdfd`, `flags` SYS_FACCESSAT => sys_access(args[1] as *const u8, args[2]), // TODO: handle `dfd` // 280 @@ -418,7 +418,7 @@ impl From for SysError { const SPIN_WAIT_TIMES: usize = 100; pub fn spin_and_wait(condvars: &[&Condvar], mut action: impl FnMut() -> Option) -> T { - for i in 0..SPIN_WAIT_TIMES { + for _i in 0..SPIN_WAIT_TIMES { if let Some(result) = action() { return result; } diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index 326985c..a955b9e 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -118,8 +118,8 @@ pub fn sys_setsockopt( fd: usize, level: usize, optname: usize, - optval: *const u8, - optlen: usize, + _optval: *const u8, + _optlen: usize, ) -> SysResult { info!( "setsockopt: fd: {}, level: {}, optname: {}", @@ -266,7 +266,7 @@ pub fn sys_sendto( fd: usize, base: *const u8, len: usize, - flags: usize, + _flags: usize, addr: *const SockAddr, addr_len: usize, ) -> SysResult { @@ -382,7 +382,7 @@ pub fn sys_listen(fd: usize, backlog: usize) -> SysResult { tcp_state.is_listening = true; Ok(0) } - Err(err) => Err(SysError::EINVAL), + Err(_err) => Err(SysError::EINVAL), } } else { Ok(0) diff --git a/kernel/src/syscall/proc.rs b/kernel/src/syscall/proc.rs index ed0ccfc..c95d788 100644 --- a/kernel/src/syscall/proc.rs +++ b/kernel/src/syscall/proc.rs @@ -98,7 +98,7 @@ pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult { pub fn sys_exec(name: *const u8, argv: *const *const u8, envp: *const *const u8, tf: &mut TrapFrame) -> SysResult { info!("exec: name: {:?}, argv: {:?} envp: {:?}", name, argv, envp); let proc = process(); - let name = if name.is_null() { String::from("") } else { + let _name = if name.is_null() { String::from("") } else { unsafe { proc.vm.check_and_clone_cstr(name)? } }; @@ -235,7 +235,7 @@ pub fn sys_exit(exit_code: usize) -> ! { /// Exit the current thread group (i.e. process) pub fn sys_exit_group(exit_code: usize) -> ! { - let mut proc = process(); + let proc = process(); info!("exit_group: {}, code: {}", proc.pid, exit_code); // quit all threads