impl pseudo INode '/proc/self/exe'

master
WangRunji 6 years ago
parent bd158e4e74
commit c885ea6d77

4
kernel/Cargo.lock generated

@ -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)",

@ -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")]

@ -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<u8>,
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<Arc<INode>> { Err(FsError::NotDir) }
fn unlink(&self, _name: &str) -> Result<()> { Err(FsError::NotDir) }
fn link(&self, _name: &str, _other: &Arc<INode>) -> Result<()> { Err(FsError::NotDir) }
fn move_(&self, _old_name: &str, _target: &Arc<INode>, _new_name: &str) -> Result<()> { Err(FsError::NotDir) }
fn find(&self, _name: &str) -> Result<Arc<INode>> { Err(FsError::NotDir) }
fn get_entry(&self, _id: usize) -> Result<String> { Err(FsError::NotDir) }
fn io_control(&self, cmd: u32, data: usize) -> Result<()> { Err(FsError::NotSupported) }
fn fs(&self) -> Arc<FileSystem> { unimplemented!() }
fn as_any_ref(&self) -> &Any { self }
};
}
impl INode for Pseudo {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
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<usize> {
Err(FsError::NotSupported)
}
fn poll(&self) -> Result<PollStatus> {
Ok(PollStatus {
read: true,
write: false,
error: false,
})
}
fn metadata(&self) -> Result<Metadata> {
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!();
}

@ -59,6 +59,7 @@ pub struct Process {
pub vm: MemorySet,
pub files: BTreeMap<usize, FileLike>,
pub cwd: String,
pub exec_path: String,
futexes: BTreeMap<usize, Arc<Condvar>>,
// 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<String>,
) -> 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()),

@ -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

@ -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,

@ -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 {

Loading…
Cancel
Save