diff --git a/src/libos/src/fs/mod.rs b/src/libos/src/fs/mod.rs index d0c57b66..d845563e 100644 --- a/src/libos/src/fs/mod.rs +++ b/src/libos/src/fs/mod.rs @@ -35,24 +35,8 @@ pub fn do_open(path: &str, flags: u32, mode: u32) -> Result { let current_ref = process::get_current(); let mut proc = current_ref.lock().unwrap(); - 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(Error::new(EEXIST, "file exists")); - } - file_inode - } - Err(FsError::EntryNotFound) => dir_inode.create(file_name, FileType::File, mode)?, - Err(e) => return Err(Error::from(e)), - } - } else { - proc.lookup_inode(&path)? - }; - - let file_ref: Arc> = Arc::new(Box::new(INodeFile::open(inode, flags.to_options())?)); + let file = proc.open_file(path, flags, mode)?; + let file_ref: Arc> = Arc::new(Box::new(file)); let fd = { let close_on_spawn = flags.contains(OpenFlags::CLOEXEC); @@ -363,6 +347,28 @@ extern "C" { } impl Process { + /// Open a file on the process. But DO NOT add it to file table. + pub fn open_file(&self, path: &str, flags: OpenFlags, mode: u32) -> Result { + let inode = if flags.contains(OpenFlags::CREATE) { + let (dir_path, file_name) = split_path(&path); + let dir_inode = self.lookup_inode(dir_path)?; + match dir_inode.find(file_name) { + Ok(file_inode) => { + if flags.contains(OpenFlags::EXCLUSIVE) { + return Err(Error::new(EEXIST, "file exists")); + } + file_inode + } + Err(FsError::EntryNotFound) => dir_inode.create(file_name, FileType::File, mode)?, + Err(e) => return Err(Error::from(e)), + } + } else { + self.lookup_inode(&path)? + }; + INodeFile::open(inode, flags.to_options()) + } + + /// Lookup INode from the cwd of the process pub fn lookup_inode(&self, path: &str) -> Result, Error> { debug!("lookup_inode: cwd: {:?}, path: {:?}", self.get_cwd(), path); if path.len() > 0 && path.as_bytes()[0] == b'/' { diff --git a/src/libos/src/process/spawn/mod.rs b/src/libos/src/process/spawn/mod.rs index ca218537..b8654c2f 100644 --- a/src/libos/src/process/spawn/mod.rs +++ b/src/libos/src/process/spawn/mod.rs @@ -1,7 +1,7 @@ use xmas_elf::{ElfFile, header, program, sections}; use xmas_elf::symbol_table::Entry; -use fs::{File, FileDesc, FileTable, INodeExt, ROOT_INODE, StdinFile, StdoutFile}; +use fs::{File, FileDesc, FileTable, INodeExt, ROOT_INODE, StdinFile, StdoutFile, OpenFlags}; use std::ffi::{CStr, CString}; use std::path::Path; use std::sgxfs::SgxFile; @@ -20,8 +20,14 @@ mod segment; #[derive(Debug)] pub enum FileAction { - // TODO: Add open action - // Open(...) + /// open(path, oflag, mode) had been called, and the returned file + /// descriptor, if not `fd`, had been changed to `fd`. + Open { + path: String, + mode: u32, + oflag: u32, + fd: FileDesc, + }, Dup2(FileDesc, FileDesc), Close(FileDesc), } @@ -92,14 +98,22 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result { - let file = cloned_file_table.get(*old_fd)?; + &FileAction::Open { ref path, mode, oflag, fd} => { + let flags = OpenFlags::from_bits_truncate(oflag); + let file = parent.open_file(path.as_str(), flags, mode)?; + let file_ref: Arc> = Arc::new(Box::new(file)); + + let close_on_spawn = flags.contains(OpenFlags::CLOEXEC); + cloned_file_table.put_at(fd, file_ref, close_on_spawn); + } + &FileAction::Dup2(old_fd, new_fd) => { + let file = cloned_file_table.get(old_fd)?; if old_fd != new_fd { - cloned_file_table.put_at(*new_fd, file, false); + cloned_file_table.put_at(new_fd, file, false); } } - FileAction::Close(fd) => { - cloned_file_table.del(*fd)?; + &FileAction::Close(fd) => { + cloned_file_table.del(fd)?; } } } diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 0bea6239..6bc09dd8 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -283,7 +283,7 @@ pub struct FdOp { srcfd: u32, oflag: u32, mode: u32, - path: *const u8, + path: *const i8, } fn clone_file_actions_safely(fdop_ptr: *const FdOp) -> Result, Error> { @@ -297,9 +297,12 @@ fn clone_file_actions_safely(fdop_ptr: *const FdOp) -> Result, E let file_action = match fdop.cmd { FDOP_CLOSE => FileAction::Close(fdop.fd), FDOP_DUP2 => FileAction::Dup2(fdop.srcfd, fdop.fd), - FDOP_OPEN => { - return errno!(EINVAL, "Not implemented"); - } + FDOP_OPEN => FileAction::Open { + path: clone_cstring_safely(fdop.path)?.to_string_lossy().into_owned(), + mode: fdop.mode, + oflag: fdop.oflag, + fd: fdop.fd, + }, _ => { return errno!(EINVAL, "Unknown file action command"); }