Merge remote-tracking branch 'origin/biscuit' into biscuit

master
Jiajie Chen 6 years ago
commit 68167efd45

@ -198,6 +198,9 @@ impl ThreadPool {
pub fn get_children(&self, tid: Tid) -> Vec<Tid> {
self.threads[tid].lock().as_ref().expect("process not exist").children.clone()
}
pub fn get_parent(&self, tid: Tid) -> Tid {
self.threads[tid].lock().as_ref().expect("process not exist").parent
}
pub fn exit(&self, tid: Tid, code: ExitCode) {
// NOTE: if `tid` is running, status change will be deferred.

@ -66,7 +66,24 @@ impl FileHandle {
Ok(self.offset)
}
pub fn info(&self) -> Result<Metadata> {
pub fn set_len(&mut self, len: u64) -> Result<()> {
if !self.options.write {
return Err(FsError::InvalidParam); // FIXME: => EBADF
}
self.inode.resize(len as usize)?;
Ok(())
}
pub fn sync_all(&mut self) -> Result<()> {
self.inode.sync()
}
pub fn sync_data(&mut self) -> Result<()> {
// TODO: add sync_data to VFS
self.inode.sync()
}
pub fn metadata(&self) -> Result<Metadata> {
self.inode.metadata()
}

@ -12,7 +12,7 @@ pub fn sys_read(fd: usize, base: *mut u8, len: usize) -> SysResult {
info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
let mut proc = process();
if !proc.memory_set.check_mut_array(base, len) {
return Err(SysError::EINVAL);
return Err(SysError::EFAULT);
}
let slice = unsafe { slice::from_raw_parts_mut(base, len) };
let len = proc.get_file(fd)?.read(slice)?;
@ -23,7 +23,7 @@ pub fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult {
info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len);
let mut proc = process();
if !proc.memory_set.check_array(base, len) {
return Err(SysError::EINVAL);
return Err(SysError::EFAULT);
}
match proc.files.get(&fd) {
Some(FileLike::File(_)) => sys_write_file(&mut proc, fd, base, len),
@ -66,17 +66,14 @@ pub fn sys_writev(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResu
pub fn sys_open(path: *const u8, flags: usize, mode: usize) -> SysResult {
let mut proc = process();
let path = unsafe { proc.memory_set.check_and_clone_cstr(path) }
.ok_or(SysError::EINVAL)?;
.ok_or(SysError::EFAULT)?;
let flags = OpenFlags::from_bits_truncate(flags);
info!("open: path: {:?}, flags: {:?}, mode: {:#o}", path, flags, mode);
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<INode>,
"stdout:" => crate::fs::STDOUT.clone() as Arc<INode>,
_ => ROOT_INODE.lookup(path.as_str())?,
_ => proc.lookup_inode(&path)?,
}
};
@ -139,10 +136,10 @@ pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult {
info!("fstat: fd: {}", fd);
let mut proc = process();
if !proc.memory_set.check_mut_ptr(stat_ptr) {
return Err(SysError::EINVAL);
return Err(SysError::EFAULT);
}
let file = proc.get_file(fd)?;
let stat = Stat::from(file.info()?);
let stat = Stat::from(file.metadata()?);
// TODO: handle symlink
unsafe { stat_ptr.write(stat); }
Ok(0)
@ -151,13 +148,13 @@ pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult {
pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
let mut proc = process();
let path = unsafe { proc.memory_set.check_and_clone_cstr(path) }
.ok_or(SysError::EINVAL)?;
.ok_or(SysError::EFAULT)?;
if !proc.memory_set.check_mut_ptr(stat_ptr) {
return Err(SysError::EINVAL);
return Err(SysError::EFAULT);
}
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)
@ -178,14 +175,41 @@ pub fn sys_lseek(fd: usize, offset: i64, whence: u8) -> SysResult {
Ok(offset as isize)
}
pub fn sys_fsync(fd: usize) -> SysResult {
info!("fsync: fd: {}", fd);
process().get_file(fd)?.sync_all()?;
Ok(0)
}
pub fn sys_fdatasync(fd: usize) -> SysResult {
info!("fdatasync: fd: {}", fd);
process().get_file(fd)?.sync_data()?;
Ok(0)
}
pub fn sys_truncate(path: *const u8, len: usize) -> SysResult {
let mut proc = process();
let path = unsafe { proc.memory_set.check_and_clone_cstr(path) }
.ok_or(SysError::EFAULT)?;
info!("truncate: path: {:?}, len: {}", path, len);
proc.lookup_inode(&path)?.resize(len)?;
Ok(0)
}
pub fn sys_ftruncate(fd: usize, len: usize) -> SysResult {
info!("ftruncate: fd: {}, len: {}", fd, len);
process().get_file(fd)?.set_len(len as u64)?;
Ok(0)
}
pub fn sys_getdents64(fd: usize, buf: *mut LinuxDirent64, buf_size: usize) -> SysResult {
info!("getdents64: fd: {}, ptr: {:?}, buf_size: {}", fd, buf, buf_size);
let mut proc = process();
if !proc.memory_set.check_mut_array(buf as *mut u8, buf_size) {
return Err(SysError::EINVAL);
return Err(SysError::EFAULT);
}
let file = proc.get_file(fd)?;
let info = file.info()?;
let info = file.metadata()?;
if info.type_ != FileType::Dir {
return Err(SysError::ENOTDIR);
}
@ -195,7 +219,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 +237,85 @@ 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)
}
pub fn sys_link(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!("link: oldpath: {:?}, newpath: {:?}", oldpath, newpath);
let (new_dir_path, new_file_name) = split_path(&newpath);
let inode = proc.lookup_inode(&oldpath)?;
let new_dir_inode = proc.lookup_inode(new_dir_path)?;
new_dir_inode.link(new_file_name, &inode)?;
Ok(0)
}
pub fn sys_unlink(path: *const u8) -> SysResult {
let mut proc = process();
let path = unsafe { proc.memory_set.check_and_clone_cstr(path) }
.ok_or(SysError::EFAULT)?;
info!("unlink: path: {:?}", path);
let (dir_path, file_name) = split_path(&path);
let dir_inode = proc.lookup_inode(dir_path)?;
dir_inode.unlink(file_name)?;
Ok(0)
}
impl Process {
fn get_file(&mut self, fd: usize) -> Result<&mut FileHandle, SysError> {
@ -222,6 +326,19 @@ impl Process {
}
})
}
fn lookup_inode(&self, path: &str) -> Result<Arc<INode>, 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<FsError> for SysError {
@ -481,14 +598,14 @@ struct IoVecs(Vec<&'static mut [u8]>);
impl IoVecs {
fn check_and_new(iov_ptr: *const IoVec, iov_count: usize, vm: &MemorySet, readv: bool) -> Result<Self, SysError> {
if !vm.check_array(iov_ptr, iov_count) {
return Err(SysError::EINVAL);
return Err(SysError::EFAULT);
}
let iovs = unsafe { slice::from_raw_parts(iov_ptr, iov_count) }.to_vec();
// check all bufs in iov
for iov in iovs.iter() {
if readv && !vm.check_mut_array(iov.base, iov.len as usize)
|| !readv && !vm.check_array(iov.base, iov.len as usize) {
return Err(SysError::EINVAL);
return Err(SysError::EFAULT);
}
}
let slices = iovs.iter().map(|iov| unsafe { slice::from_raw_parts_mut(iov.base, iov.len as usize) }).collect();

@ -50,7 +50,6 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
// 034 => sys_pause(),
035 => sys_sleep(args[0]), // TODO: nanosleep
039 => sys_getpid(),
// 040 => sys_getppid(),
041 => sys_socket(args[0], args[1], args[2]),
042 => sys_connect(args[0], args[1] as *const u8, args[2]),
// 043 => sys_accept(),
@ -70,18 +69,20 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
061 => sys_wait(args[0], args[1] as *mut i32), // TODO: wait4
062 => sys_kill(args[0]),
// 072 => sys_fcntl(),
// 074 => sys_fsync(),
// 076 => sys_trunc(),
// 077 => sys_ftrunc(),
074 => sys_fsync(args[0]),
075 => sys_fdatasync(args[0]),
076 => sys_truncate(args[0] as *const u8, args[1]),
077 => sys_ftruncate(args[0], args[1]),
079 => sys_getcwd(args[0] as *mut u8, args[1]),
// 080 => sys_chdir(),
// 082 => sys_rename(),
// 083 => sys_mkdir(),
// 086 => sys_link(),
// 087 => sys_unlink(),
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(args[0] as *const u8, args[1] as *const u8),
087 => sys_unlink(args[0] as *const u8),
096 => sys_get_time(), // TODO: sys_gettimeofday
// 097 => sys_getrlimit(),
// 098 => sys_getrusage(),
110 => sys_getppid(),
// 133 => sys_mknod(),
141 => sys_set_priority(args[0]),
158 => sys_arch_prctl(args[0] as i32, args[1], tf),
@ -117,6 +118,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)

@ -13,7 +13,9 @@ pub fn sys_fork(tf: &TrapFrame) -> SysResult {
/// Wait the process exit.
/// Return the PID. Store exit code to `code` if it's not null.
pub fn sys_wait(pid: usize, code: *mut i32) -> SysResult {
// TODO: check ptr
if !process().memory_set.check_mut_ptr(code) {
return Err(SysError::EFAULT);
}
loop {
use alloc::vec;
let wait_procs = match pid {
@ -49,19 +51,25 @@ pub fn sys_wait(pid: usize, code: *mut i32) -> SysResult {
}
pub fn sys_exec(name: *const u8, argc: usize, argv: *const *const u8, tf: &mut TrapFrame) -> SysResult {
// TODO: check ptr
let name = if name.is_null() { "" } else { unsafe { util::from_cstr(name) } };
info!("exec: {:?}, argc: {}, argv: {:?}", name, argc, argv);
// Copy args to kernel
let args: Vec<String> = unsafe {
slice::from_raw_parts(argv, argc).iter()
.map(|&arg| String::from(util::from_cstr(arg)))
.collect()
let proc = process();
let name = if name.is_null() { String::from("") } else {
unsafe { proc.memory_set.check_and_clone_cstr(name) }
.ok_or(SysError::EFAULT)?
};
if args.len() <= 0 {
if argc <= 0 {
return Err(SysError::EINVAL);
}
// Check and copy args to kernel
let mut args = Vec::new();
unsafe {
for &ptr in slice::from_raw_parts(argv, argc) {
let arg = proc.memory_set.check_and_clone_cstr(ptr)
.ok_or(SysError::EFAULT)?;
args.push(arg);
}
}
info!("exec: name: {:?}, args: {:?}", name, args);
// Read program file
let path = args[0].as_str();
let inode = crate::fs::ROOT_INODE.lookup(path)?;
@ -107,6 +115,13 @@ pub fn sys_getpid() -> SysResult {
Ok(thread::current().id() as isize)
}
/// Get the parent process id
pub fn sys_getppid() -> SysResult {
let pid = thread::current().id();
let ppid = processor().manager().get_parent(pid);
Ok(ppid as isize)
}
/// Exit the current process
pub fn sys_exit(exit_code: isize) -> ! {
let pid = thread::current().id();

Loading…
Cancel
Save