Implement null file that can only be duped or closed.

This commit is contained in:
Jeremy Soller
2017-11-16 19:43:13 -07:00
parent 34abddb2f0
commit 5e65afb769
+47 -14
View File
@@ -16,6 +16,12 @@ use syscall;
use error::{Error, Result};
use super::{post_fevent, SocketSet};
pub struct NullFile {
pub flags: usize,
pub uid: u32,
pub gid: u32,
}
pub struct SocketFile<DataT> {
pub flags: usize,
pub data: DataT,
@@ -146,6 +152,7 @@ where
SocketT: SchemeSocket + AnySocket<'static, 'static>,
{
next_fd: usize,
nulls: BTreeMap<usize, NullFile>,
files: BTreeMap<usize, SchemeFile<SocketT>>,
socket_set: Rc<RefCell<SocketSet>>,
scheme_file: File,
@@ -161,6 +168,7 @@ where
pub fn new(socket_set: Rc<RefCell<SocketSet>>, scheme_file: File) -> SocketScheme<SocketT> {
SocketScheme {
next_fd: 1,
nulls: BTreeMap::new(),
files: BTreeMap::new(),
socket_set,
scheme_data: SocketT::new_scheme_data(),
@@ -455,31 +463,50 @@ where
fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> SyscallResult<usize> {
let path = str::from_utf8(url).or_else(|_| Err(SyscallError::new(syscall::EINVAL)))?;
let (socket_handle, data) = SocketT::new_socket(
&mut self.socket_set.borrow_mut(),
path,
uid,
&mut self.scheme_data,
)?;
if path.is_empty() {
let null = NullFile {
flags: flags,
uid: uid,
gid: _gid,
};
let id = self.next_fd;
let id = self.next_fd;
self.next_fd += 1;
self.files.insert(
id,
SchemeFile::Socket(SocketFile {
self.nulls.insert(id, null);
Ok(id)
} else {
let (socket_handle, data) = SocketT::new_socket(
&mut self.socket_set.borrow_mut(),
path,
uid,
&mut self.scheme_data,
)?;
let file = SchemeFile::Socket(SocketFile {
flags,
events: 0,
socket_handle,
write_timeout: None,
read_timeout: None,
data,
}),
);
self.next_fd += 1;
Ok(id)
});
let id = self.next_fd;
self.next_fd += 1;
self.files.insert(id, file);
Ok(id)
}
}
fn close(&mut self, fd: usize) -> SyscallResult<usize> {
if let Some(_null) = self.nulls.remove(&fd) {
return Ok(0);
}
let socket_handle = {
let file = self.files
.get(&fd)
@@ -553,6 +580,12 @@ where
}
fn dup(&mut self, fd: usize, buf: &[u8]) -> SyscallResult<usize> {
if let Some((flags, uid, gid)) = self.nulls.get(&fd).map(|null| {
(null.flags, null.uid, null.gid)
}) {
return self.open(buf, flags, uid, gid);
}
let path = str::from_utf8(buf).or_else(|_| Err(SyscallError::new(syscall::EINVAL)))?;
let new_file = {