use io::{Error as IoError, Result as IoResult};
-mod alloc;
+pub mod alloc;
#[macro_use]
mod raw;
+pub(crate) fn copy_user_buffer(buf: &alloc::UserRef<ByteBuffer>) -> Vec<u8> {
+ unsafe {
+ let buf = buf.to_enclave();
+ alloc::User::from_raw_parts(buf.data as _, buf.len).to_enclave()
+ }
+}
+
+pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult<usize> {
+ unsafe {
+ let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.len());
+ let len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
+ userbuf[..len].copy_to_enclave(&mut buf[..len]);
+ Ok(len)
+ }
+}
+
+pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
+ unsafe {
+ let mut userbuf = alloc::User::<ByteBuffer>::uninitialized();
+ raw::read_alloc(fd, userbuf.as_raw_mut_ptr()).from_sgx_result()?;
+ Ok(copy_user_buffer(&userbuf))
+ }
+}
+
+pub fn write(fd: Fd, buf: &[u8]) -> IoResult<usize> {
+ unsafe {
+ let userbuf = alloc::User::new_from_enclave(buf);
+ raw::write(fd, userbuf.as_ptr(), userbuf.len()).from_sgx_result()
+ }
+}
+
+pub fn flush(fd: Fd) -> IoResult<()> {
+ unsafe { raw::flush(fd).from_sgx_result() }
+}
+
+pub fn close(fd: Fd) {
+ unsafe { raw::close(fd) }
+}
+
pub fn launch_thread() -> IoResult<()> {
unsafe { raw::launch_thread().from_sgx_result() }
}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use fortanix_sgx_abi::Fd;
+
+use io;
+use mem;
+use sys_common::AsInner;
+use super::abi::usercalls;
+
+#[derive(Debug)]
+pub struct FileDesc {
+ fd: Fd,
+}
+
+impl FileDesc {
+ pub fn new(fd: Fd) -> FileDesc {
+ FileDesc { fd: fd }
+ }
+
+ pub fn raw(&self) -> Fd { self.fd }
+
+ /// Extracts the actual filedescriptor without closing it.
+ pub fn into_raw(self) -> Fd {
+ let fd = self.fd;
+ mem::forget(self);
+ fd
+ }
+
+ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+ usercalls::read(self.fd, buf)
+ }
+
+ pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+ usercalls::write(self.fd, buf)
+ }
+
+ pub fn flush(&self) -> io::Result<()> {
+ usercalls::flush(self.fd)
+ }
+}
+
+impl AsInner<Fd> for FileDesc {
+ fn as_inner(&self) -> &Fd { &self.fd }
+}
+
+impl Drop for FileDesc {
+ fn drop(&mut self) {
+ usercalls::close(self.fd)
+ }
+}
pub mod cmath;
pub mod condvar;
pub mod env;
+pub mod fd;
pub mod fs;
pub mod memchr;
pub mod mutex;
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use fortanix_sgx_abi as abi;
+
use io;
-use sys::unsupported;
+use sys::fd::FileDesc;
+
+pub struct Stdin(());
+pub struct Stdout(());
+pub struct Stderr(());
-pub struct Stdin;
-pub struct Stdout;
-pub struct Stderr;
+fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R {
+ let fd = FileDesc::new(fd);
+ let ret = f(&fd);
+ fd.into_raw();
+ ret
+}
impl Stdin {
- pub fn new() -> io::Result<Stdin> {
- Ok(Stdin)
- }
+ pub fn new() -> io::Result<Stdin> { Ok(Stdin(())) }
- pub fn read(&self, _data: &mut [u8]) -> io::Result<usize> {
- unsupported()
+ pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
+ with_std_fd(abi::FD_STDIN, |fd| fd.read(data))
}
}
impl Stdout {
- pub fn new() -> io::Result<Stdout> {
- Ok(Stdout)
- }
+ pub fn new() -> io::Result<Stdout> { Ok(Stdout(())) }
- pub fn write(&self, _data: &[u8]) -> io::Result<usize> {
- unsupported()
+ pub fn write(&self, data: &[u8]) -> io::Result<usize> {
+ with_std_fd(abi::FD_STDOUT, |fd| fd.write(data))
}
pub fn flush(&self) -> io::Result<()> {
- Ok(())
+ with_std_fd(abi::FD_STDOUT, |fd| fd.flush())
}
}
impl Stderr {
- pub fn new() -> io::Result<Stderr> {
- Ok(Stderr)
- }
+ pub fn new() -> io::Result<Stderr> { Ok(Stderr(())) }
- pub fn write(&self, _data: &[u8]) -> io::Result<usize> {
- unsupported()
+ pub fn write(&self, data: &[u8]) -> io::Result<usize> {
+ with_std_fd(abi::FD_STDERR, |fd| fd.write(data))
}
pub fn flush(&self) -> io::Result<()> {
- Ok(())
+ with_std_fd(abi::FD_STDERR, |fd| fd.flush())
}
}
+// FIXME: right now this raw stderr handle is used in a few places because
+// std::io::stderr_raw isn't exposed, but once that's exposed this impl
+// should go away
impl io::Write for Stderr {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
- (&*self).write(data)
+ Stderr::write(self, data)
}
+
fn flush(&mut self) -> io::Result<()> {
- (&*self).flush()
+ Stderr::flush(self)
}
}
-pub const STDIN_BUF_SIZE: usize = 0;
+pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
-pub fn is_ebadf(_err: &io::Error) -> bool {
- true
+pub fn is_ebadf(err: &io::Error) -> bool {
+ // FIXME: Rust normally maps Unix EBADF to `Other`
+ err.raw_os_error() == Some(abi::Error::BrokenPipe as _)
}
pub fn panic_output() -> Option<impl io::Write> {