From c885ea6d776d4d1238e5bc8aa9361f18e672f239 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Tue, 30 Apr 2019 17:31:29 +0800 Subject: [PATCH] impl pseudo INode '/proc/self/exe' --- kernel/Cargo.lock | 4 +- kernel/src/fs/mod.rs | 2 + kernel/src/fs/pseudo.rs | 78 +++++++++++++++++++++++++++++++++++ kernel/src/process/structs.rs | 5 ++- kernel/src/syscall/fs.rs | 13 +++++- kernel/src/syscall/mod.rs | 5 +-- kernel/src/syscall/proc.rs | 32 +++++++------- 7 files changed, 114 insertions(+), 25 deletions(-) create mode 100644 kernel/src/fs/pseudo.rs diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 74ae4b9..24ac173 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -402,12 +402,12 @@ dependencies = [ [[package]] name = "rcore-fs" version = "0.1.0" -source = "git+https://github.com/rcore-os/rcore-fs#64d399fe664927f14853c22943a4bdeb34095f99" +source = "git+https://github.com/rcore-os/rcore-fs#6f282baf2fe928d2c9774e526e63125684855221" [[package]] name = "rcore-fs-sfs" version = "0.1.0" -source = "git+https://github.com/rcore-os/rcore-fs#64d399fe664927f14853c22943a4bdeb34095f99" +source = "git+https://github.com/rcore-os/rcore-fs#6f282baf2fe928d2c9774e526e63125684855221" dependencies = [ "bitvec 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/src/fs/mod.rs b/kernel/src/fs/mod.rs index 1b772a9..256ce5e 100644 --- a/kernel/src/fs/mod.rs +++ b/kernel/src/fs/mod.rs @@ -10,12 +10,14 @@ pub use self::file::*; pub use self::file_like::*; pub use self::pipe::Pipe; pub use self::stdio::{STDIN, STDOUT}; +pub use self::pseudo::*; mod device; mod file; mod file_like; mod pipe; mod stdio; +mod pseudo; /// Hard link user programs #[cfg(feature = "link_user")] diff --git a/kernel/src/fs/pseudo.rs b/kernel/src/fs/pseudo.rs new file mode 100644 index 0000000..6da58c0 --- /dev/null +++ b/kernel/src/fs/pseudo.rs @@ -0,0 +1,78 @@ +//! Pseudo file system INode + +use alloc::{string::String, sync::Arc, vec::Vec}; +use core::any::Any; + +use rcore_fs::vfs::*; + +pub struct Pseudo { + content: Vec, + type_: FileType, +} + +impl Pseudo { + pub fn new(s: &str, type_: FileType) -> Self { + Pseudo { + content: Vec::from(s.as_bytes()), + type_ + } + } +} + +// TODO: better way to provide default impl? +macro_rules! impl_inode { + () => { + fn set_metadata(&self, _metadata: &Metadata) -> Result<()> { Ok(()) } + fn sync_all(&self) -> Result<()> { Ok(()) } + fn sync_data(&self) -> Result<()> { Ok(()) } + fn resize(&self, _len: usize) -> Result<()> { Err(FsError::NotSupported) } + fn create(&self, _name: &str, _type_: FileType, _mode: u32) -> Result> { Err(FsError::NotDir) } + fn unlink(&self, _name: &str) -> Result<()> { Err(FsError::NotDir) } + fn link(&self, _name: &str, _other: &Arc) -> Result<()> { Err(FsError::NotDir) } + fn move_(&self, _old_name: &str, _target: &Arc, _new_name: &str) -> Result<()> { Err(FsError::NotDir) } + fn find(&self, _name: &str) -> Result> { Err(FsError::NotDir) } + fn get_entry(&self, _id: usize) -> Result { Err(FsError::NotDir) } + fn io_control(&self, cmd: u32, data: usize) -> Result<()> { Err(FsError::NotSupported) } + fn fs(&self) -> Arc { unimplemented!() } + fn as_any_ref(&self) -> &Any { self } + }; +} + +impl INode for Pseudo { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + if offset >= self.content.len() { + return Ok(0); + } + let len = (self.content.len() - offset).min(buf.len()); + buf[..len].copy_from_slice(&self.content[offset..offset + len]); + Ok(len) + } + fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result { + Err(FsError::NotSupported) + } + fn poll(&self) -> Result { + Ok(PollStatus { + read: true, + write: false, + error: false, + }) + } + fn metadata(&self) -> Result { + Ok(Metadata { + dev: 0, + inode: 0, + size: self.content.len(), + blk_size: 0, + blocks: 0, + atime: Timespec { sec: 0, nsec: 0 }, + mtime: Timespec { sec: 0, nsec: 0 }, + ctime: Timespec { sec: 0, nsec: 0 }, + type_: self.type_, + mode: 0, + nlinks: 0, + uid: 0, + gid: 0, + }) + } + impl_inode!(); +} diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index f9f07be..bdb72d7 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -59,6 +59,7 @@ pub struct Process { pub vm: MemorySet, pub files: BTreeMap, pub cwd: String, + pub exec_path: String, futexes: BTreeMap>, // relationship @@ -116,6 +117,7 @@ impl Thread { vm, files: BTreeMap::default(), cwd: String::from("/"), + exec_path: String::new(), futexes: BTreeMap::default(), pid: Pid(0), parent: None, @@ -137,7 +139,6 @@ impl Thread { envs: Vec, ) -> Result<(MemorySet, usize, usize), &'static str> { // Read data - use crate::fs::INodeExt; let data = inode .read_as_vec() .map_err(|_| "failed to read from INode")?; @@ -286,6 +287,7 @@ impl Thread { vm, files, cwd: String::from("/"), + exec_path: String::from(exec_path), futexes: BTreeMap::default(), pid: Pid(0), parent: None, @@ -308,6 +310,7 @@ impl Thread { vm, files: proc.files.clone(), cwd: proc.cwd.clone(), + exec_path: proc.exec_path.clone(), futexes: BTreeMap::default(), pid: Pid(0), parent: Some(self.proc.clone()), diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 113a58d..efa0852 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -361,7 +361,10 @@ pub fn sys_readlinkat(dirfd: usize, path: *const u8, base: *mut u8, len: usize) let proc = process(); let path = unsafe { proc.vm.check_and_clone_cstr(path)? }; let slice = unsafe { proc.vm.check_write_array(base, len)? }; - info!("readlink: path: {:?}, base: {:?}, len: {}", path, base, len); + info!( + "readlinkat: dirfd: {}, path: {:?}, base: {:?}, len: {}", + dirfd as isize, path, base, len + ); let inode = proc.lookup_inode_at(dirfd, &path, false)?; if inode.metadata()?.type_ == FileType::SymLink { @@ -753,6 +756,14 @@ impl Process { "lookup_inode_at: dirfd: {:?}, cwd: {:?}, path: {:?}, follow: {:?}", dirfd as isize, self.cwd, path, follow ); + // hard code special path + match path { + "/proc/self/exe" => { + return Ok(Arc::new(Pseudo::new(&self.exec_path, FileType::SymLink))); + } + _ => {} + } + let follow_max_depth = if follow { FOLLOW_MAX_DEPTH } else { 0 }; if dirfd == AT_FDCWD { Ok(ROOT_INODE diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index c247f15..45a22a8 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -252,10 +252,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { }; if !pid.is_init() { // we trust pid 0 process - debug!( - "{}:{}:{} syscall id {} ret with {:x?}", - cid, pid, tid, id, ret - ); + info!("=> {:x?}", ret); } match ret { Ok(code) => code as isize, diff --git a/kernel/src/syscall/proc.rs b/kernel/src/syscall/proc.rs index 4cb982f..9fcb97e 100644 --- a/kernel/src/syscall/proc.rs +++ b/kernel/src/syscall/proc.rs @@ -174,25 +174,23 @@ pub fn sys_exec( let inode = proc.lookup_inode(&path)?; // Make new Thread - match Thread::new_user_vm(&inode, &path, args, envs) { - Ok((mut vm, entry_addr, ustack_top)) => { - // Activate new page table - core::mem::swap(&mut proc.vm, &mut vm); - unsafe { - proc.vm.activate(); - } - - // Modify the TrapFrame - *tf = TrapFrame::new_user_thread(entry_addr, ustack_top); + let (mut vm, entry_addr, ustack_top) = + Thread::new_user_vm(&inode, &path, args, envs).map_err(|_| SysError::EINVAL)?; - info!("exec:END: path: {:?}", path); - Ok(0) - } - Err(err) => { - info!("exec failed with {}", err); - Err(SysError::EINVAL) - } + // Activate new page table + core::mem::swap(&mut proc.vm, &mut vm); + unsafe { + proc.vm.activate(); } + + // Modify exec path + proc.exec_path = path.clone(); + + // Modify the TrapFrame + *tf = TrapFrame::new_user_thread(entry_addr, ustack_top); + + info!("exec:END: path: {:?}", path); + Ok(0) } pub fn sys_yield() -> SysResult {