rename File to FileHandle. impl create for sys_open.

master
WangRunji 6 years ago
parent 6d78206f77
commit cab19688d5

9
kernel/Cargo.lock generated

@ -103,6 +103,11 @@ name = "cfg-if"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "deque"
version = "0.3.2"
source = "git+https://github.com/wangrunji0408/deque.git?branch=no_std#907d03935b9badde1902d9c84d138872f34c6763"
[[package]]
name = "device_tree"
version = "1.0.3"
@ -296,8 +301,9 @@ dependencies = [
name = "rcore-thread"
version = "0.1.0"
dependencies = [
"deque 0.3.2 (git+https://github.com/wangrunji0408/deque.git?branch=no_std)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -511,6 +517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
"checksum deque 0.3.2 (git+https://github.com/wangrunji0408/deque.git?branch=no_std)" = "<none>"
"checksum device_tree 1.0.3 (git+https://github.com/jiegec/device_tree-rs)" = "<none>"
"checksum fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c6c16d316ccdac21a4dd648e314e76facbbaf316e83ca137d0857a9c07419d0"
"checksum fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f7f8eb465745ea9b02e2704612a9946a59fa40572086c6fd49d6ddcf30bf31"

@ -1,31 +1,50 @@
//! File structure for process
//! File handle for process
use alloc::{string::String, sync::Arc};
use rcore_fs::vfs::{Metadata, INode, Result};
use rcore_fs::vfs::{Metadata, INode, Result, FsError};
#[derive(Clone)]
pub struct File {
pub struct FileHandle {
inode: Arc<INode>,
offset: usize,
readable: bool,
writable: bool,
options: OpenOptions,
}
impl File {
pub fn new(inode: Arc<INode>, readable: bool, writable: bool) -> Self {
File { inode, offset: 0, readable, writable }
#[derive(Debug, Clone)]
pub struct OpenOptions {
pub read: bool,
pub write: bool,
/// Before each write, the file offset is positioned at the end of the file.
pub append: bool,
}
impl FileHandle {
pub fn new(inode: Arc<INode>, options: OpenOptions) -> Self {
FileHandle {
inode,
offset: 0,
options,
}
}
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
assert!(self.readable);
if !self.options.read {
return Err(FsError::InvalidParam); // FIXME: => EBADF
}
let len = self.inode.read_at(self.offset, buf)?;
self.offset += len;
Ok(len)
}
pub fn write(&mut self, buf: &[u8]) -> Result<usize> {
assert!(self.writable);
if !self.options.write {
return Err(FsError::InvalidParam); // FIXME: => EBADF
}
if self.options.append {
let info = self.inode.metadata()?;
self.offset = info.size;
}
let len = self.inode.write_at(self.offset, buf)?;
self.offset += len;
Ok(len)

@ -10,7 +10,7 @@ use crate::arch::driver::ide;
use crate::drivers::{self, AsAny};
use crate::drivers::block::virtio_blk::VirtIOBlkDriver;
pub use self::file::File;
pub use self::file::*;
pub use self::stdio::{STDIN, STDOUT};
mod file;

@ -7,7 +7,7 @@ use xmas_elf::{ElfFile, header, program::{Flags, Type}};
use crate::arch::interrupt::{Context, TrapFrame};
use crate::memory::{ByFrame, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet};
use crate::fs::File;
use crate::fs::{FileHandle, OpenOptions};
use super::abi::ProcInitInfo;
@ -20,7 +20,7 @@ pub struct Thread {
pub struct Process {
pub memory_set: MemorySet,
pub files: BTreeMap<usize, File>,
pub files: BTreeMap<usize, FileHandle>,
pub cwd: String,
}
@ -112,9 +112,9 @@ impl Thread {
let kstack = KernelStack::new();
let mut files = BTreeMap::new();
files.insert(0, File::new(crate::fs::STDIN.clone(), true, false));
files.insert(1, File::new(crate::fs::STDOUT.clone(), false, true));
files.insert(2, File::new(crate::fs::STDOUT.clone(), false, true));
files.insert(0, FileHandle::new(crate::fs::STDIN.clone(), OpenOptions { read: true, write: false, append: false }));
files.insert(1, FileHandle::new(crate::fs::STDOUT.clone(), OpenOptions { read: false, write: true, append: false }));
files.insert(2, FileHandle::new(crate::fs::STDOUT.clone(), OpenOptions { read: false, write: true, append: false }));
Box::new(Thread {
context: unsafe {

@ -2,6 +2,8 @@
use super::*;
use crate::fs::{ROOT_INODE, OpenOptions};
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();
@ -24,22 +26,44 @@ pub fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult {
Ok(len as isize)
}
pub fn sys_open(path: *const u8, flags: usize) -> SysResult {
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::Inval)?;
let flags = VfsFlags::from_ucore_flags(flags);
info!("open: path: {:?}, flags: {:?}", path, flags);
let (fd, inode) = match path.as_str() {
"stdin:" => (0, crate::fs::STDIN.clone() as Arc<INode>),
"stdout:" => (1, crate::fs::STDOUT.clone() as Arc<INode>),
_ => {
let fd = (3..).find(|i| !proc.files.contains_key(i)).unwrap();
let inode = crate::fs::ROOT_INODE.lookup(path.as_str())?;
(fd, inode)
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)?;
match dir_inode.find(file_name) {
Ok(file_inode) => {
if flags.contains(OpenFlags::EXCLUSIVE) {
return Err(SysError::Exists);
}
file_inode
},
Err(FsError::EntryNotFound) => {
dir_inode.create(file_name, FileType::File, mode as u32)?
}
Err(e) => return Err(SysError::from(e)),
}
} else {
// TODO: remove "stdin:" "stdout:"
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())?,
}
};
let file = File::new(inode, flags.contains(VfsFlags::READABLE), flags.contains(VfsFlags::WRITABLE));
let fd = (3..).find(|i| !proc.files.contains_key(i)).unwrap();
let file = FileHandle::new(inode, flags.to_options());
proc.files.insert(fd, file);
Ok(fd as isize)
}
@ -98,30 +122,44 @@ pub fn sys_dup2(fd1: usize, fd2: usize) -> SysResult {
Ok(0)
}
fn get_file<'a>(proc: &'a mut MutexGuard<'static, Process>, fd: usize) -> Result<&'a mut File, SysError> {
fn get_file<'a>(proc: &'a mut MutexGuard<'static, Process>, fd: usize) -> Result<&'a mut FileHandle, SysError> {
proc.files.get_mut(&fd).ok_or(SysError::Inval)
}
bitflags! {
struct VfsFlags: usize {
// WARNING: different from origin uCore
const READABLE = 1 << 0;
const WRITABLE = 1 << 1;
struct OpenFlags: usize {
/// read only
const RDONLY = 0;
/// write only
const WRONLY = 1;
/// read write
const RDWR = 2;
/// create file if it does not exist
const CREATE = 1 << 2;
/// error if O_CREAT and the file exists
const EXCLUSIVE = 1 << 3;
const CREATE = 1 << 6;
/// error if CREATE and the file exists
const EXCLUSIVE = 1 << 7;
/// truncate file upon open
const TRUNCATE = 1 << 4;
const TRUNCATE = 1 << 9;
/// append on each write
const APPEND = 1 << 5;
const APPEND = 1 << 10;
}
}
impl VfsFlags {
fn from_ucore_flags(f: usize) -> Self {
assert_ne!(f & 0b11, 0b11);
Self::from_bits_truncate(f + 1)
impl OpenFlags {
fn readable(&self) -> bool {
let b = self.bits() & 0b11;
b == OpenFlags::RDONLY.bits() || b == OpenFlags::RDWR.bits()
}
fn writable(&self) -> bool {
let b = self.bits() & 0b11;
b == OpenFlags::WRONLY.bits() || b == OpenFlags::RDWR.bits()
}
fn to_options(&self) -> OpenOptions {
OpenOptions {
read: self.readable(),
write: self.writable(),
append: self.contains(OpenFlags::APPEND),
}
}
}

@ -8,7 +8,7 @@ use rcore_fs::vfs::{FileType, FsError, INode, Metadata};
use spin::{Mutex, MutexGuard};
use crate::arch::interrupt::TrapFrame;
use crate::fs::File;
use crate::fs::FileHandle;
use crate::process::*;
use crate::thread;
use crate::util;
@ -31,7 +31,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
// file
000 => sys_read(args[0], args[1] as *mut u8, args[2]),
001 => sys_write(args[0], args[1] as *const u8, args[2]),
002 => sys_open(args[0] as *const u8, args[1]),
002 => sys_open(args[0] as *const u8, args[1], args[2]),
003 => sys_close(args[0]),
// 004 => sys_stat(),
005 => sys_fstat(args[0], args[1] as *mut Stat),
@ -107,7 +107,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
158 => sys_arch_prctl(args[0] as i32, args[1], tf),
218 => {
warn!("sys_set_tid_address is unimplemented");
Ok(0)
Ok(thread::current().id() as isize)
}
_ => {
error!("unknown syscall id: {:#x?}, args: {:x?}", id, args);

Loading…
Cancel
Save