Use file description alongside file descriptior, matching posix
This commit is contained in:
@@ -5,7 +5,7 @@ use core::mem;
|
||||
use spin::Mutex;
|
||||
|
||||
use context::arch;
|
||||
use context::file::File;
|
||||
use context::file::FileDescriptor;
|
||||
use context::memory::{Grant, Memory, SharedMemory, Tls};
|
||||
use device;
|
||||
use scheme::{SchemeNamespace, FileHandle};
|
||||
@@ -92,7 +92,7 @@ pub struct Context {
|
||||
/// The process environment
|
||||
pub env: Arc<Mutex<BTreeMap<Box<[u8]>, Arc<Mutex<Vec<u8>>>>>>,
|
||||
/// The open files in the scheme
|
||||
pub files: Arc<Mutex<Vec<Option<File>>>>,
|
||||
pub files: Arc<Mutex<Vec<Option<FileDescriptor>>>>,
|
||||
/// Singal actions
|
||||
pub actions: Arc<Mutex<Vec<(SigAction, usize)>>>,
|
||||
}
|
||||
@@ -243,7 +243,7 @@ impl Context {
|
||||
|
||||
/// Add a file to the lowest available slot.
|
||||
/// Return the file descriptor number or None if no slot was found
|
||||
pub fn add_file(&self, file: File) -> Option<FileHandle> {
|
||||
pub fn add_file(&self, file: FileDescriptor) -> Option<FileHandle> {
|
||||
let mut files = self.files.lock();
|
||||
for (i, mut file_option) in files.iter_mut().enumerate() {
|
||||
if file_option.is_none() {
|
||||
@@ -261,7 +261,7 @@ impl Context {
|
||||
}
|
||||
|
||||
/// Get a file
|
||||
pub fn get_file(&self, i: FileHandle) -> Option<File> {
|
||||
pub fn get_file(&self, i: FileHandle) -> Option<FileDescriptor> {
|
||||
let files = self.files.lock();
|
||||
if i.into() < files.len() {
|
||||
files[i.into()].clone()
|
||||
@@ -272,7 +272,7 @@ impl Context {
|
||||
|
||||
/// Insert a file with a specific handle number. This is used by dup2
|
||||
/// Return the file descriptor number or None if the slot was not empty, or i was invalid
|
||||
pub fn insert_file(&self, i: FileHandle, file: File) -> Option<FileHandle> {
|
||||
pub fn insert_file(&self, i: FileHandle, file: FileDescriptor) -> Option<FileHandle> {
|
||||
let mut files = self.files.lock();
|
||||
if i.into() < super::CONTEXT_MAX_FILES {
|
||||
while i.into() >= files.len() {
|
||||
@@ -291,7 +291,7 @@ impl Context {
|
||||
|
||||
/// Remove a file
|
||||
// TODO: adjust files vector to smaller size if possible
|
||||
pub fn remove_file(&self, i: FileHandle) -> Option<File> {
|
||||
pub fn remove_file(&self, i: FileHandle) -> Option<FileDescriptor> {
|
||||
let mut files = self.files.lock();
|
||||
if i.into() < files.len() {
|
||||
files[i.into()].take()
|
||||
|
||||
@@ -1,17 +1,51 @@
|
||||
//! File struct
|
||||
//! File structs
|
||||
|
||||
use scheme::SchemeId;
|
||||
use alloc::arc::Arc;
|
||||
use spin::RwLock;
|
||||
use scheme::{self, SchemeId};
|
||||
use core::mem;
|
||||
use syscall::error::{Result, Error, EBADF};
|
||||
use scheme::FileHandle;
|
||||
use context;
|
||||
|
||||
/// A file
|
||||
//TODO: Close on exec
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct File {
|
||||
/// A file description
|
||||
#[derive(Debug)]
|
||||
pub struct FileDescription {
|
||||
/// The scheme that this file refers to
|
||||
pub scheme: SchemeId,
|
||||
/// The number the scheme uses to refer to this file
|
||||
pub number: usize,
|
||||
/// The flags passed to open or fcntl(SETFL)
|
||||
pub flags: usize,
|
||||
}
|
||||
|
||||
/// A file descriptor
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FileDescriptor {
|
||||
/// Corresponding file description
|
||||
pub description: Arc<RwLock<FileDescription>>,
|
||||
/// If events are on, this is the event ID
|
||||
pub event: Option<usize>,
|
||||
/// Cloexec flag
|
||||
pub cloexec: bool,
|
||||
}
|
||||
|
||||
impl FileDescriptor {
|
||||
pub fn close(self, fd: FileHandle) -> Result<usize> {
|
||||
if let Some(event_id) = self.event {
|
||||
context::event::unregister(fd, self.description.read().scheme, event_id);
|
||||
}
|
||||
|
||||
if let Ok(file) = Arc::try_unwrap(self.description) {
|
||||
let file = file.into_inner();
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
|
||||
scheme.clone()
|
||||
};
|
||||
scheme.close(file.number)
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,25 +31,27 @@ pub fn resource() -> Result<Vec<u8>> {
|
||||
Some(ref file) => file.clone()
|
||||
};
|
||||
|
||||
let description = file.description.read();
|
||||
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
match schemes.get(file.scheme) {
|
||||
match schemes.get(description.scheme) {
|
||||
Some(scheme) => scheme.clone(),
|
||||
None => {
|
||||
let _ = writeln!(string, " {:>4}: {:>8} {:>8} {:>08X}: no scheme", fd, file.scheme.into(), file.number, file.flags);
|
||||
let _ = writeln!(string, " {:>4}: {:>8} {:>8} {:>08X}: no scheme", fd, description.scheme.into(), description.number, description.flags);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mut fpath = [0; 4096];
|
||||
match scheme.fpath(file.number, &mut fpath) {
|
||||
match scheme.fpath(description.number, &mut fpath) {
|
||||
Ok(path_len) => {
|
||||
let fname = str::from_utf8(&fpath[..path_len]).unwrap_or("?");
|
||||
let _ = writeln!(string, "{:>6}: {:>8} {:>8} {:>08X}: {}", fd, file.scheme.into(), file.number, file.flags, fname);
|
||||
let _ = writeln!(string, "{:>6}: {:>8} {:>8} {:>08X}: {}", fd, description.scheme.into(), description.number, description.flags, fname);
|
||||
},
|
||||
Err(err) => {
|
||||
let _ = writeln!(string, "{:>6}: {:>8} {:>8} {:>08X}: {}", fd, file.scheme.into(), file.number, file.flags, err);
|
||||
let _ = writeln!(string, "{:>6}: {:>8} {:>8} {:>08X}: {}", fd, description.scheme.into(), description.number, description.flags, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//! Filesystem syscalls
|
||||
use core::sync::atomic::Ordering;
|
||||
use alloc::arc::Arc;
|
||||
use spin::RwLock;
|
||||
|
||||
use context;
|
||||
use scheme::{self, FileHandle};
|
||||
@@ -7,6 +9,7 @@ use syscall;
|
||||
use syscall::data::{Packet, Stat};
|
||||
use syscall::error::*;
|
||||
use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE, O_RDONLY, O_WRONLY, MODE_DIR, MODE_FILE, O_CLOEXEC};
|
||||
use context::file::{FileDescriptor, FileDescription};
|
||||
|
||||
pub fn file_op(a: usize, fd: FileHandle, c: usize, d: usize) -> Result<usize> {
|
||||
let (file, pid, uid, gid) = {
|
||||
@@ -19,7 +22,7 @@ pub fn file_op(a: usize, fd: FileHandle, c: usize, d: usize) -> Result<usize> {
|
||||
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
|
||||
let scheme = schemes.get(file.description.read().scheme).ok_or(Error::new(EBADF))?;
|
||||
scheme.clone()
|
||||
};
|
||||
|
||||
@@ -29,7 +32,7 @@ pub fn file_op(a: usize, fd: FileHandle, c: usize, d: usize) -> Result<usize> {
|
||||
uid: uid,
|
||||
gid: gid,
|
||||
a: a,
|
||||
b: file.number,
|
||||
b: file.description.read().number,
|
||||
c: c,
|
||||
d: d
|
||||
};
|
||||
@@ -109,11 +112,14 @@ pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
context.add_file(::context::file::File {
|
||||
scheme: scheme_id,
|
||||
number: file_id,
|
||||
flags: flags,
|
||||
context.add_file(FileDescriptor {
|
||||
description: Arc::new(RwLock::new(FileDescription {
|
||||
scheme: scheme_id,
|
||||
number: file_id,
|
||||
flags: flags & !O_CLOEXEC,
|
||||
})),
|
||||
event: None,
|
||||
cloexec: flags & O_CLOEXEC == O_CLOEXEC,
|
||||
}).ok_or(Error::new(EMFILE))
|
||||
}
|
||||
|
||||
@@ -126,18 +132,24 @@ pub fn pipe2(fds: &mut [usize], flags: usize) -> Result<usize> {
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
|
||||
let read_fd = context.add_file(::context::file::File {
|
||||
scheme: scheme_id,
|
||||
number: read_id,
|
||||
flags: O_RDONLY | flags & !O_ACCMODE,
|
||||
let read_fd = context.add_file(FileDescriptor {
|
||||
description: Arc::new(RwLock::new(FileDescription {
|
||||
scheme: scheme_id,
|
||||
number: read_id,
|
||||
flags: O_RDONLY | flags & !O_ACCMODE & !O_CLOEXEC,
|
||||
})),
|
||||
event: None,
|
||||
cloexec: flags & O_CLOEXEC == O_CLOEXEC,
|
||||
}).ok_or(Error::new(EMFILE))?;
|
||||
|
||||
let write_fd = context.add_file(::context::file::File {
|
||||
scheme: scheme_id,
|
||||
number: write_id,
|
||||
flags: O_WRONLY | flags & !O_ACCMODE,
|
||||
let write_fd = context.add_file(FileDescriptor {
|
||||
description: Arc::new(RwLock::new(FileDescription {
|
||||
scheme: scheme_id,
|
||||
number: write_id,
|
||||
flags: O_WRONLY | flags & !O_ACCMODE & !O_CLOEXEC,
|
||||
})),
|
||||
event: None,
|
||||
cloexec: flags & O_CLOEXEC == O_CLOEXEC,
|
||||
}).ok_or(Error::new(EMFILE))?;
|
||||
|
||||
fds[0] = read_fd.into();
|
||||
@@ -225,16 +237,7 @@ pub fn close(fd: FileHandle) -> Result<usize> {
|
||||
file
|
||||
};
|
||||
|
||||
if let Some(event_id) = file.event {
|
||||
context::event::unregister(fd, file.scheme, event_id);
|
||||
}
|
||||
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
|
||||
scheme.clone()
|
||||
};
|
||||
scheme.close(file.number)
|
||||
file.close(fd)
|
||||
}
|
||||
|
||||
/// Duplicate file descriptor
|
||||
@@ -247,24 +250,43 @@ pub fn dup(fd: FileHandle, buf: &[u8]) -> Result<FileHandle> {
|
||||
file
|
||||
};
|
||||
|
||||
let new_id = {
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
|
||||
scheme.clone()
|
||||
};
|
||||
scheme.dup(file.number, buf)?
|
||||
};
|
||||
if buf.is_empty() {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
context.add_file(::context::file::File {
|
||||
scheme: file.scheme,
|
||||
number: new_id,
|
||||
flags: file.flags & !O_CLOEXEC,
|
||||
event: None,
|
||||
}).ok_or(Error::new(EMFILE))
|
||||
context.add_file(FileDescriptor {
|
||||
description: Arc::clone(&file.description),
|
||||
event: None,
|
||||
cloexec: false,
|
||||
}).ok_or(Error::new(EMFILE))
|
||||
} else {
|
||||
let description = file.description.read();
|
||||
|
||||
let new_id = {
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(description.scheme).ok_or(Error::new(EBADF))?;
|
||||
|
||||
scheme.clone()
|
||||
};
|
||||
scheme.dup(description.number, buf)?
|
||||
};
|
||||
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
|
||||
context.add_file(FileDescriptor {
|
||||
description: Arc::new(RwLock::new(FileDescription {
|
||||
scheme: description.scheme,
|
||||
number: new_id,
|
||||
flags: description.flags,
|
||||
})),
|
||||
event: None,
|
||||
cloexec: false,
|
||||
}).ok_or(Error::new(EMFILE))
|
||||
}
|
||||
}
|
||||
|
||||
/// Duplicate file descriptor, replacing another
|
||||
@@ -278,28 +300,46 @@ pub fn dup2(fd: FileHandle, new_fd: FileHandle, buf: &[u8]) -> Result<FileHandle
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
let file = context.get_file(fd).ok_or(Error::new(EBADF))?;
|
||||
file
|
||||
context.get_file(fd).ok_or(Error::new(EBADF))?
|
||||
};
|
||||
|
||||
let new_id = {
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
|
||||
scheme.clone()
|
||||
if buf.is_empty() {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
|
||||
context.insert_file(new_fd, FileDescriptor {
|
||||
description: Arc::clone(&file.description),
|
||||
event: None,
|
||||
cloexec: false,
|
||||
}).ok_or(Error::new(EBADF))
|
||||
} else {
|
||||
let description = file.description.read();
|
||||
|
||||
let new_id = {
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(description.scheme).ok_or(Error::new(EBADF))?;
|
||||
|
||||
scheme.clone()
|
||||
};
|
||||
scheme.dup(description.number, buf)?
|
||||
};
|
||||
scheme.dup(file.number, buf)?
|
||||
};
|
||||
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
context.insert_file(new_fd, ::context::file::File {
|
||||
scheme: file.scheme,
|
||||
number: new_id,
|
||||
flags: file.flags & !O_CLOEXEC,
|
||||
event: None,
|
||||
}).ok_or(Error::new(EBADF))
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
|
||||
context.insert_file(new_fd, FileDescriptor {
|
||||
description: Arc::new(RwLock::new(FileDescription {
|
||||
scheme: description.scheme,
|
||||
number: new_id,
|
||||
flags: description.flags,
|
||||
})),
|
||||
event: None,
|
||||
cloexec: false,
|
||||
}).ok_or(Error::new(EMFILE))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,14 +353,16 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
|
||||
file
|
||||
};
|
||||
|
||||
let description = file.description.read();
|
||||
|
||||
// Communicate fcntl with scheme
|
||||
let _res = {
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
|
||||
let scheme = schemes.get(description.scheme).ok_or(Error::new(EBADF))?;
|
||||
scheme.clone()
|
||||
};
|
||||
scheme.fcntl(file.number, cmd, arg)?
|
||||
scheme.fcntl(description.number, cmd, arg)?
|
||||
};
|
||||
|
||||
// Perform kernel operation if scheme agrees
|
||||
@@ -332,11 +374,12 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
|
||||
match *files.get_mut(fd.into()).ok_or(Error::new(EBADF))? {
|
||||
Some(ref mut file) => match cmd {
|
||||
F_GETFL => {
|
||||
Ok(file.flags)
|
||||
Ok(description.flags)
|
||||
},
|
||||
F_SETFL => {
|
||||
let new_flags = (file.flags & O_ACCMODE) | (arg & ! O_ACCMODE);
|
||||
file.flags = new_flags;
|
||||
let new_flags = (description.flags & O_ACCMODE) | (arg & ! O_ACCMODE);
|
||||
drop(description);
|
||||
file.description.write().flags = new_flags;
|
||||
Ok(0)
|
||||
},
|
||||
_ => {
|
||||
@@ -357,9 +400,10 @@ pub fn fevent(fd: FileHandle, flags: usize) -> Result<usize> {
|
||||
let mut files = context.files.lock();
|
||||
match *files.get_mut(fd.into()).ok_or(Error::new(EBADF))? {
|
||||
Some(ref mut file) => {
|
||||
let description = file.description.read();
|
||||
if let Some(event_id) = file.event.take() {
|
||||
println!("{:?}: {:?}:{}: events already registered: {}", fd, file.scheme, file.number, event_id);
|
||||
context::event::unregister(fd, file.scheme, event_id);
|
||||
println!("{:?}: {:?}:{}: events already registered: {}", fd, description.scheme, description.number, event_id);
|
||||
context::event::unregister(fd, description.scheme, event_id);
|
||||
}
|
||||
file.clone()
|
||||
},
|
||||
@@ -367,12 +411,14 @@ pub fn fevent(fd: FileHandle, flags: usize) -> Result<usize> {
|
||||
}
|
||||
};
|
||||
|
||||
let description = file.description.read();
|
||||
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
|
||||
let scheme = schemes.get(description.scheme).ok_or(Error::new(EBADF))?;
|
||||
scheme.clone()
|
||||
};
|
||||
let event_id = scheme.fevent(file.number, flags)?;
|
||||
let event_id = scheme.fevent(description.number, flags)?;
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
@@ -383,7 +429,7 @@ pub fn fevent(fd: FileHandle, flags: usize) -> Result<usize> {
|
||||
None => return Err(Error::new(EBADF)),
|
||||
}
|
||||
}
|
||||
context::event::register(fd, file.scheme, event_id);
|
||||
context::event::register(fd, description.scheme, event_id);
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
///! Process syscalls
|
||||
use alloc::allocator::{Alloc, Layout};
|
||||
use alloc::arc::Arc;
|
||||
use alloc::boxed::Box;
|
||||
@@ -15,6 +14,7 @@ use start::usermode;
|
||||
use interrupt;
|
||||
use context;
|
||||
use context::ContextId;
|
||||
use context::file::FileDescriptor;
|
||||
use elf::{self, program_header};
|
||||
use scheme::{self, FileHandle};
|
||||
use syscall;
|
||||
@@ -284,27 +284,11 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
|
||||
if flags & CLONE_FILES == 0 {
|
||||
for (_fd, mut file_option) in files.lock().iter_mut().enumerate() {
|
||||
let new_file_option = if let Some(ref file) = *file_option {
|
||||
let result = {
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
|
||||
scheme.clone()
|
||||
};
|
||||
scheme.dup(file.number, b"")
|
||||
};
|
||||
match result {
|
||||
Ok(new_number) => {
|
||||
Some(context::file::File {
|
||||
scheme: file.scheme,
|
||||
number: new_number,
|
||||
flags: file.flags,
|
||||
event: None,
|
||||
})
|
||||
},
|
||||
Err(_err) => {
|
||||
None
|
||||
}
|
||||
}
|
||||
Some(FileDescriptor {
|
||||
description: Arc::clone(&file.description),
|
||||
event: None,
|
||||
cloexec: file.cloexec,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -617,7 +601,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
|
||||
drop(path); // Drop so that usage is not allowed after unmapping context
|
||||
drop(arg_ptrs); // Drop so that usage is not allowed after unmapping context
|
||||
|
||||
let (vfork, ppid, files) = {
|
||||
let (vfork, ppid) = {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let mut context = context_lock.write();
|
||||
@@ -777,9 +761,6 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
|
||||
context.image.push(memory.to_shared());
|
||||
}
|
||||
|
||||
let files = Arc::new(Mutex::new(context.files.lock().clone()));
|
||||
context.files = files.clone();
|
||||
|
||||
context.actions = Arc::new(Mutex::new(vec![(
|
||||
SigAction {
|
||||
sa_handler: unsafe { mem::transmute(SIG_DFL) },
|
||||
@@ -791,65 +772,23 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
|
||||
|
||||
let vfork = context.vfork;
|
||||
context.vfork = false;
|
||||
(vfork, context.ppid, files)
|
||||
|
||||
for (fd, file_option) in context.files.lock().iter_mut().enumerate() {
|
||||
let mut cloexec = false;
|
||||
if let Some(ref file) = *file_option {
|
||||
if file.cloexec {
|
||||
cloexec = true;
|
||||
}
|
||||
}
|
||||
|
||||
if cloexec {
|
||||
let _ = file_option.take().unwrap().close(FileHandle::from(fd));
|
||||
}
|
||||
}
|
||||
|
||||
(vfork, context.ppid)
|
||||
};
|
||||
|
||||
// Duplicate current files, close previous
|
||||
for (fd, mut file_option) in files.lock().iter_mut().enumerate() {
|
||||
let new_file_option = if let Some(ref file) = *file_option {
|
||||
// Duplicate
|
||||
let result = {
|
||||
if file.flags & O_CLOEXEC == O_CLOEXEC {
|
||||
Err(Error::new(EBADF))
|
||||
} else {
|
||||
let scheme_option = {
|
||||
let schemes = scheme::schemes();
|
||||
schemes.get(file.scheme).map(|scheme| scheme.clone())
|
||||
};
|
||||
if let Some(scheme) = scheme_option {
|
||||
scheme.dup(file.number, b"")
|
||||
} else {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Close
|
||||
{
|
||||
if let Some(event_id) = file.event {
|
||||
context::event::unregister(FileHandle::from(fd), file.scheme, event_id);
|
||||
}
|
||||
|
||||
let scheme_option = {
|
||||
let schemes = scheme::schemes();
|
||||
schemes.get(file.scheme).map(|scheme| scheme.clone())
|
||||
};
|
||||
if let Some(scheme) = scheme_option {
|
||||
let _ = scheme.close(file.number);
|
||||
}
|
||||
}
|
||||
|
||||
// Return new descriptor
|
||||
match result {
|
||||
Ok(new_number) => {
|
||||
Some(context::file::File {
|
||||
scheme: file.scheme,
|
||||
number: new_number,
|
||||
flags: file.flags,
|
||||
event: None,
|
||||
})
|
||||
},
|
||||
Err(_err) => {
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
*file_option = new_file_option;
|
||||
}
|
||||
|
||||
if vfork {
|
||||
let contexts = context::contexts();
|
||||
if let Some(context_lock) = contexts.get(ppid) {
|
||||
@@ -897,17 +836,7 @@ pub fn exit(status: usize) -> ! {
|
||||
/// Files must be closed while context is valid so that messages can be passed
|
||||
for (fd, file_option) in close_files.drain(..).enumerate() {
|
||||
if let Some(file) = file_option {
|
||||
if let Some(event_id) = file.event {
|
||||
context::event::unregister(FileHandle::from(fd), file.scheme, event_id);
|
||||
}
|
||||
|
||||
let scheme_option = {
|
||||
let schemes = scheme::schemes();
|
||||
schemes.get(file.scheme).map(|scheme| scheme.clone())
|
||||
};
|
||||
if let Some(scheme) = scheme_option {
|
||||
let _ = scheme.close(file.number);
|
||||
}
|
||||
let _ = file.close(FileHandle::from(fd));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user