fix for php. include incomplete code for UnixSocket
This commit is contained in:
parent
f846ba11f2
commit
9106bd46f2
@ -3,7 +3,7 @@
|
|||||||
<ProdID>0</ProdID>
|
<ProdID>0</ProdID>
|
||||||
<ISVSVN>0</ISVSVN>
|
<ISVSVN>0</ISVSVN>
|
||||||
<StackMaxSize>0x100000</StackMaxSize>
|
<StackMaxSize>0x100000</StackMaxSize>
|
||||||
<HeapMaxSize>0x1000000</HeapMaxSize>
|
<HeapMaxSize>0x2000000</HeapMaxSize>
|
||||||
<TCSNum>8</TCSNum>
|
<TCSNum>8</TCSNum>
|
||||||
<TCSPolicy>1</TCSPolicy>
|
<TCSPolicy>1</TCSPolicy>
|
||||||
<DisableDebug>0</DisableDebug>
|
<DisableDebug>0</DisableDebug>
|
||||||
|
@ -373,7 +373,7 @@ impl File for StdoutFile {
|
|||||||
atime: Timespec { sec: 0, nsec: 0 },
|
atime: Timespec { sec: 0, nsec: 0 },
|
||||||
mtime: Timespec { sec: 0, nsec: 0 },
|
mtime: Timespec { sec: 0, nsec: 0 },
|
||||||
ctime: Timespec { sec: 0, nsec: 0 },
|
ctime: Timespec { sec: 0, nsec: 0 },
|
||||||
type_: FileType::File,
|
type_: FileType::CharDevice,
|
||||||
mode: 0,
|
mode: 0,
|
||||||
nlinks: 0,
|
nlinks: 0,
|
||||||
uid: 0,
|
uid: 0,
|
||||||
@ -489,7 +489,7 @@ impl File for StdinFile {
|
|||||||
atime: Timespec { sec: 0, nsec: 0 },
|
atime: Timespec { sec: 0, nsec: 0 },
|
||||||
mtime: Timespec { sec: 0, nsec: 0 },
|
mtime: Timespec { sec: 0, nsec: 0 },
|
||||||
ctime: Timespec { sec: 0, nsec: 0 },
|
ctime: Timespec { sec: 0, nsec: 0 },
|
||||||
type_: FileType::File,
|
type_: FileType::CharDevice,
|
||||||
mode: 0,
|
mode: 0,
|
||||||
nlinks: 0,
|
nlinks: 0,
|
||||||
uid: 0,
|
uid: 0,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::syscall::AsSocket;
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::btree_map::BTreeMap;
|
use std::collections::btree_map::BTreeMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -9,7 +9,8 @@ use super::*;
|
|||||||
pub use self::file::{File, FileRef, SgxFile, StdinFile, StdoutFile};
|
pub use self::file::{File, FileRef, SgxFile, StdinFile, StdoutFile};
|
||||||
pub use self::file_table::{FileDesc, FileTable};
|
pub use self::file_table::{FileDesc, FileTable};
|
||||||
pub use self::inode_file::{INodeExt, INodeFile, ROOT_INODE};
|
pub use self::inode_file::{INodeExt, INodeFile, ROOT_INODE};
|
||||||
pub use self::socket_file::SocketFile;
|
pub use self::socket_file::{SocketFile, AsSocket};
|
||||||
|
pub use self::unix_socket::{UnixSocketFile, AsUnixSocket};
|
||||||
use self::inode_file::OpenOptions;
|
use self::inode_file::OpenOptions;
|
||||||
pub use self::pipe::Pipe;
|
pub use self::pipe::Pipe;
|
||||||
pub use self::io_multiplexing::*;
|
pub use self::io_multiplexing::*;
|
||||||
@ -27,6 +28,7 @@ mod sgx_impl;
|
|||||||
mod io_multiplexing;
|
mod io_multiplexing;
|
||||||
mod access;
|
mod access;
|
||||||
mod null;
|
mod null;
|
||||||
|
mod unix_socket;
|
||||||
|
|
||||||
|
|
||||||
pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
|
pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
|
||||||
@ -363,7 +365,7 @@ pub fn do_sendfile(
|
|||||||
|
|
||||||
let in_file = file_table.get(in_fd)?;
|
let in_file = file_table.get(in_fd)?;
|
||||||
let out_file = file_table.get(out_fd)?;
|
let out_file = file_table.get(out_fd)?;
|
||||||
let mut buffer: [u8; 1024] = unsafe { uninitialized() };
|
let mut buffer: [u8; 1024 * 11] = unsafe { uninitialized() };
|
||||||
|
|
||||||
let mut read_offset = match offset {
|
let mut read_offset = match offset {
|
||||||
Some(offset) => offset,
|
Some(offset) => offset,
|
||||||
|
@ -90,7 +90,21 @@ impl File for SocketFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn metadata(&self) -> Result<Metadata, Error> {
|
fn metadata(&self) -> Result<Metadata, Error> {
|
||||||
unimplemented!()
|
Ok(Metadata {
|
||||||
|
dev: 0,
|
||||||
|
inode: 0,
|
||||||
|
size: 0,
|
||||||
|
blk_size: 0,
|
||||||
|
blocks: 0,
|
||||||
|
atime: Timespec { sec: 0, nsec: 0 },
|
||||||
|
mtime: Timespec { sec: 0, nsec: 0 },
|
||||||
|
ctime: Timespec { sec: 0, nsec: 0 },
|
||||||
|
type_: FileType::Socket,
|
||||||
|
mode: 0,
|
||||||
|
nlinks: 0,
|
||||||
|
uid: 0,
|
||||||
|
gid: 0
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||||
@ -113,3 +127,15 @@ impl File for SocketFile {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait AsSocket {
|
||||||
|
fn as_socket(&self) -> Result<&SocketFile, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsSocket for FileRef {
|
||||||
|
fn as_socket(&self) -> Result<&SocketFile, Error> {
|
||||||
|
self.as_any()
|
||||||
|
.downcast_ref::<SocketFile>()
|
||||||
|
.ok_or(Error::new(Errno::EBADF, "not a socket"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
310
src/libos/src/fs/unix_socket.rs
Normal file
310
src/libos/src/fs/unix_socket.rs
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
use super::*;
|
||||||
|
use std::collections::btree_map::BTreeMap;
|
||||||
|
use util::ring_buf::{RingBufReader, RingBufWriter, RingBuf};
|
||||||
|
use std::sync::SgxMutex as Mutex;
|
||||||
|
use alloc::prelude::ToString;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
pub struct UnixSocketFile {
|
||||||
|
inner: Mutex<UnixSocket>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl File for UnixSocketFile {
|
||||||
|
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
let mut inner = self.inner.lock().unwrap();
|
||||||
|
inner.read(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||||
|
let mut inner = self.inner.lock().unwrap();
|
||||||
|
inner.write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
self.read(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize, Error> {
|
||||||
|
self.write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||||
|
let mut inner = self.inner.lock().unwrap();
|
||||||
|
let mut total_len = 0;
|
||||||
|
for buf in bufs {
|
||||||
|
match inner.read(buf) {
|
||||||
|
Ok(len) => {
|
||||||
|
total_len += len;
|
||||||
|
}
|
||||||
|
Err(_) if total_len != 0 => break,
|
||||||
|
Err(e) => return Err(e.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(total_len)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||||
|
let mut inner = self.inner.lock().unwrap();
|
||||||
|
let mut total_len = 0;
|
||||||
|
for buf in bufs {
|
||||||
|
match inner.write(buf) {
|
||||||
|
Ok(len) => {
|
||||||
|
total_len += len;
|
||||||
|
}
|
||||||
|
Err(_) if total_len != 0 => break,
|
||||||
|
Err(e) => return Err(e.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(total_len)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||||
|
errno!(ESPIPE, "UnixSocket does not support seek")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn metadata(&self) -> Result<Metadata, Error> {
|
||||||
|
Ok(Metadata {
|
||||||
|
dev: 0,
|
||||||
|
inode: 0,
|
||||||
|
size: 0,
|
||||||
|
blk_size: 0,
|
||||||
|
blocks: 0,
|
||||||
|
atime: Timespec { sec: 0, nsec: 0 },
|
||||||
|
mtime: Timespec { sec: 0, nsec: 0 },
|
||||||
|
ctime: Timespec { sec: 0, nsec: 0 },
|
||||||
|
type_: FileType::Socket,
|
||||||
|
mode: 0,
|
||||||
|
nlinks: 0,
|
||||||
|
uid: 0,
|
||||||
|
gid: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sync_all(&self) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sync_data(&self) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_entry(&self) -> Result<String, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UnixSocketFile {
|
||||||
|
pub fn new(socket_type: c_int, protocol: c_int) -> Result<Self, Error> {
|
||||||
|
let inner = UnixSocket::new(socket_type, protocol)?;
|
||||||
|
Ok(UnixSocketFile { inner: Mutex::new(inner) })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bind(&self, path: impl AsRef<str>) -> Result<(), Error> {
|
||||||
|
let mut inner = self.inner.lock().unwrap();
|
||||||
|
inner.bind(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn listen(&self) -> Result<(), Error> {
|
||||||
|
let mut inner = self.inner.lock().unwrap();
|
||||||
|
inner.listen()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn accept(&self) -> Result<UnixSocketFile, Error> {
|
||||||
|
let mut inner = self.inner.lock().unwrap();
|
||||||
|
let new_socket = inner.accept()?;
|
||||||
|
Ok(UnixSocketFile { inner: Mutex::new(new_socket) })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn connect(&self, path: impl AsRef<str>) -> Result<(), Error> {
|
||||||
|
let mut inner = self.inner.lock().unwrap();
|
||||||
|
inner.connect(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for UnixSocketFile {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "UnixSocketFile {{ ... }}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub trait AsUnixSocket {
|
||||||
|
fn as_unix_socket(&self) -> Result<&UnixSocketFile, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsUnixSocket for FileRef {
|
||||||
|
fn as_unix_socket(&self) -> Result<&UnixSocketFile, Error> {
|
||||||
|
self.as_any()
|
||||||
|
.downcast_ref::<UnixSocketFile>()
|
||||||
|
.ok_or(Error::new(Errno::EBADF, "not a unix socket"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct UnixSocket {
|
||||||
|
obj: Option<Arc<UnixSocketObject>>,
|
||||||
|
status: Status,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
None,
|
||||||
|
Listening,
|
||||||
|
Connected(Channel),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UnixSocket {
|
||||||
|
/// C/S 1: Create a new unix socket
|
||||||
|
pub fn new(socket_type: c_int, protocol: c_int) -> Result<Self, Error> {
|
||||||
|
if socket_type == libc::SOCK_STREAM && protocol == 0 {
|
||||||
|
Ok(UnixSocket {
|
||||||
|
obj: None,
|
||||||
|
status: Status::None
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
errno!(ENOSYS, "unimplemented unix socket type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Server 2: Bind the socket to a file system path
|
||||||
|
pub fn bind(&mut self, path: impl AsRef<str>) -> Result<(), Error> {
|
||||||
|
// TODO: check permission
|
||||||
|
if self.obj.is_some() {
|
||||||
|
return errno!(EINVAL, "The socket is already bound to an address.");
|
||||||
|
}
|
||||||
|
self.obj = Some(UnixSocketObject::create(path)?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Server 3: Listen to a socket
|
||||||
|
pub fn listen(&mut self) -> Result<(), Error> {
|
||||||
|
self.status = Status::Listening;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Server 4: Accept a connection on listening. Non-blocking.
|
||||||
|
pub fn accept(&mut self) -> Result<UnixSocket, Error> {
|
||||||
|
match self.status {
|
||||||
|
Status::Listening => {}
|
||||||
|
_ => return errno!(EINVAL, "unix socket is not listening"),
|
||||||
|
};
|
||||||
|
let socket = self.obj.as_mut().unwrap().pop()
|
||||||
|
.ok_or(Error::new(EAGAIN, "no connections are present to be accepted"))?;
|
||||||
|
Ok(socket)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Client 2: Connect to a path
|
||||||
|
pub fn connect(&mut self, path: impl AsRef<str>) -> Result<(), Error> {
|
||||||
|
if let Status::Listening = self.status {
|
||||||
|
return errno!(EINVAL, "unix socket is listening?");
|
||||||
|
}
|
||||||
|
let obj = UnixSocketObject::get(path)
|
||||||
|
.ok_or(Error::new(EINVAL, "unix socket path not found"))?;
|
||||||
|
let (channel1, channel2) = Channel::new_pair();
|
||||||
|
self.status = Status::Connected(channel1);
|
||||||
|
obj.push(UnixSocket {
|
||||||
|
obj: Some(obj.clone()),
|
||||||
|
status: Status::Connected(channel2),
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
if let Status::Connected(channel) = &self.status {
|
||||||
|
channel.reader.read(buf)
|
||||||
|
} else {
|
||||||
|
errno!(EBADF, "UnixSocket is not connected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||||
|
if let Status::Connected(channel) = &self.status {
|
||||||
|
channel.writer.write(buf)
|
||||||
|
} else {
|
||||||
|
errno!(EBADF, "UnixSocket is not connected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for UnixSocket {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Status::Listening = self.status {
|
||||||
|
let path = &self.obj.as_ref().unwrap().path;
|
||||||
|
UnixSocketObject::remove(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UnixSocketObject {
|
||||||
|
path: String,
|
||||||
|
accepted_sockets: Mutex<VecDeque<UnixSocket>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UnixSocketObject {
|
||||||
|
fn push(&self, unix_socket: UnixSocket) {
|
||||||
|
let mut queue = self.accepted_sockets.lock().unwrap();
|
||||||
|
queue.push_back(unix_socket);
|
||||||
|
}
|
||||||
|
fn pop(&self) -> Option<UnixSocket> {
|
||||||
|
let mut queue = self.accepted_sockets.lock().unwrap();
|
||||||
|
queue.pop_front()
|
||||||
|
}
|
||||||
|
fn get(path: impl AsRef<str>) -> Option<Arc<Self>> {
|
||||||
|
let mut paths = UNIX_SOCKET_OBJS.lock().unwrap();
|
||||||
|
paths.get(path.as_ref()).map(|obj| obj.clone())
|
||||||
|
}
|
||||||
|
fn create(path: impl AsRef<str>) -> Result<Arc<Self>, Error> {
|
||||||
|
let mut paths = UNIX_SOCKET_OBJS.lock().unwrap();
|
||||||
|
if paths.contains_key(path.as_ref()) {
|
||||||
|
return errno!(EADDRINUSE, "unix socket path already exists");
|
||||||
|
}
|
||||||
|
let obj = Arc::new(UnixSocketObject {
|
||||||
|
path: path.as_ref().to_string(),
|
||||||
|
accepted_sockets: Mutex::new(VecDeque::new())
|
||||||
|
});
|
||||||
|
paths.insert(path.as_ref().to_string(), obj.clone());
|
||||||
|
Ok(obj)
|
||||||
|
}
|
||||||
|
fn remove(path: impl AsRef<str>) {
|
||||||
|
let mut paths = UNIX_SOCKET_OBJS.lock().unwrap();
|
||||||
|
paths.remove(path.as_ref());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Channel {
|
||||||
|
reader: RingBufReader,
|
||||||
|
writer: RingBufWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for Channel {}
|
||||||
|
unsafe impl Sync for Channel {}
|
||||||
|
|
||||||
|
impl Channel {
|
||||||
|
fn new_pair() -> (Channel, Channel) {
|
||||||
|
let buf1 = RingBuf::new(DEFAULT_BUF_SIZE);
|
||||||
|
let buf2 = RingBuf::new(DEFAULT_BUF_SIZE);
|
||||||
|
let channel1 = Channel {
|
||||||
|
reader: buf1.reader,
|
||||||
|
writer: buf2.writer,
|
||||||
|
};
|
||||||
|
let channel2 = Channel {
|
||||||
|
reader: buf2.reader,
|
||||||
|
writer: buf1.writer,
|
||||||
|
};
|
||||||
|
(channel1, channel2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const DEFAULT_BUF_SIZE: usize = 1 * 1024 * 1024;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref UNIX_SOCKET_OBJS: Mutex<BTreeMap<String, Arc<UnixSocketObject>>>
|
||||||
|
= Mutex::new(BTreeMap::new());
|
||||||
|
}
|
@ -36,7 +36,7 @@ macro_rules! debug_trace {
|
|||||||
|
|
||||||
macro_rules! errno {
|
macro_rules! errno {
|
||||||
($errno: ident, $msg: expr) => {{
|
($errno: ident, $msg: expr) => {{
|
||||||
println!(
|
error!(
|
||||||
"ERROR: {} ({}, line {} in file {})",
|
"ERROR: {} ({}, line {} in file {})",
|
||||||
$errno,
|
$errno,
|
||||||
$msg,
|
$msg,
|
||||||
@ -54,7 +54,7 @@ macro_rules! try_libc {
|
|||||||
if ret == -1 {
|
if ret == -1 {
|
||||||
let errno = unsafe { libc::errno() };
|
let errno = unsafe { libc::errno() };
|
||||||
// println will cause libc ocall and overwrite errno
|
// println will cause libc ocall and overwrite errno
|
||||||
println!(
|
error!(
|
||||||
"ERROR from libc: {} (line {} in file {})",
|
"ERROR from libc: {} (line {} in file {})",
|
||||||
errno,
|
errno,
|
||||||
line!(),
|
line!(),
|
||||||
|
@ -101,7 +101,7 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Res
|
|||||||
waiter
|
waiter
|
||||||
};
|
};
|
||||||
|
|
||||||
let child_pid = Waiter::sleep_until_woken_with_result(waiter);
|
let child_pid = waiter.sleep_until_woken_with_result();
|
||||||
|
|
||||||
let mut current = current_ref.lock().unwrap();
|
let mut current = current_ref.lock().unwrap();
|
||||||
let child_i = {
|
let child_i = {
|
||||||
|
@ -4,8 +4,8 @@ use std::ptr;
|
|||||||
use xmas_elf::{header, program, sections, ElfFile};
|
use xmas_elf::{header, program, sections, ElfFile};
|
||||||
|
|
||||||
pub const DEFAULT_STACK_SIZE: usize = 1 * 1024 * 1024;
|
pub const DEFAULT_STACK_SIZE: usize = 1 * 1024 * 1024;
|
||||||
pub const DEFAULT_HEAP_SIZE: usize = 2 * 1024 * 1024;
|
pub const DEFAULT_HEAP_SIZE: usize = 10 * 1024 * 1024;
|
||||||
pub const DEFAULT_MMAP_SIZE: usize = 8 * 1024 * 1024;
|
pub const DEFAULT_MMAP_SIZE: usize = 40 * 1024 * 1024;
|
||||||
|
|
||||||
pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> {
|
pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> {
|
||||||
let mut code_seg = get_code_segment(elf_file)?;
|
let mut code_seg = get_code_segment(elf_file)?;
|
||||||
|
@ -113,7 +113,8 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result<Fi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&FileAction::Close(fd) => {
|
&FileAction::Close(fd) => {
|
||||||
cloned_file_table.del(fd)?;
|
// ignore error
|
||||||
|
cloned_file_table.del(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,14 +48,14 @@ where
|
|||||||
self.inner.lock().unwrap().data
|
self.inner.lock().unwrap().data
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sleep_until_woken_with_result(waiter: Waiter<D, R>) -> R {
|
pub fn sleep_until_woken_with_result(self) -> R {
|
||||||
while !waiter.inner.lock().unwrap().is_woken {
|
while !self.inner.lock().unwrap().is_woken {
|
||||||
unsafe {
|
unsafe {
|
||||||
wait_event(waiter.thread);
|
wait_event(self.thread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
waiter.inner.lock().unwrap().result.unwrap()
|
self.inner.lock().unwrap().result.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
//! 3. Dispatch the syscall to `do_*` (at this file)
|
//! 3. Dispatch the syscall to `do_*` (at this file)
|
||||||
//! 4. Do some memory checks then call `mod::do_*` (at each module)
|
//! 4. Do some memory checks then call `mod::do_*` (at each module)
|
||||||
|
|
||||||
use fs::{AccessFlags, AccessModes, FcntlCmd, File, FileDesc, FileRef, SocketFile, AT_FDCWD};
|
use fs::*;
|
||||||
use misc::{resource_t, rlimit_t, utsname_t};
|
use misc::{resource_t, rlimit_t, utsname_t};
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
use process::{pid_t, ChildProcessFilter, CloneFlags, FileAction, FutexFlags, FutexOp};
|
use process::{pid_t, ChildProcessFilter, CloneFlags, FileAction, FutexFlags, FutexOp};
|
||||||
@ -48,10 +48,15 @@ pub extern "C" fn dispatch_syscall(
|
|||||||
);
|
);
|
||||||
#[cfg(feature = "syscall_timing")]
|
#[cfg(feature = "syscall_timing")]
|
||||||
let time_start = {
|
let time_start = {
|
||||||
if crate::process::current_pid() == 1 && num == SYS_EXIT {
|
static mut LAST_PRINT: usize = 0;
|
||||||
print_syscall_timing();
|
let time = crate::time::do_gettimeofday().as_usec();
|
||||||
|
unsafe {
|
||||||
|
if time / 1000000 / 5 > LAST_PRINT {
|
||||||
|
LAST_PRINT = time / 1000000 / 5;
|
||||||
|
print_syscall_timing();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
crate::time::do_gettimeofday().as_usec()
|
time
|
||||||
};
|
};
|
||||||
|
|
||||||
let ret = match num {
|
let ret = match num {
|
||||||
@ -248,6 +253,11 @@ pub extern "C" fn dispatch_syscall(
|
|||||||
arg3 as *mut c_void,
|
arg3 as *mut c_void,
|
||||||
arg4 as *mut libc::socklen_t,
|
arg4 as *mut libc::socklen_t,
|
||||||
),
|
),
|
||||||
|
SYS_GETPEERNAME => do_getpeername(
|
||||||
|
arg0 as c_int,
|
||||||
|
arg1 as *mut libc::sockaddr,
|
||||||
|
arg2 as *mut libc::socklen_t,
|
||||||
|
),
|
||||||
SYS_SENDTO => do_sendto(
|
SYS_SENDTO => do_sendto(
|
||||||
arg0 as c_int,
|
arg0 as c_int,
|
||||||
arg1 as *const c_void,
|
arg1 as *const c_void,
|
||||||
@ -295,6 +305,9 @@ fn print_syscall_timing() {
|
|||||||
}
|
}
|
||||||
println!("{:>3}: {:>6} us", i, time);
|
println!("{:>3}: {:>6} us", i, time);
|
||||||
}
|
}
|
||||||
|
for x in unsafe { SYSCALL_TIMING.iter_mut() } {
|
||||||
|
*x = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
@ -936,8 +949,16 @@ fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<isize
|
|||||||
domain, socket_type, protocol
|
domain, socket_type, protocol
|
||||||
);
|
);
|
||||||
|
|
||||||
let socket = SocketFile::new(domain, socket_type, protocol)?;
|
let file_ref: Arc<Box<File>> = match domain {
|
||||||
let file_ref: Arc<Box<File>> = Arc::new(Box::new(socket));
|
// libc::AF_LOCAL => {
|
||||||
|
// let unix_socket = UnixSocketFile::new(socket_type, protocol)?;
|
||||||
|
// Arc::new(Box::new(unix_socket))
|
||||||
|
// }
|
||||||
|
_ => {
|
||||||
|
let socket = SocketFile::new(domain, socket_type, protocol)?;
|
||||||
|
Arc::new(Box::new(socket))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let current_ref = process::get_current();
|
let current_ref = process::get_current();
|
||||||
let mut proc = current_ref.lock().unwrap();
|
let mut proc = current_ref.lock().unwrap();
|
||||||
@ -958,10 +979,18 @@ fn do_connect(
|
|||||||
let current_ref = process::get_current();
|
let current_ref = process::get_current();
|
||||||
let mut proc = current_ref.lock().unwrap();
|
let mut proc = current_ref.lock().unwrap();
|
||||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||||
let socket = file_ref.as_socket()?;
|
if let Ok(socket) = file_ref.as_socket() {
|
||||||
|
let ret = try_libc!(libc::ocall::connect(socket.fd(), addr, addr_len));
|
||||||
let ret = try_libc!(libc::ocall::connect(socket.fd(), addr, addr_len));
|
Ok(ret as isize)
|
||||||
Ok(ret as isize)
|
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||||
|
let addr = addr as *const libc::sockaddr_un;
|
||||||
|
check_ptr(addr)?; // TODO: check addr_len
|
||||||
|
let path = clone_cstring_safely(unsafe { (&*addr).sun_path.as_ptr() })?.to_string_lossy().into_owned();
|
||||||
|
unix_socket.connect(path)?;
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_accept4(
|
fn do_accept4(
|
||||||
@ -977,13 +1006,26 @@ fn do_accept4(
|
|||||||
let current_ref = process::get_current();
|
let current_ref = process::get_current();
|
||||||
let mut proc = current_ref.lock().unwrap();
|
let mut proc = current_ref.lock().unwrap();
|
||||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||||
let socket = file_ref.as_socket()?;
|
if let Ok(socket) = file_ref.as_socket() {
|
||||||
|
let socket = file_ref.as_socket()?;
|
||||||
|
|
||||||
let new_socket = socket.accept(addr, addr_len, flags)?;
|
let new_socket = socket.accept(addr, addr_len, flags)?;
|
||||||
let new_file_ref: Arc<Box<File>> = Arc::new(Box::new(new_socket));
|
let new_file_ref: Arc<Box<File>> = Arc::new(Box::new(new_socket));
|
||||||
let new_fd = proc.get_files().lock().unwrap().put(new_file_ref, false);
|
let new_fd = proc.get_files().lock().unwrap().put(new_file_ref, false);
|
||||||
|
|
||||||
Ok(new_fd as isize)
|
Ok(new_fd as isize)
|
||||||
|
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||||
|
let addr = addr as *mut libc::sockaddr_un;
|
||||||
|
check_mut_ptr(addr)?; // TODO: check addr_len
|
||||||
|
|
||||||
|
let new_socket = unix_socket.accept()?;
|
||||||
|
let new_file_ref: Arc<Box<File>> = Arc::new(Box::new(new_socket));
|
||||||
|
let new_fd = proc.get_files().lock().unwrap().put(new_file_ref, false);
|
||||||
|
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_shutdown(fd: c_int, how: c_int) -> Result<isize, Error> {
|
fn do_shutdown(fd: c_int, how: c_int) -> Result<isize, Error> {
|
||||||
@ -991,10 +1033,12 @@ fn do_shutdown(fd: c_int, how: c_int) -> Result<isize, Error> {
|
|||||||
let current_ref = process::get_current();
|
let current_ref = process::get_current();
|
||||||
let mut proc = current_ref.lock().unwrap();
|
let mut proc = current_ref.lock().unwrap();
|
||||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||||
let socket = file_ref.as_socket()?;
|
if let Ok(socket) = file_ref.as_socket() {
|
||||||
|
let ret = try_libc!(libc::ocall::shutdown(socket.fd(), how));
|
||||||
let ret = try_libc!(libc::ocall::shutdown(socket.fd(), how));
|
Ok(ret as isize)
|
||||||
Ok(ret as isize)
|
} else {
|
||||||
|
errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_bind(
|
fn do_bind(
|
||||||
@ -1006,10 +1050,19 @@ fn do_bind(
|
|||||||
let current_ref = process::get_current();
|
let current_ref = process::get_current();
|
||||||
let mut proc = current_ref.lock().unwrap();
|
let mut proc = current_ref.lock().unwrap();
|
||||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||||
let socket = file_ref.as_socket()?;
|
if let Ok(socket) = file_ref.as_socket() {
|
||||||
|
check_ptr(addr)?; // TODO: check addr_len
|
||||||
let ret = try_libc!(libc::ocall::bind(socket.fd(), addr, addr_len));
|
let ret = try_libc!(libc::ocall::bind(socket.fd(), addr, addr_len));
|
||||||
Ok(ret as isize)
|
Ok(ret as isize)
|
||||||
|
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||||
|
let addr = addr as *const libc::sockaddr_un;
|
||||||
|
check_ptr(addr)?; // TODO: check addr_len
|
||||||
|
let path = clone_cstring_safely(unsafe { (&*addr).sun_path.as_ptr() })?.to_string_lossy().into_owned();
|
||||||
|
unix_socket.bind(path)?;
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_listen(fd: c_int, backlog: c_int) -> Result<isize, Error> {
|
fn do_listen(fd: c_int, backlog: c_int) -> Result<isize, Error> {
|
||||||
@ -1017,10 +1070,15 @@ fn do_listen(fd: c_int, backlog: c_int) -> Result<isize, Error> {
|
|||||||
let current_ref = process::get_current();
|
let current_ref = process::get_current();
|
||||||
let mut proc = current_ref.lock().unwrap();
|
let mut proc = current_ref.lock().unwrap();
|
||||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||||
let socket = file_ref.as_socket()?;
|
if let Ok(socket) = file_ref.as_socket() {
|
||||||
|
let ret = try_libc!(libc::ocall::listen(socket.fd(), backlog));
|
||||||
let ret = try_libc!(libc::ocall::listen(socket.fd(), backlog));
|
Ok(ret as isize)
|
||||||
Ok(ret as isize)
|
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||||
|
unix_socket.listen()?;
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_setsockopt(
|
fn do_setsockopt(
|
||||||
@ -1037,16 +1095,21 @@ fn do_setsockopt(
|
|||||||
let current_ref = process::get_current();
|
let current_ref = process::get_current();
|
||||||
let mut proc = current_ref.lock().unwrap();
|
let mut proc = current_ref.lock().unwrap();
|
||||||
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||||
let socket = file_ref.as_socket()?;
|
if let Ok(socket) = file_ref.as_socket() {
|
||||||
|
let ret = try_libc!(libc::ocall::setsockopt(
|
||||||
let ret = try_libc!(libc::ocall::setsockopt(
|
socket.fd(),
|
||||||
socket.fd(),
|
level,
|
||||||
level,
|
optname,
|
||||||
optname,
|
optval,
|
||||||
optval,
|
optlen
|
||||||
optlen
|
));
|
||||||
));
|
Ok(ret as isize)
|
||||||
Ok(ret as isize)
|
} else if let Ok(unix_socket) = file_ref.as_unix_socket() {
|
||||||
|
warn!("setsockopt for unix socket is unimplemented");
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
errno!(EBADF, "not a socket")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_getsockopt(
|
fn do_getsockopt(
|
||||||
@ -1075,6 +1138,25 @@ fn do_getsockopt(
|
|||||||
Ok(ret as isize)
|
Ok(ret as isize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn do_getpeername(
|
||||||
|
fd: c_int,
|
||||||
|
addr: *mut libc::sockaddr,
|
||||||
|
addr_len: *mut libc::socklen_t,
|
||||||
|
) -> Result<isize, Error> {
|
||||||
|
info!("getpeername: fd: {}, addr: {:?}, addr_len: {:?}", fd, addr, addr_len);
|
||||||
|
let current_ref = process::get_current();
|
||||||
|
let mut proc = current_ref.lock().unwrap();
|
||||||
|
let file_ref = proc.get_files().lock().unwrap().get(fd as FileDesc)?;
|
||||||
|
let socket = file_ref.as_socket()?;
|
||||||
|
|
||||||
|
let ret = try_libc!(libc::ocall::getpeername(
|
||||||
|
socket.fd(),
|
||||||
|
addr,
|
||||||
|
addr_len
|
||||||
|
));
|
||||||
|
Ok(ret as isize)
|
||||||
|
}
|
||||||
|
|
||||||
fn do_sendto(
|
fn do_sendto(
|
||||||
fd: c_int,
|
fd: c_int,
|
||||||
base: *const c_void,
|
base: *const c_void,
|
||||||
@ -1230,18 +1312,6 @@ fn do_epoll_wait(
|
|||||||
Ok(count as isize)
|
Ok(count as isize)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AsSocket {
|
|
||||||
fn as_socket(&self) -> Result<&SocketFile, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsSocket for FileRef {
|
|
||||||
fn as_socket(&self) -> Result<&SocketFile, Error> {
|
|
||||||
self.as_any()
|
|
||||||
.downcast_ref::<SocketFile>()
|
|
||||||
.ok_or(Error::new(Errno::EBADF, "not a socket"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_uname(name: *mut utsname_t) -> Result<isize, Error> {
|
fn do_uname(name: *mut utsname_t) -> Result<isize, Error> {
|
||||||
check_mut_ptr(name)?;
|
check_mut_ptr(name)?;
|
||||||
let name = unsafe { &mut *name };
|
let name = unsafe { &mut *name };
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define DATA_SPACE_SIZE (96*1024*1024)
|
#define DATA_SPACE_SIZE (128*1024*1024)
|
||||||
|
|
||||||
static char __prealloced_data_space[DATA_SPACE_SIZE]
|
static char __prealloced_data_space[DATA_SPACE_SIZE]
|
||||||
__attribute__ ((
|
__attribute__ ((
|
||||||
|
Loading…
Reference in New Issue
Block a user