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; | ||||||
|  |         let time = crate::time::do_gettimeofday().as_usec(); | ||||||
|  |         unsafe { | ||||||
|  |             if time / 1000000 / 5 > LAST_PRINT { | ||||||
|  |                 LAST_PRINT = time / 1000000 / 5; | ||||||
|                 print_syscall_timing(); |                 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 file_ref: Arc<Box<File>> = match domain { | ||||||
|  | //        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)?; |             let socket = SocketFile::new(domain, socket_type, protocol)?; | ||||||
|     let file_ref: Arc<Box<File>> = Arc::new(Box::new(socket)); |             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,6 +1006,7 @@ 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)?; | ||||||
|  |     if let Ok(socket) = file_ref.as_socket() { | ||||||
|         let 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)?; | ||||||
| @ -984,6 +1014,18 @@ fn do_accept4( | |||||||
|         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,8 +1095,7 @@ 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, | ||||||
| @ -1047,6 +1104,12 @@ fn do_setsockopt( | |||||||
|             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