You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by zf...@apache.org on 2021/04/15 06:40:36 UTC

[incubator-teaclave-sgx-sdk] 01/01: Change sgx_libc interface.

This is an automated email from the ASF dual-hosted git repository.

zfc pushed a commit to branch sec-liboc
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-sgx-sdk.git

commit a1728f2d910e4da342940e834d2c43130d4a68ff
Author: Zhaofeng Chen <zf...@apache.com>
AuthorDate: Wed Apr 14 23:38:51 2021 -0700

    Change sgx_libc interface.
    
    Fix hw_test test_file.
    
    Update epoll_wait
    
    Update patch for crates taking sgx_oc as dependency
    
    Comment workflow matrix for xargo.
    
    Patch dependency for sim-example action.
    
    Clean up hello-rust.
    
    Bring back Xargo actions.
---
 .github/workflows/dep_patch.txt                 |    9 +
 .github/workflows/patch.txt                     |    2 +-
 .github/workflows/sgx-world.yml                 |    6 +-
 .github/workflows/sim-example.yml               |    5 +
 edl/sgx_env.edl                                 |   12 +-
 edl/sgx_fd.edl                                  |    4 -
 edl/sgx_file.edl                                |    4 +-
 edl/sgx_net.edl                                 |    7 +-
 edl/sgx_pipe.edl                                |    1 -
 edl/sgx_socket.edl                              |    7 -
 samplecode/hello-rust/enclave/Enclave.edl       |    3 +
 samplecode/http_req/Makefile                    |    4 +-
 samplecode/unit-test/enclave/Cargo.toml         |    2 +-
 samplecode/unit-test/enclave/Enclave.edl        |    2 +
 samplecode/unit-test/enclave/src/lib.rs         |    8 +-
 samplecode/unit-test/enclave/src/test_env.rs    |    7 +-
 samplecode/unit-test/enclave/src/test_file.rs   |    3 +-
 samplecode/unit-test/enclave/src/test_net.rs    |   77 +
 samplecode/unit-test/enclave/src/test_path.rs   |   70 +
 samplecode/unit-test/enclave/src/test_rts.rs    |  150 +-
 samplecode/unit-test/enclave/src/test_signal.rs |    2 +-
 sgx_edl/edl/sgx_env.edl                         |   12 +-
 sgx_edl/edl/sgx_fd.edl                          |    4 -
 sgx_edl/edl/sgx_file.edl                        |    4 +-
 sgx_edl/edl/sgx_net.edl                         |    7 +-
 sgx_edl/edl/sgx_pipe.edl                        |    1 -
 sgx_edl/edl/sgx_socket.edl                      |    7 -
 sgx_edl/edl/sgx_sys.edl                         |    1 -
 {sgx_trts => sgx_libc}/src/ascii.rs             |    0
 {sgx_trts => sgx_libc}/src/c_str.rs             |    5 +-
 sgx_libc/src/lib.rs                             |    9 +
 sgx_libc/src/linux/mod.rs                       |    1 +
 sgx_libc/src/linux/x86_64/mod.rs                |  571 +--
 sgx_libc/src/linux/x86_64/ocall.rs              | 4498 ++++++++++-------------
 sgx_libc/src/macros.rs                          |   43 +
 {sgx_trts => sgx_libc}/src/memchr.rs            |   52 +-
 sgx_trts/src/lib.rs                             |    8 +-
 sgx_tstd/src/io/error.rs                        |   47 +-
 sgx_tstd/src/net/addr.rs                        |   82 +-
 sgx_tstd/src/sys/ext/net.rs                     |  125 +-
 sgx_tstd/src/sys/fd.rs                          |   99 +-
 sgx_tstd/src/sys/fs.rs                          |  231 +-
 sgx_tstd/src/sys/mod.rs                         |   62 +-
 sgx_tstd/src/sys/net.rs                         |  126 +-
 sgx_tstd/src/sys/os.rs                          |  184 +-
 sgx_tstd/src/sys/pipe.rs                        |   13 +-
 sgx_tstd/src/sys/thread.rs                      |    7 +-
 sgx_tstd/src/sys/time.rs                        |   76 +-
 sgx_tstd/src/sys_common/net.rs                  |  245 +-
 sgx_urts/src/env.rs                             |   52 +-
 sgx_urts/src/fd.rs                              |   84 +-
 sgx_urts/src/file.rs                            |   25 +-
 sgx_urts/src/net.rs                             |   47 +-
 sgx_urts/src/socket.rs                          |   22 -
 sgx_ustdc/net.c                                 |    5 -
 sgx_ustdc/socket.c                              |   13 -
 56 files changed, 3409 insertions(+), 3744 deletions(-)

diff --git a/.github/workflows/dep_patch.txt b/.github/workflows/dep_patch.txt
new file mode 100644
index 0000000..4e1d426
--- /dev/null
+++ b/.github/workflows/dep_patch.txt
@@ -0,0 +1,9 @@
+
+[patch.'https://github.com/mesalock-linux/net2-rs-sgx']
+net2 = { git = "https://github.com/m4sterchain/net2-rs-sgx", branch = "sgx_oc" }
+
+[patch.'https://github.com/mesalock-linux/mio-sgx']
+mio = { git = "https://github.com/m4sterchain/mio-sgx", branch = "sgx_oc" }
+
+[patch.'https://github.com/mesalock-linux/rusty_leveldb_sgx']
+rusty-leveldb = { git = "https://github.com/m4sterchain/rusty_leveldb_sgx", branch = "sgx_oc" }
\ No newline at end of file
diff --git a/.github/workflows/patch.txt b/.github/workflows/patch.txt
index 71b3847..e728d06 100644
--- a/.github/workflows/patch.txt
+++ b/.github/workflows/patch.txt
@@ -28,4 +28,4 @@ sgx_tunittest = { path = "../../sgx_tunittest" }
 sgx_types = { path = "../../sgx_types" }
 sgx_ucrypto = { path = "../../sgx_ucrypto" }
 sgx_unwind = { path = "../../sgx_unwind" }
-sgx_urts = { path = "../../sgx_urts" }
+sgx_urts = { path = "../../sgx_urts" }
\ No newline at end of file
diff --git a/.github/workflows/sgx-world.yml b/.github/workflows/sgx-world.yml
index f509a3a..8ec3055 100644
--- a/.github/workflows/sgx-world.yml
+++ b/.github/workflows/sgx-world.yml
@@ -22,8 +22,8 @@ jobs:
         build-command:
           - "cp ../../.github/workflows/Xargo.toml . && RUST_TARGET_PATH=$(pwd) xargo build --target x86_64-unknown-linux-sgx"
           - "cp ../../.github/workflows/Xargo.toml . && RUST_TARGET_PATH=$(pwd) xargo build --target x86_64-unknown-linux-sgx --release"
-          - "cat ../../.github/workflows/patch.txt >> ./Cargo.toml && cargo build"
-          - "cat ../../.github/workflows/patch.txt >> ./Cargo.toml && cargo build --release"
+          - "cargo build"
+          - "cargo build --release"
     runs-on: ${{ matrix.runs-on }}
     container: 
       image: ${{ matrix.image }}
@@ -49,6 +49,8 @@ jobs:
         . /opt/sgxsdk/environment && 
         git clone https://github.com/dingelish/sgx-world &&
         cd sgx-world/dumb-all &&
+        cat ../../.github/workflows/patch.txt >> ./Cargo.toml &&
+        cat ../../.github/workflows/dep_patch.txt >> ./Cargo.toml &&
         ${{ matrix.build-command }} &&
         cd ../.. &&
         rm -rf sgx-world
diff --git a/.github/workflows/sim-example.yml b/.github/workflows/sim-example.yml
index 29f9a6d..b04389c 100644
--- a/.github/workflows/sim-example.yml
+++ b/.github/workflows/sim-example.yml
@@ -69,6 +69,7 @@ jobs:
         . /opt/sgxsdk/environment && 
         export SGX_SDK_RUST=`git worktree list | head | cut -d ' ' -f 1` &&
         cd samplecode/${{ matrix.single-sample }} &&
+        cat ../../.github/workflows/dep_patch.txt >> ./enclave/Cargo.toml &&
         if [ "${{  matrix.single-sample }}" == "protobuf" ]; then cargo install protobuf-codegen --vers=2.8.1; fi
         SGX_MODE=SW make && 
         cd bin &&
@@ -115,6 +116,8 @@ jobs:
         IFS=$(echo -en "\n\b")
         compiles=('make' 'XARGO_SGX=1 make')
         cd samplecode/tls
+        cat ../../.github/workflows/dep_patch.txt >> tlsclient/enclave/Cargo.toml
+        cat ../../.github/workflows/dep_patch.txt >> tlsserver/enclave/Cargo.toml
         for client in ${compiles[@]}
         do
             for server in ${compiles[@]}
@@ -183,6 +186,8 @@ jobs:
         IFS=$(echo -en "\n\b")
         compiles=('make' 'XARGO_SGX=1 make')
         cd samplecode/mio
+        cat ../../.github/workflows/dep_patch.txt >> client/enclave/Cargo.toml
+        cat ../../.github/workflows/dep_patch.txt >> server/enclave/Cargo.toml
         for client in ${compiles[@]}
         do
             for server in ${compiles[@]}
diff --git a/edl/sgx_env.edl b/edl/sgx_env.edl
index d4a77cc..3139ca4 100644
--- a/edl/sgx_env.edl
+++ b/edl/sgx_env.edl
@@ -24,17 +24,9 @@ enclave {
     };
 
     untrusted {
-        char **u_environ_ocall();
-        char *u_getenv_ocall([in, string] const char *name);
-        int u_setenv_ocall([out] int *error, [in, string] const char *name, [in, string] const char *value, int overwrite);
-        int u_unsetenv_ocall([out] int *error, [in, string] const char *name);
+        int u_getenv_ocall([out] int *error, [in, string] const char *name, [out, size=bufsz] char *buf, size_t bufsz, [out] int *isset);
         int u_chdir_ocall([out] int *error, [in, string] const char *dir);
-        char *u_getcwd_ocall([out] int *error, [out, size=buflen] char *buf, size_t buflen);
-        int u_getpwuid_r_ocall(unsigned int uid,
-                               [out] struct passwd *pwd,
-                               [out, size=buflen] char *buf,
-                               size_t buflen,
-                               [out] struct passwd **passwd_result);
+        int u_getcwd_ocall([out] int *error, [out, size=buflen] char *buf, size_t buflen);
         unsigned int u_getuid_ocall();
     };
 };
diff --git a/edl/sgx_fd.edl b/edl/sgx_fd.edl
index 8cfc822..e2ea291 100644
--- a/edl/sgx_fd.edl
+++ b/edl/sgx_fd.edl
@@ -29,13 +29,9 @@ enclave {
     untrusted {
         size_t u_read_ocall([out] int *error, int fd, [user_check] void *buf, size_t count);
         size_t u_pread64_ocall([out] int *error, int fd, [user_check] void *buf, size_t count, int64_t offset);
-        size_t u_readv_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt);
-        size_t u_preadv64_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt, int64_t offset);
 
         size_t u_write_ocall([out] int *error, int fd, [user_check] const void *buf, size_t count);
         size_t u_pwrite64_ocall([out] int *error, int fd, [user_check] const void *buf, size_t count, int64_t offset);
-        size_t u_writev_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt);
-        size_t u_pwritev64_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt, int64_t offset);
 
         int u_fcntl_arg0_ocall([out] int *error, int fd, int cmd);
         int u_fcntl_arg1_ocall([out] int *error, int fd, int cmd, int arg);
diff --git a/edl/sgx_file.edl b/edl/sgx_file.edl
index 1e28036..215ac1a 100644
--- a/edl/sgx_file.edl
+++ b/edl/sgx_file.edl
@@ -50,11 +50,11 @@ enclave {
         int u_chmod_ocall([out] int *error, [in, string] const char *path, uint32_t mode);
         size_t u_readlink_ocall([out] int *error, [in, string] const char *path, [out, size=bufsz] char *buf, size_t bufsz);
         int u_symlink_ocall([out] int *error, [in, string] const char *path1, [in, string] const char *path2);
-        char *u_realpath_ocall([out] int *error, [in, string] const char *pathname);
+        int u_realpath_ocall([out] int *error, [in, string] const char *pathname, [out, size=bufsz] char *buf, size_t bufsz);
         int u_mkdir_ocall([out] int *error, [in, string] const char *pathname, uint32_t mode);
         int u_rmdir_ocall([out] int *error, [in, string] const char *pathname);
         void *u_opendir_ocall([out] int *error, [in, string] const char *pathname);
-        int u_readdir64_r_ocall([user_check] void *dirp, [in, out] struct dirent64_t *entry, [out] struct dirent64_t **result);
+        int u_readdir64_r_ocall([user_check] void *dirp, [in, out] struct dirent64_t *entry, [out] int *eods);
         int u_closedir_ocall([out] int *error, [user_check] void *dirp);
         int u_dirfd_ocall([out] int *error, [user_check] void *dirp);
         int u_fstatat64_ocall([out] int *error, int dirfd, [in, string] const char *pathname, [out] struct stat64_t *buf, int flags);
diff --git a/edl/sgx_net.edl b/edl/sgx_net.edl
index a803b53..64692de 100644
--- a/edl/sgx_net.edl
+++ b/edl/sgx_net.edl
@@ -34,8 +34,9 @@ enclave {
                                 [in, string] const char *node,
                                 [in, string] const char *service,
                                 [in] const struct addrinfo *hints,
-                                [out] struct addrinfo **res);
-        void u_freeaddrinfo_ocall([user_check] struct addrinfo *res);
-        char *u_gai_strerror_ocall(int errcode);
+                                size_t entry_size,
+                                [out, size=bufsz] uint8_t *buf,
+                                size_t bufsz,
+                                [out] size_t *entry_count);
     };
 };
diff --git a/edl/sgx_pipe.edl b/edl/sgx_pipe.edl
index 00c12f5..1729fe1 100644
--- a/edl/sgx_pipe.edl
+++ b/edl/sgx_pipe.edl
@@ -25,7 +25,6 @@ enclave {
     };
 
     untrusted {
-        int u_pipe_ocall([out] int *error, [out, count=2] int *pipefd);
         int u_pipe2_ocall([out] int *error, [out, count=2] int *pipefd, int flags);
     };
 };
diff --git a/edl/sgx_socket.edl b/edl/sgx_socket.edl
index 68ce3b6..d6d9f8f 100644
--- a/edl/sgx_socket.edl
+++ b/edl/sgx_socket.edl
@@ -30,11 +30,6 @@ enclave {
         int u_socketpair_ocall([out] int *error, int domain, int ty, int protocol, [out] int sv[2]);
         int u_bind_ocall([out] int *error, int sockfd, [in, size=addrlen] const struct sockaddr *addr, socklen_t addrlen);
         int u_listen_ocall([out] int *error, int sockfd, int backlog);
-        int u_accept_ocall([out] int *error,
-                           int sockfd,
-                           [in, out, size=addrlen_in] struct sockaddr *addr,
-                           socklen_t addrlen_in,
-                           [out] socklen_t *addrlen_out);
         int u_accept4_ocall([out] int *error,
                             int sockfd,
                             [in, out, size=addrlen_in] struct sockaddr *addr,
@@ -54,7 +49,6 @@ enclave {
                                 [out, size=addrlen_in] struct sockaddr *src_addr,
                                 socklen_t addrlen_in,
                                 [out] socklen_t *addrlen_out);
-        size_t u_recvmsg_ocall([out] int *error, int sockfd, [in, out] struct msghdr *msg, int flags);
         size_t u_send_ocall([out] int *error, int sockfd, [user_check] const void *buf, size_t len, int flags);
         size_t u_sendto_ocall([out] int *error,
                               int sockfd,
@@ -63,7 +57,6 @@ enclave {
                               int flags,
                               [in, size=addrlen] const struct sockaddr *dest_addr,
                               socklen_t addrlen);
-        size_t u_sendmsg_ocall([out] int *error, int sockfd, [in] const struct msghdr *msg, int flags);
         int u_getsockopt_ocall([out] int *error,
                                int sockfd,
                                int level,
diff --git a/samplecode/hello-rust/enclave/Enclave.edl b/samplecode/hello-rust/enclave/Enclave.edl
index 0263761..9b173b4 100644
--- a/samplecode/hello-rust/enclave/Enclave.edl
+++ b/samplecode/hello-rust/enclave/Enclave.edl
@@ -20,6 +20,9 @@ enclave {
     from "sgx_stdio.edl" import *;
     from "sgx_backtrace.edl" import *;
     from "sgx_tstdc.edl" import *;
+    from "sgx_net.edl" import *;
+    from "sgx_socket.edl" import *;
+
     trusted {
         /* define ECALLs here. */
 
diff --git a/samplecode/http_req/Makefile b/samplecode/http_req/Makefile
index fee080a..bb39037 100644
--- a/samplecode/http_req/Makefile
+++ b/samplecode/http_req/Makefile
@@ -46,8 +46,8 @@ SGX_COMMON_CFLAGS += -fstack-protector
 
 CUSTOM_LIBRARY_PATH := ./lib
 CUSTOM_BIN_PATH := ./bin
-CUSTOM_EDL_PATH := $(SGX_SDK_RUST)/edl
-CUSTOM_COMMON_PATH := $(SGX_SDK_RUST)/common
+CUSTOM_EDL_PATH := ../../edl
+CUSTOM_COMMON_PATH := ../../common
 
 ######## EDL Settings ########
 
diff --git a/samplecode/unit-test/enclave/Cargo.toml b/samplecode/unit-test/enclave/Cargo.toml
index 1e0e6d9..1410ce4 100644
--- a/samplecode/unit-test/enclave/Cargo.toml
+++ b/samplecode/unit-test/enclave/Cargo.toml
@@ -13,7 +13,7 @@ hw_test = []
 
 [target.'cfg(not(target_env = "sgx"))'.dependencies]
 sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" }
-sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["untrusted_fs", "thread", "backtrace"] }
+sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["untrusted_fs", "thread", "backtrace", "net", "pipe"] }
 sgx_tcrypto = { git = "https://github.com/apache/teaclave-sgx-sdk.git" }
 sgx_tunittest = { git = "https://github.com/apache/teaclave-sgx-sdk.git" }
 sgx_trts = { git = "https://github.com/apache/teaclave-sgx-sdk.git" }
diff --git a/samplecode/unit-test/enclave/Enclave.edl b/samplecode/unit-test/enclave/Enclave.edl
index 59eff09..eb13833 100644
--- a/samplecode/unit-test/enclave/Enclave.edl
+++ b/samplecode/unit-test/enclave/Enclave.edl
@@ -23,10 +23,12 @@ enclave {
     from "sgx_fs.edl" import *;
     from "sgx_time.edl" import *;
     from "sgx_thread.edl" import *;
+    from "sgx_pthread.edl" import *;
     from "sgx_sys.edl" import *;
     from "sgx_backtrace.edl" import *;
     from "sgx_signal.edl" import*;
     from "sgx_process.edl" import*;
+    from "sgx_net.edl" import*;
     trusted {
         /* define ECALLs here. */
 
diff --git a/samplecode/unit-test/enclave/src/lib.rs b/samplecode/unit-test/enclave/src/lib.rs
index e010cd5..6a06d3d 100644
--- a/samplecode/unit-test/enclave/src/lib.rs
+++ b/samplecode/unit-test/enclave/src/lib.rs
@@ -93,6 +93,9 @@ use test_env::*;
 mod test_path;
 use test_path::*;
 
+mod test_net;
+use test_net::*;
+
 mod test_thread;
 use test_thread::*;
 
@@ -178,7 +181,6 @@ fn test_main_entrance() -> size_t {
                     check_metadata_size,
                     check_version,
                     // env
-                    test_env_vars_os,
                     test_env_self_exe_path,
                     test_env_current_dir,
                     test_env_home_dir,
@@ -205,6 +207,10 @@ fn test_main_entrance() -> size_t {
                     test_path_mkdir_trailing_slash,
                     test_path_create_dir_all_with_junctions,
                     test_path_copy_file_follows_dst_symlink,
+                    test_rwv,
+                    // net
+                    test_gai_error,
+                    test_udp,
                     // thread
                     test_thread_unnamed_thread,
                     test_thread_named_thread,
diff --git a/samplecode/unit-test/enclave/src/test_env.rs b/samplecode/unit-test/enclave/src/test_env.rs
index 3f177e7..756a978 100644
--- a/samplecode/unit-test/enclave/src/test_env.rs
+++ b/samplecode/unit-test/enclave/src/test_env.rs
@@ -1,11 +1,6 @@
 use std::env::*;
 use std::path::Path;
 
-pub fn test_env_vars_os() {
-    let p = vars_os();
-    assert_ne!(0, p.size_hint().0);
-}
-
 pub  fn test_env_self_exe_path() {
     let path = current_exe();
     assert!(path.is_ok());
@@ -22,5 +17,5 @@ pub fn test_env_current_dir() {
 
 pub fn test_env_home_dir() {
     let dir = home_dir();
-    println!("{:?}", dir.unwrap());
+    println!("[ENV] HOME: {:?}", dir.unwrap());
 }
diff --git a/samplecode/unit-test/enclave/src/test_file.rs b/samplecode/unit-test/enclave/src/test_file.rs
index 715794f..eb0f622 100644
--- a/samplecode/unit-test/enclave/src/test_file.rs
+++ b/samplecode/unit-test/enclave/src/test_file.rs
@@ -71,7 +71,8 @@ pub fn test_sgxfs() {
     {
         let opt1 = SgxFile::open("/dev/isgx");
         let opt2 = SgxFile::open("/dev/sgx/enclave");
-        assert_eq!(opt1.is_ok() || opt2.is_ok(), true);
+        let opt3 = SgxFile::open("/dev/sgx");
+        assert_eq!(opt1.is_ok() || opt2.is_ok() || opt3.is_ok(), true);
     }
     {
         let opt = SgxFile::create("/");
diff --git a/samplecode/unit-test/enclave/src/test_net.rs b/samplecode/unit-test/enclave/src/test_net.rs
new file mode 100644
index 0000000..3e492f4
--- /dev/null
+++ b/samplecode/unit-test/enclave/src/test_net.rs
@@ -0,0 +1,77 @@
+use std::net::ToSocketAddrs;
+
+pub fn test_gai_error() {
+    let result = ("rust-lang.org", 80).to_socket_addrs();
+    assert!(result.is_ok());
+    let result = ("rust-lang.or", 80).to_socket_addrs(); 
+    assert!(result.is_err());
+}
+
+
+use std::thread;
+use std::net;
+use std::vec::Vec;
+
+fn socket(listen_on: net::SocketAddr) -> net::UdpSocket {
+  let attempt = net::UdpSocket::bind(listen_on);
+  let socket;
+  match attempt {
+    Ok(sock) => {
+      println!("Bound socket to {}", listen_on);
+      socket = sock;
+    },
+    Err(err) => panic!("Could not bind: {}", err)
+  }
+  socket
+}
+
+fn read_message(socket: net::UdpSocket) -> Vec<u8> {
+  let mut buf: [u8; 1] = [0; 1];
+  println!("Reading data");
+  let result = socket.recv_from(&mut buf);
+  drop(socket);
+  let data;
+  match result {
+    Ok((amt, src)) => {
+      println!("Received data from {}", src);
+      data = Vec::from(&buf[0..amt]);
+    },
+    Err(err) => panic!("Read error: {}", err)
+  }
+  data
+}
+
+pub fn send_message(send_addr: net::SocketAddr, target: net::SocketAddr, data: Vec<u8>) {
+  let socket = socket(send_addr);
+  println!("Sending data");
+  let result = socket.send_to(&data, target);
+  drop(socket);
+  match result {
+    Ok(amt) => println!("Sent {} bytes", amt),
+    Err(err) => panic!("Write error: {}", err)
+  }
+}
+
+fn listen(listen_on: net::SocketAddr) -> thread::JoinHandle<Vec<u8>> {
+  let socket = socket(listen_on);
+  let handle = thread::spawn(move || {
+    read_message(socket)
+  });
+  handle
+}
+
+pub fn test_udp() {
+    println!("UDP");
+    let ip = net::Ipv4Addr::new(127, 0, 0, 1);
+    let listen_addr = net::SocketAddrV4::new(ip, 8888);
+    let send_addr = net::SocketAddrV4::new(ip, 8889);
+    let future = listen(net::SocketAddr::V4(listen_addr));
+    let message: Vec<u8> = vec![10];
+    thread::sleep_ms(3000);
+    send_message(net::SocketAddr::V4(send_addr), net::SocketAddr::V4(listen_addr), message);
+    println!("Waiting");
+    let received = future.join().unwrap();
+    println!("Got {} bytes", received.len());
+    assert_eq!(1, received.len());
+    assert_eq!(10, received[0]);
+  }
\ No newline at end of file
diff --git a/samplecode/unit-test/enclave/src/test_path.rs b/samplecode/unit-test/enclave/src/test_path.rs
index b550d39..b7e6c8e 100644
--- a/samplecode/unit-test/enclave/src/test_path.rs
+++ b/samplecode/unit-test/enclave/src/test_path.rs
@@ -6,6 +6,7 @@ use std::fs;
 use std::panic;
 use core::str;
 use std::io::{Read, Write, ErrorKind};
+use std::io::{IoSliceMut, IoSlice};
 
 macro_rules! check { ($e:expr) => (
     match $e {
@@ -315,3 +316,72 @@ pub fn test_path_copy_file_follows_dst_symlink() {
     assert_eq!(check!(fs::read(&out_path_symlink)), b"foo".to_vec());
     assert_eq!(check!(fs::read(&out_path)), b"foo".to_vec());
 }
+
+pub fn test_rwv() {
+    let chunck_size = 100;
+    let n = 6;
+    let block_size = n * chunck_size;
+
+    let buffer1 = vec![1; block_size];
+    let buffer2 = vec![2; block_size];
+    let buffer3 = vec![3; block_size];
+    let buffer4 = vec![4; block_size];
+
+    let fname = "foo.txt";
+
+    {
+        let mut file = File::create(&fname).unwrap();
+        let input = &[
+            IoSlice::new(&buffer1),
+        ][..];
+        file.write_vectored(input).unwrap();
+
+        let input = &[
+            IoSlice::new(&buffer2),
+            IoSlice::new(&buffer3),
+            IoSlice::new(&buffer4),
+        ][..];
+        file.write_vectored(input).unwrap();
+    }
+
+
+    let mut b1 = vec![0; chunck_size];
+    let mut b2 = vec![0; chunck_size];
+    let mut b3 = vec![0; chunck_size];
+    let mut b4 = vec![0; chunck_size];
+    let mut b5 = vec![0; chunck_size];
+    let mut b6 = vec![0; chunck_size];
+    {
+        let mut file2 = File::open(&fname).unwrap();
+
+        let mut i = 1;
+        loop {
+            {
+                let mut bufs = &mut [
+                    IoSliceMut::new(&mut b1),
+                    IoSliceMut::new(&mut b2),
+                    IoSliceMut::new(&mut b3),
+                    IoSliceMut::new(&mut b4),
+                    IoSliceMut::new(&mut b5),
+                    IoSliceMut::new(&mut b6),
+                ][..];
+
+                if file2.read_vectored(&mut bufs).unwrap() == 0 {
+                    break
+                }
+            }
+
+            let data = vec![i; chunck_size];
+            assert_eq!(&data[..], &b1[..]);
+            assert_eq!(&b1[..], &b2[..]);
+            assert_eq!(&b2[..], &b3[..]);
+            assert_eq!(&b3[..], &b4[..]);
+            assert_eq!(&b4[..], &b5[..]);
+            assert_eq!(&b5[..], &b6[..]);
+
+            i += 1;
+        }
+    }
+
+    check!(fs::remove_file(&fname));
+}
\ No newline at end of file
diff --git a/samplecode/unit-test/enclave/src/test_rts.rs b/samplecode/unit-test/enclave/src/test_rts.rs
index 668e50f..a11c71f 100644
--- a/samplecode/unit-test/enclave/src/test_rts.rs
+++ b/samplecode/unit-test/enclave/src/test_rts.rs
@@ -16,17 +16,17 @@
 // under the License..
 
 use sgx_types::*;
-use std::vec::Vec;
 use std::string::String;
+use std::vec::Vec;
 
-use sgx_trts::trts::*;
-use sgx_trts::veh::*;
 use sgx_trts::ascii::AsciiExt;
 use sgx_trts::c_str::*;
+use sgx_trts::enclave::*;
 use sgx_trts::error;
-use sgx_trts::memchr;
 use sgx_trts::libc;
-use sgx_trts::enclave::*;
+use sgx_trts::memchr;
+use sgx_trts::trts::*;
+use sgx_trts::veh::*;
 
 //Only during dev
 //use core::mem;
@@ -36,7 +36,7 @@ global_ctors_object! {
 }
 
 // veh
-extern "C" fn sample_exception_handler(_ : *mut sgx_exception_info_t) -> int32_t {
+extern "C" fn sample_exception_handler(_: *mut sgx_exception_info_t) -> int32_t {
     0
 }
 
@@ -63,12 +63,11 @@ pub fn test_register_last_exception_handler() {
 }
 
 pub fn test_register_multiple_exception_handler() {
-    let mut handler_vec : Vec<exception_handle> = Vec::new();
-    let ntest:usize = 100;
+    let mut handler_vec: Vec<exception_handle> = Vec::new();
+    let ntest: usize = 100;
 
     for i in 0..ntest {
-        let handle = rsgx_register_exception_handler(i as uint32_t % 2,
-                                                     sample_exception_handler);
+        let handle = rsgx_register_exception_handler(i as uint32_t % 2, sample_exception_handler);
         assert!(handle.is_some());
         handler_vec.push(handle.unwrap());
     }
@@ -85,7 +84,7 @@ pub fn test_register_multiple_exception_handler() {
 }
 
 // trts
-pub fn test_read_rand(){
+pub fn test_read_rand() {
     let mut rand_arr = [0; 100];
     assert_eq!(rsgx_read_rand(&mut rand_arr[..]), Ok(()));
     // Cannot all be zero
@@ -96,7 +95,7 @@ pub fn test_read_rand(){
 pub fn test_data_is_within_enclave() {
     #[allow(dead_code)]
     #[derive(Clone, Copy)]
-    struct SampleDs{
+    struct SampleDs {
         x: i32,
         y: i32,
         z: [i32; 100],
@@ -110,7 +109,7 @@ pub fn test_data_is_within_enclave() {
 
     let ooo;
     unsafe {
-        let ppp = 0xdeadbeafdeadbeaf as * const u8;
+        let ppp = 0xdeadbeafdeadbeaf as *const u8;
         ooo = &*ppp;
     }
     assert_eq!(rsgx_data_is_within_enclave(ooo), false);
@@ -129,19 +128,21 @@ pub fn test_slice_is_within_enlave() {
     //assert_eq!(rsgx_slice_is_within_enclave(ooo), false);
 }
 
-pub fn test_raw_is_within_enclave(){
-    assert_eq!(rsgx_raw_is_within_enclave(test_raw_is_within_enclave as * const u8,
-                                          10),
-               true);
-    assert_eq!(rsgx_raw_is_within_enclave(0xdeadbeafdeadbeaf as * const u8,
-                                          10),
-               false);
+pub fn test_raw_is_within_enclave() {
+    assert_eq!(
+        rsgx_raw_is_within_enclave(test_raw_is_within_enclave as *const u8, 10),
+        true
+    );
+    assert_eq!(
+        rsgx_raw_is_within_enclave(0xdeadbeafdeadbeaf as *const u8, 10),
+        false
+    );
 }
 
 pub fn test_data_is_outside_enclave() {
     #[allow(dead_code)]
     #[derive(Clone, Copy)]
-    struct SampleDs{
+    struct SampleDs {
         x: i32,
         y: i32,
         z: [i32; 100],
@@ -155,7 +156,7 @@ pub fn test_data_is_outside_enclave() {
 
     let ooo;
     unsafe {
-        let ppp = 0xdeadbeafdeadbeaf as * const u8;
+        let ppp = 0xdeadbeafdeadbeaf as *const u8;
         ooo = &*ppp;
     }
     assert_eq!(rsgx_data_is_outside_enclave(ooo), true);
@@ -174,18 +175,20 @@ pub fn test_slice_is_outside_enclave() {
     //assert_eq!(rsgx_slice_is_within_enclave(ooo), true);
 }
 
-pub fn test_raw_is_outside_enclave(){
-    assert_eq!(rsgx_raw_is_outside_enclave(test_raw_is_outside_enclave as * const u8,
-                                          10),
-               false);
-    assert_eq!(rsgx_raw_is_outside_enclave(0xdeadbeafdeadbeaf as * const u8,
-                                          10),
-               true);
+pub fn test_raw_is_outside_enclave() {
+    assert_eq!(
+        rsgx_raw_is_outside_enclave(test_raw_is_outside_enclave as *const u8, 10),
+        false
+    );
+    assert_eq!(
+        rsgx_raw_is_outside_enclave(0xdeadbeafdeadbeaf as *const u8, 10),
+        true
+    );
 }
 
 // macros
 
-pub fn test_global_ctors_object (){
+pub fn test_global_ctors_object() {
     assert_eq!(VARNAME(), ());
 }
 
@@ -195,72 +198,54 @@ pub fn test_global_ctors_object (){
 // error
 pub fn test_error() {
     // XXX: Top 11 should be the same in all unix?
-    let errorinfo_vec:Vec<(i32,&'static str)> = vec![
-        (1 , "Operation not permitted"),
-        (2 , "No such file or directory"),
-        (3 , "No such process"),
-        (4 , "Interrupted system call"),
-        (5 , "Input/output error"),
-        (6 , "Device not configured"),
-        (7 , "Argument list too long"),
-        (8 , "Exec format error"),
-        (9 , "Bad file descriptor"),
+    let errorinfo_vec: Vec<(i32, &'static str)> = vec![
+        (1, "Operation not permitted"),
+        (2, "No such file or directory"),
+        (3, "No such process"),
+        (4, "Interrupted system call"),
+        (5, "Input/output error"),
+        (6, "Device not configured"),
+        (7, "Argument list too long"),
+        (8, "Exec format error"),
+        (9, "Bad file descriptor"),
         (10, "No child processes"),
         (11, "Resource deadlock avoided"),
-        ];
+    ];
 
     for case in errorinfo_vec {
-        let mut buf:[i8;64] = [0;64];
+        let mut buf: [i8; 64] = [0; 64];
         error::set_errno(case.0);
-        unsafe { error::error_string(error::errno(),&mut buf[..]);}
-        let answer:Vec<u8> = buf.iter().map(|&x| x as u8).collect();
+        unsafe {
+            error::error_string(error::errno(), &mut buf[..]);
+        }
+        let answer: Vec<u8> = buf.iter().map(|&x| x as u8).collect();
         let ans_str = String::from_utf8(answer).unwrap();
-        assert_eq!(ans_str.trim_matches('\0'),
-                   case.1);
+        assert_eq!(ans_str.trim_matches('\0'), case.1);
     }
-
 }
 
 // libc
-pub fn test_rts_libc_memchr(){
+pub fn test_rts_libc_memchr() {
     let test_str = "abcdedfg";
     assert_eq!(
-            unsafe {
-                libc::memchr(
-                        test_str.as_ptr() as * const u8,
-                        'd' as u8,
-                        test_str.len())},
-            test_str[3..].as_ptr());
-    assert_eq!(
-            unsafe {
-                libc::memchr(
-                        "abcdefg".as_ptr() as * const u8,
-                        'z' as u8,
-                        test_str.len())},
-            0 as * const u8);
+        libc::memchr::memchr('d' as u8, test_str.as_bytes()),
+        Some(3)
+    );
+    assert_eq!(libc::memchr::memchr('z' as u8, "abcdefg".as_bytes()), None);
 }
 
-pub fn test_rts_libc_memrchr(){
+pub fn test_rts_libc_memrchr() {
     let test_str = "abcdedfg";
     assert_eq!(
-            unsafe {
-                libc::memrchr(
-                        test_str.as_ptr() as * const u8,
-                        'd' as u8,
-                        test_str.len())},
-            test_str[5..].as_ptr());
-    assert_eq!(
-            unsafe {
-                libc::memrchr(
-                        "abcdefg".as_ptr() as * const u8,
-                        'z' as u8,
-                        test_str.len())},
-            0 as * const u8);
+        libc::memchr::memrchr('d' as u8, test_str.as_bytes()),
+        Some(5)
+    );
+    assert_eq!(libc::memchr::memrchr('z' as u8, "abcdefg".as_bytes()), None);
 }
 
 // memchr
 
-pub fn test_rts_memchr_memchr(){
+pub fn test_rts_memchr_memchr() {
     let test_str = "abcdedfg".as_bytes();
     let needle = 'd' as u8;
     assert_eq!(memchr::memchr(needle, test_str), Some(3));
@@ -268,7 +253,7 @@ pub fn test_rts_memchr_memchr(){
     assert_eq!(memchr::memchr(needle, test_str), None);
 }
 
-pub fn test_rts_memchr_memrchr(){
+pub fn test_rts_memchr_memrchr() {
     let test_str = "abcdedfg".as_bytes();
     let needle = 'd' as u8;
     assert_eq!(memchr::memrchr(needle, test_str), Some(5));
@@ -277,7 +262,7 @@ pub fn test_rts_memchr_memrchr(){
 }
 
 // ascii
-pub fn test_ascii(){
+pub fn test_ascii() {
     assert_eq!("café".to_ascii_uppercase(), "CAFÉ");
     assert_eq!("café".to_ascii_uppercase(), "CAFé");
 
@@ -292,7 +277,6 @@ pub fn test_ascii(){
     assert_eq!('❤', non_ascii.to_ascii_uppercase());
     assert_eq!(65, int_ascii.to_ascii_uppercase());
 
-
     let ascii = 'A';
     let non_ascii = '❤';
     let int_ascii = 65;
@@ -320,7 +304,7 @@ pub fn test_ascii(){
 }
 
 // c_str
-pub fn test_cstr(){
+pub fn test_cstr() {
     let c_string = CString::new("foo").unwrap();
     let ptr = c_string.into_raw();
 
@@ -373,7 +357,7 @@ pub fn test_cstr(){
 
     let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0").unwrap();
     assert_eq!(
-                c_str.to_string_lossy(),
-                    Cow::Owned(String::from("Hello �World")) as Cow<str>
-            );
+        c_str.to_string_lossy(),
+        Cow::Owned(String::from("Hello �World")) as Cow<str>
+    );
 }
diff --git a/samplecode/unit-test/enclave/src/test_signal.rs b/samplecode/unit-test/enclave/src/test_signal.rs
index c944e14..e6f13a4 100644
--- a/samplecode/unit-test/enclave/src/test_signal.rs
+++ b/samplecode/unit-test/enclave/src/test_signal.rs
@@ -63,7 +63,7 @@ pub fn test_signal_with_pid() {
       }
    };
 
-   let pid = unsafe { getpid() };
+   let pid = unsafe { getpid().unwrap() };
    register_sigaction(SIGUSR2, action).unwrap();
    raise_signal(SIGUSR2);
 
diff --git a/sgx_edl/edl/sgx_env.edl b/sgx_edl/edl/sgx_env.edl
index d4a77cc..3139ca4 100644
--- a/sgx_edl/edl/sgx_env.edl
+++ b/sgx_edl/edl/sgx_env.edl
@@ -24,17 +24,9 @@ enclave {
     };
 
     untrusted {
-        char **u_environ_ocall();
-        char *u_getenv_ocall([in, string] const char *name);
-        int u_setenv_ocall([out] int *error, [in, string] const char *name, [in, string] const char *value, int overwrite);
-        int u_unsetenv_ocall([out] int *error, [in, string] const char *name);
+        int u_getenv_ocall([out] int *error, [in, string] const char *name, [out, size=bufsz] char *buf, size_t bufsz, [out] int *isset);
         int u_chdir_ocall([out] int *error, [in, string] const char *dir);
-        char *u_getcwd_ocall([out] int *error, [out, size=buflen] char *buf, size_t buflen);
-        int u_getpwuid_r_ocall(unsigned int uid,
-                               [out] struct passwd *pwd,
-                               [out, size=buflen] char *buf,
-                               size_t buflen,
-                               [out] struct passwd **passwd_result);
+        int u_getcwd_ocall([out] int *error, [out, size=buflen] char *buf, size_t buflen);
         unsigned int u_getuid_ocall();
     };
 };
diff --git a/sgx_edl/edl/sgx_fd.edl b/sgx_edl/edl/sgx_fd.edl
index 8cfc822..e2ea291 100644
--- a/sgx_edl/edl/sgx_fd.edl
+++ b/sgx_edl/edl/sgx_fd.edl
@@ -29,13 +29,9 @@ enclave {
     untrusted {
         size_t u_read_ocall([out] int *error, int fd, [user_check] void *buf, size_t count);
         size_t u_pread64_ocall([out] int *error, int fd, [user_check] void *buf, size_t count, int64_t offset);
-        size_t u_readv_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt);
-        size_t u_preadv64_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt, int64_t offset);
 
         size_t u_write_ocall([out] int *error, int fd, [user_check] const void *buf, size_t count);
         size_t u_pwrite64_ocall([out] int *error, int fd, [user_check] const void *buf, size_t count, int64_t offset);
-        size_t u_writev_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt);
-        size_t u_pwritev64_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt, int64_t offset);
 
         int u_fcntl_arg0_ocall([out] int *error, int fd, int cmd);
         int u_fcntl_arg1_ocall([out] int *error, int fd, int cmd, int arg);
diff --git a/sgx_edl/edl/sgx_file.edl b/sgx_edl/edl/sgx_file.edl
index 1e28036..1c95f3e 100644
--- a/sgx_edl/edl/sgx_file.edl
+++ b/sgx_edl/edl/sgx_file.edl
@@ -50,11 +50,11 @@ enclave {
         int u_chmod_ocall([out] int *error, [in, string] const char *path, uint32_t mode);
         size_t u_readlink_ocall([out] int *error, [in, string] const char *path, [out, size=bufsz] char *buf, size_t bufsz);
         int u_symlink_ocall([out] int *error, [in, string] const char *path1, [in, string] const char *path2);
-        char *u_realpath_ocall([out] int *error, [in, string] const char *pathname);
+        int u_realpath_ocall([out] int *error, [in, string] const char *pathname, [out, size=bufsz] char *buf, size_t bufsz);
         int u_mkdir_ocall([out] int *error, [in, string] const char *pathname, uint32_t mode);
         int u_rmdir_ocall([out] int *error, [in, string] const char *pathname);
         void *u_opendir_ocall([out] int *error, [in, string] const char *pathname);
-        int u_readdir64_r_ocall([user_check] void *dirp, [in, out] struct dirent64_t *entry, [out] struct dirent64_t **result);
+        int u_readdir64_r_ocall([user_check] void *dirp, [in, out] struct dirent64_t *entry, [out] int * eods);
         int u_closedir_ocall([out] int *error, [user_check] void *dirp);
         int u_dirfd_ocall([out] int *error, [user_check] void *dirp);
         int u_fstatat64_ocall([out] int *error, int dirfd, [in, string] const char *pathname, [out] struct stat64_t *buf, int flags);
diff --git a/sgx_edl/edl/sgx_net.edl b/sgx_edl/edl/sgx_net.edl
index a803b53..64692de 100644
--- a/sgx_edl/edl/sgx_net.edl
+++ b/sgx_edl/edl/sgx_net.edl
@@ -34,8 +34,9 @@ enclave {
                                 [in, string] const char *node,
                                 [in, string] const char *service,
                                 [in] const struct addrinfo *hints,
-                                [out] struct addrinfo **res);
-        void u_freeaddrinfo_ocall([user_check] struct addrinfo *res);
-        char *u_gai_strerror_ocall(int errcode);
+                                size_t entry_size,
+                                [out, size=bufsz] uint8_t *buf,
+                                size_t bufsz,
+                                [out] size_t *entry_count);
     };
 };
diff --git a/sgx_edl/edl/sgx_pipe.edl b/sgx_edl/edl/sgx_pipe.edl
index 00c12f5..1729fe1 100644
--- a/sgx_edl/edl/sgx_pipe.edl
+++ b/sgx_edl/edl/sgx_pipe.edl
@@ -25,7 +25,6 @@ enclave {
     };
 
     untrusted {
-        int u_pipe_ocall([out] int *error, [out, count=2] int *pipefd);
         int u_pipe2_ocall([out] int *error, [out, count=2] int *pipefd, int flags);
     };
 };
diff --git a/sgx_edl/edl/sgx_socket.edl b/sgx_edl/edl/sgx_socket.edl
index 68ce3b6..d6d9f8f 100644
--- a/sgx_edl/edl/sgx_socket.edl
+++ b/sgx_edl/edl/sgx_socket.edl
@@ -30,11 +30,6 @@ enclave {
         int u_socketpair_ocall([out] int *error, int domain, int ty, int protocol, [out] int sv[2]);
         int u_bind_ocall([out] int *error, int sockfd, [in, size=addrlen] const struct sockaddr *addr, socklen_t addrlen);
         int u_listen_ocall([out] int *error, int sockfd, int backlog);
-        int u_accept_ocall([out] int *error,
-                           int sockfd,
-                           [in, out, size=addrlen_in] struct sockaddr *addr,
-                           socklen_t addrlen_in,
-                           [out] socklen_t *addrlen_out);
         int u_accept4_ocall([out] int *error,
                             int sockfd,
                             [in, out, size=addrlen_in] struct sockaddr *addr,
@@ -54,7 +49,6 @@ enclave {
                                 [out, size=addrlen_in] struct sockaddr *src_addr,
                                 socklen_t addrlen_in,
                                 [out] socklen_t *addrlen_out);
-        size_t u_recvmsg_ocall([out] int *error, int sockfd, [in, out] struct msghdr *msg, int flags);
         size_t u_send_ocall([out] int *error, int sockfd, [user_check] const void *buf, size_t len, int flags);
         size_t u_sendto_ocall([out] int *error,
                               int sockfd,
@@ -63,7 +57,6 @@ enclave {
                               int flags,
                               [in, size=addrlen] const struct sockaddr *dest_addr,
                               socklen_t addrlen);
-        size_t u_sendmsg_ocall([out] int *error, int sockfd, [in] const struct msghdr *msg, int flags);
         int u_getsockopt_ocall([out] int *error,
                                int sockfd,
                                int level,
diff --git a/sgx_edl/edl/sgx_sys.edl b/sgx_edl/edl/sgx_sys.edl
index f5f3d2c..6561725 100644
--- a/sgx_edl/edl/sgx_sys.edl
+++ b/sgx_edl/edl/sgx_sys.edl
@@ -24,7 +24,6 @@ enclave {
     };
 
     untrusted {
-        long u_sysconf_ocall([out] int *error, int name);
         int u_prctl_ocall([out] int *error, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
         int u_sched_setaffinity_ocall([out] int *error, pid_t pid, size_t cpusetsize, [in, size=cpusetsize]cpu_set_t *mask);
         int u_sched_getaffinity_ocall([out] int *error, pid_t pid, size_t cpusetsize, [out, size=cpusetsize]cpu_set_t *mask);
diff --git a/sgx_trts/src/ascii.rs b/sgx_libc/src/ascii.rs
similarity index 100%
rename from sgx_trts/src/ascii.rs
rename to sgx_libc/src/ascii.rs
diff --git a/sgx_trts/src/c_str.rs b/sgx_libc/src/c_str.rs
similarity index 99%
rename from sgx_trts/src/c_str.rs
rename to sgx_libc/src/c_str.rs
index 8e55c92..30b37fd 100644
--- a/sgx_trts/src/c_str.rs
+++ b/sgx_libc/src/c_str.rs
@@ -24,7 +24,6 @@
 /// bytes ("nul characters") and that the final byte is 0 ("nul terminator").
 ///
 use sgx_types::c_char;
-use crate::libc;
 use crate::memchr;
 use crate::ascii;
 
@@ -267,7 +266,7 @@ impl CString {
     /// [`CStr`]: struct.CStr.html
     ///
     pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
-        let len = libc::strlen(ptr) + 1; // Including the NUL byte
+        let len = crate::strlen(ptr) + 1; // Including the NUL byte
         let slice = slice::from_raw_parts_mut(ptr, len as usize);
         CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) }
     }
@@ -634,7 +633,7 @@ impl CStr {
     /// > the string. This is not guaranteed to always be the case.
     ///
     pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
-        let len = libc::strlen(ptr);
+        let len = crate::strlen(ptr);
         let ptr = ptr as *const u8;
         CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
     }
diff --git a/sgx_libc/src/lib.rs b/sgx_libc/src/lib.rs
index d669e18..61b751f 100644
--- a/sgx_libc/src/lib.rs
+++ b/sgx_libc/src/lib.rs
@@ -25,6 +25,11 @@
 #![allow(non_snake_case)]
 #![allow(unused_macros)]
 #![allow(unused_assignments)]
+#![feature(const_raw_ptr_deref)]
+#![feature(min_specialization)]
+#![feature(vec_into_raw_parts)]
+#![feature(toowned_clone_into)]
+#![feature(slice_index_methods)]
 
 #[macro_use]
 extern crate alloc;
@@ -46,3 +51,7 @@ cfg_if! {
 
     }
 }
+
+pub mod memchr;
+pub mod ascii;
+pub mod c_str;
\ No newline at end of file
diff --git a/sgx_libc/src/linux/mod.rs b/sgx_libc/src/linux/mod.rs
index f05c8e9..9d79204 100644
--- a/sgx_libc/src/linux/mod.rs
+++ b/sgx_libc/src/linux/mod.rs
@@ -17,6 +17,7 @@
 
 cfg_if! {
     if #[cfg(all(target_os = "linux", target_arch = "x86_64"))] {
+        #[macro_use]
         mod x86_64;
         pub use self::x86_64::*;
     } else {
diff --git a/sgx_libc/src/linux/x86_64/mod.rs b/sgx_libc/src/linux/x86_64/mod.rs
index 4477875..40f85df 100644
--- a/sgx_libc/src/linux/x86_64/mod.rs
+++ b/sgx_libc/src/linux/x86_64/mod.rs
@@ -21,15 +21,19 @@
 //! It is a c-style interface and self-explained. Currently we don't have much
 //! time for documenting it.
 
-pub use sgx_types::{int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t, uint64_t};
-pub use sgx_types::{c_void, c_schar, c_char, c_uchar, c_short, c_ushort, c_int, c_uint, c_float,
-                    c_double, c_longlong, c_ulonglong, intmax_t, uintmax_t, c_ulong, c_long};
-pub use sgx_types::{size_t, ptrdiff_t, intptr_t, uintptr_t, ssize_t};
 pub use sgx_types::time_t;
+pub use sgx_types::{
+    c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
+    c_ulong, c_ulonglong, c_ushort, c_void, intmax_t, uintmax_t,
+};
+pub use sgx_types::{int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t};
+pub use sgx_types::{intptr_t, ptrdiff_t, size_t, ssize_t, uintptr_t};
 
-use sgx_types::{sgx_thread_mutex_t, sgx_thread_mutex_attr_t, sgx_thread_cond_t, sgx_thread_cond_attr_t};
-use core::ptr;
 use core::mem;
+use core::ptr;
+use sgx_types::{
+    sgx_thread_cond_attr_t, sgx_thread_cond_t, sgx_thread_mutex_attr_t, sgx_thread_mutex_t,
+};
 
 extern "C" {
     pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void;
@@ -41,35 +45,38 @@ extern "C" {
 
 #[link(name = "sgx_pthread")]
 extern "C" {
-    pub fn pthread_create(native: *mut pthread_t,
-                          attr: *const pthread_attr_t,
-                          f: extern "C" fn(*mut c_void) -> *mut c_void,
-                          value: *mut c_void) -> c_int;
-    pub fn pthread_join(native: pthread_t,
-                        value: *mut *mut c_void) -> c_int;
+    pub fn pthread_create(
+        native: *mut pthread_t,
+        attr: *const pthread_attr_t,
+        f: extern "C" fn(*mut c_void) -> *mut c_void,
+        value: *mut c_void,
+    ) -> c_int;
+    pub fn pthread_join(native: pthread_t, value: *mut *mut c_void) -> c_int;
     pub fn pthread_exit(value: *mut c_void);
     pub fn pthread_self() -> pthread_t;
     pub fn pthread_equal(t1: pthread_t, t2: pthread_t) -> c_int;
 
     pub fn pthread_once(once_control: *mut pthread_once_t, init_routine: extern "C" fn()) -> c_int;
 
-    pub fn pthread_key_create(key: *mut pthread_key_t,
-                              dtor: Option<unsafe extern "C" fn(*mut c_void)>) -> c_int;
+    pub fn pthread_key_create(
+        key: *mut pthread_key_t,
+        dtor: Option<unsafe extern "C" fn(*mut c_void)>,
+    ) -> c_int;
     pub fn pthread_key_delete(key: pthread_key_t) -> c_int;
     pub fn pthread_getspecific(key: pthread_key_t) -> *mut c_void;
     pub fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int;
-    
-    pub fn pthread_mutex_init(lock: *mut pthread_mutex_t,
-                              attr: *const pthread_mutexattr_t) -> c_int;
+
+    pub fn pthread_mutex_init(
+        lock: *mut pthread_mutex_t,
+        attr: *const pthread_mutexattr_t,
+    ) -> c_int;
     pub fn pthread_mutex_destroy(lock: *mut pthread_mutex_t) -> c_int;
     pub fn pthread_mutex_lock(lock: *mut pthread_mutex_t) -> c_int;
     pub fn pthread_mutex_trylock(lock: *mut pthread_mutex_t) -> c_int;
     pub fn pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> c_int;
 
-    pub fn pthread_cond_init(cond: *mut pthread_cond_t,
-                             attr: *const pthread_condattr_t) -> c_int;
-    pub fn pthread_cond_wait(cond: *mut pthread_cond_t,
-                             lock: *mut pthread_mutex_t) -> c_int;
+    pub fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int;
+    pub fn pthread_cond_wait(cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t) -> c_int;
     pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int;
     pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int;
     pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int;
@@ -100,16 +107,12 @@ extern "C" {
 
 /// Get the last error number.
 pub fn errno() -> i32 {
-    unsafe {
-        (*errno_location()) as i32
-    }
+    unsafe { (*errno_location()) as i32 }
 }
 
 /// Set the last error number.
 pub fn set_errno(e: i32) {
-    unsafe {
-        *errno_location() = e as c_int
-    }
+    unsafe { *errno_location() = e as c_int }
 }
 
 /// Gets a detailed string description for the given error number.
@@ -118,33 +121,6 @@ pub unsafe fn error_string(errno: i32, buf: &mut [i8]) -> i32 {
     strerror_r(errno as c_int, p as *mut c_char, buf.len()) as i32
 }
 
-pub unsafe fn memchr(s: *const u8, c: u8, n: usize) -> *const u8 {
-    let mut ret = ptr::null();
-    let mut p = s;
-    for _ in 0..n {
-        if *p == c {
-            ret = p;
-            break;
-        }
-        p = p.offset(1);
-    }
-    ret
-}
-
-pub unsafe fn memrchr(s: *const u8, c: u8, n: usize) -> *const u8 {
-    if n == 0 { return ptr::null(); }
-    let mut ret = ptr::null();
-    let mut p: *const u8 = (s as usize + (n - 1)) as *const u8;
-    for _ in 0..n {
-        if *p == c {
-            ret = p;
-            break;
-        }
-         p = p.offset(-1);
-    }
-    ret
-}
-
 // intentionally not public, only used for fd_set
 cfg_if! {
     if #[cfg(target_pointer_width = "32")] {
@@ -193,8 +169,8 @@ pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = ptr::null_mut();
 pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = ptr::null_mut();
 pub const PTHREAD_ONCE_INIT: pthread_once_t = pthread_once_t {
     state: PTHREAD_NEEDS_INIT,
-    mutex: PTHREAD_MUTEX_INITIALIZER
-    };
+    mutex: PTHREAD_MUTEX_INITIALIZER,
+};
 
 #[derive(Copy, Clone, Debug)]
 pub enum DIR {}
@@ -271,7 +247,6 @@ s! {
         pub sin6_addr: in6_addr,
         pub sin6_scope_id: u32,
     }
-
     pub struct sockaddr_un {
         pub sun_family: sa_family_t,
         pub sun_path: [c_char; 108],
@@ -761,7 +736,6 @@ pub const _IOLBF: c_int = 1;
 pub const FILENAME_MAX: c_uint = 4096;
 pub const FOPEN_MAX: c_uint = 16;
 
-
 pub const IFF_UP: c_int = 0x1;
 pub const IFF_BROADCAST: c_int = 0x2;
 pub const IFF_DEBUG: c_int = 0x4;
@@ -1003,6 +977,16 @@ pub const EAI_SOCKTYPE: c_int = -7;
 pub const EAI_SERVICE: c_int = -8;
 pub const EAI_MEMORY: c_int = -10;
 pub const EAI_OVERFLOW: c_int = -12;
+pub const EAI_SYSTEM: c_int = -11;
+
+pub const EAI_NODATA: c_int = -5;
+pub const EAI_ADDRFAMILY: c_int = -9;
+pub const EAI_INPROGRESS: c_int = -100;
+pub const EAI_CANCELED: c_int = -101;
+pub const EAI_NOTCANCELED: c_int = -102;
+pub const EAI_ALLDONE: c_int = -103;
+pub const EAI_INTR: c_int = -104;
+pub const EAI_IDN_ENCODE: c_int = -105;
 
 pub const NI_NUMERICHOST: c_int = 1;
 pub const NI_NUMERICSERV: c_int = 2;
@@ -1014,8 +998,6 @@ pub const SYNC_FILE_RANGE_WAIT_BEFORE: c_uint = 1;
 pub const SYNC_FILE_RANGE_WRITE: c_uint = 2;
 pub const SYNC_FILE_RANGE_WAIT_AFTER: c_uint = 4;
 
-pub const EAI_SYSTEM: c_int = -11;
-
 pub const AIO_CANCELED: c_int = 0;
 pub const AIO_NOTCANCELED: c_int = 1;
 pub const AIO_ALLDONE: c_int = 2;
@@ -1257,141 +1239,141 @@ pub const _SC_THREAD_ROBUST_PRIO_PROTECT: c_int = 248;
 
 pub const CPU_SETSIZE: c_int = 0x400;
 
-pub const EPERM: int32_t              = 1;
-pub const ENOENT: int32_t             = 2;
-pub const ESRCH: int32_t              = 3;
-pub const EINTR: int32_t              = 4;
-pub const EIO: int32_t                = 5;
-pub const ENXIO: int32_t              = 6;
-pub const E2BIG: int32_t              = 7;
-pub const ENOEXEC: int32_t            = 8;
-pub const EBADF: int32_t              = 9;
-pub const ECHILD: int32_t             = 10;
-pub const EAGAIN: int32_t             = 11;
-pub const ENOMEM: int32_t             = 12;
-pub const EACCES: int32_t             = 13;
-pub const EFAULT: int32_t             = 14;
-pub const ENOTBLK: int32_t            = 15;
-pub const EBUSY: int32_t              = 16;
-pub const EEXIST: int32_t             = 17;
-pub const EXDEV: int32_t              = 18;
-pub const ENODEV: int32_t             = 19;
-pub const ENOTDIR: int32_t            = 20;
-pub const EISDIR: int32_t             = 21;
-pub const EINVAL: int32_t             = 22;
-pub const ENFILE: int32_t             = 23;
-pub const EMFILE: int32_t             = 24;
-pub const ENOTTY: int32_t             = 25;
-pub const ETXTBSY: int32_t            = 26;
-pub const EFBIG: int32_t              = 27;
-pub const ENOSPC: int32_t             = 28;
-pub const ESPIPE: int32_t             = 29;
-pub const EROFS: int32_t              = 30;
-pub const EMLINK: int32_t             = 31;
-pub const EPIPE: int32_t              = 32;
-pub const EDOM: int32_t               = 33;
-pub const ERANGE: int32_t             = 34;
-pub const EDEADLK: int32_t            = 35;
-pub const ENAMETOOLONG: int32_t       = 36;
-pub const ENOLCK: int32_t             = 37;
-pub const ENOSYS: int32_t             = 38;
-pub const ENOTEMPTY: int32_t          = 39;
-pub const ELOOP: int32_t              = 40;
-pub const EWOULDBLOCK: int32_t        = EAGAIN;
-pub const ENOMSG: int32_t             = 42;
-pub const EIDRM: int32_t              = 43;
-pub const ECHRNG: int32_t             = 44;
-pub const EL2NSYNC: int32_t           = 45;
-pub const EL3HLT: int32_t             = 46;
-pub const EL3RST: int32_t             = 47;
-pub const ELNRNG: int32_t             = 48;
-pub const EUNATCH: int32_t            = 49;
-pub const ENOCSI: int32_t             = 50;
-pub const EL2HLT: int32_t             = 51;
-pub const EBADE: int32_t              = 52;
-pub const EBADR: int32_t              = 53;
-pub const EXFULL: int32_t             = 54;
-pub const ENOANO: int32_t             = 55;
-pub const EBADRQC: int32_t            = 56;
-pub const EBADSLT: int32_t            = 57;
-pub const EDEADLOCK: int32_t          = EDEADLK;
-pub const EBFONT: int32_t             = 59;
-pub const ENOSTR: int32_t             = 60;
-pub const ENODATA: int32_t            = 61;
-pub const ETIME: int32_t              = 62;
-pub const ENOSR: int32_t              = 63;
-pub const ENONET: int32_t             = 64;
-pub const ENOPKG: int32_t             = 65;
-pub const EREMOTE: int32_t            = 66;
-pub const ENOLINK: int32_t            = 67;
-pub const EADV: int32_t               = 68;
-pub const ESRMNT: int32_t             = 69;
-pub const ECOMM: int32_t              = 70;
-pub const EPROTO: int32_t             = 71;
-pub const EMULTIHOP: int32_t          = 72;
-pub const EDOTDOT: int32_t            = 73;
-pub const EBADMSG: int32_t            = 74;
-pub const EOVERFLOW: int32_t          = 75;
-pub const ENOTUNIQ: int32_t           = 76;
-pub const EBADFD: int32_t             = 77;
-pub const EREMCHG: int32_t            = 78;
-pub const ELIBACC: int32_t            = 79;
-pub const ELIBBAD: int32_t            = 80;
-pub const ELIBSCN: int32_t            = 81;
-pub const ELIBMAX: int32_t            = 82;
-pub const ELIBEXEC: int32_t           = 83;
-pub const EILSEQ: int32_t             = 84;
-pub const ERESTART: int32_t           = 85;
-pub const ESTRPIPE: int32_t           = 86;
-pub const EUSERS: int32_t             = 87;
-pub const ENOTSOCK: int32_t           = 88;
-pub const EDESTADDRREQ: int32_t       = 89;
-pub const EMSGSIZE: int32_t           = 90;
-pub const EPROTOTYPE: int32_t         = 91;
-pub const ENOPROTOOPT: int32_t        = 92;
-pub const EPROTONOSUPPORT: int32_t    = 93;
-pub const ESOCKTNOSUPPORT: int32_t    = 94;
-pub const EOPNOTSUPP: int32_t         = 95;
-pub const EPFNOSUPPORT: int32_t       = 96;
-pub const EAFNOSUPPORT: int32_t       = 97;
-pub const EADDRINUSE: int32_t         = 98;
-pub const EADDRNOTAVAIL: int32_t      = 99;
-pub const ENETDOWN: int32_t           = 100;
-pub const ENETUNREACH: int32_t        = 101;
-pub const ENETRESET: int32_t          = 102;
-pub const ECONNABORTED: int32_t       = 103;
-pub const ECONNRESET: int32_t         = 104;
-pub const ENOBUFS: int32_t            = 105;
-pub const EISCONN: int32_t            = 106;
-pub const ENOTCONN: int32_t           = 107;
-pub const ESHUTDOWN: int32_t          = 108;
-pub const ETOOMANYREFS: int32_t       = 109;
-pub const ETIMEDOUT: int32_t          = 110;
-pub const ECONNREFUSED: int32_t       = 111;
-pub const EHOSTDOWN: int32_t          = 112;
-pub const EHOSTUNREACH: int32_t       = 113;
-pub const EALREADY: int32_t           = 114;
-pub const EINPROGRESS: int32_t        = 115;
-pub const ESTALE: int32_t             = 116;
-pub const EUCLEAN: int32_t            = 117;
-pub const ENOTNAM: int32_t            = 118;
-pub const ENAVAIL: int32_t            = 119;
-pub const EISNAM: int32_t             = 120;
-pub const EREMOTEIO: int32_t          = 121;
-pub const EDQUOT: int32_t             = 122;
-pub const ENOMEDIUM: int32_t          = 123;
-pub const EMEDIUMTYPE: int32_t        = 124;
-pub const ECANCELED: int32_t          = 125;
-pub const ENOKEY: int32_t             = 126;
-pub const EKEYEXPIRED: int32_t        = 127;
-pub const EKEYREVOKED: int32_t        = 128;
-pub const EKEYREJECTED: int32_t       = 129;
-pub const EOWNERDEAD: int32_t         = 130;
-pub const ENOTRECOVERABLE: int32_t    = 131;
-pub const ERFKILL: int32_t            = 132;
-pub const EHWPOISON: int32_t          = 133;
-pub const ENOTSUP: int32_t            = EOPNOTSUPP;
-pub const ESGX: int32_t               = 0x0000_FFFF;
+pub const EPERM: int32_t = 1;
+pub const ENOENT: int32_t = 2;
+pub const ESRCH: int32_t = 3;
+pub const EINTR: int32_t = 4;
+pub const EIO: int32_t = 5;
+pub const ENXIO: int32_t = 6;
+pub const E2BIG: int32_t = 7;
+pub const ENOEXEC: int32_t = 8;
+pub const EBADF: int32_t = 9;
+pub const ECHILD: int32_t = 10;
+pub const EAGAIN: int32_t = 11;
+pub const ENOMEM: int32_t = 12;
+pub const EACCES: int32_t = 13;
+pub const EFAULT: int32_t = 14;
+pub const ENOTBLK: int32_t = 15;
+pub const EBUSY: int32_t = 16;
+pub const EEXIST: int32_t = 17;
+pub const EXDEV: int32_t = 18;
+pub const ENODEV: int32_t = 19;
+pub const ENOTDIR: int32_t = 20;
+pub const EISDIR: int32_t = 21;
+pub const EINVAL: int32_t = 22;
+pub const ENFILE: int32_t = 23;
+pub const EMFILE: int32_t = 24;
+pub const ENOTTY: int32_t = 25;
+pub const ETXTBSY: int32_t = 26;
+pub const EFBIG: int32_t = 27;
+pub const ENOSPC: int32_t = 28;
+pub const ESPIPE: int32_t = 29;
+pub const EROFS: int32_t = 30;
+pub const EMLINK: int32_t = 31;
+pub const EPIPE: int32_t = 32;
+pub const EDOM: int32_t = 33;
+pub const ERANGE: int32_t = 34;
+pub const EDEADLK: int32_t = 35;
+pub const ENAMETOOLONG: int32_t = 36;
+pub const ENOLCK: int32_t = 37;
+pub const ENOSYS: int32_t = 38;
+pub const ENOTEMPTY: int32_t = 39;
+pub const ELOOP: int32_t = 40;
+pub const EWOULDBLOCK: int32_t = EAGAIN;
+pub const ENOMSG: int32_t = 42;
+pub const EIDRM: int32_t = 43;
+pub const ECHRNG: int32_t = 44;
+pub const EL2NSYNC: int32_t = 45;
+pub const EL3HLT: int32_t = 46;
+pub const EL3RST: int32_t = 47;
+pub const ELNRNG: int32_t = 48;
+pub const EUNATCH: int32_t = 49;
+pub const ENOCSI: int32_t = 50;
+pub const EL2HLT: int32_t = 51;
+pub const EBADE: int32_t = 52;
+pub const EBADR: int32_t = 53;
+pub const EXFULL: int32_t = 54;
+pub const ENOANO: int32_t = 55;
+pub const EBADRQC: int32_t = 56;
+pub const EBADSLT: int32_t = 57;
+pub const EDEADLOCK: int32_t = EDEADLK;
+pub const EBFONT: int32_t = 59;
+pub const ENOSTR: int32_t = 60;
+pub const ENODATA: int32_t = 61;
+pub const ETIME: int32_t = 62;
+pub const ENOSR: int32_t = 63;
+pub const ENONET: int32_t = 64;
+pub const ENOPKG: int32_t = 65;
+pub const EREMOTE: int32_t = 66;
+pub const ENOLINK: int32_t = 67;
+pub const EADV: int32_t = 68;
+pub const ESRMNT: int32_t = 69;
+pub const ECOMM: int32_t = 70;
+pub const EPROTO: int32_t = 71;
+pub const EMULTIHOP: int32_t = 72;
+pub const EDOTDOT: int32_t = 73;
+pub const EBADMSG: int32_t = 74;
+pub const EOVERFLOW: int32_t = 75;
+pub const ENOTUNIQ: int32_t = 76;
+pub const EBADFD: int32_t = 77;
+pub const EREMCHG: int32_t = 78;
+pub const ELIBACC: int32_t = 79;
+pub const ELIBBAD: int32_t = 80;
+pub const ELIBSCN: int32_t = 81;
+pub const ELIBMAX: int32_t = 82;
+pub const ELIBEXEC: int32_t = 83;
+pub const EILSEQ: int32_t = 84;
+pub const ERESTART: int32_t = 85;
+pub const ESTRPIPE: int32_t = 86;
+pub const EUSERS: int32_t = 87;
+pub const ENOTSOCK: int32_t = 88;
+pub const EDESTADDRREQ: int32_t = 89;
+pub const EMSGSIZE: int32_t = 90;
+pub const EPROTOTYPE: int32_t = 91;
+pub const ENOPROTOOPT: int32_t = 92;
+pub const EPROTONOSUPPORT: int32_t = 93;
+pub const ESOCKTNOSUPPORT: int32_t = 94;
+pub const EOPNOTSUPP: int32_t = 95;
+pub const EPFNOSUPPORT: int32_t = 96;
+pub const EAFNOSUPPORT: int32_t = 97;
+pub const EADDRINUSE: int32_t = 98;
+pub const EADDRNOTAVAIL: int32_t = 99;
+pub const ENETDOWN: int32_t = 100;
+pub const ENETUNREACH: int32_t = 101;
+pub const ENETRESET: int32_t = 102;
+pub const ECONNABORTED: int32_t = 103;
+pub const ECONNRESET: int32_t = 104;
+pub const ENOBUFS: int32_t = 105;
+pub const EISCONN: int32_t = 106;
+pub const ENOTCONN: int32_t = 107;
+pub const ESHUTDOWN: int32_t = 108;
+pub const ETOOMANYREFS: int32_t = 109;
+pub const ETIMEDOUT: int32_t = 110;
+pub const ECONNREFUSED: int32_t = 111;
+pub const EHOSTDOWN: int32_t = 112;
+pub const EHOSTUNREACH: int32_t = 113;
+pub const EALREADY: int32_t = 114;
+pub const EINPROGRESS: int32_t = 115;
+pub const ESTALE: int32_t = 116;
+pub const EUCLEAN: int32_t = 117;
+pub const ENOTNAM: int32_t = 118;
+pub const ENAVAIL: int32_t = 119;
+pub const EISNAM: int32_t = 120;
+pub const EREMOTEIO: int32_t = 121;
+pub const EDQUOT: int32_t = 122;
+pub const ENOMEDIUM: int32_t = 123;
+pub const EMEDIUMTYPE: int32_t = 124;
+pub const ECANCELED: int32_t = 125;
+pub const ENOKEY: int32_t = 126;
+pub const EKEYEXPIRED: int32_t = 127;
+pub const EKEYREVOKED: int32_t = 128;
+pub const EKEYREJECTED: int32_t = 129;
+pub const EOWNERDEAD: int32_t = 130;
+pub const ENOTRECOVERABLE: int32_t = 131;
+pub const ERFKILL: int32_t = 132;
+pub const EHWPOISON: int32_t = 133;
+pub const ENOTSUP: int32_t = EOPNOTSUPP;
+pub const ESGX: int32_t = 0x0000_FFFF;
 
 pub const SA_NODEFER: c_int = 0x40000000;
 pub const SA_RESETHAND: c_int = 0x80000000;
@@ -1440,14 +1422,14 @@ pub unsafe fn FD_CLR(fd: c_int, set: *mut fd_set) -> () {
     let fd = fd as usize;
     let size = mem::size_of_val(&(*set).fds_bits[0]) * 8;
     (*set).fds_bits[fd / size] &= !(1 << (fd % size));
-    return
+    return;
 }
 
 #[inline]
 pub unsafe fn FD_ISSET(fd: c_int, set: *mut fd_set) -> bool {
     let fd = fd as usize;
     let size = mem::size_of_val(&(*set).fds_bits[0]) * 8;
-    return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0
+    return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0;
 }
 
 #[inline]
@@ -1455,7 +1437,7 @@ pub unsafe fn FD_SET(fd: c_int, set: *mut fd_set) -> () {
     let fd = fd as usize;
     let size = mem::size_of_val(&(*set).fds_bits[0]) * 8;
     (*set).fds_bits[fd / size] |= 1 << (fd % size);
-    return
+    return;
 }
 
 #[inline]
@@ -1474,8 +1456,7 @@ pub unsafe fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () {
 
 #[inline]
 pub unsafe fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () {
-    let size_in_bits
-        = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc
+    let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc
     let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits);
     cpuset.bits[idx] |= 1 << offset;
     ()
@@ -1483,8 +1464,7 @@ pub unsafe fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () {
 
 #[inline]
 pub unsafe fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () {
-    let size_in_bits
-        = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc
+    let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc
     let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits);
     cpuset.bits[idx] &= !(1 << offset);
     ()
@@ -1509,32 +1489,28 @@ unsafe fn __sigmask(sig: c_int) -> u64 {
 
 #[inline]
 unsafe fn __sigword(sig: c_int) -> u64 {
-   ((sig - 1) / ((8 *  mem::size_of::<u64>()) as i32)) as u64
+    ((sig - 1) / ((8 * mem::size_of::<u64>()) as i32)) as u64
 }
 
 #[inline]
 unsafe fn __sigaddset(set: *mut sigset_t, sig: c_int) {
-    let mask: u64 = __sigmask (sig);
-    let word: u64 = __sigword (sig);
+    let mask: u64 = __sigmask(sig);
+    let word: u64 = __sigword(sig);
     (*set).__val[word as usize] |= mask;
 }
 
 #[inline]
 unsafe fn __sigdelset(set: *mut sigset_t, sig: c_int) {
-    let mask: u64 = __sigmask (sig);
-    let word: u64 = __sigword (sig);
+    let mask: u64 = __sigmask(sig);
+    let word: u64 = __sigword(sig);
     (*set).__val[word as usize] &= !mask;
 }
 
 #[inline]
 unsafe fn __sigismember(set: *const sigset_t, sig: c_int) -> c_int {
-    let mask: u64 = __sigmask (sig);
-    let word: u64 = __sigword (sig);
-    let val = if mask != 0 {
-        1
-    } else {
-        0
-    };
+    let mask: u64 = __sigmask(sig);
+    let word: u64 = __sigword(sig);
+    let val = if mask != 0 { 1 } else { 0 };
     ((*set).__val[word as usize] & val) as c_int
 }
 
@@ -1543,7 +1519,7 @@ pub unsafe fn sigemptyset(set: *mut sigset_t) -> c_int {
         set_errno(EINVAL);
         return -1;
     }
-    ptr::write_bytes(set as * mut sigset_t, 0,  1);
+    ptr::write_bytes(set as *mut sigset_t, 0, 1);
     0
 }
 
@@ -1582,4 +1558,169 @@ pub unsafe fn sigismember(set: *const sigset_t, signum: c_int) -> c_int {
     __sigismember(set, signum)
 }
 
+pub const DIRENT64_NAME_OFFSET: usize = 20;
+
+#[macro_export]
+macro_rules! align8 {
+    ($v:expr) => {
+        (($v + 7) & (!7))
+    };
+}
+
+pub enum PolledOk {
+    TimeLimitExpired,
+    ReadyDescsCount(usize),
+}
+
+#[derive(Debug)]
+pub enum OCallError {
+    SgxError(sgx_types::sgx_status_t),
+    OsError(i32),
+    GaiError(i32),
+    CustomError(&'static str),
+}
+
+impl OCallError {
+    fn from_sgx_error(errno: sgx_types::sgx_status_t) -> Self {
+        OCallError::SgxError(errno)
+    }
+
+    fn from_os_error(errno: i32) -> Self {
+        set_errno(errno);
+        OCallError::OsError(errno)
+    }
+
+    fn from_gai_error(err: i32) -> Self {
+        OCallError::GaiError(err)
+    }
+
+    fn from_custom_error(err: &'static str) -> Self {
+        OCallError::CustomError(err)
+    }
+
+    pub fn equal_to_os_error(&self, other: i32) -> bool {
+        match self {
+            OCallError::OsError(e) if *e == other => true,
+            _ => false,
+        }
+    }
+}
+
+pub type OCallResult<T> = Result<T, OCallError>;
+
+#[macro_export]
+macro_rules! as_u8_slice {
+    ($p:expr, $len:expr) => {
+        core::slice::from_raw_parts($p as *const _ as *const u8, $len)
+    };
+}
+
+pub enum SockAddr {
+    IN4(sockaddr_in),
+    IN6(sockaddr_in6),
+    UN((sockaddr_un, socklen_t)),
+}
+
+impl SockAddr {
+    pub fn as_bytes(&self) -> &[u8] {
+        unsafe {
+            match self {
+                SockAddr::IN4(addr) => as_u8_slice!(addr, core::mem::size_of::<sockaddr_in>()),
+                SockAddr::IN6(addr) => as_u8_slice!(addr, core::mem::size_of::<sockaddr_in6>()),
+                SockAddr::UN((addr, len)) => as_u8_slice!(addr, *len as usize),
+            }
+        }
+    }
+
+    pub unsafe fn try_from_storage(
+        storage: sockaddr_storage,
+        len_out: socklen_t,
+    ) -> OCallResult<Self> {
+        let addr = match storage.ss_family as i32 {
+            AF_INET => {
+                ensure!(
+                    len_out as usize == mem::size_of::<sockaddr_in>(),
+                    ecust!("Malformed addr_len")
+                );
+                let sockaddr: *const sockaddr_in = mem::transmute(&storage);
+                SockAddr::IN4(*sockaddr)
+            }
+            AF_INET6 => {
+                ensure!(
+                    len_out as usize == mem::size_of::<sockaddr_in6>(),
+                    ecust!("Malformed addr_len")
+                );
+                let sockaddr: *const sockaddr_in6 = mem::transmute(&storage);
+                SockAddr::IN6(*sockaddr)
+            }
+            AF_UNIX => {
+                ensure!(
+                    len_out as usize <= mem::size_of::<sockaddr_un>(),
+                    ecust!("Malformed addr_len")
+                );
+                let sockaddr: *const sockaddr_un = mem::transmute(&storage);
+                SockAddr::UN((*sockaddr, len_out))
+            }
+            _ => bail!(ecust!("Unsupported family info")),
+        };
+
+        Ok(addr)
+    }
+}
+
+pub struct AddrInfoHints {
+    pub socktype: i32,
+    pub protocol: i32,
+    pub family: i32,
+    pub flags: i32,
+}
+
+impl AddrInfoHints {
+    fn to_addrinfo(&self) -> addrinfo {
+        let mut addrinfo: addrinfo = unsafe { mem::zeroed() };
+        addrinfo.ai_socktype = self.socktype;
+        addrinfo.ai_protocol = self.protocol;
+        addrinfo.ai_family = self.family;
+        addrinfo.ai_flags = self.flags;
+        addrinfo
+    }
+}
+
+impl Default for AddrInfoHints {
+    fn default() -> Self {
+        AddrInfoHints {
+            socktype: 0,
+            protocol: 0,
+            family: AF_UNSPEC,
+            flags: 0,
+        }
+    }
+}
+
+pub fn gai_error_str(errcode: c_int) -> &'static str {
+    match errcode {
+        EAI_BADFLAGS => "Bad value for ai_flags",
+        EAI_NONAME => "Name or service not known",
+        EAI_AGAIN => "Temporary failure in name resolution",
+        EAI_FAIL => "Non-recoverable failure in name resolution",
+        EAI_FAMILY => "ai_family not supported",
+        EAI_SOCKTYPE => "ai_socktype not supported",
+        EAI_SERVICE => "Servname not supported for ai_socktype",
+        EAI_MEMORY => "Memory allocation failure",
+        EAI_SYSTEM => "System error",
+        EAI_OVERFLOW => "Argument buffer overflow",
+
+        EAI_NODATA => "No address associated with hostname",
+        EAI_ADDRFAMILY => "Address family for hostname not supported",
+        EAI_INPROGRESS => "Processing request in progress",
+        EAI_CANCELED => "Request canceled",
+        EAI_NOTCANCELED => "Request not canceled",
+        EAI_ALLDONE => "All requests done",
+        EAI_INTR => "Interrupted by a signal",
+        EAI_IDN_ENCODE => "Parameter string not correctly encoded",
+
+        _ => "Unknown gai_error_code",
+    }
+}
+
 pub mod ocall;
diff --git a/sgx_libc/src/linux/x86_64/ocall.rs b/sgx_libc/src/linux/x86_64/ocall.rs
index 650845a..4d36659 100644
--- a/sgx_libc/src/linux/x86_64/ocall.rs
+++ b/sgx_libc/src/linux/x86_64/ocall.rs
@@ -15,2910 +15,2230 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use sgx_types::*;
 use super::*;
-use alloc::slice;
+use crate::c_str::CStr;
+use crate::memchr;
 use alloc::vec::Vec;
-use alloc::boxed::Box;
-use core::ptr;
+use core::cmp;
 use core::mem;
+use core::ptr;
+use sgx_types::*;
 
-const MAX_OCALL_ALLOC_SIZE: size_t = 0x4000; //16K
 extern "C" {
     // memory
-    pub fn u_malloc_ocall(result: *mut *mut c_void, error: *mut c_int, size: size_t) -> sgx_status_t;
+    pub fn u_malloc_ocall(
+        result: *mut *mut c_void,
+        error: *mut c_int,
+        size: size_t,
+    ) -> sgx_status_t;
     pub fn u_free_ocall(p: *mut c_void) -> sgx_status_t;
-    pub fn u_mmap_ocall(result: *mut *mut c_void,
-                        error: *mut c_int,
-                        start: *mut c_void,
-                        length: size_t,
-                        prot: c_int,
-                        flags: c_int,
-                        fd: c_int,
-                        offset: off_t) -> sgx_status_t;
-    pub fn u_munmap_ocall(result: *mut c_int,
-                          error: *mut c_int,
-                          start: *mut c_void,
-                          length: size_t) -> sgx_status_t;
-    pub fn u_msync_ocall(result: *mut c_int,
-                         error: *mut c_int,
-                         addr: *mut c_void,
-                         length: size_t,
-                         flags: c_int) -> sgx_status_t;
-
-    pub fn u_mprotect_ocall(result: *mut c_int,
-                            error: *mut c_int,
-                            addr: *mut c_void,
-                            length: size_t,
-                            prot: c_int) -> sgx_status_t;
+    pub fn u_mmap_ocall(
+        result: *mut *mut c_void,
+        error: *mut c_int,
+        start: *mut c_void,
+        length: size_t,
+        prot: c_int,
+        flags: c_int,
+        fd: c_int,
+        offset: off_t,
+    ) -> sgx_status_t;
+    pub fn u_munmap_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        start: *mut c_void,
+        length: size_t,
+    ) -> sgx_status_t;
+    pub fn u_msync_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        addr: *mut c_void,
+        length: size_t,
+        flags: c_int,
+    ) -> sgx_status_t;
+
+    pub fn u_mprotect_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        addr: *mut c_void,
+        length: size_t,
+        prot: c_int,
+    ) -> sgx_status_t;
     // env
     pub fn u_getuid_ocall(result: *mut uid_t) -> sgx_status_t;
-    pub fn u_environ_ocall(result: *mut *const *const c_char) -> sgx_status_t;
-    pub fn u_getenv_ocall(result: *mut *const c_char,
-                          name: *const c_char) -> sgx_status_t;
-    pub fn u_setenv_ocall(result: *mut c_int,
-                          error: *mut c_int,
-                          name: *const c_char,
-                          value: *const c_char,
-                          overwrite: c_int) -> sgx_status_t;
-    pub fn u_unsetenv_ocall(result: *mut c_int,
-                            error: *mut c_int,
-                            name: *const c_char) -> sgx_status_t;
-    pub fn u_getcwd_ocall(result: *mut *mut c_char,
-                          error: *mut c_int,
-                          buf: *mut c_char,
-                          size: size_t) -> sgx_status_t;
-    pub fn u_chdir_ocall(result: *mut c_int,  error: *mut c_int, dir: *const c_char) -> sgx_status_t;
-    pub fn u_getpwuid_r_ocall(result: *mut c_int,
-                              uid: uid_t,
-                              pwd: *mut passwd,
-                              buf: *mut c_char,
-                              buflen: size_t,
-                              passwd_result: *mut *mut passwd) -> sgx_status_t;
+    pub fn u_getenv_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        name: *const c_char,
+        buf: *mut c_char,
+        size: size_t,
+        isset: *mut c_int,
+    ) -> sgx_status_t;
+    pub fn u_getcwd_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        buf: *mut c_char,
+        size: size_t,
+    ) -> sgx_status_t;
+    pub fn u_chdir_ocall(result: *mut c_int, error: *mut c_int, dir: *const c_char)
+        -> sgx_status_t;
     // file
-    pub fn u_open_ocall(result: *mut c_int,
-                        error: *mut c_int,
-                        path: *const c_char,
-                        flags: c_int) -> sgx_status_t;
-    pub fn u_open64_ocall(result: *mut c_int,
-                          error: *mut c_int,
-                          path: *const c_char,
-                          oflag: c_int,
-                          mode: c_int) -> sgx_status_t;
-    pub fn u_fstat_ocall(result: *mut c_int,
-                         error: *mut c_int,
-                         fd: c_int,
-                         buf: *mut stat) -> sgx_status_t;
-    pub fn u_fstat64_ocall(result: *mut c_int,
-                           error: *mut c_int,
-                           fd: c_int,
-                           buf: *mut stat64) -> sgx_status_t;
-    pub fn u_stat_ocall(result: *mut c_int,
-                        error: *mut c_int,
-                        path: *const c_char,
-                        buf: *mut stat) -> sgx_status_t;
-    pub fn u_stat64_ocall(result: *mut c_int,
-                          error: *mut c_int,
-                          path: *const c_char,
-                          buf: *mut stat64) -> sgx_status_t;
-    pub fn u_lstat_ocall(result: *mut c_int,
-                         error: *mut c_int,
-                         path: *const c_char,
-                         buf: *mut stat) -> sgx_status_t;
-    pub fn u_lstat64_ocall(result: *mut c_int,
-                           error: *mut c_int,
-                           path: *const c_char,
-                           buf: *mut stat64) -> sgx_status_t;
-    pub fn u_lseek_ocall(result: *mut off_t,
-                         error: *mut c_int,
-                         fd: c_int,
-                         offset: off_t,
-                         whence: c_int) -> sgx_status_t;
-    pub fn u_lseek64_ocall(result: *mut off64_t,
-                           error: *mut c_int,
-                           fd: c_int,
-                           offset: off64_t,
-                           whence: c_int) -> sgx_status_t;
-    pub fn u_ftruncate_ocall(result: *mut c_int,
-                             error: *mut c_int,
-                             fd: c_int,
-                             length: off_t) -> sgx_status_t;
-    pub fn u_ftruncate64_ocall(result: *mut c_int,
-                               error: *mut c_int,
-                               fd: c_int,
-                               length: off64_t) -> sgx_status_t;
-    pub fn u_truncate_ocall(result: *mut c_int,
-                            error: *mut c_int,
-                            path: *const c_char,
-                            length: off_t) -> sgx_status_t;
-    pub fn u_truncate64_ocall(result: *mut c_int,
-                              error: *mut c_int,
-                              path: *const c_char,
-                              length: off64_t) -> sgx_status_t;
-    pub fn u_fsync_ocall(result: *mut c_int,
-                         error: *mut c_int,
-                         fd: c_int) -> sgx_status_t;
-    pub fn u_fdatasync_ocall(result: *mut c_int,
-                             error: *mut c_int,
-                             fd: c_int) -> sgx_status_t;
-    pub fn u_fchmod_ocall(result: *mut c_int,
-                          error: *mut c_int,
-                          fd: c_int,
-                          mode: mode_t) -> sgx_status_t;
-    pub fn u_unlink_ocall(result: *mut c_int,
-                          error: *mut c_int,
-                          pathname: *const c_char) -> sgx_status_t;
-    pub fn u_link_ocall(result: *mut c_int,
-                        error: *mut c_int,
-                        oldpath: *const c_char,
-                        newpath: *const c_char) -> sgx_status_t;
-    pub fn u_rename_ocall(result: *mut c_int,
-                          error: *mut c_int,
-                          oldpath: *const c_char,
-                          newpath: *const c_char) -> sgx_status_t;
-    pub fn u_chmod_ocall(result: *mut c_int,
-                         error: *mut c_int,
-                         path: *const c_char,
-                         mode: mode_t) -> sgx_status_t;
-    pub fn u_readlink_ocall(result: *mut ssize_t,
-                            error: *mut c_int,
-                            path: *const c_char,
-                            buf: *mut c_char,
-                            bufsz: size_t) -> sgx_status_t;
-    pub fn u_symlink_ocall(result: *mut c_int,
-                           error: *mut c_int,
-                           path1: *const c_char,
-                           path2: *const c_char) -> sgx_status_t;
-    pub fn u_realpath_ocall(result: *mut *mut c_char,
-                            error: *mut c_int,
-                            pathname: *const c_char) -> sgx_status_t;
-    pub fn u_mkdir_ocall(result: *mut c_int,
-                         error: *mut c_int,
-                         pathname: *const c_char,
-                         mode: mode_t) -> sgx_status_t;
-    pub fn u_rmdir_ocall(result: *mut c_int,
-                         error: *mut c_int,
-                         pathname: *const c_char) -> sgx_status_t;
-    pub fn u_opendir_ocall(result: *mut *mut DIR,
-                           error: *mut c_int,
-                           pathname: *const c_char) -> sgx_status_t;
-    pub fn u_readdir64_r_ocall(result: *mut c_int,
-                               dirp: *mut DIR,
-                               entry: *mut dirent64,
-                               dirresult: *mut *mut  dirent64) -> sgx_status_t;
-    pub fn u_closedir_ocall(result: *mut c_int,
-                            error: *mut c_int,
-                            dirp: *mut DIR) -> sgx_status_t;
-    pub fn u_dirfd_ocall(result: *mut c_int,
-                         error: *mut c_int,
-                         dirp: *mut DIR) -> sgx_status_t;
-    pub fn u_fstatat64_ocall(result: *mut c_int,
-                             error: *mut c_int,
-                             dirfd: c_int,
-                             pathname: *const c_char,
-                             buf: *mut stat64,
-                             flags: c_int) -> sgx_status_t;
+    pub fn u_open_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        path: *const c_char,
+        flags: c_int,
+    ) -> sgx_status_t;
+    pub fn u_open64_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        path: *const c_char,
+        oflag: c_int,
+        mode: c_int,
+    ) -> sgx_status_t;
+    pub fn u_fstat_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        fd: c_int,
+        buf: *mut stat,
+    ) -> sgx_status_t;
+    pub fn u_fstat64_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        fd: c_int,
+        buf: *mut stat64,
+    ) -> sgx_status_t;
+    pub fn u_stat_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        path: *const c_char,
+        buf: *mut stat,
+    ) -> sgx_status_t;
+    pub fn u_stat64_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        path: *const c_char,
+        buf: *mut stat64,
+    ) -> sgx_status_t;
+    pub fn u_lstat_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        path: *const c_char,
+        buf: *mut stat,
+    ) -> sgx_status_t;
+    pub fn u_lstat64_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        path: *const c_char,
+        buf: *mut stat64,
+    ) -> sgx_status_t;
+    pub fn u_lseek_ocall(
+        result: *mut off_t,
+        error: *mut c_int,
+        fd: c_int,
+        offset: off_t,
+        whence: c_int,
+    ) -> sgx_status_t;
+    pub fn u_lseek64_ocall(
+        result: *mut off64_t,
+        error: *mut c_int,
+        fd: c_int,
+        offset: off64_t,
+        whence: c_int,
+    ) -> sgx_status_t;
+    pub fn u_ftruncate_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        fd: c_int,
+        length: off_t,
+    ) -> sgx_status_t;
+    pub fn u_ftruncate64_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        fd: c_int,
+        length: off64_t,
+    ) -> sgx_status_t;
+    pub fn u_truncate_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        path: *const c_char,
+        length: off_t,
+    ) -> sgx_status_t;
+    pub fn u_truncate64_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        path: *const c_char,
+        length: off64_t,
+    ) -> sgx_status_t;
+    pub fn u_fsync_ocall(result: *mut c_int, error: *mut c_int, fd: c_int) -> sgx_status_t;
+    pub fn u_fdatasync_ocall(result: *mut c_int, error: *mut c_int, fd: c_int) -> sgx_status_t;
+    pub fn u_fchmod_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        fd: c_int,
+        mode: mode_t,
+    ) -> sgx_status_t;
+    pub fn u_unlink_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        pathname: *const c_char,
+    ) -> sgx_status_t;
+    pub fn u_link_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        oldpath: *const c_char,
+        newpath: *const c_char,
+    ) -> sgx_status_t;
+    pub fn u_rename_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        oldpath: *const c_char,
+        newpath: *const c_char,
+    ) -> sgx_status_t;
+    pub fn u_chmod_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        path: *const c_char,
+        mode: mode_t,
+    ) -> sgx_status_t;
+    pub fn u_readlink_ocall(
+        result: *mut ssize_t,
+        error: *mut c_int,
+        path: *const c_char,
+        buf: *mut c_char,
+        bufsz: size_t,
+    ) -> sgx_status_t;
+    pub fn u_symlink_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        path1: *const c_char,
+        path2: *const c_char,
+    ) -> sgx_status_t;
+    pub fn u_realpath_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        pathname: *const c_char,
+        resolved_buf: *mut c_char,
+        bufsz: size_t,
+    ) -> sgx_status_t;
+    pub fn u_mkdir_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        pathname: *const c_char,
+        mode: mode_t,
+    ) -> sgx_status_t;
+    pub fn u_rmdir_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        pathname: *const c_char,
+    ) -> sgx_status_t;
+    pub fn u_opendir_ocall(
+        result: *mut *mut DIR,
+        error: *mut c_int,
+        pathname: *const c_char,
+    ) -> sgx_status_t;
+    pub fn u_readdir64_r_ocall(
+        result: *mut c_int,
+        dirp: *mut DIR,
+        entry: *mut dirent64,
+        eods: *mut c_int,
+    ) -> sgx_status_t;
+    pub fn u_closedir_ocall(result: *mut c_int, error: *mut c_int, dirp: *mut DIR) -> sgx_status_t;
+    pub fn u_dirfd_ocall(result: *mut c_int, error: *mut c_int, dirp: *mut DIR) -> sgx_status_t;
+    pub fn u_fstatat64_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        dirfd: c_int,
+        pathname: *const c_char,
+        buf: *mut stat64,
+        flags: c_int,
+    ) -> sgx_status_t;
     // fd
-    pub fn u_read_ocall(result: *mut ssize_t,
-                        errno: *mut c_int,
-                        fd: c_int,
-                        buf: *mut c_void,
-                        count: size_t) -> sgx_status_t;
-    pub fn u_pread64_ocall(result: *mut ssize_t,
-                           errno: *mut c_int,
-                           fd: c_int,
-                           buf: *mut c_void,
-                           count: size_t,
-                           offset: off64_t) -> sgx_status_t;
-    pub fn u_readv_ocall(result: *mut ssize_t,
-                         errno: *mut c_int,
-                         fd: c_int,
-                         iov: *const iovec,
-                         iovcnt: c_int) -> sgx_status_t;
-    pub fn u_preadv64_ocall(result: *mut ssize_t,
-                            errno: *mut c_int,
-                            fd: c_int,
-                            iov: *const iovec,
-                            iovcnt: c_int,
-                            offset: off64_t) -> sgx_status_t;
-    pub fn u_write_ocall(result: *mut ssize_t,
-                         errno: *mut c_int,
-                         fd: c_int,
-                         buf: *const c_void,
-                         count: size_t) -> sgx_status_t;
-    pub fn u_pwrite64_ocall(result: *mut ssize_t,
-                            errno: *mut c_int,
-                            fd: c_int,
-                            buf: *const c_void,
-                            count: size_t,
-                            offset: off64_t) -> sgx_status_t;
-    pub fn u_writev_ocall(result: *mut ssize_t,
-                          errno: *mut c_int,
-                          fd: c_int,
-                          iov: *const iovec,
-                          iovcnt: c_int) -> sgx_status_t;
-    pub fn u_pwritev64_ocall(result: *mut ssize_t,
-                             errno: *mut c_int,
-                             fd: c_int,
-                             iov: *const iovec,
-                             iovcnt: c_int,
-                             offset: off64_t) -> sgx_status_t;
-    pub fn u_fcntl_arg0_ocall(result: *mut c_int,
-                              errno: *mut c_int,
-                              fd: c_int,
-                              cmd: c_int) -> sgx_status_t;
-    pub fn u_fcntl_arg1_ocall(result: *mut c_int,
-                              errno: *mut c_int,
-                              fd: c_int,
-                              cmd: c_int,
-                              arg: c_int) -> sgx_status_t;
-    pub fn u_ioctl_arg0_ocall(result: *mut c_int,
-                              errno: *mut c_int,
-                              fd: c_int,
-                              request: c_int) -> sgx_status_t;
-    pub fn u_ioctl_arg1_ocall(result: *mut c_int,
-                              errno: *mut c_int,
-                              fd: c_int,
-                              request: c_int,
-                              arg: *mut c_int) -> sgx_status_t;
-    pub fn u_close_ocall(result: *mut c_int,
-                         errno: *mut c_int,
-                         fd: c_int) -> sgx_status_t;
+    pub fn u_read_ocall(
+        result: *mut ssize_t,
+        errno: *mut c_int,
+        fd: c_int,
+        buf: *mut c_void,
+        count: size_t,
+    ) -> sgx_status_t;
+    pub fn u_pread64_ocall(
+        result: *mut ssize_t,
+        errno: *mut c_int,
+        fd: c_int,
+        buf: *mut c_void,
+        count: size_t,
+        offset: off64_t,
+    ) -> sgx_status_t;
+    pub fn u_write_ocall(
+        result: *mut ssize_t,
+        errno: *mut c_int,
+        fd: c_int,
+        buf: *const c_void,
+        count: size_t,
+    ) -> sgx_status_t;
+    pub fn u_pwrite64_ocall(
+        result: *mut ssize_t,
+        errno: *mut c_int,
+        fd: c_int,
+        buf: *const c_void,
+        count: size_t,
+        offset: off64_t,
+    ) -> sgx_status_t;
+    pub fn u_fcntl_arg0_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        fd: c_int,
+        cmd: c_int,
+    ) -> sgx_status_t;
+    pub fn u_fcntl_arg1_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        fd: c_int,
+        cmd: c_int,
+        arg: c_int,
+    ) -> sgx_status_t;
+    pub fn u_ioctl_arg0_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        fd: c_int,
+        request: c_int,
+    ) -> sgx_status_t;
+    pub fn u_ioctl_arg1_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        fd: c_int,
+        request: c_int,
+        arg: *mut c_int,
+    ) -> sgx_status_t;
+    pub fn u_close_ocall(result: *mut c_int, errno: *mut c_int, fd: c_int) -> sgx_status_t;
     // time
-    pub fn u_clock_gettime_ocall(result: *mut c_int,
-                                 errno: *mut c_int,
-                                 clk_id: clockid_t,
-                                 tp: *mut timespec) -> sgx_status_t;
+    pub fn u_clock_gettime_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        clk_id: clockid_t,
+        tp: *mut timespec,
+    ) -> sgx_status_t;
     // socket
-    pub fn u_socket_ocall(result: *mut c_int,
-                          errno: *mut c_int,
-                          domain: c_int,
-                          ty: c_int,
-                          protocol: c_int) -> sgx_status_t;
-    pub fn u_socketpair_ocall(result: *mut c_int,
-                              errno: *mut c_int,
-                              domain: c_int,
-                              ty: c_int,
-                              protocol: c_int,
-                              sv: *mut c_int) -> sgx_status_t;
-    pub fn u_bind_ocall(result: *mut c_int,
-                        errno: *mut c_int,
-                        sockfd: c_int,
-                        address: *const sockaddr,
-                        addrlen: socklen_t) -> sgx_status_t;
-    pub fn u_listen_ocall(result: *mut c_int,
-                          error: *mut c_int,
-                          sockfd: c_int,
-                          backlog: c_int) -> sgx_status_t;
-    pub fn u_accept_ocall(result: *mut c_int,
-                          errno: *mut c_int,
-                          sockfd: c_int,
-                          addr: *mut sockaddr,
-                          addrlen_in: socklen_t,
-                          addrlen_out: *mut socklen_t) -> sgx_status_t;
-    pub fn u_accept4_ocall(result: *mut c_int,
-                           errno: *mut c_int,
-                           sockfd: c_int,
-                           addr: *mut sockaddr,
-                           addrlen_in: socklen_t,
-                           addrlen_out: *mut socklen_t,
-                           flags: c_int) -> sgx_status_t;
-    pub fn u_connect_ocall(result: *mut c_int,
-                           errno: *mut c_int,
-                           sockfd: c_int,
-                           address: *const sockaddr,
-                           addrlen: socklen_t) -> sgx_status_t;
-    pub fn u_send_ocall(result: *mut ssize_t,
-                        errno: *mut c_int,
-                        sockfd: c_int,
-                        buf: *const c_void,
-                        len: size_t,
-                        flags: c_int) -> sgx_status_t;
-    pub fn u_sendto_ocall(result: *mut ssize_t,
-                          errno: *mut c_int,
-                          sockfd: c_int,
-                          buf: *const c_void,
-                          len: size_t,
-                          flags: c_int,
-                          addr: *const sockaddr,
-                          addrlen: socklen_t) -> sgx_status_t;
-    pub fn u_sendmsg_ocall(result: *mut ssize_t,
-                           error: *mut c_int,
-                           sockfd: c_int,
-                           msg: *const msghdr,
-                           flags: c_int) -> sgx_status_t;
-    pub fn u_recv_ocall(result: *mut ssize_t,
-                        errno: *mut c_int,
-                        sockfd: c_int,
-                        buf: *mut c_void,
-                        len: size_t,
-                        flags: c_int) -> sgx_status_t;
-    pub fn u_recvfrom_ocall(result: *mut ssize_t,
-                            errno: *mut c_int,
-                            sockfd: c_int,
-                            buf: *mut c_void,
-                            len: size_t,
-                            flags: c_int,
-                            addr: *mut sockaddr,
-                            addrlen_in: socklen_t,
-                            addrlen_out: *mut socklen_t) -> sgx_status_t;
-    pub fn u_recvmsg_ocall(result: *mut ssize_t,
-                           error: *mut c_int,
-                           sockfd: c_int,
-                           msg: *mut msghdr,
-                           flags: c_int) -> sgx_status_t;
-    pub fn u_setsockopt_ocall(result: *mut c_int,
-                              errno: *mut c_int,
-                              sockfd: c_int,
-                              level: c_int,
-                              optname: c_int,
-                              optval: *const c_void,
-                              optlen: socklen_t) -> sgx_status_t;
-    pub fn u_getsockopt_ocall(result: *mut c_int,
-                              errno: *mut c_int,
-                              sockfd: c_int,
-                              level: c_int,
-                              optname: c_int,
-                              optval: *mut c_void,
-                              optlen_in: socklen_t,
-                              optlen_out: *mut socklen_t) -> sgx_status_t;
-    pub fn u_getpeername_ocall(result: *mut c_int,
-                               errno: *mut c_int,
-                               sockfd: c_int,
-                               address: *mut sockaddr,
-                               addrlen_in: socklen_t,
-                               addrlen_out: *mut socklen_t) -> sgx_status_t;
-    pub fn u_getsockname_ocall(result: *mut c_int,
-                               errno: *mut c_int,
-                               sockfd: c_int,
-                               address: *mut sockaddr,
-                               addrlen_in: socklen_t,
-                               addrlen_out: *mut socklen_t) -> sgx_status_t;
-    pub fn u_shutdown_ocall(result: *mut c_int,
-                            errno: *mut c_int,
-                            sockfd: c_int,
-                            how: c_int) -> sgx_status_t;
+    pub fn u_socket_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        domain: c_int,
+        ty: c_int,
+        protocol: c_int,
+    ) -> sgx_status_t;
+    pub fn u_socketpair_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        domain: c_int,
+        ty: c_int,
+        protocol: c_int,
+        sv: *mut c_int,
+    ) -> sgx_status_t;
+    pub fn u_bind_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        sockfd: c_int,
+        address: *const sockaddr,
+        addrlen: socklen_t,
+    ) -> sgx_status_t;
+    pub fn u_listen_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        sockfd: c_int,
+        backlog: c_int,
+    ) -> sgx_status_t;
+    pub fn u_accept4_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        sockfd: c_int,
+        addr: *mut sockaddr,
+        addrlen_in: socklen_t,
+        addrlen_out: *mut socklen_t,
+        flags: c_int,
+    ) -> sgx_status_t;
+    pub fn u_connect_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        sockfd: c_int,
+        address: *const sockaddr,
+        addrlen: socklen_t,
+    ) -> sgx_status_t;
+    pub fn u_send_ocall(
+        result: *mut ssize_t,
+        errno: *mut c_int,
+        sockfd: c_int,
+        buf: *const c_void,
+        len: size_t,
+        flags: c_int,
+    ) -> sgx_status_t;
+    pub fn u_sendto_ocall(
+        result: *mut ssize_t,
+        errno: *mut c_int,
+        sockfd: c_int,
+        buf: *const c_void,
+        len: size_t,
+        flags: c_int,
+        addr: *const sockaddr,
+        addrlen: socklen_t,
+    ) -> sgx_status_t;
+    pub fn u_sendmsg_ocall(
+        result: *mut ssize_t,
+        error: *mut c_int,
+        sockfd: c_int,
+        msg: *const msghdr,
+        flags: c_int,
+    ) -> sgx_status_t;
+    pub fn u_recv_ocall(
+        result: *mut ssize_t,
+        errno: *mut c_int,
+        sockfd: c_int,
+        buf: *mut c_void,
+        len: size_t,
+        flags: c_int,
+    ) -> sgx_status_t;
+    pub fn u_recvfrom_ocall(
+        result: *mut ssize_t,
+        errno: *mut c_int,
+        sockfd: c_int,
+        buf: *mut c_void,
+        len: size_t,
+        flags: c_int,
+        addr: *mut sockaddr,
+        addrlen_in: socklen_t,
+        addrlen_out: *mut socklen_t,
+    ) -> sgx_status_t;
+    pub fn u_recvmsg_ocall(
+        result: *mut ssize_t,
+        error: *mut c_int,
+        sockfd: c_int,
+        msg: *mut msghdr,
+        flags: c_int,
+    ) -> sgx_status_t;
+    pub fn u_setsockopt_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        sockfd: c_int,
+        level: c_int,
+        optname: c_int,
+        optval: *const c_void,
+        optlen: socklen_t,
+    ) -> sgx_status_t;
+    pub fn u_getsockopt_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        sockfd: c_int,
+        level: c_int,
+        optname: c_int,
+        optval: *mut c_void,
+        optlen_in: socklen_t,
+        optlen_out: *mut socklen_t,
+    ) -> sgx_status_t;
+    pub fn u_getpeername_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        sockfd: c_int,
+        address: *mut sockaddr,
+        addrlen_in: socklen_t,
+        addrlen_out: *mut socklen_t,
+    ) -> sgx_status_t;
+    pub fn u_getsockname_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        sockfd: c_int,
+        address: *mut sockaddr,
+        addrlen_in: socklen_t,
+        addrlen_out: *mut socklen_t,
+    ) -> sgx_status_t;
+    pub fn u_shutdown_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        sockfd: c_int,
+        how: c_int,
+    ) -> sgx_status_t;
     // net
-    pub fn u_getaddrinfo_ocall(result: *mut c_int,
-                               errno: *mut c_int,
-                               node: *const c_char,
-                               service: *const c_char,
-                               hints: *const addrinfo,
-                               res: *mut *mut addrinfo) -> sgx_status_t;
-    pub fn u_freeaddrinfo_ocall(res: *mut addrinfo) -> sgx_status_t;
-    pub fn u_gai_strerror_ocall(result: *mut *const c_char, errcode: c_int) -> sgx_status_t;
+    pub fn u_getaddrinfo_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        node: *const c_char,
+        service: *const c_char,
+        hints: *const addrinfo,
+        entry_size: size_t,
+        buf: *mut u8,
+        bufsz: size_t,
+        out_entry_count: *mut size_t,
+    ) -> sgx_status_t;
     // async io
-    pub fn u_poll_ocall(result: *mut c_int,
-                        errno: *mut c_int,
-                        fds: *mut pollfd,
-                        nfds: nfds_t,
-                        timeout: c_int) -> sgx_status_t;
-    pub fn u_epoll_create1_ocall(result: *mut c_int,
-                                 error: *mut c_int,
-                                 flags: c_int) -> sgx_status_t;
-    pub fn u_epoll_ctl_ocall(result: *mut c_int,
-                             error: *mut c_int,
-                             epfd: c_int,
-                             op: c_int,
-                             fd: c_int,
-                             event: *mut epoll_event) -> sgx_status_t;
-    pub fn u_epoll_wait_ocall(result: *mut c_int,
-                              error: *mut c_int,
-                              epfd: c_int,
-                              events: *mut epoll_event,
-                              maxevents: c_int,
-                              timeout: c_int) -> sgx_status_t;
+    pub fn u_poll_ocall(
+        result: *mut c_int,
+        errno: *mut c_int,
+        fds: *mut pollfd,
+        nfds: nfds_t,
+        timeout: c_int,
+    ) -> sgx_status_t;
+    pub fn u_epoll_create1_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        flags: c_int,
+    ) -> sgx_status_t;
+    pub fn u_epoll_ctl_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        epfd: c_int,
+        op: c_int,
+        fd: c_int,
+        event: *mut epoll_event,
+    ) -> sgx_status_t;
+    pub fn u_epoll_wait_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        epfd: c_int,
+        events: *mut epoll_event,
+        maxevents: c_int,
+        timeout: c_int,
+    ) -> sgx_status_t;
     // sys
-    pub fn u_sysconf_ocall(result: *mut c_long,
-                           error: *mut c_int,
-                           name: c_int) -> sgx_status_t;
-    pub fn u_prctl_ocall(result: *mut c_int,
-                         error: *mut c_int,
-                         option: c_int,
-                         arg2: c_ulong,
-                         arg3: c_ulong,
-                         arg4: c_ulong,
-                         arg5: c_ulong) -> sgx_status_t;
-    pub fn u_sched_setaffinity_ocall(result: *mut c_int,
-                                     error: *mut c_int,
-                                     pid: pid_t,
-                                     cpusetsize: size_t,
-                                     mask: *const cpu_set_t) -> sgx_status_t;
-    pub fn u_sched_getaffinity_ocall(result: *mut c_int,
-                                     error: *mut c_int,
-                                     pid: pid_t,
-                                     cpusetsize: size_t,
-                                     mask: *mut cpu_set_t) -> sgx_status_t;
+    pub fn u_sysconf_ocall(result: *mut c_long, error: *mut c_int, name: c_int) -> sgx_status_t;
+    pub fn u_prctl_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        option: c_int,
+        arg2: c_ulong,
+        arg3: c_ulong,
+        arg4: c_ulong,
+        arg5: c_ulong,
+    ) -> sgx_status_t;
+    pub fn u_sched_setaffinity_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        pid: pid_t,
+        cpusetsize: size_t,
+        mask: *const cpu_set_t,
+    ) -> sgx_status_t;
+    pub fn u_sched_getaffinity_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        pid: pid_t,
+        cpusetsize: size_t,
+        mask: *mut cpu_set_t,
+    ) -> sgx_status_t;
     // pipe
-    pub fn u_pipe_ocall(result: *mut c_int,
-                        error: *mut c_int,
-                        fds: *mut c_int) -> sgx_status_t;
-    pub fn u_pipe2_ocall(result: *mut c_int,
-                         error: *mut c_int,
-                         fds: *mut c_int,
-                         flags: c_int) -> sgx_status_t;
+    pub fn u_pipe2_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        fds: *mut c_int,
+        flags: c_int,
+    ) -> sgx_status_t;
     //thread
-    pub  fn u_sched_yield_ocall(result: *mut c_int,
-                                error: *mut c_int) -> sgx_status_t;
-    pub  fn u_nanosleep_ocall(result: *mut c_int,
-                              error: *mut c_int,
-                              rqtp: *const timespec,
-                              rmtp: *mut timespec) -> sgx_status_t;
+    pub fn u_sched_yield_ocall(result: *mut c_int, error: *mut c_int) -> sgx_status_t;
+    pub fn u_nanosleep_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        rqtp: *const timespec,
+        rmtp: *mut timespec,
+    ) -> sgx_status_t;
     //signal
-    pub fn u_sigaction_ocall(result: *mut c_int,
-                             error: *mut c_int,
-                             signum: c_int,
-                             act: *const sigaction,
-                             oldact: *mut sigaction,
-                             enclave_id: uint64_t) -> sgx_status_t;
-    pub fn u_sigprocmask_ocall(result: *mut c_int,
-                                error: *mut c_int,
-                                signum: c_int,
-                                set: *const sigset_t,
-                                oldset: *mut sigset_t) -> sgx_status_t;
+    pub fn u_sigaction_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        signum: c_int,
+        act: *const sigaction,
+        oldact: *mut sigaction,
+        enclave_id: uint64_t,
+    ) -> sgx_status_t;
+    pub fn u_sigprocmask_ocall(
+        result: *mut c_int,
+        error: *mut c_int,
+        signum: c_int,
+        set: *const sigset_t,
+        oldset: *mut sigset_t,
+    ) -> sgx_status_t;
     pub fn u_raise_ocall(result: *mut c_int, signum: c_int) -> sgx_status_t;
     //process
     pub fn u_getpid_ocall(result: *mut pid_t) -> sgx_status_t;
 }
 
-pub unsafe fn malloc(size: size_t) -> *mut c_void {
-    let mut result: *mut c_void = ptr::null_mut();
-    let mut error: c_int = 0;
-    let status = u_malloc_ocall(&mut result as *mut *mut c_void,
-                                &mut error as *mut c_int,
-                                size);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result.is_null() {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = ptr::null_mut();
-    }
+pub unsafe fn shrink_to_fit_os_string<T: Into<Vec<u8>>>(buf: T) -> OCallResult<Vec<u8>> {
+    let mut buf = buf.into();
+    if let Some(i) = memchr::memchr(0, &buf) {
+        buf.set_len(i);
+        buf.shrink_to_fit();
+        return Ok(buf);
+    };
+    return Err(ecust!("Malformed Linux OsString Vec: not null terminated"));
+}
 
-    if sgx_is_outside_enclave(result, size) == 0 {
-        set_errno(ESGX);
-        result = ptr::null_mut();
-    }
+pub unsafe fn getuid() -> OCallResult<uid_t> {
+    let mut result: uid_t = 0;
 
-    result
-}
+    let status = u_getuid_ocall(&mut result as *mut uid_t);
 
-pub unsafe fn free(p: *mut c_void) {
-    let _ = u_free_ocall(p);
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    Ok(result)
 }
 
-pub unsafe fn mmap(start: *mut c_void,
-                   length: size_t,
-                   prot: c_int,
-                   flags: c_int,
-                   fd: c_int,
-                   offset: off_t) -> *mut c_void {
-    let mut result: *mut c_void = ptr::null_mut();
+const MAX_ENV_VALUE_SIZE: usize = 1024;
+pub unsafe fn getenv(name: &CStr) -> OCallResult<Option<Vec<u8>>> {
+    let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_mmap_ocall(&mut result as *mut *mut c_void,
-                              &mut error as *mut c_int,
-                              start,
-                              length,
-                              prot,
-                              flags,
-                              fd,
-                              offset);
+    let mut isset: c_int = 0;
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result as isize == -1 {
-            set_errno(error);
-        }
+    let bufsz = MAX_ENV_VALUE_SIZE;
+    let mut buf = vec![0; bufsz];
+
+    // a) isset is used to indicate the NULL return value of conventional libc::getenv function
+    // b) if isset, a '\0' terminated string is expected in the buf
+    let status = u_getenv_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        name.as_ptr(),
+        buf.as_mut_ptr() as *mut c_char,
+        bufsz,
+        &mut isset as *mut c_int,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+
+    if isset == 1 {
+        let v = shrink_to_fit_os_string(buf)?;
+        Ok(Some(v))
     } else {
-        set_errno(ESGX);
-        result = -1 as isize as *mut c_void;
+        Ok(None)
     }
+}
 
-    if sgx_is_outside_enclave(result, length) == 0 {
-        set_errno(ESGX);
-        result = -1 as isize as *mut c_void;
-    }
+pub unsafe fn getcwd() -> OCallResult<Vec<u8>> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let bufsz = PATH_MAX as usize;
+    let mut buf = vec![0; bufsz];
 
-    result
+    let status = u_getcwd_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        buf.as_mut_ptr() as *mut c_char,
+        bufsz,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+
+    shrink_to_fit_os_string(buf)
 }
 
-pub unsafe fn munmap(start: *mut c_void, length: size_t) -> c_int {
+pub unsafe fn chdir(dir: &CStr) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_munmap_ocall(&mut result as *mut c_int,
-                                &mut error as *mut c_int,
-                                start,
-                                length);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_chdir_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        dir.as_ptr(),
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn msync(addr: *mut c_void, length: size_t, flags: c_int) -> c_int {
+pub unsafe fn open(path: &CStr, flags: c_int) -> OCallResult<c_int> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_msync_ocall(&mut result as *mut c_int,
-                               &mut error as *mut c_int,
-                               addr,
-                               length,
-                               flags);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_open_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        path.as_ptr(),
+        flags,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    Ok(result)
 }
 
-pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: c_int) -> c_int {
+pub unsafe fn open64(path: &CStr, oflag: c_int, mode: c_int) -> OCallResult<c_int> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_mprotect_ocall(&mut result as *mut c_int,
-                                  &mut error as *mut c_int,
-                                  addr,
-                                  length,
-                                  prot);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
+    let status = u_open64_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        path.as_ptr(),
+        oflag,
+        mode,
+    );
 
-pub unsafe fn getuid() -> uid_t {
-    let mut result: uid_t = 0;
-    let status = u_getuid_ocall(&mut result as *mut uid_t);
-    if status != sgx_status_t::SGX_SUCCESS {
-         set_errno(ESGX);
-         result = 0;
-    }
-    result
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    Ok(result)
 }
 
-pub unsafe fn environ() -> *const *const c_char {
-    let mut result: *const *const c_char = ptr::null();
-    let status = u_environ_ocall(&mut result as *mut *const *const c_char);
+pub unsafe fn fstat(fd: c_int, buf: &mut stat) -> OCallResult<()> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
 
-    if status != sgx_status_t::SGX_SUCCESS {
-        result = ptr::null();
-    }
-    result
+    let status = u_fstat_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        fd,
+        buf as *mut stat,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn getenv(name: *const c_char) -> *const c_char {
-    let mut result: *const c_char = ptr::null();
-    let status = u_getenv_ocall(&mut result as *mut *const c_char, name);
+pub unsafe fn fstat64(fd: c_int, buf: &mut stat64) -> OCallResult<()> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+
+    let status = u_fstat64_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        fd,
+        buf as *mut stat64,
+    );
 
-    if status != sgx_status_t::SGX_SUCCESS {
-        result = ptr::null();
-    }
-    result
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn setenv(name: *const c_char, value: *const c_char, overwrite: c_int) -> c_int {
+pub unsafe fn stat(path: &CStr, buf: &mut stat) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_setenv_ocall(&mut result as *mut c_int,
-                                &mut error as *mut c_int,
-                                name,
-                                value,
-                                overwrite);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_stat_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        path.as_ptr(),
+        buf as *mut stat,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn unsetenv(name: *const c_char) -> c_int {
+pub unsafe fn stat64(path: &CStr, buf: &mut stat64) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_unsetenv_ocall(&mut result as *mut c_int,
-                                  &mut error as *mut c_int,
-                                  name);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_stat64_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        path.as_ptr(),
+        buf as *mut stat64,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char {
-    let mut result: *mut c_char = ptr::null_mut();
+pub unsafe fn lstat(path: &CStr, buf: &mut stat) -> OCallResult<()> {
+    let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_getcwd_ocall(&mut result as *mut *mut c_char, &mut error as *mut c_int, buf, size);
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result.is_null() {
-            set_errno(error);
-        } else {
-            result = buf;
-        }
-    } else {
-        set_errno(ESGX);
-        result = ptr::null_mut();
-    }
-    result
+
+    let status = u_lstat_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        path.as_ptr(),
+        buf as *mut stat,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn chdir(dir: *const c_char) -> c_int {
+pub unsafe fn lstat64(path: &CStr, buf: &mut stat64) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_chdir_ocall(&mut result as *mut c_int, &mut error as *mut c_int, dir);
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+
+    let status = u_lstat64_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        path.as_ptr(),
+        buf as *mut stat64,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn getpwuid_r(uid: uid_t,
-                         pwd: *mut passwd,
-                         buf: *mut c_char,
-                         buflen: size_t,
-                         passwd_result:  *mut *mut passwd) -> c_int {
-    let mut result: c_int = 0;
-    let status = u_getpwuid_r_ocall(&mut result as *mut c_int,
-                                    uid,
-                                    pwd,
-                                    buf,
-                                    buflen,
-                                    passwd_result);
-    if status == sgx_status_t::SGX_SUCCESS && result == 0 {
-        let pwd_ret = *passwd_result;
-        if !pwd_ret.is_null() {
-            let mut temp_pwd = &mut *pwd;
-            let mut temp_buf = buf;
-            if temp_pwd.pw_name as usize != -1_isize as usize {
-                temp_pwd.pw_name = temp_buf.offset(temp_pwd.pw_name as isize);
-            } else {
-                temp_pwd.pw_name = ptr::null_mut();
-            }
-            temp_buf = buf;
-            if temp_pwd.pw_passwd as usize != -1_isize as usize {
-                temp_pwd.pw_passwd = temp_buf.offset(temp_pwd.pw_passwd as isize);
-            } else {
-                temp_pwd.pw_passwd = ptr::null_mut();
-            }
-            temp_buf = buf;
-            if temp_pwd.pw_gecos as usize != -1_isize as usize {
-                temp_pwd.pw_gecos = temp_buf.offset(temp_pwd.pw_gecos as isize);
-            } else {
-                temp_pwd.pw_gecos = ptr::null_mut();
-            }
-            temp_buf = buf;
-            if temp_pwd.pw_dir as usize != -1_isize as usize {
-                temp_pwd.pw_dir = temp_buf.offset(temp_pwd.pw_dir as isize);
-            } else {
-                temp_pwd.pw_dir = ptr::null_mut();
-            }
-            temp_buf = buf;
-            if temp_pwd.pw_shell as usize != -1_isize as usize {
-                temp_pwd.pw_shell = temp_buf.offset(temp_pwd.pw_shell as isize);
-            } else {
-                temp_pwd.pw_shell = ptr::null_mut();
-            }
-            *passwd_result = pwd;
-        }
-    } else {
-        *passwd_result = ptr::null_mut();
-        if status != sgx_status_t::SGX_SUCCESS {
-            result = ESGX;
-        }
-    }
-    result
+pub unsafe fn lseek(fd: c_int, offset: off_t, whence: c_int) -> OCallResult<u64> {
+    let mut result: off_t = 0;
+    let mut error: c_int = 0;
+
+    let status = u_lseek_ocall(
+        &mut result as *mut off_t,
+        &mut error as *mut c_int,
+        fd,
+        offset,
+        whence,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    Ok(result as u64)
+}
+
+pub unsafe fn lseek64(fd: c_int, offset: off64_t, whence: c_int) -> OCallResult<u64> {
+    let mut result: off64_t = 0;
+    let mut error: c_int = 0;
+
+    let status = u_lseek64_ocall(
+        &mut result as *mut off64_t,
+        &mut error as *mut c_int,
+        fd,
+        offset,
+        whence,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    Ok(result as u64)
 }
 
-pub unsafe fn open(path: *const c_char, flags: c_int) -> c_int {
+pub unsafe fn ftruncate(fd: c_int, length: off_t) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_open_ocall(&mut result as *mut c_int,
-                              &mut error as *mut c_int,
-                              path,
-                              flags);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_ftruncate_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        fd,
+        length,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn open64(path: *const c_char, oflag: c_int, mode: c_int) -> c_int {
+pub unsafe fn ftruncate64(fd: c_int, length: off64_t) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_open64_ocall(&mut result as *mut c_int,
-                                &mut error as *mut c_int,
-                                path,
-                                oflag,
-                                mode);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_ftruncate64_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        fd,
+        length,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn fstat(fd: c_int, buf: *mut stat) -> c_int {
+pub unsafe fn truncate(path: &CStr, length: off_t) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_fstat_ocall(&mut result as *mut c_int,
-                               &mut error as *mut c_int,
-                               fd,
-                               buf);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_truncate_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        path.as_ptr(),
+        length,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn fstat64(fd: c_int, buf: *mut stat64) -> c_int {
+pub unsafe fn truncate64(path: &CStr, length: off64_t) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_fstat64_ocall(&mut result as *mut c_int,
-                                 &mut error as *mut c_int,
-                                 fd,
-                                 buf);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_truncate64_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        path.as_ptr(),
+        length,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn stat(path: *const c_char, buf: *mut stat) -> c_int {
+pub unsafe fn fsync(fd: c_int) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_stat_ocall(&mut result as *mut c_int,
-                              &mut error as *mut c_int,
-                              path,
-                              buf);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_fsync_ocall(&mut result as *mut c_int, &mut error as *mut c_int, fd);
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn stat64(path: *const c_char, buf: *mut stat64) -> c_int {
+pub unsafe fn fdatasync(fd: c_int) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_stat64_ocall(&mut result as *mut c_int,
-                                &mut error as *mut c_int,
-                                path,
-                                buf);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_fdatasync_ocall(&mut result as *mut c_int, &mut error as *mut c_int, fd);
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn lstat(path: *const c_char, buf: *mut stat) -> c_int {
+pub unsafe fn fchmod(fd: c_int, mode: mode_t) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_lstat_ocall(&mut result as *mut c_int,
-                               &mut error as *mut c_int,
-                               path,
-                               buf);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_fchmod_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        fd,
+        mode,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn lstat64(path: *const c_char, buf: *mut stat64) -> c_int {
+pub unsafe fn unlink(pathname: &CStr) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_lstat64_ocall(&mut result as *mut c_int,
-                                 &mut error as *mut c_int,
-                                 path,
-                                 buf);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_unlink_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        pathname.as_ptr(),
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t {
-    let mut result: off_t = 0;
+pub unsafe fn link(oldpath: &CStr, newpath: &CStr) -> OCallResult<()> {
+    let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_lseek_ocall(&mut result as *mut off_t,
-                               &mut error as *mut c_int,
-                               fd,
-                               offset,
-                               whence);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_link_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        oldpath.as_ptr(),
+        newpath.as_ptr(),
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn lseek64(fd: c_int, offset: off64_t, whence: c_int) -> off64_t {
-    let mut result: off64_t = 0;
+pub unsafe fn rename(oldpath: &CStr, newpath: &CStr) -> OCallResult<()> {
+    let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_lseek64_ocall(&mut result as *mut off64_t,
-                                 &mut error as *mut c_int,
-                                 fd,
-                                 offset,
-                                 whence);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_rename_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        oldpath.as_ptr(),
+        newpath.as_ptr(),
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn ftruncate(fd: c_int, length: off_t) -> c_int {
+pub unsafe fn chmod(path: &CStr, mode: mode_t) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_ftruncate_ocall(&mut result as *mut c_int,
-                                   &mut error as *mut c_int,
-                                   fd,
-                                   length);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn ftruncate64(fd: c_int, length: off64_t) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_ftruncate64_ocall(&mut result as *mut c_int,
-                                     &mut error as *mut c_int,
-                                     fd,
-                                     length);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn truncate(path: *const c_char, length: off_t) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_truncate_ocall(&mut result as *mut c_int,
-                                  &mut error as *mut c_int,
-                                  path,
-                                  length);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn truncate64(path: *const c_char, length: off64_t) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_truncate64_ocall(&mut result as *mut c_int,
-                                    &mut error as *mut c_int,
-                                    path,
-                                    length);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn fsync(fd: c_int) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_fsync_ocall(&mut result as *mut c_int,
-                               &mut error as *mut c_int,
-                               fd);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn fdatasync(fd: c_int) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_fdatasync_ocall(&mut result as *mut c_int,
-                                   &mut error as *mut c_int,
-                                   fd);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn fchmod(fd: c_int, mode: mode_t) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_fchmod_ocall(&mut result as *mut c_int,
-                                &mut error as *mut c_int,
-                                fd,
-                                mode);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn unlink(pathname: *const c_char) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_unlink_ocall(&mut result as *mut c_int,
-                                &mut error as *mut c_int,
-                                pathname);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn link(oldpath: *const c_char, newpath: *const c_char) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_link_ocall(&mut result as *mut c_int,
-                              &mut error as *mut c_int,
-                              oldpath,
-                              newpath);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn rename(oldpath: *const c_char, newpath: *const c_char) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_rename_ocall(&mut result as *mut c_int,
-                                &mut error as *mut c_int,
-                                oldpath,
-                                newpath);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn chmod(path: *const c_char, mode: mode_t) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_chmod_ocall(&mut result as *mut c_int,
-                               &mut error as *mut c_int,
-                               path,
-                               mode);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn readlink(path: *const c_char, buf: *mut c_char, bufsz: size_t) -> ssize_t {
-    let mut result: ssize_t = 0;
-    let mut error: c_int = 0;
-    let status = u_readlink_ocall(&mut result as *mut ssize_t,
-                                  &mut error as *mut c_int,
-                                  path,
-                                  buf,
-                                  bufsz);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn symlink(path1: *const c_char, path2: *const c_char) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_symlink_ocall(&mut result as *mut c_int,
-                                 &mut error as *mut c_int,
-                                 path1,
-                                 path2);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn realpath(pathname: *const c_char) -> *mut c_char {
-    let mut result: *mut c_char = ptr::null_mut();
-    let mut error: c_int = 0;
-    let status = u_realpath_ocall(&mut result as *mut *mut c_char,
-                                  &mut error as *mut c_int,
-                                  pathname);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result.is_null() {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = ptr::null_mut();
-    }
-    result
-}
-
-pub unsafe fn mkdir(pathname: *const c_char, mode: mode_t) -> c_int {
-    let mut error: c_int = 0;
-    let mut result: c_int = 0;
-    let status = u_mkdir_ocall(&mut result as *mut c_int,
-                               &mut error as *mut c_int,
-                               pathname,
-                               mode);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn rmdir(pathname: *const c_char) -> c_int {
-    let mut error: c_int = 0;
-    let mut result: c_int = 0;
-    let status = u_rmdir_ocall(&mut result as *mut c_int,
-                               &mut error as *mut c_int,
-                               pathname);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn opendir(pathname: *const c_char) -> *mut DIR {
-    let mut result: *mut DIR = ptr::null_mut();
-    let mut error: c_int = 0;
-    let status = u_opendir_ocall(&mut result as *mut *mut DIR,
-                                 &mut error as *mut c_int,
-                                 pathname);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result.is_null() {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = ptr::null_mut();
-    }
-    result
-}
-
-pub unsafe fn readdir64_r(dirp: *mut DIR,
-                          entry: *mut dirent64,
-                          dirresult: *mut *mut dirent64) -> c_int {
-    let mut result: c_int = 0;
-    let status = u_readdir64_r_ocall(&mut result as *mut c_int,
-                                     dirp,
-                                     entry,
-                                     dirresult);
-    if status == sgx_status_t::SGX_SUCCESS && result == 0 {
-        let dir_ret = *dirresult;
-        if !dir_ret.is_null() {
-            *dirresult = entry;
-        }
-    } else {
-        *dirresult = ptr::null_mut();
-        if status != sgx_status_t::SGX_SUCCESS {
-            result = ESGX;
-        }
-    }
-    result
-}
-                           
-pub unsafe fn closedir(dirp: *mut DIR) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_closedir_ocall(&mut result as *mut c_int,
-                                  &mut error as *mut c_int,
-                                  dirp);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}   
-
-pub unsafe fn dirfd(dirp: *mut DIR) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_dirfd_ocall(&mut result as *mut c_int,
-                               &mut error as *mut c_int,
-                               dirp);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn fstatat64(dirfd: c_int,
-                        pathname: *const c_char,
-                        buf: *mut stat64,
-                        flags: c_int) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_fstatat64_ocall(&mut result as *mut c_int,
-                                   &mut error as *mut c_int,
-                                   dirfd,
-                                   pathname,
-                                   buf,
-                                   flags);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn read(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t {
-    let mut result: ssize_t = 0;
-    let mut error: c_int = 0;
-
-    if buf.is_null() || sgx_is_within_enclave(buf, count) == 0 {
-        set_errno(EINVAL);
-        return -1;
-    }
-    if count >= usize::max_value() {
-        set_errno(EINVAL);
-        return -1;
-    }
-
-    let tmp_buf = if count <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocalloc(count)
-    } else {
-        malloc(count)
-    };
-    if tmp_buf.is_null() {
-        set_errno(ENOMEM );
-        return -1;
-    }
-    tmp_buf.write_bytes(0_u8, count);
-
-    let status = u_read_ocall(&mut result as *mut ssize_t,
-                              &mut error as *mut c_int,
-                              fd,
-                              tmp_buf,
-                              count);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-
-    if result != -1 {
-        ptr::copy_nonoverlapping(tmp_buf as *const u8, buf as *mut u8, count);
-    }
-    if count <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocfree();
-    } else {
-        free(tmp_buf);
-    }
-    result
-}
-
-pub unsafe fn pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: off64_t) -> ssize_t {
-    let mut result: ssize_t = 0;
-    let mut error: c_int = 0;
-
-    if buf.is_null() || sgx_is_within_enclave(buf, count) == 0 {
-        set_errno(EINVAL);
-        return -1;
-    }
-    if count >= usize::max_value() {
-        set_errno(EINVAL);
-        return -1;
-    }
-
-    let tmp_buf = if count <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocalloc(count)
-    } else {
-        malloc(count)
-    };
-    if tmp_buf.is_null() {
-        set_errno(ENOMEM );
-        return -1;
-    }
-    tmp_buf.write_bytes(0_u8, count);
-
-    let status = u_pread64_ocall(&mut result as *mut ssize_t,
-                                 &mut error as *mut c_int,
-                                 fd,
-                                 tmp_buf,
-                                 count,
-                                 offset);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-
-    if result != -1 {
-        ptr::copy_nonoverlapping(tmp_buf as *const u8, buf as *mut u8, count);
-    }
-    if count <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocfree();
-    } else {
-        free(tmp_buf);
-    }
-    result
-}
-
-pub unsafe fn readv(fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t {
-    let mut result: ssize_t = 0;
-    let mut error: c_int = 0;
-    let mut ptr: *mut u8 = ptr::null_mut();
-    let mut iosize: usize = 0;
-
-    if iov.is_null() || iovcnt <= 0 ||
-       sgx_is_within_enclave(iov as *const c_void, iovcnt as usize * mem::size_of::<iovec>()) == 0 {
-        set_errno(EINVAL);
-        return -1;
-    }
-
-    let v = slice::from_raw_parts(iov, iovcnt as usize);
-    for io in v {
-        if !io.iov_base.is_null() && io.iov_len > 0 &&
-            sgx_is_within_enclave(io.iov_base, io.iov_len as usize) != 0 {
-            iosize += io.iov_len as usize;
-        } else {
-            set_errno(EINVAL);
-            return -1;
-        }
-    }
-
-    let iobase = malloc(iosize) as *mut u8;
-    if iobase.is_null() {
-        set_errno(ENOMEM );
-        return -1;
-    }
-    iobase.write_bytes(0_u8, iosize);
-
-    let mut tmpiovec: Vec<iovec> = Vec::with_capacity(iovcnt as usize);
-    ptr = iobase;
-    for io in v {
-        let tmpiov = iovec{iov_base: ptr as *mut c_void,
-                           iov_len: io.iov_len};
-        tmpiovec.push(tmpiov);
-        ptr = ptr.add(io.iov_len as usize);
-    }
-
-    let status = u_readv_ocall(&mut result as *mut ssize_t,
-                               &mut error as *mut c_int,
-                               fd,
-                               tmpiovec.as_slice().as_ptr(),
-                               iovcnt);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-
-    if result != -1 {
-        for i in 0..v.len() {
-            ptr::copy_nonoverlapping(tmpiovec[i].iov_base as *const u8, v[i].iov_base as *mut u8, v[i].iov_len as usize);
-        }
-    }
-
-    free(iobase as *mut c_void);
-    result
-}
-
-pub unsafe fn preadv64(fd: c_int, iov: *const iovec, iovcnt: c_int, offset: off64_t) -> ssize_t {
-    let mut result: ssize_t = 0;
-    let mut error: c_int = 0;
-    let mut ptr: *mut u8 = ptr::null_mut();
-    let mut iosize: usize = 0;
-
-    if iov.is_null() || iovcnt <= 0 ||
-       sgx_is_within_enclave(iov as *const c_void, iovcnt as usize * mem::size_of::<iovec>()) == 0 {
-        set_errno(EINVAL);
-        return -1;
-    }
-
-    let v = slice::from_raw_parts(iov, iovcnt as usize);
-    for io in v {
-        if !io.iov_base.is_null() && io.iov_len > 0 &&
-            sgx_is_within_enclave(io.iov_base, io.iov_len as usize) != 0 {
-            iosize += io.iov_len as usize;
-        } else {
-            set_errno(EINVAL);
-            return -1;
-        }
-    }
-
-    let iobase = malloc(iosize) as *mut u8;
-    if iobase.is_null() {
-        set_errno(ENOMEM );
-        return -1;
-    }
-    iobase.write_bytes(0_u8, iosize);
-
-    let mut tmpiovec: Vec<iovec> = Vec::with_capacity(iovcnt as usize);
-    ptr = iobase;
-    for io in v {
-        let tmpiov = iovec{iov_base: ptr as *mut c_void,
-                           iov_len: io.iov_len};
-        tmpiovec.push(tmpiov);
-        ptr = ptr.add(io.iov_len as usize);
-    }
-
-    let status = u_preadv64_ocall(&mut result as *mut ssize_t,
-                               &mut error as *mut c_int,
-                               fd,
-                               tmpiovec.as_slice().as_ptr(),
-                               iovcnt,
-                               offset);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-
-    if result != -1 {
-        for i in 0..v.len() {
-            ptr::copy_nonoverlapping(tmpiovec[i].iov_base as *const u8, v[i].iov_base as *mut u8, v[i].iov_len as usize);
-        }
-    }
-
-    free(iobase as *mut c_void);
-    result
-}
-
-pub unsafe fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t {
-    let mut result: ssize_t = 0;
-    let mut error: c_int = 0;
-
-    if buf.is_null() || sgx_is_within_enclave(buf, count) == 0 {
-        set_errno(EINVAL);
-        return -1;
-    }
-    if count >= usize::max_value() {
-        set_errno(EINVAL);
-        return -1;
-    }
-
-    let tmp_buf = if count <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocalloc(count)
-    } else {
-        malloc(count)
-    };
-    if tmp_buf.is_null() {
-        set_errno(ENOMEM );
-        return -1;
-    }
-    ptr::copy_nonoverlapping(buf as *const u8, tmp_buf as *mut u8, count);
-
-    let status = u_write_ocall(&mut result as *mut ssize_t,
-                               &mut error as *mut c_int,
-                               fd,
-                               tmp_buf,
-                               count);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-
-    if count <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocfree();
-    } else {
-        free(tmp_buf);
-    }
-    result
-}
-
-pub unsafe fn pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: off64_t) -> ssize_t {
-    let mut result: ssize_t = 0;
-    let mut error: c_int = 0;
-
-    if buf.is_null() || sgx_is_within_enclave(buf, count) == 0 {
-        set_errno(EINVAL);
-        return -1;
-    }
-    if count >= usize::max_value() {
-        set_errno(EINVAL);
-        return -1;
-    }
+    let status = u_chmod_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        path.as_ptr(),
+        mode,
+    );
 
-    let tmp_buf = if count <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocalloc(count)
-    } else {
-        malloc(count)
-    };
-    if tmp_buf.is_null() {
-        set_errno(ENOMEM );
-        return -1;
-    }
-    ptr::copy_nonoverlapping(buf as *const u8, tmp_buf as *mut u8, count);
-
-    let status = u_pwrite64_ocall(&mut result as *mut ssize_t,
-                                  &mut error as *mut c_int,
-                                  fd,
-                                  tmp_buf,
-                                  count,
-                                  offset);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-
-    if count <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocfree();
-    } else {
-        free(tmp_buf);
-    }
-    result
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn writev(fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t {
+pub unsafe fn readlink(path: &CStr) -> OCallResult<Vec<u8>> {
     let mut result: ssize_t = 0;
     let mut error: c_int = 0;
-    let mut ptr: *mut u8 = ptr::null_mut();
-    let mut iosize: usize = 0;
-
-    if iov.is_null() || iovcnt <= 0 ||
-       sgx_is_within_enclave(iov as *const c_void, iovcnt as usize * mem::size_of::<iovec>()) == 0 {
-        set_errno(EINVAL);
-        return -1;
-    }
-
-    let v = slice::from_raw_parts(iov, iovcnt as usize);
-    for io in v {
-        if !io.iov_base.is_null() && io.iov_len > 0 &&
-            sgx_is_within_enclave(io.iov_base, io.iov_len as usize) != 0 {
-            iosize += io.iov_len as usize;
-        } else {
-            set_errno(EINVAL);
-            return -1;
-        }
-    }
-
-    let iobase = malloc(iosize) as *mut u8;
-    if iobase.is_null() {
-        set_errno(ENOMEM );
-        return -1;
-    }
-    iobase.write_bytes(0_u8, iosize);
-
-    let mut tmpiovec: Vec<iovec> = Vec::with_capacity(iovcnt as usize);
-    ptr = iobase;
-    for io in v {
-        let tmpiov = iovec{iov_base: ptr as *mut c_void,
-                           iov_len: io.iov_len};
-        ptr::copy_nonoverlapping(io.iov_base as *const u8, tmpiov.iov_base as *mut u8, io.iov_len as usize);
-        tmpiovec.push(tmpiov);
-        ptr = ptr.add(io.iov_len as usize);
-    }
-
-    let status = u_writev_ocall(&mut result as *mut ssize_t,
-                                &mut error as *mut c_int,
-                                fd,
-                                tmpiovec.as_slice().as_ptr(),
-                                iovcnt);
+    let mut buf: Vec<u8> = Vec::with_capacity(256);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
+    loop {
+        let bufsz = buf.capacity();
 
-    free(iobase as *mut c_void);
-    result
-}
+        let status = u_readlink_ocall(
+            &mut result as *mut ssize_t,
+            &mut error as *mut c_int,
+            path.as_ptr(),
+            buf.as_mut_ptr() as *mut c_char,
+            bufsz,
+        );
 
-pub unsafe fn pwritev64(fd: c_int, iov: *const iovec, iovcnt: c_int, offset: off64_t) -> ssize_t {
-    let mut result: ssize_t = 0;
-    let mut error: c_int = 0;
-    let mut ptr: *mut u8 = ptr::null_mut();
-    let mut iosize: usize = 0;
+        ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+        ensure!(result >= 0, eos!(error));
 
-    if iov.is_null() || iovcnt <= 0 ||
-       sgx_is_within_enclave(iov as *const c_void, iovcnt as usize * mem::size_of::<iovec>()) ==0 {
-        set_errno(EINVAL);
-        return -1;
-    }
+        // On success, these calls return the number of bytes placed in buf.
+        // If the returned value equals bufsz, then truncation may have occurred.
+        let buf_read = result as usize;
+        ensure!(buf_read <= bufsz, ecust!("Malformed return value."));
+        buf.set_len(buf_read);
 
-    let v = slice::from_raw_parts(iov, iovcnt as usize);
-    for io in v {
-        if !io.iov_base.is_null() && io.iov_len > 0 &&
-            sgx_is_within_enclave(io.iov_base, io.iov_len as usize) != 0 {
-            iosize += io.iov_len as usize;
-        } else {
-            set_errno(EINVAL);
-            return -1;
+        if buf_read < buf.capacity() {
+            buf.shrink_to_fit();
+            return Ok(buf);
         }
-    }
 
-    let iobase = malloc(iosize) as *mut u8;
-    if iobase.is_null() {
-        set_errno(ENOMEM );
-        return -1;
-    }
-    iobase.write_bytes(0_u8, iosize);
-
-    let mut tmpiovec: Vec<iovec> = Vec::with_capacity(iovcnt as usize);
-    ptr = iobase;
-    for io in v {
-        let tmpiov = iovec{iov_base: ptr as *mut c_void,
-                           iov_len: io.iov_len};
-        ptr::copy_nonoverlapping(io.iov_base as *const u8, tmpiov.iov_base as *mut u8, io.iov_len as usize);
-        tmpiovec.push(tmpiov);
-        ptr = ptr.add(io.iov_len as usize);
-    }
-
-    let status = u_pwritev64_ocall(&mut result as *mut ssize_t,
-                                   &mut error as *mut c_int,
-                                   fd,
-                                   tmpiovec.as_slice().as_ptr(),
-                                   iovcnt,
-                                   offset);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
+        // Trigger the internal buffer resizing logic of `Vec` by requiring
+        // more space than the current capacity. The length is guaranteed to be
+        // the same as the capacity due to the if statement above.
+        buf.reserve(1);
     }
-
-    free(iobase as *mut c_void);
-    result
 }
 
-pub unsafe fn fcntl_arg0(fd: c_int, cmd: c_int) -> c_int {
+pub unsafe fn symlink(path1: &CStr, path2: &CStr) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_fcntl_arg0_ocall(&mut result as *mut c_int,
-                                    &mut error as *mut c_int,
-                                    fd,
-                                    cmd);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
 
-pub unsafe fn fcntl_arg1(fd: c_int, cmd: c_int, arg: c_int) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_fcntl_arg1_ocall(&mut result as *mut c_int,
-                                    &mut error as *mut c_int,
-                                    fd,
-                                    cmd,
-                                    arg);
+    let status = u_symlink_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        path1.as_ptr(),
+        path2.as_ptr(),
+    );
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn ioctl_arg0(fd: c_int, request: c_int) -> c_int {
+pub unsafe fn realpath(path: &CStr) -> OCallResult<Vec<u8>> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_ioctl_arg0_ocall(&mut result as *mut c_int,
-                                    &mut error as *mut c_int,
-                                    fd,
-                                    request);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
+    let bufsz = PATH_MAX as usize;
+    let mut resolved_buf = vec![0u8; bufsz];
 
-pub unsafe fn ioctl_arg1(fd: c_int, request: c_int, arg: *mut c_int) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_ioctl_arg1_ocall(&mut result as *mut c_int,
-                                    &mut error as *mut c_int,
-                                    fd,
-                                    request,
-                                    arg);
+    let status = u_realpath_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        path.as_ptr(),
+        resolved_buf.as_mut_ptr() as *mut c_char,
+        bufsz,
+    );
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    shrink_to_fit_os_string(resolved_buf)
 }
 
-pub unsafe fn close(fd: c_int) -> c_int {
-    let mut result: c_int = 0;
+pub unsafe fn mkdir(pathname: &CStr, mode: mode_t) -> OCallResult<()> {
     let mut error: c_int = 0;
-    let status = u_close_ocall(&mut result as *mut c_int,
-                               &mut error as *mut c_int,
-                               fd);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
-
-pub unsafe fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
     let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_clock_gettime_ocall(&mut result as *mut c_int,
-                                       &mut error as *mut c_int,
-                                       clk_id,
-                                       tp);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
-}
 
-pub unsafe fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_socket_ocall(&mut result as *mut c_int,
-                                &mut error as *mut c_int,
-                                domain,
-                                ty,
-                                protocol);
+    let status = u_mkdir_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        pathname.as_ptr(),
+        mode,
+    );
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> c_int {
-    let mut result: c_int = 0;
+pub unsafe fn rmdir(pathname: &CStr) -> OCallResult<()> {
     let mut error: c_int = 0;
-    let status = u_socketpair_ocall(&mut result as *mut c_int,
-                                    &mut error as *mut c_int,
-                                    domain,
-                                    ty,
-                                    protocol,
-                                    sv);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let mut result: c_int = 0;
+
+    let status = u_rmdir_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        pathname.as_ptr(),
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn bind(sockfd: c_int, address: *const sockaddr, addrlen: socklen_t) -> c_int {
-    let mut result: c_int = 0;
+// todo: change DIR to handle
+pub unsafe fn opendir(pathname: &CStr) -> OCallResult<*mut DIR> {
+    let mut result: *mut DIR = ptr::null_mut();
     let mut error: c_int = 0;
-    let status = u_bind_ocall(&mut result as *mut c_int,
-                              &mut error as *mut c_int,
-                              sockfd,
-                              address,
-                              addrlen);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_opendir_ocall(
+        &mut result as *mut *mut DIR,
+        &mut error as *mut c_int,
+        pathname.as_ptr(),
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(!result.is_null(), eos!(error));
+    Ok(result)
 }
 
-pub unsafe fn listen(sockfd: c_int, backlog: c_int) -> c_int {
+// todo: change the interface, dirresult
+// result: success or error
+// hint: end-of-dir or continue
+pub unsafe fn readdir64_r(
+    dirp: *mut DIR,
+    entry: &mut dirent64,
+    dirresult: *mut *mut dirent64,
+) -> OCallResult<()> {
     let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_listen_ocall(&mut result as *mut c_int,
-                                &mut error as *mut c_int,
-                                sockfd,
-                                backlog);
+    let mut eods: c_int = 0;
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
+    // if there is any error or or end-of-dir, the result is always null.
+    *dirresult = ptr::null_mut();
+
+    let status = u_readdir64_r_ocall(
+        &mut result as *mut c_int,
+        dirp,
+        entry,
+        &mut eods as *mut c_int,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(result));
+
+    // inspect contents of dirent64
+    // d_reclen is 8 bytes aligned on 64-bit platform
+    let dn_slice = as_u8_slice!(entry.d_name.as_ptr(), entry.d_name.len());
+    if let Some(slen) = memchr::memchr(0, dn_slice) {
+        ensure!(
+            (slen == 0 && entry.d_reclen == 0)
+                || align8!(slen + DIRENT64_NAME_OFFSET) == entry.d_reclen as usize,
+            ecust!("readdir64_r: inconsistant dirent content")
+        );
     } else {
-        set_errno(ESGX);
-        result = -1;
+        return Err(ecust!("readdir64_r: d_name is not null terminated"));
     }
-    result
+
+    if eods == 0 {
+        *dirresult = entry;
+    }
+
+    Ok(())
 }
 
-pub unsafe fn accept(sockfd: c_int, addr: *mut sockaddr, addrlen: *mut socklen_t) -> c_int {
+pub unsafe fn closedir(dirp: *mut DIR) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let len_in: socklen_t = if !addrlen.is_null() { *addrlen } else { 0 };
-    let mut len_out: socklen_t = 0 as socklen_t;
-    let status = u_accept_ocall(&mut result as *mut c_int,
-                                &mut error as *mut c_int,
-                                sockfd,
-                                addr,
-                                len_in, // This additional arg is just for EDL
-                                &mut len_out as *mut socklen_t);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
+    let status = u_closedir_ocall(&mut result as *mut c_int, &mut error as *mut c_int, dirp);
 
-    if !addrlen.is_null() {
-        *addrlen = len_out;
-    }
-    result
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn accept4(sockfd: c_int, addr: *mut sockaddr, addrlen: *mut socklen_t, flags: c_int) -> c_int {
+// todo: change the interface
+pub unsafe fn dirfd(dirp: *mut DIR) -> OCallResult<c_int> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let len_in: socklen_t = if !addrlen.is_null() { *addrlen } else { 0 };
-    let mut len_out: socklen_t = 0 as socklen_t;
-    let status = u_accept4_ocall(&mut result as *mut c_int,
-                                 &mut error as *mut c_int,
-                                 sockfd,
-                                 addr,
-                                 len_in, // This additional arg is just for EDL
-                                 &mut len_out as *mut socklen_t,
-                                 flags);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
+    let status = u_dirfd_ocall(&mut result as *mut c_int, &mut error as *mut c_int, dirp);
 
-    if !addrlen.is_null() {
-        *addrlen = len_out;
-    }
-    result
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    Ok(result)
 }
 
-pub unsafe fn connect(sockfd: c_int, address: *const sockaddr, addrlen: socklen_t) -> c_int {
+pub unsafe fn fstatat64(
+    dirfd: c_int,
+    pathname: &CStr,
+    buf: &mut stat64,
+    flags: c_int,
+) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_connect_ocall(&mut result as *mut c_int,
-                                 &mut error as *mut c_int,
-                                 sockfd,
-                                 address,
-                                 addrlen);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let status = u_fstatat64_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        dirfd,
+        pathname.as_ptr(),
+        buf,
+        flags,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn send(sockfd: c_int, buf: *const c_void, len: size_t, flags: c_int) -> ssize_t {
-    let mut result: ssize_t = 0;
+fn check_trusted_enclave_buffer(buf: *const u8, count: size_t) -> OCallResult<()> {
+    ensure!(!buf.is_null(), ecust!("Invalid null buffer."));
+    ensure!(count > 0, ecust!("Invalid buffer checking length."));
+    ensure!(
+        unsafe { sgx_is_within_enclave(buf as *const c_void, count) } == 1,
+        ecust!("Buffer is not strictly inside enclave")
+    );
+    Ok(())
+}
+
+struct HostBuffer {
+    data: *mut u8,
+    len: usize,
+}
+
+unsafe fn host_malloc(size: usize) -> OCallResult<*mut c_void> {
+    let mut result: *mut c_void = ptr::null_mut();
     let mut error: c_int = 0;
+    let status = u_malloc_ocall(
+        &mut result as *mut *mut c_void,
+        &mut error as *mut c_int,
+        size,
+    );
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(!result.is_null(), ecust!("Out of memory"));
+    ensure!(
+        sgx_is_outside_enclave(result, size) == 1,
+        ecust!("Malformed malloc address")
+    );
+
+    Ok(result as _)
+}
 
-    if buf.is_null() || sgx_is_within_enclave(buf, len) == 0 {
-        set_errno(EINVAL);
-        return -1;
+impl HostBuffer {
+    fn zeroed(size: usize) -> OCallResult<Self> {
+        ensure!(
+            size != 0,
+            ecust!("Trying to allocate zero byte host memory.")
+        );
+        let host_ptr = unsafe { host_malloc(size)? };
+        unsafe { host_ptr.write_bytes(0_u8, size) };
+
+        Ok(HostBuffer {
+            data: host_ptr as _,
+            len: size,
+        })
     }
-    if len >= usize::max_value() {
-        set_errno(EINVAL);
-        return -1;
+
+    fn from_enclave(buf: &[u8]) -> OCallResult<Self> {
+        let bufsz = buf.len();
+        ensure!(
+            bufsz != 0,
+            ecust!("Trying to allocate zero byte host memory.")
+        );
+        check_trusted_enclave_buffer(buf.as_ptr(), bufsz)?;
+        let host_ptr = unsafe { host_malloc(bufsz)? };
+        unsafe { ptr::copy_nonoverlapping(buf.as_ptr() as *const u8, host_ptr as *mut u8, bufsz) };
+
+        Ok(HostBuffer {
+            data: host_ptr as _,
+            len: bufsz,
+        })
     }
 
-    let tmp_buf = if len <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocalloc(len)
-    } else {
-        malloc(len)
-    };
-    if tmp_buf.is_null() {
-        set_errno(ENOMEM );
-        return -1;
+    fn as_ptr(&self) -> *const c_void {
+        self.data as _
     }
-    ptr::copy_nonoverlapping(buf as *const u8, tmp_buf as *mut u8, len);
 
-    let status = u_send_ocall(&mut result as *mut ssize_t,
-                              &mut error as *mut c_int,
-                              sockfd,
-                              tmp_buf,
-                              len,
-                              flags);
+    fn as_mut_ptr(&mut self) -> *mut c_void {
+        self.data as _
+    }
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
+    fn len(&self) -> usize {
+        self.len
+    }
+
+    fn to_enclave_slice(&self, ecl_slice: &mut [u8]) -> OCallResult<usize> {
+        if ecl_slice.len() == 0 {
+            return Ok(0);
         }
-    } else {
-        set_errno(ESGX);
-        result = -1;
+        ensure!(ecl_slice.len() <= self.len);
+        check_trusted_enclave_buffer(ecl_slice.as_ptr(), ecl_slice.len())?;
+        unsafe {
+            ptr::copy_nonoverlapping(
+                self.data as *const u8,
+                ecl_slice.as_mut_ptr(),
+                ecl_slice.len(),
+            );
+        }
+        Ok(ecl_slice.len())
     }
+}
 
-    if len <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocfree();
-    } else {
-        free(tmp_buf);
+impl Drop for HostBuffer {
+    fn drop(&mut self) {
+        let _ = unsafe { u_free_ocall(self.data as _) };
     }
-    result
 }
 
-pub unsafe fn sendto(sockfd: c_int,
-                     buf: *const c_void,
-                     len: size_t,
-                     flags: c_int,
-                     addr: *const sockaddr,
-                     addrlen: socklen_t) -> ssize_t {
+pub unsafe fn read(fd: c_int, buf: &mut [u8]) -> OCallResult<usize> {
     let mut result: ssize_t = 0;
     let mut error: c_int = 0;
+    let bufsz = buf.len();
+    check_trusted_enclave_buffer(buf.as_ptr(), bufsz)?;
 
-    if buf.is_null() || sgx_is_within_enclave(buf, len) == 0 {
-        set_errno(EINVAL);
-        return -1;
-    }
-    if len >= usize::max_value() {
-        set_errno(EINVAL);
-        return -1;
-    }
+    let mut host_buf = HostBuffer::zeroed(bufsz)?;
 
-    let tmp_buf = if len <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocalloc(len)
-    } else {
-        malloc(len)
-    };
-    if tmp_buf.is_null() {
-        set_errno(ENOMEM );
-        return -1;
-    }
-    ptr::copy_nonoverlapping(buf as *const u8, tmp_buf as *mut u8, len);
+    let status = u_read_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        fd,
+        host_buf.as_mut_ptr(),
+        host_buf.len(),
+    );
 
-    let status = u_sendto_ocall(&mut result as *mut ssize_t,
-                                &mut error as *mut c_int,
-                                sockfd,
-                                tmp_buf,
-                                len,
-                                flags,
-                                addr,
-                                addrlen);
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
+    let nread = result as usize;
+    ensure!(nread <= bufsz, ecust!("Malformed return size"));
 
-    if len <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocfree();
-    } else {
-        free(tmp_buf);
-    }
-    result
+    host_buf.to_enclave_slice(&mut buf[..nread])
 }
 
-pub unsafe fn sendmsg(sockfd: c_int, msg: *const msghdr, flags: c_int) -> ssize_t {
+pub unsafe fn pread64(fd: c_int, buf: &mut [u8], offset: off64_t) -> OCallResult<usize> {
     let mut result: ssize_t = 0;
     let mut error: c_int = 0;
-    let mut hdrsize: usize = 0;
-    let mut ptr: *mut u8 = ptr::null_mut();
+    let bufsz = buf.len();
 
-    if msg.is_null() || sgx_is_within_enclave(msg as *const c_void, mem::size_of::<msghdr>()) == 0 {
-        set_errno(EINVAL);
-        return -1;
-    }
+    check_trusted_enclave_buffer(buf.as_ptr(), bufsz)?;
+    let mut host_buf = HostBuffer::zeroed(bufsz)?;
 
-    let mhdr: &msghdr = &*msg;
-    if !mhdr.msg_name.is_null() && mhdr.msg_namelen > 0 &&
-        sgx_is_within_enclave(mhdr.msg_name, mhdr.msg_namelen as usize) != 0 {
-        hdrsize += mhdr.msg_namelen as usize;
-    }
+    let status = u_pread64_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        fd,
+        host_buf.as_mut_ptr(),
+        host_buf.len(),
+        offset,
+    );
 
-    if !mhdr.msg_iov.is_null() && mhdr.msg_iovlen > 0 &&
-       sgx_is_within_enclave(mhdr.msg_iov as *const c_void, mhdr.msg_iovlen as usize * mem::size_of::<iovec>()) != 0 {
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
 
-        hdrsize += mhdr.msg_iovlen as usize * mem::size_of::<iovec>();
-        let v = slice::from_raw_parts(mhdr.msg_iov, mhdr.msg_iovlen as usize);
-        for io in v {
-            if !io.iov_base.is_null() && io.iov_len > 0 &&
-                sgx_is_within_enclave(io.iov_base, io.iov_len as usize) != 0 {
-                hdrsize += io.iov_len as usize;
-            } else {
-                set_errno(EINVAL);
-                return -1;
-            }
-        }
-    }
+    let nread = result as usize;
+    ensure!(nread <= bufsz, ecust!("Malformed return size"));
 
-    if !mhdr.msg_control.is_null() &&  mhdr.msg_controllen > 0 &&
-        sgx_is_within_enclave(mhdr.msg_control, mhdr.msg_controllen as usize) != 0 {
-        hdrsize += mhdr.msg_controllen as usize;
-    }
+    host_buf.to_enclave_slice(&mut buf[..nread])
+}
 
-    let hdrbase = malloc(hdrsize) as *mut u8;
-    if hdrbase.is_null() {
-        set_errno(ENOMEM );
-        return -1;
+// Caller is responsible to ensure the iov parameter and its content (slices) are inside enclave memory.
+pub unsafe fn readv(fd: c_int, mut iov: Vec<&mut [u8]>) -> OCallResult<size_t> {
+    let mut total_size: usize = 0;
+    for s in iov.iter() {
+        check_trusted_enclave_buffer(s.as_ptr(), s.len())?;
+        total_size = total_size
+            .checked_add(s.len())
+            .ok_or_else(|| OCallError::from_custom_error("Overflow"))?;
     }
-    hdrbase.write_bytes(0_u8, hdrsize);
-
-    let mut tmpmsg: msghdr = mem::zeroed();
-    ptr = hdrbase;
-    if !mhdr.msg_name.is_null() && mhdr.msg_namelen > 0 {
-        tmpmsg.msg_name = ptr as *mut c_void;
-        tmpmsg.msg_namelen = mhdr.msg_namelen;
-        ptr::copy_nonoverlapping(mhdr.msg_name as *const u8, tmpmsg.msg_name as *mut u8, mhdr.msg_namelen as usize);
-        ptr = ptr.add(mhdr.msg_namelen as usize);
+
+    let bufsz = total_size;
+    if total_size == 0 {
+        return Ok(0);
     }
 
-    if !mhdr.msg_iov.is_null() && mhdr.msg_iovlen > 0 {
-        let tmpiov = slice::from_raw_parts_mut(ptr as *mut iovec, mhdr.msg_iovlen as usize);
-        ptr = ptr.add(mhdr.msg_iovlen as usize * mem::size_of::<iovec>());
+    let mut host_buf = HostBuffer::zeroed(bufsz)?;
+    let mut result: ssize_t = 0;
+    let mut error: c_int = 0;
+    let status = u_read_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        fd,
+        host_buf.as_mut_ptr(),
+        host_buf.len(),
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
 
-        let v = slice::from_raw_parts(mhdr.msg_iov, mhdr.msg_iovlen as usize);
-        for i in 0..v.len() {
-            tmpiov[i].iov_base = ptr as *mut c_void;
-            tmpiov[i].iov_len = v[i].iov_len;
-            ptr::copy_nonoverlapping(v[i].iov_base as *const u8, tmpiov[i].iov_base as *mut u8, v[i].iov_len as usize);
-            ptr = ptr.add(v[i].iov_len as usize);
-        }
-    }
+    let u_read = result as usize;
+    ensure!(u_read <= bufsz, ecust!("Malformed result"));
 
-    if !mhdr.msg_control.is_null() &&  mhdr.msg_controllen > 0 {
-        tmpmsg.msg_control = ptr as *mut c_void;
-        tmpmsg.msg_controllen = mhdr.msg_controllen;
-        ptr::copy_nonoverlapping(mhdr.msg_control as *const u8, tmpmsg.msg_control as *mut u8, mhdr.msg_controllen as usize);
+    if u_read == 0 {
+        return Ok(0);
     }
 
-    let status = u_sendmsg_ocall(&mut result as *mut ssize_t,
-                                 &mut error as *mut c_int,
-                                 sockfd,
-                                 &tmpmsg as *const msghdr,
-                                 flags);
+    // Buffers are processed in array order.  This means that readv() com‐
+    // pletely fills iov[0] before proceeding to iov[1], and so on.  (If
+    // there is insufficient data, then not all buffers pointed to by iov
+    // may be filled.)  Similarly, writev() writes out the entire contents
+    // of iov[0] before proceeding to iov[1], and so on.
+    let mut bytes_left: usize = u_read;
+    let mut copied: usize = 0;
+    let mut i = 0;
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
+    let mut v = vec![0; u_read];
+    host_buf.to_enclave_slice(v.as_mut_slice())?;
+    while i < iov.len() && bytes_left > 0 {
+        let n = cmp::min(iov[i].len(), bytes_left);
+        iov[i][..n].copy_from_slice(&v[copied..copied + n]);
+        bytes_left -= n;
+        copied += n;
+        i += 1;
     }
 
-    free(hdrbase as *mut c_void);
-    result
+    Ok(u_read)
 }
 
-pub unsafe fn recv(sockfd: c_int, buf: *mut c_void, len: size_t, flags: c_int) -> ssize_t {
+pub unsafe fn write(fd: c_int, buf: &[u8]) -> OCallResult<usize> {
     let mut result: ssize_t = 0;
     let mut error: c_int = 0;
-
-    if buf.is_null() || sgx_is_within_enclave(buf, len) == 0 {
-        set_errno(EINVAL);
-        return -1;
-    }
-    if len >= usize::max_value() {
-        set_errno(EINVAL);
-        return -1;
+    let bufsz = buf.len();
+    if bufsz == 0 {
+        return Ok(0);
     }
 
-    let tmp_buf = if len <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocalloc(len)
-    } else {
-        malloc(len)
-    };
-    if tmp_buf.is_null() {
-        set_errno(ENOMEM );
-        return -1;
-    }
-    tmp_buf.write_bytes(0_u8, len);
+    let host_buf = HostBuffer::from_enclave(buf)?;
 
-    let status = u_recv_ocall(&mut result as *mut ssize_t,
-                              &mut error as *mut c_int,
-                              sockfd,
-                              tmp_buf,
-                              len,
-                              flags);
+    let status = u_write_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        fd,
+        host_buf.as_ptr(),
+        host_buf.len(),
+    );
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
 
-    if result != -1 {
-        ptr::copy_nonoverlapping(tmp_buf as *const u8, buf as *mut u8, len);
-    }
-    if len <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocfree();
-    } else {
-        free(tmp_buf);
-    }
-    result
+    let nwritten = result as usize;
+    ensure!(nwritten <= bufsz, ecust!("Malformed return size"));
+    Ok(nwritten)
 }
 
-pub unsafe fn recvfrom(sockfd: c_int,
-                       buf: *mut c_void,
-                       len: size_t,
-                       flags: c_int,
-                       addr: *mut sockaddr,
-                       addrlen: *mut socklen_t) -> ssize_t {
+pub unsafe fn pwrite64(fd: c_int, buf: &[u8], offset: off64_t) -> OCallResult<usize> {
     let mut result: ssize_t = 0;
     let mut error: c_int = 0;
-    let len_in: socklen_t = if !addrlen.is_null() { *addrlen } else { 0 };
-    let mut len_out: socklen_t = 0 as socklen_t;
-
-    if buf.is_null() || sgx_is_within_enclave(buf, len) == 0 {
-        set_errno(EINVAL);
-        return -1;
-    }
-    if len >= usize::max_value() {
-        set_errno(EINVAL);
-        return -1;
+    let bufsz = buf.len();
+    if bufsz == 0 {
+        return Ok(0);
     }
 
-    let tmp_buf = if len <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocalloc(len)
-    } else {
-        malloc(len)
-    };
-    if tmp_buf.is_null() {
-        set_errno(ENOMEM );
-        return -1;
-    }
-    tmp_buf.write_bytes(0_u8, len);
-
-    let status = u_recvfrom_ocall(&mut result as *mut ssize_t,
-                                  &mut error as *mut c_int,
-                                  sockfd,
-                                  tmp_buf,
-                                  len,
-                                  flags,
-                                  addr,
-                                  len_in, // This additional arg is just for EDL
-                                  &mut len_out as *mut socklen_t);
+    let host_buf = HostBuffer::from_enclave(buf)?;
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
+    let status = u_pwrite64_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        fd,
+        host_buf.as_ptr(),
+        host_buf.len(),
+        offset,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
 
-    if result != -1 {
-        ptr::copy_nonoverlapping(tmp_buf as *const u8, buf as *mut u8, len);
+    let nwritten = result as usize;
+    ensure!(nwritten <= bufsz, ecust!("Malformed return size"));
+
+    Ok(nwritten)
+}
+
+pub unsafe fn writev(fd: c_int, iov: Vec<&[u8]>) -> OCallResult<size_t> {
+    let mut total_size: usize = 0;
+    for s in iov.iter() {
+        check_trusted_enclave_buffer(s.as_ptr(), s.len())?;
+        total_size = total_size
+            .checked_add(s.len())
+            .ok_or_else(|| OCallError::from_custom_error("Overflow"))?;
     }
-    if len <= MAX_OCALL_ALLOC_SIZE {
-        sgx_ocfree();
-    } else {
-        free(tmp_buf);
+
+    if total_size == 0 {
+        return Ok(0);
     }
 
-    if !addrlen.is_null() {
-        *addrlen = len_out;
+    let bufsz = total_size;
+    let mut buffer = vec![0; total_size];
+
+    let mut copied = 0;
+    for io_slice in iov.iter() {
+        buffer[copied..copied + io_slice.len()].copy_from_slice(io_slice);
+        copied += io_slice.len();
     }
-    result
-}
 
-pub unsafe fn recvmsg(sockfd: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t {
+    let host_buf = HostBuffer::from_enclave(&buffer)?;
     let mut result: ssize_t = 0;
     let mut error: c_int = 0;
-    let mut hdrsize: usize = 0;
-    let mut ptr: *mut u8 = ptr::null_mut();
 
-    if msg.is_null() || sgx_is_within_enclave(msg as *const c_void, mem::size_of::<msghdr>()) == 0 {
-        set_errno(EINVAL);
-        return -1;
-    }
+    let status = u_write_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        fd,
+        host_buf.as_ptr(),
+        host_buf.len(),
+    );
 
-    let mhdr: &mut msghdr = &mut *msg;
-    if !mhdr.msg_name.is_null() && mhdr.msg_namelen > 0 &&
-        sgx_is_within_enclave(mhdr.msg_name, mhdr.msg_namelen as usize) != 0 {
-        hdrsize += mhdr.msg_namelen as usize;
-    }
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
 
-    if !mhdr.msg_iov.is_null() && mhdr.msg_iovlen > 0 &&
-       sgx_is_within_enclave(mhdr.msg_iov as *const c_void, mhdr.msg_iovlen as usize * mem::size_of::<iovec>()) != 0 {
+    let nwritten = result as size_t;
+    ensure!(nwritten <= bufsz, ecust!("Malformed result"));
 
-        hdrsize += mhdr.msg_iovlen as usize * mem::size_of::<iovec>();
-        let v = slice::from_raw_parts(mhdr.msg_iov, mhdr.msg_iovlen as usize);
-        for io in v {
-            if !io.iov_base.is_null() && io.iov_len > 0 &&
-                sgx_is_within_enclave(io.iov_base, io.iov_len as usize) != 0 {
-                hdrsize += io.iov_len as usize;
-            } else {
-                set_errno(EINVAL);
-                return -1;
-            }
-        }
-    }
+    Ok(nwritten)
+}
 
-    if !mhdr.msg_control.is_null() &&  mhdr.msg_controllen > 0 &&
-        sgx_is_within_enclave(mhdr.msg_control, mhdr.msg_controllen as usize) != 0 {
-        hdrsize += mhdr.msg_controllen as usize;
-    }
+pub unsafe fn fcntl_arg0(fd: c_int, cmd: c_int) -> OCallResult<c_int> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let status = u_fcntl_arg0_ocall(&mut result as *mut c_int, &mut error as *mut c_int, fd, cmd);
 
-    let hdrbase = malloc(hdrsize) as *mut u8;
-    if hdrbase.is_null() {
-        set_errno(ENOMEM );
-        return -1;
-    }
-    hdrbase.write_bytes(0_u8, hdrsize);
-
-    let mut tmpmsg: msghdr = mem::zeroed();
-    ptr = hdrbase;
-    if !mhdr.msg_name.is_null() && mhdr.msg_namelen > 0 {
-        tmpmsg.msg_name = ptr as *mut c_void;
-        tmpmsg.msg_namelen = mhdr.msg_namelen;
-        ptr::copy_nonoverlapping(mhdr.msg_name as *const u8, tmpmsg.msg_name as *mut u8, mhdr.msg_namelen as usize);
-        ptr = ptr.add(mhdr.msg_namelen as usize);
-    }
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    Ok(result)
+}
 
-    if !mhdr.msg_iov.is_null() && mhdr.msg_iovlen > 0 {
-        let tmpiov = slice::from_raw_parts_mut(ptr as *mut iovec, mhdr.msg_iovlen as usize);
-        ptr = ptr.add(mhdr.msg_iovlen as usize * mem::size_of::<iovec>());
+pub unsafe fn fcntl_arg1(fd: c_int, cmd: c_int, arg: c_int) -> OCallResult<c_int> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let status = u_fcntl_arg1_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        fd,
+        cmd,
+        arg,
+    );
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    Ok(result)
+}
 
-        let v = slice::from_raw_parts(mhdr.msg_iov, mhdr.msg_iovlen as usize);
-        for i in 0..v.len() {
-            tmpiov[i].iov_base = ptr as *mut c_void;
-            tmpiov[i].iov_len = v[i].iov_len;
-            ptr = ptr.add(v[i].iov_len as usize);
-        }
-    }
+pub unsafe fn ioctl_arg0(fd: c_int, request: c_int) -> OCallResult<()> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let status = u_ioctl_arg0_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        fd,
+        request,
+    );
 
-    if !mhdr.msg_control.is_null() &&  mhdr.msg_controllen > 0 {
-        tmpmsg.msg_control = ptr as *mut c_void;
-        tmpmsg.msg_controllen = mhdr.msg_controllen;
-        ptr::copy_nonoverlapping(mhdr.msg_control as *const u8, tmpmsg.msg_control as *mut u8, mhdr.msg_controllen as usize);
-    }
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
+}
 
-    let status = u_recvmsg_ocall(&mut result as *mut ssize_t,
-                                 &mut error as *mut c_int,
-                                 sockfd,
-                                 &mut tmpmsg as *mut msghdr,
-                                 flags);
+pub unsafe fn ioctl_arg1(fd: c_int, request: c_int, arg: &mut c_int) -> OCallResult<()> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let status = u_ioctl_arg1_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        fd,
+        request,
+        arg,
+    );
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
+}
+
+pub unsafe fn close(fd: c_int) -> OCallResult<()> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let status = u_close_ocall(&mut result as *mut c_int, &mut error as *mut c_int, fd);
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+
+    Ok(())
+}
+
+pub unsafe fn clock_gettime(clk_id: clockid_t, tp: &mut timespec) -> OCallResult<()> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let status = u_clock_gettime_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        clk_id,
+        tp,
+    );
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+
+    Ok(())
+}
+
+pub unsafe fn socket(domain: c_int, ty: c_int, protocol: c_int) -> OCallResult<c_int> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let status = u_socket_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        domain,
+        ty,
+        protocol,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+
+    Ok(result)
+}
+
+pub unsafe fn socketpair(
+    domain: c_int,
+    ty: c_int,
+    protocol: c_int,
+    sv: &mut [c_int; 2],
+) -> OCallResult<()> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let mut out_sv = [0 as c_int; 2];
+
+    let status = u_socketpair_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        domain,
+        ty,
+        protocol,
+        out_sv.as_mut_ptr() as *mut c_int,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+
+    sv.copy_from_slice(&out_sv);
+    Ok(())
+}
+
+pub unsafe fn bind(sockfd: c_int, sock_addr: &SockAddr) -> OCallResult<()> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+
+    let address = sock_addr.as_bytes();
+
+    let status = u_bind_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        sockfd,
+        address.as_ptr() as *const sockaddr,
+        address.len() as socklen_t,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
+}
+
+pub unsafe fn listen(sockfd: c_int, backlog: c_int) -> OCallResult<()> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let status = u_listen_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        sockfd,
+        backlog,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
+}
+
+pub unsafe fn accept4(sockfd: c_int, flags: c_int) -> OCallResult<(c_int, SockAddr)> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let mut storage: sockaddr_storage = mem::zeroed();
+    let len_in = mem::size_of_val(&storage) as socklen_t;
+
+    let mut len_out: socklen_t = 0 as socklen_t;
+    let status = u_accept4_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        sockfd,
+        &mut storage as *mut _ as *mut _,
+        len_in, // This additional arg is just for EDL
+        &mut len_out as *mut socklen_t,
+        flags,
+    );
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    ensure!(
+        len_out <= len_in,
+        ecust!("Caller should alloc enough addr buffer.")
+    );
+
+    let addr = SockAddr::try_from_storage(storage, len_out)?;
+    Ok((result, addr))
+}
+
+pub unsafe fn connect(sockfd: c_int, address: &SockAddr) -> OCallResult<()> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+    let address = address.as_bytes();
+
+    let status = u_connect_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        sockfd,
+        address.as_ptr() as *const sockaddr,
+        address.len() as socklen_t,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
+}
+
+pub unsafe fn send(sockfd: c_int, buf: &[u8], flags: c_int) -> OCallResult<usize> {
+    let bufsz = buf.len();
+    // size zero
+
+    let mut result: ssize_t = 0;
+    let mut error: c_int = 0;
+    let host_buf = HostBuffer::from_enclave(buf)?;
+
+    let status = u_send_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        sockfd,
+        host_buf.as_ptr(),
+        host_buf.len(),
+        flags,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+
+    let nsent = result as usize;
+    ensure!(nsent <= bufsz, ecust!("Malformed return size"));
+
+    Ok(nsent)
+}
+
+pub unsafe fn sendto(
+    sockfd: c_int,
+    buf: &[u8],
+    flags: c_int,
+    sock_addr: &SockAddr,
+) -> OCallResult<usize> {
+    let mut result: ssize_t = 0;
+    let mut error: c_int = 0;
 
-    ptr = hdrbase;
-    if !mhdr.msg_name.is_null() && mhdr.msg_namelen > 0 {
-        ptr = ptr.add(mhdr.msg_namelen as usize);
-    }
+    let bufsz = buf.len();
+    let host_buf = HostBuffer::from_enclave(buf)?;
 
-    if !mhdr.msg_iov.is_null() && mhdr.msg_iovlen > 0 {
-        let tmpiov = slice::from_raw_parts_mut(ptr as *mut iovec, mhdr.msg_iovlen as usize);
-        ptr = ptr.add(mhdr.msg_iovlen as usize * mem::size_of::<iovec>());
+    let addr = sock_addr.as_bytes();
 
-        let v = slice::from_raw_parts(mhdr.msg_iov, mhdr.msg_iovlen as usize);
-        for i in 0..v.len() {
-            ptr::copy_nonoverlapping(tmpiov[i].iov_base as *const u8, v[i].iov_base as *mut u8, v[i].iov_len as usize);
-            ptr = ptr.add(v[i].iov_len as usize);
-        }
-    }
+    //todo: add check for addrlen
+    let status = u_sendto_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        sockfd,
+        host_buf.as_ptr(),
+        host_buf.len(),
+        flags,
+        addr.as_ptr() as *const sockaddr,
+        addr.len() as socklen_t,
+    );
 
-    if !mhdr.msg_control.is_null() &&  mhdr.msg_controllen > 0 {
-        ptr::copy_nonoverlapping(tmpmsg.msg_control as *const u8, mhdr.msg_control as *mut u8, mhdr.msg_controllen as usize);
-    }
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
 
-    free(hdrbase as *mut c_void);
-    result
+    let nsent = result as usize;
+    ensure!(nsent <= bufsz, ecust!("Malformed return size"));
+
+    Ok(nsent)
 }
 
-pub unsafe fn setsockopt(sockfd: c_int,
-                         level: c_int,
-                         optname: c_int,
-                         optval: *const c_void,
-                         optlen: socklen_t) -> c_int {
-    let mut result: c_int = 0;
+pub unsafe fn recv(sockfd: c_int, buf: &mut [u8], flags: c_int) -> OCallResult<usize> {
+    let mut result: ssize_t = 0;
     let mut error: c_int = 0;
-    let status = u_setsockopt_ocall(&mut result as *mut c_int,
-                                    &mut error as *mut c_int,
-                                    sockfd,
-                                    level,
-                                    optname,
-                                    optval,
-                                    optlen);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let buf_ptr = buf.as_ptr();
+    let bufsz = buf.len();
+    check_trusted_enclave_buffer(buf_ptr, bufsz)?;
+    let mut host_buf = HostBuffer::zeroed(bufsz)?;
+
+    let status = u_recv_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        sockfd,
+        host_buf.as_mut_ptr(),
+        host_buf.len(),
+        flags,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+
+    let nrecv = result as usize;
+    ensure!(nrecv <= bufsz, ecust!("Malformed return size"));
+    host_buf.to_enclave_slice(&mut buf[..nrecv])
 }
 
-pub unsafe fn getsockopt(sockfd: c_int,
-                         level: c_int,
-                         optname: c_int,
-                         optval: *mut c_void,
-                         optlen: *mut socklen_t) -> c_int {
+pub unsafe fn recvfrom(
+    sockfd: c_int,
+    buf: &mut [u8],
+    flags: c_int,
+) -> OCallResult<(size_t, SockAddr)> {
+    let mut result: ssize_t = 0;
+    let mut error: c_int = 0;
+
+    let mut storage: sockaddr_storage = mem::zeroed();
+    let len_in = mem::size_of_val(&storage) as socklen_t;
+    let mut len_out: socklen_t = 0 as socklen_t;
+
+    let bufsz = buf.len();
+    let mut host_buf = HostBuffer::zeroed(bufsz)?;
+
+    // todo: add check for len_in
+    let status = u_recvfrom_ocall(
+        &mut result as *mut ssize_t,
+        &mut error as *mut c_int,
+        sockfd,
+        host_buf.as_mut_ptr(),
+        host_buf.len(),
+        flags,
+        &mut storage as *mut _ as *mut _,
+        len_in, // This additional arg is just for EDL
+        &mut len_out as *mut socklen_t,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    ensure!(
+        len_out <= len_in,
+        ecust!("Caller should alloc enough addr buffer.")
+    );
+
+    let nrecv = result as usize;
+    ensure!(nrecv <= bufsz, ecust!("Malformed return value"));
+
+    host_buf.to_enclave_slice(&mut buf[..nrecv])?;
+    let addr = SockAddr::try_from_storage(storage, len_out)?;
+    Ok((nrecv, addr))
+}
+
+pub unsafe fn setsockopt(
+    sockfd: c_int,
+    level: c_int,
+    optname: c_int,
+    optval: *const c_void,
+    optlen: socklen_t,
+) -> OCallResult<()> {
+    let mut result: c_int = 0;
+    let mut error: c_int = 0;
+
+    let status = u_setsockopt_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        sockfd,
+        level,
+        optname,
+        optval,
+        optlen,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
+}
+
+pub unsafe fn getsockopt(
+    sockfd: c_int,
+    level: c_int,
+    optname: c_int,
+    optval: *mut c_void,
+    optlen: *mut socklen_t,
+) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
     let len_in: socklen_t = if !optlen.is_null() { *optlen } else { 0 };
     let mut len_out: socklen_t = 0 as socklen_t;
 
-    let status = u_getsockopt_ocall(&mut result as *mut c_int,
-                                    &mut error as *mut c_int,
-                                    sockfd,
-                                    level,
-                                    optname,
-                                    optval,
-                                    len_in,
-                                    &mut len_out as *mut socklen_t);
-
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-
+    let status = u_getsockopt_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        sockfd,
+        level,
+        optname,
+        optval,
+        len_in,
+        &mut len_out as *mut socklen_t,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    ensure!(
+        len_out <= len_in,
+        ecust!("Caller should alloc enough opt buffer.")
+    );
     if !optlen.is_null() {
         *optlen = len_out;
     }
-    result
+    Ok(())
 }
 
-pub unsafe fn getpeername(sockfd: c_int, address: *mut sockaddr, addrlen: *mut socklen_t) -> c_int {
+pub unsafe fn getpeername(sockfd: c_int) -> OCallResult<SockAddr> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let len_in: socklen_t = if !addrlen.is_null() { *addrlen } else { 0 };
+    let mut storage: sockaddr_storage = mem::zeroed();
+    let len_in = mem::size_of_val(&storage) as socklen_t;
     let mut len_out: socklen_t = 0 as socklen_t;
-    let status = u_getpeername_ocall(&mut result as *mut c_int,
-                                     &mut error as *mut c_int,
-                                     sockfd,
-                                     address,
-                                     len_in,
-                                     &mut len_out as *mut socklen_t);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
+    let status = u_getpeername_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        sockfd,
+        &mut storage as *mut _ as *mut _,
+        len_in,
+        &mut len_out as *mut socklen_t,
+    );
 
-    if !addrlen.is_null() {
-        *addrlen = len_out;
-    }
-    result
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    ensure!(
+        len_out <= len_in,
+        ecust!("Caller should alloc enough addr buffer.")
+    );
+
+    let addr = SockAddr::try_from_storage(storage, len_out)?;
+    Ok(addr)
 }
 
-pub unsafe fn getsockname(sockfd: c_int, address: *mut sockaddr, addrlen: *mut socklen_t) -> c_int {
+pub unsafe fn getsockname(sockfd: c_int) -> OCallResult<SockAddr> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let len_in: socklen_t = if !addrlen.is_null() { *addrlen } else { 0 };
+    let mut storage: sockaddr_storage = mem::zeroed();
+    let len_in = mem::size_of_val(&storage) as socklen_t;
     let mut len_out: socklen_t = 0 as socklen_t;
-    let status = u_getsockname_ocall(&mut result as *mut c_int,
-                                     &mut error as *mut c_int,
-                                     sockfd,
-                                     address,
-                                     len_in,
-                                     &mut len_out as *mut socklen_t);
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
+    let status = u_getsockname_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        sockfd,
+        &mut storage as *mut _ as *mut _,
+        len_in,
+        &mut len_out as *mut socklen_t,
+    );
 
-    if !addrlen.is_null() {
-        *addrlen = len_out;
-    }
-    result
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    ensure!(
+        len_out <= len_in,
+        ecust!("Caller should alloc enough addr buffer.")
+    );
+
+    let addr = SockAddr::try_from_storage(storage, len_out)?;
+    Ok(addr)
 }
 
-pub unsafe fn shutdown(sockfd: c_int, how: c_int) -> c_int {
+pub unsafe fn shutdown(sockfd: c_int, how: c_int) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_shutdown_ocall(&mut result as *mut c_int,
-                                  &mut error as *mut c_int,
-                                  sockfd,
-                                  how);
+    let status = u_shutdown_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        sockfd,
+        how,
+    );
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn getaddrinfo(node: *const c_char,
-                          service: *const c_char,
-                          hints: *const addrinfo,
-                          res: *mut *mut addrinfo) -> c_int {
+// exchange only struct sockaddr *ai_addr; information across the boundary
+// information filtering by hint is also not supported
+pub unsafe fn getaddrinfo(
+    node: Option<&CStr>,
+    service: Option<&CStr>,
+    hints: Option<AddrInfoHints>,
+) -> OCallResult<Vec<SockAddr>> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let mut ret_res: *mut addrinfo = ptr::null_mut();
-    let hint: addrinfo = if !hints.is_null() {
-        addrinfo {
-            ai_flags: (*hints).ai_flags,
-            ai_family: (*hints).ai_family,
-            ai_socktype: (*hints).ai_socktype,
-            ai_protocol: (*hints).ai_protocol,
-            ai_addrlen: 0,
-            ai_addr: ptr::null_mut(),
-            ai_canonname: ptr::null_mut(),
-            ai_next: ptr::null_mut(),
-        }
-    } else {
-        addrinfo {
-            ai_flags: AI_V4MAPPED | AI_ADDRCONFIG,
-            ai_family: AF_UNSPEC,
-            ai_socktype: 0,
-            ai_protocol: 0,
-            ai_addrlen: 0,
-            ai_addr: ptr::null_mut(),
-            ai_canonname: ptr::null_mut(),
-            ai_next: ptr::null_mut(),
-        }
-    };
 
-    let status = u_getaddrinfo_ocall(&mut result as *mut c_int,
-                                     &mut error as *mut c_int,
-                                     node,
-                                     service,
-                                     &hint as *const addrinfo,
-                                     &mut ret_res as *mut *mut addrinfo);
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == 0 {
-            *res = ptr::null_mut();
-            let mut cur_ptr: *mut addrinfo = ret_res;
-            let mut addrinfo_vec: Vec<Box<addrinfo>> = Vec::new();
-            while cur_ptr != ptr::null_mut() {
-                let cur: &addrinfo = &*cur_ptr;
-                let mut info = addrinfo {
-                    ai_flags: cur.ai_flags,
-                    ai_family: cur.ai_family,
-                    ai_socktype: cur.ai_socktype,
-                    ai_protocol: cur.ai_protocol,
-                    ai_addrlen: 0,
-                    ai_addr: ptr::null_mut(),
-                    ai_canonname: ptr::null_mut(),
-                    ai_next: ptr::null_mut(),
-                };
-
-                if !cur.ai_addr.is_null() && cur.ai_addrlen > 0 {
-                    let mut addr_vec = vec![0u8; cur.ai_addrlen as usize];
-                    let addr_slice: &[u8] = slice::from_raw_parts(cur.ai_addr as *const u8, cur.ai_addrlen as usize);
-                    addr_vec.copy_from_slice(addr_slice);
-                    addr_vec.shrink_to_fit();
-                    info.ai_addrlen = cur.ai_addrlen;
-                    info.ai_addr = addr_vec.as_mut_ptr() as *mut sockaddr;
-                    mem::forget(addr_vec);
-                }
-
-                if !cur.ai_canonname.is_null() {
-                    let len: usize = strlen(cur.ai_canonname) + 1;
-                    let mut name_vec = vec![0u8; len];
-                    let name_slice: &[u8] = slice::from_raw_parts(cur.ai_canonname as *const u8, len);
-                    name_vec.copy_from_slice(name_slice);
-                    name_vec.shrink_to_fit();
-                    info.ai_canonname = name_vec.as_mut_ptr() as *mut c_char;
-                    mem::forget(name_vec);
-                }
-
-                addrinfo_vec.push(Box::new(info));
-                cur_ptr = cur.ai_next;
-            }
+    let entry_size = cmp::max(
+        mem::size_of::<sockaddr_in6>(),
+        mem::size_of::<sockaddr_in>(),
+    );
 
-            if addrinfo_vec.len() > 0 {
-                for i in 0..addrinfo_vec.len() - 1 {
-                    addrinfo_vec[i].ai_next = addrinfo_vec[i + 1].as_mut() as *mut addrinfo;
-                }
-                let res_ptr = addrinfo_vec[0].as_mut() as *mut addrinfo;
+    let entry_count = 32;
+    let buf_sz = entry_size * entry_count;
 
-                for info in addrinfo_vec {
-                    let _ = Box::into_raw(info);
-                }
-                *res = res_ptr;
-            }
-            let _ = u_freeaddrinfo_ocall(ret_res);
+    let mut buffer = vec![0u8; buf_sz];
+    let mut out_count = 0usize;
 
-        } else if result == EAI_SYSTEM {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = EAI_SYSTEM;
-    }
-    result
-}
+    let node_ptr = match node {
+        Some(n) => n.as_ptr(),
+        None => ptr::null(),
+    };
 
-pub unsafe fn freeaddrinfo(res: *mut addrinfo ) {
-    let mut cur_ptr: *mut addrinfo = res;
-    let mut addrinfo_vec: Vec<Box<addrinfo>> = Vec::new();
-    while cur_ptr != ptr::null_mut() {
-        let cur: &addrinfo = &*cur_ptr;
-        if !cur.ai_addr.is_null() && cur.ai_addrlen > 0 {
-            let addr_vec = Vec::from_raw_parts(cur.ai_addr as *mut u8, cur.ai_addrlen as usize, cur.ai_addrlen as usize);
-            drop(addr_vec);
-        }
-        if !cur.ai_canonname.is_null() {
-            let len: usize = strlen(cur.ai_canonname) + 1;
-            let name_vec = Vec::from_raw_parts(cur.ai_canonname as *mut u8, len, len);
-            drop(name_vec);
+    let service_ptr = match service {
+        Some(s) => s.as_ptr(),
+        None => ptr::null(),
+    };
+
+    let hints = hints.map(|h| h.to_addrinfo());
+    let hints_ptr = match &hints {
+        Some(h) => h,
+        None => ptr::null(),
+    };
+
+    let status = u_getaddrinfo_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        node_ptr,
+        service_ptr,
+        hints_ptr,
+        entry_size,
+        buffer.as_mut_ptr() as *mut u8,
+        buf_sz,
+        &mut out_count as *mut size_t,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    match result {
+        0 => {}
+        EAI_SYSTEM => return Err(eos!(error)),
+        1 => return Err(ecust!("Untrusted side error")),
+        e => return Err(egai!(e)),
+    };
+
+    ensure!(result == 0, ecust!("Unkonwn error"));
+    ensure!(out_count <= entry_count, ecust!("Malformed out_count"));
+
+    let mut addr_vec = Vec::<SockAddr>::with_capacity(out_count);
+    let mut cur_ptr = buffer.as_ptr() as *const u8;
+    for _ in 0..out_count {
+        let family: *const sa_family_t = mem::transmute(cur_ptr);
+        match *family as i32 {
+            AF_INET => {
+                let sockaddr: *const sockaddr_in = mem::transmute(cur_ptr);
+                addr_vec.push(SockAddr::IN4(*sockaddr))
+            }
+            AF_INET6 => {
+                let sockaddr: *const sockaddr_in6 = mem::transmute(cur_ptr);
+                addr_vec.push(SockAddr::IN6(*sockaddr))
+            }
+            _ => bail!(ecust!("Unsupported family info")),
         }
-        addrinfo_vec.push(Box::from_raw(cur_ptr));
-        cur_ptr = cur.ai_next;
+        cur_ptr = cur_ptr.add(entry_size);
     }
-    drop(addrinfo_vec);
+    Ok(addr_vec)
 }
 
-pub unsafe fn gai_strerror(errcode: c_int) -> *const c_char {
-    let mut result: *const c_char = ptr::null();
-    let status = u_gai_strerror_ocall(&mut result as *mut *const c_char, errcode);
-    if status != sgx_status_t::SGX_SUCCESS {
-        set_errno(ESGX);
-    }
-    result
-}
+pub unsafe fn poll(fds: &mut [pollfd], timeout: c_int) -> OCallResult<PolledOk> {
+    let nfds = fds.len() as u64;
 
-pub unsafe fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_poll_ocall(&mut result as *mut c_int,
-                              &mut error as *mut c_int,
-                              fds,
-                              nfds,
-                              timeout);
+    let status = u_poll_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        fds.as_mut_ptr(),
+        nfds,
+        timeout,
+    );
 
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    match result {
+        1..=i32::MAX => {
+            if result as u64 > nfds {
+                Err(ecust!("Malformed return value"))
+            } else {
+                Ok(PolledOk::ReadyDescsCount(result as usize))
+            }
         }
-    } else {
-        set_errno(ESGX);
-        result = -1;
+        0 => Ok(PolledOk::TimeLimitExpired),
+        _ => Err(eos!(error)),
     }
-    result
 }
 
-pub unsafe fn epoll_create1(flags: c_int) -> c_int {
+pub unsafe fn epoll_create1(flags: c_int) -> OCallResult<c_int> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_epoll_create1_ocall(&mut result as *mut c_int,
-                                       &mut error as *mut c_int,
-                                       flags);
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+
+    let status = u_epoll_create1_ocall(&mut result as *mut c_int, &mut error as *mut c_int, flags);
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+
+    Ok(result)
 }
 
-pub unsafe fn epoll_ctl(epfd: c_int,
-                        op: c_int,
-                        fd: c_int,
-                        event: *mut epoll_event) -> c_int {
+pub unsafe fn epoll_ctl(
+    epfd: c_int,
+    op: c_int,
+    fd: c_int,
+    event: &mut epoll_event,
+) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_epoll_ctl_ocall(&mut result as *mut c_int,
-                                   &mut error as *mut c_int,
-                                   epfd,
-                                   op,
-                                   fd,
-                                   event);
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+
+    let status = u_epoll_ctl_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        epfd,
+        op,
+        fd,
+        event,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+
+    Ok(())
 }
 
-pub unsafe fn epoll_wait(epfd: c_int,
-                         events: *mut epoll_event,
-                         maxevents: c_int,
-                         timeout: c_int) -> c_int {
+pub unsafe fn epoll_wait(
+    epfd: c_int,
+    events: &mut Vec<epoll_event>,
+    timeout: c_int,
+) -> OCallResult<usize> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_epoll_wait_ocall(&mut result as *mut c_int,
-                                    &mut error as *mut c_int,
-                                    epfd,
-                                    events,
-                                    maxevents,
-                                    timeout);
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+    let maxevents: c_int = events.capacity() as c_int;
+    ensure!(maxevents > 0, ecust!("Invalid events capacity"));
+
+    let status = u_epoll_wait_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        epfd,
+        events.as_mut_ptr(),
+        maxevents,
+        timeout,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    ensure!(result <= maxevents, ecust!("Malformed event count"));
+
+    events.set_len(result as usize);
+    Ok(result as usize)
 }
 
-pub unsafe fn sysconf(name: c_int) -> c_long {
+pub unsafe fn sysconf(name: c_int) -> OCallResult<c_long> {
     let mut result: c_long = 0;
     let mut error: c_int = 0;
-    let status = u_sysconf_ocall(&mut result as *mut c_long,
-                                 &mut error as *mut c_int,
-                                 name);
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+
+    let status = u_sysconf_ocall(&mut result as *mut c_long, &mut error as *mut c_int, name);
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    Ok(result)
 }
 
-pub unsafe fn prctl(option: c_int,
-                    arg2: c_ulong,
-                    arg3: c_ulong,
-                    arg4: c_ulong,
-                    arg5: c_ulong) -> c_int {
+pub unsafe fn prctl(
+    option: c_int,
+    arg2: c_ulong,
+    arg3: c_ulong,
+    arg4: c_ulong,
+    arg5: c_ulong,
+) -> OCallResult<c_int> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_prctl_ocall(&mut result as *mut c_int,
-                               &mut error as *mut c_int,
-                               option,
-                               arg2,
-                               arg3,
-                               arg4,
-                               arg5);
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+
+    let status = u_prctl_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        option,
+        arg2,
+        arg3,
+        arg4,
+        arg5,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result >= 0, eos!(error));
+    Ok(result)
 }
 
-pub unsafe fn sched_setaffinity(pid: pid_t, cpusetsize: size_t, mask: *const cpu_set_t) -> c_int {
+pub unsafe fn pipe2(fds: &mut [c_int; 2], flags: c_int) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_sched_setaffinity_ocall(&mut result as *mut c_int,
-                                           &mut error as *mut c_int,
-                                           pid,
-                                           cpusetsize,
-                                           mask);
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+
+    let status = u_pipe2_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        fds.as_mut_ptr(),
+        flags,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
 }
 
-pub unsafe fn sched_getaffinity(pid: pid_t, cpusetsize: size_t, mask: *mut cpu_set_t) -> c_int {
+pub unsafe fn sched_yield() -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_sched_getaffinity_ocall(&mut result as *mut c_int,
-                                           &mut error as *mut c_int,
-                                           pid,
-                                           cpusetsize,
-                                           mask);
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
-    }
-    result
+
+    let status = u_sched_yield_ocall(&mut result as *mut c_int, &mut error as *mut c_int);
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    ensure!(result == 0, eos!(error));
+    Ok(())
+}
+
+pub unsafe fn getpid() -> OCallResult<pid_t> {
+    let mut result = -1;
+
+    let status = u_getpid_ocall(&mut result as *mut pid_t);
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+    Ok(result)
 }
 
-pub unsafe fn pipe(fds: *mut c_int) -> c_int {
+pub unsafe fn nanosleep(req: &mut timespec) -> OCallResult<()> {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_pipe_ocall(&mut result as *mut c_int,
-                              &mut error as *mut c_int,
-                              fds);
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
-        result = -1;
+
+    let mut rem = req.clone();
+
+    let status = u_nanosleep_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        req,
+        &mut rem,
+    );
+
+    ensure!(status == sgx_status_t::SGX_SUCCESS, esgx!(status));
+
+    ensure!(rem.tv_sec <= req.tv_sec, ecust!("Malformed remaining time"));
+    if rem.tv_sec == req.tv_sec {
+        ensure!(
+            rem.tv_nsec < req.tv_nsec,
+            ecust!("Malformed remaining time")
+        );
     }
-    result
+
+    req.tv_sec = rem.tv_sec;
+    req.tv_nsec = rem.tv_nsec;
+
+    ensure!(result == 0, eos!(error));
+
+    req.tv_sec = 0;
+    req.tv_nsec = 0;
+    Ok(())
 }
 
-pub unsafe fn pipe2(fds: *mut c_int, flags: c_int) -> c_int {
+pub unsafe fn sigaction(
+    signum: c_int,
+    act: *const sigaction,
+    oldact: *mut sigaction,
+    enclave_id: uint64_t,
+) -> c_int {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_pipe2_ocall(&mut result as *mut c_int,
-                               &mut error as *mut c_int,
-                               fds,
-                               flags);
+
+    let status = u_sigaction_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        signum,
+        act,
+        oldact,
+        enclave_id,
+    );
+
     if status == sgx_status_t::SGX_SUCCESS {
         if result == -1 {
             set_errno(error);
@@ -2930,11 +2250,18 @@ pub unsafe fn pipe2(fds: *mut c_int, flags: c_int) -> c_int {
     result
 }
 
-pub unsafe fn sched_yield() -> c_int {
+pub unsafe fn sigprocmask(signum: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_sched_yield_ocall(&mut result as *mut c_int,
-                                     &mut error as *mut c_int);
+
+    let status = u_sigprocmask_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        signum,
+        set,
+        oldset,
+    );
+
     if status == sgx_status_t::SGX_SUCCESS {
         if result == -1 {
             set_errno(error);
@@ -2946,36 +2273,33 @@ pub unsafe fn sched_yield() -> c_int {
     result
 }
 
-pub unsafe fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
-    let mut result: c_int = 0;
-    let mut error: c_int = 0;
-    let status = u_nanosleep_ocall(&mut result as *mut c_int,
-                                   &mut error as *mut c_int,
-                                   rqtp,
-                                   rmtp);
-    if status == sgx_status_t::SGX_SUCCESS {
-        if result == -1 {
-            set_errno(error);
-        }
-    } else {
-        set_errno(ESGX);
+pub unsafe fn raise(signum: c_int) -> c_int {
+    let mut result: c_int = -1;
+
+    let status = u_raise_ocall(&mut result as *mut c_int, signum);
+
+    if status != sgx_status_t::SGX_SUCCESS {
         result = -1;
     }
     result
 }
 
-pub unsafe fn sigaction(signum: c_int,
-                        act: *const sigaction,
-                        oldact: *mut sigaction,
-                        enclave_id: uint64_t) -> c_int {
+pub unsafe fn pthread_sigmask(signum: c_int, set: &sigset_t, oldset: &mut sigset_t) -> c_int {
+    sigprocmask(signum, set, oldset)
+}
+
+pub unsafe fn sched_setaffinity(pid: pid_t, cpusetsize: size_t, mask: *const cpu_set_t) -> c_int {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status = u_sigaction_ocall(&mut result as *mut c_int,
-                                   &mut error as *mut c_int,
-                                   signum,
-                                   act,
-                                   oldact,
-                                   enclave_id);
+
+    let status = u_sched_setaffinity_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        pid,
+        cpusetsize,
+        mask,
+    );
+
     if status == sgx_status_t::SGX_SUCCESS {
         if result == -1 {
             set_errno(error);
@@ -2987,16 +2311,18 @@ pub unsafe fn sigaction(signum: c_int,
     result
 }
 
-pub unsafe fn sigprocmask(signum: c_int,
-                          set: *const sigset_t,
-                          oldset: *mut sigset_t) -> c_int {
+pub unsafe fn sched_getaffinity(pid: pid_t, cpusetsize: size_t, mask: &mut cpu_set_t) -> c_int {
     let mut result: c_int = 0;
     let mut error: c_int = 0;
-    let status =  u_sigprocmask_ocall(&mut result as *mut c_int,
-                                      &mut error as *mut c_int,
-                                      signum,
-                                      set,
-                                      oldset);
+
+    let status = u_sched_getaffinity_ocall(
+        &mut result as *mut c_int,
+        &mut error as *mut c_int,
+        pid,
+        cpusetsize,
+        mask,
+    );
+
     if status == sgx_status_t::SGX_SUCCESS {
         if result == -1 {
             set_errno(error);
@@ -3007,25 +2333,3 @@ pub unsafe fn sigprocmask(signum: c_int,
     }
     result
 }
-
-pub unsafe fn raise(signum: c_int) -> c_int {
-    let mut result: c_int = -1;
-    let status = u_raise_ocall(&mut result as *mut c_int, signum);
-    if status != sgx_status_t::SGX_SUCCESS {
-       result = -1;
-    }
-    result
-}
-
-pub unsafe fn pthread_sigmask(signum: c_int, set: &sigset_t, oldset: &mut sigset_t) -> c_int {
-    sigprocmask(signum, set, oldset)
-}
-
-pub unsafe fn getpid() -> pid_t {
-    let mut result = -1;
-    let status = u_getpid_ocall(&mut result as *mut pid_t);
-    if status != sgx_status_t::SGX_SUCCESS {
-        result = -1;
-    }
-    result
-}
diff --git a/sgx_libc/src/macros.rs b/sgx_libc/src/macros.rs
index e105de9..c40bb05 100644
--- a/sgx_libc/src/macros.rs
+++ b/sgx_libc/src/macros.rs
@@ -161,3 +161,46 @@ macro_rules! align_const {
         };
     )*)
 }
+
+macro_rules! bail {
+    ($e:expr) => {
+        return Err($e);
+    };
+}
+
+macro_rules! ensure {
+    ($cond:expr) => {
+        if !($cond) {
+            bail!(OCallError::from_custom_error(stringify!($cond)));
+        }
+    };
+    ($cond:expr, $e:expr) => {
+        if !($cond) {
+            bail!($e);
+        }
+    };
+}
+
+macro_rules! esgx {
+    ($status:ident) => {
+        OCallError::from_sgx_error($status)
+    };
+}
+
+macro_rules! eos {
+    ($errno:ident) => {
+        OCallError::from_os_error($errno)
+    };
+}
+
+macro_rules! ecust {
+    ($lt:literal) => {
+        OCallError::from_custom_error($lt)
+    };
+}
+
+macro_rules! egai {
+    ($errno:ident) => {
+        OCallError::from_gai_error($errno)
+    };
+}
diff --git a/sgx_trts/src/memchr.rs b/sgx_libc/src/memchr.rs
similarity index 65%
rename from sgx_trts/src/memchr.rs
rename to sgx_libc/src/memchr.rs
index ea27c07..d6bec9d 100644
--- a/sgx_trts/src/memchr.rs
+++ b/sgx_libc/src/memchr.rs
@@ -15,6 +15,8 @@
 // specific language governing permissions and limitations
 // under the License..
 
+use core::ptr;
+
 /// A safe interface to `memchr`.
 ///
 /// Returns the index corresponding to the first occurrence of `needle` in
@@ -36,7 +38,12 @@
 // }
 
 pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-    let p = unsafe { sgx_libc::memchr(haystack.as_ptr(), needle, haystack.len()) };
+    let p = unsafe {
+        memchr_impl(
+            haystack.as_ptr(),
+            needle,
+            haystack.len())
+    };
     if p.is_null() {
         None
     } else {
@@ -44,19 +51,50 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
     }
 }
 
+unsafe fn memchr_impl(s: *const u8, c: u8, n: usize) -> *const u8 {
+    let mut ret = ptr::null();
+    let mut p = s;
+    for _ in 0..n {
+        if *p == c {
+            ret = p;
+            break;
+        }
+        p = p.offset(1);
+    }
+    ret
+}
+
 pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
     fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
         // GNU's memrchr() will - unlike memchr() - error if haystack is empty.
         if haystack.is_empty() {
             return None;
         }
-        let p = unsafe { sgx_libc::memrchr(haystack.as_ptr(), needle, haystack.len()) };
-        if p.is_null() {
-            None
-        } else {
-            Some(p as usize - (haystack.as_ptr() as usize))
-        }
+        let p = unsafe {
+            memrchr_impl(
+                haystack.as_ptr(),
+                needle,
+                haystack.len(),
+            )
+        };
+        if p.is_null() { None } else { Some(p as usize - (haystack.as_ptr() as usize)) }
     }
 
     memrchr_specific(needle, haystack)
 }
+
+unsafe fn memrchr_impl(s: *const u8, c: u8, n: usize) -> *const u8 {
+    if n == 0 {
+        return ptr::null();
+    }
+    let mut ret = ptr::null();
+    let mut p: *const u8 = (s as usize + (n - 1)) as *const u8;
+    for _ in 0..n {
+        if *p == c {
+            ret = p;
+            break;
+        }
+        p = p.offset(-1);
+    }
+    ret
+}
diff --git a/sgx_trts/src/lib.rs b/sgx_trts/src/lib.rs
index e22093d..7e2f02a 100644
--- a/sgx_trts/src/lib.rs
+++ b/sgx_trts/src/lib.rs
@@ -67,7 +67,6 @@
 
 #![feature(allocator_api)]
 #![feature(asm)]
-#![feature(const_raw_ptr_deref)]
 #![allow(non_camel_case_types)]
 #![allow(non_upper_case_globals)]
 #![allow(non_snake_case)]
@@ -86,12 +85,9 @@ extern crate alloc;
 #[macro_use]
 mod macros;
 
-pub mod ascii;
-pub mod c_str;
 pub mod cpu_feature;
 pub mod cpuid;
 pub mod enclave;
-pub mod memchr;
 pub mod memeq;
 pub mod oom;
 pub mod trts;
@@ -105,6 +101,10 @@ pub mod libc {
     pub use sgx_libc::*;
 }
 
+pub use libc::c_str;
+pub use libc::ascii;
+pub use libc::memchr;
+
 pub mod error {
     pub use sgx_libc::{errno, error_string, set_errno};
 }
diff --git a/sgx_tstd/src/io/error.rs b/sgx_tstd/src/io/error.rs
index 1f1ccaf..9b4f2ef 100644
--- a/sgx_tstd/src/io/error.rs
+++ b/sgx_tstd/src/io/error.rs
@@ -15,15 +15,14 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use sgx_types::sgx_status_t;
 use crate::error;
 use crate::sys;
+use alloc_crate::boxed::Box;
+use alloc_crate::str;
+use core::convert::From;
 use core::fmt;
 use core::result;
-use core::convert::From;
-use alloc_crate::str;
-use alloc_crate::boxed::Box;
-
+use sgx_types::sgx_status_t;
 
 /// A specialized [`Result`](../result/enum.Result.html) type for I/O
 /// operations.
@@ -188,14 +187,30 @@ impl From<ErrorKind> for Error {
     ///
     #[inline]
     fn from(kind: ErrorKind) -> Error {
-        Error { repr: Repr::Simple(kind) }
+        Error {
+            repr: Repr::Simple(kind),
+        }
     }
 }
 
 impl From<sgx_status_t> for Error {
     #[inline]
     fn from(status: sgx_status_t) -> Error {
-        Error { repr: Repr::SgxStatus(status) }
+        Error {
+            repr: Repr::SgxStatus(status),
+        }
+    }
+}
+
+use sgx_libc::OCallError;
+impl From<OCallError> for Error {
+    fn from(e: OCallError) -> Error {
+        match e {
+            OCallError::SgxError(status) => Error::from_sgx_error(status),
+            OCallError::OsError(errno) => Error::from_raw_os_error(errno),
+            OCallError::GaiError(errno) => Error::new(ErrorKind::Other, sgx_libc::gai_error_str(errno)),
+            OCallError::CustomError(err) => Error::new(ErrorKind::Other, err),
+        }
     }
 }
 
@@ -215,7 +230,9 @@ impl Error {
     }
 
     fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
-        Error { repr: Repr::Custom(Box::new(Custom { kind, error })) }
+        Error {
+            repr: Repr::Custom(Box::new(Custom { kind, error })),
+        }
     }
 
     /// Returns an error representing the last OS error which occurred.
@@ -231,7 +248,9 @@ impl Error {
     /// Creates a new instance of an `Error` from a particular OS error code.
     ///
     pub fn from_raw_os_error(code: i32) -> Error {
-        Error { repr: Repr::Os(code) }
+        Error {
+            repr: Repr::Os(code),
+        }
     }
 
     /// Returns the OS error that this error represents (if any).
@@ -252,7 +271,9 @@ impl Error {
     /// Creates a new instance of an `Error` from a particular SGX error status.
     ///
     pub fn from_sgx_error(status: sgx_status_t) -> Error {
-        Error { repr: Repr::SgxStatus(status) }
+        Error {
+            repr: Repr::SgxStatus(status),
+        }
     }
 
     /// Returns the SGX error that this error represents (if any).
@@ -275,7 +296,7 @@ impl Error {
     /// If this `Error` was constructed via `new` then this function will
     /// return `Some`, otherwise it will return `None`.
     ///
-    pub fn get_ref(&self) -> Option<&(dyn error::Error+Send+Sync+'static)> {
+    pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> {
         match self.repr {
             Repr::Os(..) => None,
             Repr::Simple(..) => None,
@@ -392,7 +413,7 @@ impl error::Error for Error {
 }
 
 fn _assert_error_is_sync_send() {
-    fn _is_sync_send<T: Sync+Send>() {}
+    fn _is_sync_send<T: Sync + Send>() {}
     _is_sync_send::<Error>();
 }
 
@@ -400,4 +421,4 @@ impl error::Error for sgx_status_t {
     fn description(&self) -> &str {
         self.__description()
     }
-}
\ No newline at end of file
+}
diff --git a/sgx_tstd/src/net/addr.rs b/sgx_tstd/src/net/addr.rs
index a4dbc4f..b57030a 100644
--- a/sgx_tstd/src/net/addr.rs
+++ b/sgx_tstd/src/net/addr.rs
@@ -15,21 +15,22 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use sgx_trts::libc as c;
-use core::fmt;
-use core::hash;
-use core::mem;
-use core::option;
-use core::iter;
-#[cfg(feature = "net")]
-use core::convert::TryInto;
-use alloc_crate::vec;
-use alloc_crate::slice;
 use crate::io;
 use crate::net::{htons, ntohs, IpAddr, Ipv4Addr, Ipv6Addr};
-use crate::sys_common::{AsInner, FromInner, IntoInner};
 #[cfg(feature = "net")]
 use crate::sys_common::net::LookupHost;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use alloc_crate::slice;
+use alloc_crate::vec;
+#[cfg(feature = "net")]
+use core::convert::TryInto;
+use core::convert::TryFrom;
+use core::fmt;
+use core::hash;
+use core::iter;
+use core::mem;
+use core::option;
+use sgx_trts::libc as c;
 
 /// An internet socket address, either IPv4 or IPv6.
 ///
@@ -319,12 +320,47 @@ impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
 impl<'a> IntoInner<(*const c::sockaddr, c::socklen_t)> for &'a SocketAddr {
     fn into_inner(self) -> (*const c::sockaddr, c::socklen_t) {
         match *self {
-            SocketAddr::V4(ref a) => {
-                (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t)
-            }
-            SocketAddr::V6(ref a) => {
-                (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t)
-            }
+            SocketAddr::V4(ref a) => (
+                a as *const _ as *const _,
+                mem::size_of_val(a) as c::socklen_t,
+            ),
+            SocketAddr::V6(ref a) => (
+                a as *const _ as *const _,
+                mem::size_of_val(a) as c::socklen_t,
+            ),
+        }
+    }
+}
+
+impl IntoInner<c::sockaddr_in> for SocketAddrV4 {
+    fn into_inner(self) -> c::sockaddr_in {
+        self.inner
+    }
+}
+
+impl IntoInner<c::sockaddr_in6> for SocketAddrV6 {
+    fn into_inner(self) -> c::sockaddr_in6 {
+        self.inner
+    }
+}
+
+impl From<SocketAddr> for c::SockAddr {
+    fn from(addr: SocketAddr) -> c::SockAddr {
+        match addr {
+            SocketAddr::V4(sa) => c::SockAddr::IN4(sa.into_inner()),
+            SocketAddr::V6(sa) => c::SockAddr::IN6(sa.into_inner()),
+        }
+    }
+}
+
+impl TryFrom<c::SockAddr> for SocketAddr {
+    type Error = io::Error;
+
+    fn try_from(addr: c::SockAddr) -> io::Result<SocketAddr> {
+        match addr {
+            c::SockAddr::IN4(sa) => Ok(SocketAddr::V4(SocketAddrV4::from_inner(sa))),
+            c::SockAddr::IN6(sa) => Ok(SocketAddr::V6(SocketAddrV6::from_inner(sa))),
+            _ => Err(io::Error::new(io::ErrorKind::InvalidData, "Unsupported SocketAddr")),
         }
     }
 }
@@ -548,7 +584,10 @@ impl ToSocketAddrs for (&str, u16) {
         }
 
         #[cfg(not(feature = "net"))]
-        let r = Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid socket address"));
+        let r = Err(io::Error::new(
+            io::ErrorKind::InvalidInput,
+            "invalid socket address",
+        ));
         #[cfg(feature = "net")]
         let r = resolve_socket_addr((host, port).try_into()?);
         r
@@ -565,7 +604,10 @@ impl ToSocketAddrs for str {
         }
 
         #[cfg(not(feature = "net"))]
-        let r = Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid socket address"));
+        let r = Err(io::Error::new(
+            io::ErrorKind::InvalidInput,
+            "invalid socket address",
+        ));
         #[cfg(feature = "net")]
         let r = resolve_socket_addr(self.try_into()?);
         r
@@ -592,4 +634,4 @@ impl ToSocketAddrs for String {
     fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
         (&**self).to_socket_addrs()
     }
-}
\ No newline at end of file
+}
diff --git a/sgx_tstd/src/sys/ext/net.rs b/sgx_tstd/src/sys/ext/net.rs
index 65c3249..620ff0e 100644
--- a/sgx_tstd/src/sys/ext/net.rs
+++ b/sgx_tstd/src/sys/ext/net.rs
@@ -15,8 +15,6 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use core::mem;
-use core::fmt;
 use crate::ascii;
 use crate::ffi::OsStr;
 use crate::io::{self, Initializer, IoSlice, IoSliceMut};
@@ -24,10 +22,13 @@ use crate::net::{self, Shutdown};
 use crate::os::unix::ffi::OsStrExt;
 use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
 use crate::path::Path;
-use crate::time::Duration;
-use crate::sys::{self, cvt};
 use crate::sys::net::Socket;
+use crate::sys::{self, cvt_ocall};
 use crate::sys_common::{self, AsInner, FromInner, IntoInner};
+use crate::time::Duration;
+use core::convert::{TryFrom, TryInto};
+use core::fmt;
+use core::mem;
 
 fn sun_path_offset(addr: &libc::sockaddr_un) -> usize {
     // Work with an actual instance of the type since using a null pointer is UB
@@ -86,14 +87,10 @@ pub struct SocketAddr {
 impl SocketAddr {
     fn new<F>(f: F) -> io::Result<SocketAddr>
     where
-        F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int,
+        F: FnOnce() -> libc::OCallResult<libc::SockAddr>,
     {
-        unsafe {
-            let mut addr: libc::sockaddr_un = mem::zeroed();
-            let mut len = mem::size_of::<libc::sockaddr_un>() as libc::socklen_t;
-            cvt(f(&mut addr as *mut _ as *mut _, &mut len))?;
-            SocketAddr::from_parts(addr, len)
-        }
+        let addr = cvt_ocall(f())?;
+        addr.try_into()
     }
 
     fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result<SocketAddr> {
@@ -114,13 +111,21 @@ impl SocketAddr {
     /// Returns `true` if the address is unnamed.
     ///
     pub fn is_unnamed(&self) -> bool {
-        if let AddressKind::Unnamed = self.address() { true } else { false }
+        if let AddressKind::Unnamed = self.address() {
+            true
+        } else {
+            false
+        }
     }
 
     /// Returns the contents of this address if it is a `pathname` address.
     ///
     pub fn as_pathname(&self) -> Option<&Path> {
-        if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None }
+        if let AddressKind::Pathname(path) = self.address() {
+            Some(path)
+        } else {
+            None
+        }
     }
 
     fn address(&self) -> AddressKind<'_> {
@@ -128,8 +133,7 @@ impl SocketAddr {
         let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
 
         // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses
-        if len == 0
-        {
+        if len == 0 {
             AddressKind::Unnamed
         } else if self.addr.sun_path[0] == 0 {
             AddressKind::Abstract(&path[1..len])
@@ -149,6 +153,20 @@ impl fmt::Debug for SocketAddr {
     }
 }
 
+impl TryFrom<libc::SockAddr> for SocketAddr {
+    type Error = io::Error;
+
+    fn try_from(addr: libc::SockAddr) -> io::Result<SocketAddr> {
+        match addr {
+            libc::SockAddr::UN((sa, len)) => SocketAddr::from_parts(sa, len),
+            _ => Err(io::Error::new(
+                io::ErrorKind::InvalidData,
+                "Unsupported SocketAddr",
+            )),
+        }
+    }
+}
+
 struct AsciiEscaped<'a>(&'a [u8]);
 
 impl<'a> fmt::Display for AsciiEscaped<'a> {
@@ -186,9 +204,9 @@ impl UnixStream {
         fn inner(path: &Path) -> io::Result<UnixStream> {
             unsafe {
                 let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
-                let (addr, len) = sockaddr_un(path)?;
+                let addr = libc::SockAddr::UN(sockaddr_un(path)?);
 
-                cvt(libc::connect(*inner.as_inner(), &addr as *const _ as *const _, len))?;
+                cvt_ocall(libc::connect(*inner.as_inner(), &addr))?;
                 Ok(UnixStream(inner))
             }
         }
@@ -218,13 +236,13 @@ impl UnixStream {
     /// Returns the socket address of the local half of this connection.
     ///
     pub fn local_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
+        SocketAddr::new(|| unsafe { libc::getsockname(*self.0.as_inner()) })
     }
 
     /// Returns the socket address of the remote half of this connection.
     ///
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
+        SocketAddr::new(|| unsafe { libc::getpeername(*self.0.as_inner()) })
     }
 
     /// Sets the read timeout for the socket.
@@ -450,9 +468,10 @@ impl UnixListener {
             unsafe {
                 let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
                 let (addr, len) = sockaddr_un(path)?;
+                let sock_addr = libc::SockAddr::UN((addr, len));
 
-                cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?;
-                cvt(libc::listen(*inner.as_inner(), 128))?;
+                cvt_ocall(libc::bind(*inner.as_inner(), &sock_addr))?;
+                cvt_ocall(libc::listen(*inner.as_inner(), 128))?;
 
                 Ok(UnixListener(inner))
             }
@@ -467,11 +486,9 @@ impl UnixListener {
     /// the remote peer's address will be returned.
     ///
     pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
-        let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() };
-        let mut len = mem::size_of_val(&storage) as libc::socklen_t;
-        let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?;
-        let addr = SocketAddr::from_parts(storage, len)?;
-        Ok((UnixStream(sock), addr))
+        let (sock, addr) = self.0.accept()?;
+        let sa = addr.try_into()?;
+        Ok((UnixStream(sock), sa))
     }
 
     /// Creates a new independently owned handle to the underlying socket.
@@ -487,7 +504,7 @@ impl UnixListener {
     /// Returns the local socket address of this listener.
     ///
     pub fn local_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
+        SocketAddr::new(|| unsafe { libc::getsockname(*self.0.as_inner()) })
     }
 
     /// Moves the socket into or out of nonblocking mode.
@@ -592,8 +609,9 @@ impl UnixDatagram {
             unsafe {
                 let socket = UnixDatagram::unbound()?;
                 let (addr, len) = sockaddr_un(path)?;
+                let sock_addr = libc::SockAddr::UN((addr, len));
 
-                cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?;
+                cvt_ocall(libc::bind(*socket.0.as_inner(), &sock_addr))?;
 
                 Ok(socket)
             }
@@ -629,10 +647,8 @@ impl UnixDatagram {
     pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
         fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> {
             unsafe {
-                let (addr, len) = sockaddr_un(path)?;
-
-                cvt(libc::connect(*d.0.as_inner(), &addr as *const _ as *const _, len))?;
-
+                let addr = libc::SockAddr::UN(sockaddr_un(path)?);
+                cvt_ocall(libc::connect(*d.0.as_inner(), &addr))?;
                 Ok(())
             }
         }
@@ -652,7 +668,7 @@ impl UnixDatagram {
     /// Returns the address of this socket.
     ///
     pub fn local_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
+        SocketAddr::new(|| unsafe { libc::getsockname(*self.0.as_inner()) })
     }
 
     /// Returns the address of this socket's peer.
@@ -662,7 +678,7 @@ impl UnixDatagram {
     /// [`connect`]: #method.connect
     ///
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
+        SocketAddr::new(|| unsafe { libc::getpeername(*self.0.as_inner()) })
     }
 
     /// Receives data from the socket.
@@ -671,26 +687,11 @@ impl UnixDatagram {
     /// whence the data came.
     ///
     pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        let mut count = 0;
-        let addr = SocketAddr::new(|addr, len| unsafe {
-            count = libc::recvfrom(
-                *self.0.as_inner(),
-                buf.as_mut_ptr() as *mut _,
-                buf.len(),
-                0,
-                addr,
-                len,
-            );
-            if count > 0 {
-                1
-            } else if count == 0 {
-                0
-            } else {
-                -1
-            }
-        })?;
-
-        Ok((count as usize, addr))
+        unsafe {
+            let (count, addr) = cvt_ocall(libc::recvfrom(*self.0.as_inner(), buf, 0))?;
+            let addr = addr.try_into()?;
+            Ok((count as usize, addr))
+        }
     }
 
     /// Receives data from the socket.
@@ -708,15 +709,13 @@ impl UnixDatagram {
     pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
         fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result<usize> {
             unsafe {
-                let (addr, len) = sockaddr_un(path)?;
+                let addr = libc::SockAddr::UN(sockaddr_un(path)?);
 
-                let count = cvt(libc::sendto(
+                let count = cvt_ocall(libc::sendto(
                     *d.0.as_inner(),
-                    buf.as_ptr() as *const _,
-                    buf.len(),
+                    buf,
                     libc::MSG_NOSIGNAL,
-                    &addr as *const _ as *const _,
-                    len,
+                    &addr,
                 ))?;
                 Ok(count as usize)
             }
@@ -820,6 +819,8 @@ impl IntoRawFd for UnixDatagram {
 }
 
 mod libc {
+    pub use sgx_trts::libc::ocall::{
+        bind, connect, getpeername, getsockname, listen, recvfrom, sendto,
+    };
     pub use sgx_trts::libc::*;
-    pub use sgx_trts::libc::ocall::{connect, listen, bind, sendto, recvfrom, getsockname, getpeername};
-}
\ No newline at end of file
+}
diff --git a/sgx_tstd/src/sys/fd.rs b/sgx_tstd/src/sys/fd.rs
index 430e86f..8b6f5f7 100644
--- a/sgx_tstd/src/sys/fd.rs
+++ b/sgx_tstd/src/sys/fd.rs
@@ -15,13 +15,13 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use sgx_trts::libc::{c_int, c_void, ssize_t};
-use core::cmp;
-use core::mem;
-use core::sync::atomic::{AtomicBool, Ordering};
 use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read};
-use crate::sys::cvt;
+use crate::sys::cvt_ocall;
 use crate::sys_common::AsInner;
+use core::mem;
+use core::sync::atomic::{AtomicBool, Ordering};
+use sgx_trts::libc::{c_int, ssize_t};
+use core::ops::{Deref, DerefMut};
 
 #[derive(Debug)]
 pub struct FileDesc {
@@ -61,18 +61,16 @@ impl FileDesc {
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
-        let ret = cvt(unsafe {
-            libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), max_len()))
-        })?;
+        let ret = cvt_ocall(unsafe { libc::read(self.fd, buf) })?;
         Ok(ret as usize)
     }
 
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        let ret = cvt(unsafe {
+        let vbufs: Vec<&mut [u8]> = bufs.iter_mut().map(|msl| msl.deref_mut()).collect();
+        let ret = cvt_ocall(unsafe {
             libc::readv(
                 self.fd,
-                bufs.as_ptr() as *const libc::iovec,
-                cmp::min(bufs.len(), c_int::max_value() as usize) as c_int,
+                vbufs
             )
         })?;
         Ok(ret as usize)
@@ -84,77 +82,41 @@ impl FileDesc {
     }
 
     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
-        unsafe fn cvt_pread64(
-            fd: c_int,
-            buf: *mut c_void,
-            count: usize,
-            offset: i64,
-        ) -> io::Result<isize> {
-            use libc::pread64;
-            cvt(pread64(fd, buf, count, offset))
-        }
-
-        unsafe {
-            cvt_pread64(
-                self.fd,
-                buf.as_mut_ptr() as *mut c_void,
-                cmp::min(buf.len(), max_len()),
-                offset as i64,
-            )
-            .map(|n| n as usize)
-        }
+        cvt_ocall(unsafe { libc::pread64(self.fd, buf, offset as i64) })
     }
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
-        let ret = cvt(unsafe {
-            libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), max_len()))
-        })?;
+        let ret = cvt_ocall(unsafe { libc::write(self.fd, buf) })?;
         Ok(ret as usize)
     }
 
     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let ret = cvt(unsafe {
+        let vbufs: Vec<&[u8]> = bufs.iter().map(|msl| msl.deref()).collect();
+        let ret = cvt_ocall(unsafe {
             libc::writev(
                 self.fd,
-                bufs.as_ptr() as *const libc::iovec,
-                cmp::min(bufs.len(), c_int::max_value() as usize) as c_int,
+                vbufs
             )
         })?;
         Ok(ret as usize)
     }
 
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
-        unsafe fn cvt_pwrite64(
-            fd: c_int,
-            buf: *const c_void,
-            count: usize,
-            offset: i64,
-        ) -> io::Result<isize> {
-            use libc::pwrite64;
-            cvt(pwrite64(fd, buf, count, offset))
-        }
-
-        unsafe {
-            cvt_pwrite64(
-                self.fd,
-                buf.as_ptr() as *const c_void,
-                cmp::min(buf.len(), max_len()),
-                offset as i64,
-            )
-            .map(|n| n as usize)
-        }
+        cvt_ocall(unsafe { libc::pwrite64(self.fd, buf, offset as i64) })
     }
 
     pub fn get_cloexec(&self) -> io::Result<bool> {
-        unsafe { Ok((cvt(libc::fcntl_arg0(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
+        unsafe {
+            Ok((cvt_ocall(libc::fcntl_arg0(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0)
+        }
     }
 
     pub fn set_cloexec(&self) -> io::Result<()> {
         unsafe {
-            let previous = cvt(libc::fcntl_arg0(self.fd, libc::F_GETFD))?;
+            let previous = cvt_ocall(libc::fcntl_arg0(self.fd, libc::F_GETFD))?;
             let new = previous | libc::FD_CLOEXEC;
             if new != previous {
-                cvt(libc::fcntl_arg1(self.fd, libc::F_SETFD, new))?;
+                cvt_ocall(libc::fcntl_arg1(self.fd, libc::F_SETFD, new))?;
             }
             Ok(())
         }
@@ -163,7 +125,11 @@ impl FileDesc {
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         unsafe {
             let mut v = nonblocking as c_int;
-            cvt(libc::ioctl_arg1(self.fd, libc::FIONBIO, &mut v as *mut c_int))?;
+            cvt_ocall(libc::ioctl_arg1(
+                self.fd,
+                libc::FIONBIO,
+                &mut v,
+            ))?;
             Ok(())
         }
     }
@@ -194,7 +160,7 @@ impl FileDesc {
         static TRY_CLOEXEC: AtomicBool = AtomicBool::new(!cfg!(target_os = "android"));
         let fd = self.raw();
         if TRY_CLOEXEC.load(Ordering::Relaxed) {
-            match cvt(unsafe { libc::fcntl_arg1(fd, F_DUPFD_CLOEXEC, 0) }) {
+            match unsafe { libc::fcntl_arg1(fd, F_DUPFD_CLOEXEC, 0) } {
                 // We *still* call the `set_cloexec` method as apparently some
                 // linux kernel at some point stopped setting CLOEXEC even
                 // though it reported doing so on F_DUPFD_CLOEXEC.
@@ -205,13 +171,13 @@ impl FileDesc {
                         FileDesc::new(fd)
                     });
                 }
-                Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {
+                Err(ref e) if e.equal_to_os_error(libc::EINVAL) => {
                     TRY_CLOEXEC.store(false, Ordering::Relaxed);
                 }
-                Err(e) => return Err(e),
+                Err(e) => return cvt_ocall(Err(e)),
             }
         }
-        cvt(unsafe { libc::fcntl_arg1(fd, libc::F_DUPFD, 0) }).and_then(make_filedesc)
+        cvt_ocall(unsafe { libc::fcntl_arg1(fd, libc::F_DUPFD, 0) }).and_then(make_filedesc)
     }
 }
 
@@ -244,8 +210,9 @@ impl Drop for FileDesc {
 }
 
 mod libc {
+    pub use sgx_trts::libc::ocall::{
+        close, fcntl_arg0, fcntl_arg1, ioctl_arg0, ioctl_arg1, pread64, pwrite64, read, readv,
+        write, writev,
+    };
     pub use sgx_trts::libc::*;
-    pub use sgx_trts::libc::ocall::{read, pread64, write, pwrite64, readv, writev,
-                                    fcntl_arg0, fcntl_arg1, ioctl_arg0, ioctl_arg1,
-                                    close};
 }
diff --git a/sgx_tstd/src/sys/fs.rs b/sgx_tstd/src/sys/fs.rs
index d701810..7884f5a 100644
--- a/sgx_tstd/src/sys/fs.rs
+++ b/sgx_tstd/src/sys/fs.rs
@@ -15,17 +15,17 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use sgx_trts::libc::{c_int, mode_t, time_t, stat64, off64_t, DIR, dirent64};
-use crate::os::unix::prelude::*;
 use crate::ffi::{CStr, CString, OsStr, OsString};
 use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut, SeekFrom};
+use crate::os::unix::prelude::*;
 use crate::path::{Path, PathBuf};
 use crate::sys::fd::FileDesc;
 use crate::sys::time::SystemTime;
-use crate::sys::{cvt, cvt_r};
+use crate::sys::{cvt_ocall, cvt_ocall_r};
 use crate::sys_common::{AsInner, FromInner};
-use core::{fmt, mem, ptr};
 use alloc_crate::sync::Arc;
+use core::{fmt, mem, ptr};
+use sgx_trts::libc::{c_int, dirent64, mode_t, off64_t, stat64, time_t, DIR};
 
 pub use crate::sys_common::fs::remove_dir_all;
 
@@ -37,9 +37,9 @@ pub struct FileAttr {
 }
 
 #[derive(Debug)]
-pub struct DirBuilder { 
+pub struct DirBuilder {
     mode: mode_t,
- }
+}
 
 // all DirEntry's will have a reference to this struct
 struct InnerReadDir {
@@ -98,11 +98,15 @@ impl FileAttr {
         self.stat.st_size as u64
     }
     pub fn perm(&self) -> FilePermissions {
-        FilePermissions { mode: (self.stat.st_mode as mode_t) }
+        FilePermissions {
+            mode: (self.stat.st_mode as mode_t),
+        }
     }
 
     pub fn file_type(&self) -> FileType {
-        FileType { mode: self.stat.st_mode as mode_t }
+        FileType {
+            mode: self.stat.st_mode as mode_t,
+        }
     }
 }
 
@@ -174,7 +178,9 @@ impl FileType {
 
 impl FromInner<u32> for FilePermissions {
     fn from_inner(mode: u32) -> FilePermissions {
-        FilePermissions { mode: mode as mode_t }
+        FilePermissions {
+            mode: mode as mode_t,
+        }
     }
 }
 
@@ -195,10 +201,14 @@ impl Iterator for ReadDir {
         }
 
         unsafe {
-            let mut ret = DirEntry { entry: mem::zeroed(), dir: self.clone() };
+            let mut ret = DirEntry {
+                entry: mem::zeroed(),
+                dir: self.clone(),
+            };
             let mut entry_ptr = ptr::null_mut();
             loop {
-                if libc::readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+                if let Err(e) = libc::readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr)
+                {
                     if entry_ptr.is_null() {
                         // We encountered an error (which will be returned in this iteration), but
                         // we also reached the end of the directory stream. The `end_of_stream`
@@ -206,8 +216,9 @@ impl Iterator for ReadDir {
                         // (instead of looping forever)
                         self.end_of_stream = true;
                     }
-                    return Some(Err(Error::last_os_error()));
-                }
+                    return Some(Err(e.into()));
+                };
+
                 if entry_ptr.is_null() {
                     return None;
                 }
@@ -222,13 +233,16 @@ impl Iterator for ReadDir {
 impl Drop for Dir {
     fn drop(&mut self) {
         let r = unsafe { libc::closedir(self.0) };
-        debug_assert_eq!(r, 0);
+        debug_assert!(r.is_ok());
     }
 }
 
 impl DirEntry {
     pub fn path(&self) -> PathBuf {
-        self.dir.inner.root.join(OsStr::from_bytes(self.name_bytes()))
+        self.dir
+            .inner
+            .root
+            .join(OsStr::from_bytes(self.name_bytes()))
     }
 
     pub fn file_name(&self) -> OsString {
@@ -236,23 +250,47 @@ impl DirEntry {
     }
 
     pub fn metadata(&self) -> io::Result<FileAttr> {
-        let fd = cvt(unsafe {libc::dirfd(self.dir.inner.dirp.0)})?;
+        let fd = cvt_ocall(unsafe { libc::dirfd(self.dir.inner.dirp.0) })?;
         let mut stat: stat64 = unsafe { mem::zeroed() };
-        cvt(unsafe {
-            libc::fstatat64(fd, self.entry.d_name.as_ptr(), &mut stat, libc::AT_SYMLINK_NOFOLLOW)
+
+        let dname_bytes: Vec<u8> = self.entry.d_name.iter().map(|b| *b as u8).collect();
+        let v = unsafe { libc::shrink_to_fit_os_string(dname_bytes) }?;
+        let dname = CString::new(v)?;
+
+        cvt_ocall(unsafe {
+            libc::fstatat64(
+                fd,
+                &dname,
+                &mut stat,
+                libc::AT_SYMLINK_NOFOLLOW,
+            )
         })?;
         Ok(FileAttr { stat })
     }
 
     pub fn file_type(&self) -> io::Result<FileType> {
         match self.entry.d_type {
-            libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
-            libc::DT_FIFO => Ok(FileType { mode: libc::S_IFIFO }),
-            libc::DT_LNK => Ok(FileType { mode: libc::S_IFLNK }),
-            libc::DT_REG => Ok(FileType { mode: libc::S_IFREG }),
-            libc::DT_SOCK => Ok(FileType { mode: libc::S_IFSOCK }),
-            libc::DT_DIR => Ok(FileType { mode: libc::S_IFDIR }),
-            libc::DT_BLK => Ok(FileType { mode: libc::S_IFBLK }),
+            libc::DT_CHR => Ok(FileType {
+                mode: libc::S_IFCHR,
+            }),
+            libc::DT_FIFO => Ok(FileType {
+                mode: libc::S_IFIFO,
+            }),
+            libc::DT_LNK => Ok(FileType {
+                mode: libc::S_IFLNK,
+            }),
+            libc::DT_REG => Ok(FileType {
+                mode: libc::S_IFREG,
+            }),
+            libc::DT_SOCK => Ok(FileType {
+                mode: libc::S_IFSOCK,
+            }),
+            libc::DT_DIR => Ok(FileType {
+                mode: libc::S_IFDIR,
+            }),
+            libc::DT_BLK => Ok(FileType {
+                mode: libc::S_IFBLK,
+            }),
             _ => lstat(&self.path()).map(|m| m.file_type()),
         }
     }
@@ -310,11 +348,11 @@ impl OpenOptions {
 
     fn get_access_mode(&self) -> io::Result<c_int> {
         match (self.read, self.write, self.append) {
-            (true,  false, false) => Ok(libc::O_RDONLY),
-            (false, true,  false) => Ok(libc::O_WRONLY),
-            (true,  true,  false) => Ok(libc::O_RDWR),
-            (false, _,     true)  => Ok(libc::O_WRONLY | libc::O_APPEND),
-            (true,  _,     true)  => Ok(libc::O_RDWR | libc::O_APPEND),
+            (true, false, false) => Ok(libc::O_RDONLY),
+            (false, true, false) => Ok(libc::O_WRONLY),
+            (true, true, false) => Ok(libc::O_RDWR),
+            (false, _, true) => Ok(libc::O_WRONLY | libc::O_APPEND),
+            (true, _, true) => Ok(libc::O_RDWR | libc::O_APPEND),
             (false, false, false) => Err(Error::from_raw_os_error(libc::EINVAL)),
         }
     }
@@ -335,12 +373,12 @@ impl OpenOptions {
         }
 
         Ok(match (self.create, self.truncate, self.create_new) {
-                (false, false, false) => 0,
-                (true,  false, false) => libc::O_CREAT,
-                (false, true,  false) => libc::O_TRUNC,
-                (true,  true,  false) => libc::O_CREAT | libc::O_TRUNC,
-                (_,      _,    true)  => libc::O_CREAT | libc::O_EXCL,
-           })
+            (false, false, false) => 0,
+            (true, false, false) => libc::O_CREAT,
+            (false, true, false) => libc::O_TRUNC,
+            (true, true, false) => libc::O_CREAT | libc::O_TRUNC,
+            (_, _, true) => libc::O_CREAT | libc::O_EXCL,
+        })
     }
 }
 
@@ -355,7 +393,7 @@ impl File {
             | opts.get_access_mode()?
             | opts.get_creation_mode()?
             | (opts.custom_flags as c_int & !libc::O_ACCMODE);
-        let fd = cvt_r(|| unsafe { libc::open64(path.as_ptr(), flags, opts.mode as c_int) })?;
+        let fd = cvt_ocall_r(|| unsafe { libc::open64(path, flags, opts.mode as c_int) })?;
         let fd = FileDesc::new(fd);
 
         // Currently the standard library supports Linux 2.6.18 which did not
@@ -404,29 +442,26 @@ impl File {
 
     pub fn file_attr(&self) -> io::Result<FileAttr> {
         let mut stat: stat64 = unsafe { mem::zeroed() };
-        cvt(unsafe { libc::fstat64(self.0.raw(), &mut stat) })?;
+        cvt_ocall(unsafe { libc::fstat64(self.0.raw(), &mut stat) })?;
         Ok(FileAttr::from_stat64(stat))
     }
 
     pub fn fsync(&self) -> io::Result<()> {
-        cvt_r(|| unsafe { libc::fsync(self.0.raw()) })?;
+        cvt_ocall_r(|| unsafe { libc::fsync(self.0.raw()) })?;
         Ok(())
     }
 
     pub fn datasync(&self) -> io::Result<()> {
-        cvt_r(|| unsafe { os_datasync(self.0.raw()) })?;
+        cvt_ocall_r(|| unsafe { libc::fdatasync(self.0.raw()) })?;
         return Ok(());
-
-        unsafe fn os_datasync(fd: c_int) -> c_int {
-            libc::fdatasync(fd)
-        }
     }
 
     pub fn truncate(&self, size: u64) -> io::Result<()> {
         use crate::convert::TryInto;
-            let size: off64_t =
-                size.try_into().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
-            cvt_r(|| unsafe { libc::ftruncate64(self.0.raw(), size) }).map(drop)
+        let size: off64_t = size
+            .try_into()
+            .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
+        cvt_ocall_r(|| unsafe { libc::ftruncate64(self.0.raw(), size) }).map(drop)
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
@@ -466,7 +501,7 @@ impl File {
             SeekFrom::Current(off) => (libc::SEEK_CUR, off),
         };
 
-        let n = cvt(unsafe { libc::lseek64(self.0.raw(), pos, whence) })?;
+        let n = cvt_ocall(unsafe { libc::lseek64(self.0.raw(), pos, whence) })?;
         Ok(n as u64)
     }
 
@@ -483,7 +518,7 @@ impl File {
     }
 
     pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> {
-        cvt_r(|| unsafe { libc::fchmod(self.0.raw(), perm.mode) })?;
+        cvt_ocall_r(|| unsafe { libc::fchmod(self.0.raw(), perm.mode) })?;
         Ok(())
     }
 }
@@ -495,7 +530,7 @@ impl DirBuilder {
 
     pub fn mkdir(&self, p: &Path) -> io::Result<()> {
         let p = cstr(p)?;
-        cvt(unsafe { libc::mkdir(p.as_ptr(), self.mode) })?;
+        cvt_ocall(unsafe { libc::mkdir(&p, self.mode) })?;
         Ok(())
     }
 
@@ -523,15 +558,14 @@ impl fmt::Debug for File {
         }
 
         fn get_mode(fd: c_int) -> Option<(bool, bool)> {
-            let mode = unsafe { libc::fcntl_arg0(fd, libc::F_GETFL) };
-            if mode == -1 {
-                return None;
-            }
-            match mode & libc::O_ACCMODE {
-                libc::O_RDONLY => Some((true, false)),
-                libc::O_RDWR => Some((true, true)),
-                libc::O_WRONLY => Some((false, true)),
-                _ => None,
+            match unsafe { libc::fcntl_arg0(fd, libc::F_GETFL) } {
+                Err(_) => None,
+                Ok(mode) => match mode & libc::O_ACCMODE {
+                    libc::O_RDONLY => Some((true, false)),
+                    libc::O_RDWR => Some((true, true)),
+                    libc::O_WRONLY => Some((false, true)),
+                    _ => None,
+                },
             }
         }
 
@@ -552,108 +586,81 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
     let root = p.to_path_buf();
     let p = cstr(p)?;
     unsafe {
-        let ptr = libc::opendir(p.as_ptr());
-        if ptr.is_null() {
-            Err(Error::last_os_error())
-        } else {
-            let inner = InnerReadDir { dirp: Dir(ptr), root };
-            Ok(ReadDir { inner: Arc::new(inner), end_of_stream: false })
-        }
+        let ptr = cvt_ocall(libc::opendir(&p))?;
+        let inner = InnerReadDir {
+            dirp: Dir(ptr),
+            root,
+        };
+        Ok(ReadDir {
+            inner: Arc::new(inner),
+            end_of_stream: false,
+        })
     }
 }
 
 pub fn unlink(p: &Path) -> io::Result<()> {
     let p = cstr(p)?;
-    cvt(unsafe { libc::unlink(p.as_ptr()) })?;
+    cvt_ocall(unsafe { libc::unlink(&p) })?;
     Ok(())
 }
 
 pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
     let old = cstr(old)?;
     let new = cstr(new)?;
-    cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) })?;
+    cvt_ocall(unsafe { libc::rename(&old, &new) })?;
     Ok(())
 }
 
 pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
     let p = cstr(p)?;
-    cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) })?;
+    cvt_ocall_r(|| unsafe { libc::chmod(&p, perm.mode) })?;
     Ok(())
 }
 
 pub fn rmdir(p: &Path) -> io::Result<()> {
     let p = cstr(p)?;
-    cvt(unsafe { libc::rmdir(p.as_ptr()) })?;
+    cvt_ocall(unsafe { libc::rmdir(&p) })?;
     Ok(())
 }
 
 pub fn readlink(p: &Path) -> io::Result<PathBuf> {
     let c_path = cstr(p)?;
-    let p = c_path.as_ptr();
-
-    let mut buf = Vec::with_capacity(256);
-
-    loop {
-        let buf_read =
-            cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? as usize;
-
-        unsafe {
-            buf.set_len(buf_read);
-        }
-
-        if buf_read != buf.capacity() {
-            buf.shrink_to_fit();
-
-            return Ok(PathBuf::from(OsString::from_vec(buf)));
-        }
-
-        // Trigger the internal buffer resizing logic of `Vec` by requiring
-        // more space than the current capacity. The length is guaranteed to be
-        // the same as the capacity due to the if statement above.
-        buf.reserve(1);
-    }
+    let v = cvt_ocall(unsafe { libc::readlink(&c_path) })?;
+    return Ok(PathBuf::from(OsString::from_vec(v)));
 }
 
 pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
     let src = cstr(src)?;
     let dst = cstr(dst)?;
-    cvt(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })?;
+    cvt_ocall(unsafe { libc::symlink(&src, &dst) })?;
     Ok(())
 }
 
 pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
     let src = cstr(src)?;
     let dst = cstr(dst)?;
-    cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?;
+    cvt_ocall(unsafe { libc::link(&src, &dst) })?;
     Ok(())
 }
 
 pub fn stat(p: &Path) -> io::Result<FileAttr> {
     let p = cstr(p)?;
     let mut stat: stat64 = unsafe { mem::zeroed() };
-    cvt(unsafe { libc::stat64(p.as_ptr(), &mut stat as *mut _) })?;
+    cvt_ocall(unsafe { libc::stat64(&p, &mut stat) })?;
     Ok(FileAttr::from_stat64(stat))
 }
 
 pub fn lstat(p: &Path) -> io::Result<FileAttr> {
     let p = cstr(p)?;
     let mut stat: stat64 = unsafe { mem::zeroed() };
-    cvt(unsafe { libc::lstat64(p.as_ptr(), &mut stat as *mut _) })?;
+    cvt_ocall(unsafe { libc::lstat64(&p, &mut stat) })?;
     Ok(FileAttr::from_stat64(stat))
 }
 
 pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
     let path = CString::new(p.as_os_str().as_bytes())?;
-    let buf;
-    unsafe {
-        let r = libc::realpath(path.as_ptr());
-        if r.is_null() {
-            return Err(io::Error::last_os_error());
-        }
-        buf = CStr::from_ptr(r).to_bytes().to_vec();
-        libc::free(r as *mut _);
-    }
-    Ok(PathBuf::from(OsString::from_vec(buf)))
+    let v = cvt_ocall(unsafe { libc::realpath(&path) })?;
+    Ok(PathBuf::from(OsString::from_vec(v)))
 }
 
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
@@ -683,8 +690,10 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
 }
 
 mod libc {
+    pub use sgx_trts::libc::ocall::{
+        chmod, closedir, dirfd, fchmod, fcntl_arg0, fdatasync, fstat64, fstatat64, fsync,
+        ftruncate64, link, lseek64, lstat64, mkdir, open64, opendir, readdir64_r, readlink,
+        realpath, rename, rmdir, stat64, symlink, unlink, shrink_to_fit_os_string,
+    };
     pub use sgx_trts::libc::*;
-    pub use sgx_trts::libc::ocall::{open64, fstat64, fsync, fdatasync, ftruncate64, lseek64, fchmod,
-                                    unlink, link, rename, chmod, readlink, symlink, stat64, lstat64,
-                                    fcntl_arg0, realpath, free, readdir64_r, closedir, dirfd, mkdir, rmdir, opendir, fstatat64};
-}
\ No newline at end of file
+}
diff --git a/sgx_tstd/src/sys/mod.rs b/sgx_tstd/src/sys/mod.rs
index 15c6441..54ffd19 100644
--- a/sgx_tstd/src/sys/mod.rs
+++ b/sgx_tstd/src/sys/mod.rs
@@ -15,41 +15,41 @@
 // specific language governing permissions and limitations
 // under the License..
 
+use crate::io::ErrorKind;
 use sgx_trts::libc;
 use sgx_trts::trts;
-use crate::io::ErrorKind;
 
 pub use self::rand::hashmap_random_keys;
 
-pub mod mutex;
+#[cfg(feature = "backtrace")]
+pub mod backtrace;
+pub mod cmath;
 pub mod condvar;
-pub mod rwlock;
+pub mod env;
+pub mod ext;
+#[cfg(feature = "thread")]
+pub mod fast_thread_local;
 pub mod fd;
 pub mod fs;
-pub mod sgxfs;
 pub mod io;
-#[cfg(feature = "thread")]
-pub mod thread;
-#[cfg(feature = "thread")]
-pub mod fast_thread_local;
-#[cfg(feature = "thread")]
-pub mod thread_local;
+pub mod memchr;
+pub mod mutex;
 #[cfg(feature = "net")]
 pub mod net;
+pub mod os;
 pub mod path;
-pub mod ext;
+#[cfg(feature = "pipe")]
+pub mod pipe;
 pub mod rand;
-pub mod os;
+pub mod rwlock;
+pub mod sgxfs;
 #[cfg(feature = "stdio")]
 pub mod stdio;
-#[cfg(feature = "backtrace")]
-pub mod backtrace;
+#[cfg(feature = "thread")]
+pub mod thread;
+#[cfg(feature = "thread")]
+pub mod thread_local;
 pub mod time;
-pub mod memchr;
-pub mod cmath;
-pub mod env;
-#[cfg(feature = "pipe")]
-pub mod pipe;
 
 pub use crate::sys_common::os_str_bytes as os_str;
 
@@ -93,7 +93,11 @@ macro_rules! impl_is_minus_one {
 impl_is_minus_one! { i8 i16 i32 i64 isize }
 
 pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
-    if t.is_minus_one() { Err(crate::io::Error::last_os_error()) } else { Ok(t) }
+    if t.is_minus_one() {
+        Err(crate::io::Error::last_os_error())
+    } else {
+        Ok(t)
+    }
 }
 
 pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
@@ -112,3 +116,21 @@ where
 pub unsafe fn abort_internal() -> ! {
     trts::rsgx_abort()
 }
+
+use sgx_trts::libc::OCallResult;
+
+pub fn cvt_ocall<T>(result: OCallResult<T>) -> crate::io::Result<T> {
+    result.map_err(|e| e.into())
+}
+
+pub fn cvt_ocall_r<T, F>(mut f: F) -> crate::io::Result<T>
+where
+    F: FnMut() -> OCallResult<T>,
+{
+    loop {
+        match cvt_ocall(f()) {
+            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
+            other => return other,
+        }
+    }
+}
diff --git a/sgx_tstd/src/sys/net.rs b/sgx_tstd/src/sys/net.rs
index b6aa6c7..128363b 100644
--- a/sgx_tstd/src/sys/net.rs
+++ b/sgx_tstd/src/sys/net.rs
@@ -16,20 +16,18 @@
 // under the License..
 
 #![allow(dead_code)]
-use sgx_trts::libc::{c_int, size_t, c_void};
-use core::mem;
-use core::cmp;
-use core::str;
-use crate::ffi::CStr;
 use crate::io::{self, IoSlice, IoSliceMut};
 use crate::net::{Shutdown, SocketAddr};
 use crate::sys::fd::FileDesc;
+pub use crate::sys::{cvt, cvt_ocall, cvt_ocall_r, cvt_r};
+use crate::sys_common::net::{getsockopt, setsockopt};
 use crate::sys_common::{AsInner, FromInner, IntoInner};
-use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
 use crate::time::{Duration, Instant};
 #[cfg(not(feature = "untrusted_time"))]
 use crate::untrusted::time::InstantEx;
-pub use crate::sys::{cvt, cvt_r};
+use core::cmp;
+use core::convert::TryInto;
+use sgx_trts::libc::{c_int, size_t, PolledOk};
 
 pub type wrlen_t = size_t;
 
@@ -49,13 +47,7 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
         return Err(io::Error::last_os_error());
     }
 
-    let detail = unsafe {
-        let strerr = libc::gai_strerror(err);
-        if strerr.is_null() {
-            return Err(io::Error::from_raw_os_error(libc::ESGX));
-        }
-        str::from_utf8(CStr::from_ptr(strerr).to_bytes()).unwrap().to_owned()
-    };
+    let detail = libc::gai_error_str(err);
     Err(io::Error::new(
         io::ErrorKind::Other,
         &format!("failed to lookup address information: {}", detail)[..],
@@ -84,13 +76,13 @@ impl Socket {
             // this option, however, was added in 2.6.27, and we still support
             // 2.6.18 as a kernel, so if the returned error is EINVAL we
             // fallthrough to the fallback.
-            match cvt(libc::socket(fam, ty | libc::SOCK_CLOEXEC, 0)) {
+            match libc::socket(fam, ty | libc::SOCK_CLOEXEC, 0) {
                 Ok(fd) => return Ok(Socket(FileDesc::new(fd))),
-                Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {}
-                Err(e) => return Err(e),
+                Err(ref e) if e.equal_to_os_error(libc::EINVAL) => {}
+                Err(e) => return cvt_ocall(Err(e)),
             }
 
-            let fd = cvt(libc::socket(fam, ty, 0))?;
+            let fd = cvt_ocall(libc::socket(fam, ty, 0))?;
             let fd = FileDesc::new(fd);
             fd.set_cloexec()?;
             let socket = Socket(fd);
@@ -104,15 +96,15 @@ impl Socket {
             let mut fds = [0, 0];
 
             // Like above, see if we can set cloexec atomically
-            match cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr())) {
+            match libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, &mut fds) {
                 Ok(_) => {
                     return Ok((Socket(FileDesc::new(fds[0])), Socket(FileDesc::new(fds[1]))));
                 }
-                Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {}
-                Err(e) => return Err(e),
+                Err(ref e) if e.equal_to_os_error(libc::EINVAL) => {}
+                Err(e) => return cvt_ocall(Err(e)),
             }
 
-            cvt(libc::socketpair(fam, ty, 0, fds.as_mut_ptr()))?;
+            cvt_ocall(libc::socketpair(fam, ty, 0, &mut fds))?;
             let a = FileDesc::new(fds[0]);
             let b = FileDesc::new(fds[1]);
             a.set_cloexec()?;
@@ -124,19 +116,23 @@ impl Socket {
     pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
         self.set_nonblocking(true)?;
         let r = unsafe {
-            let (addrp, len) = addr.into_inner();
-            cvt(libc::connect(self.0.raw(), addrp, len))
+            let addr = addr.to_owned().into();
+            libc::connect(self.0.raw(), &addr)
         };
         self.set_nonblocking(false)?;
 
         match r {
             Ok(_) => return Ok(()),
             // there's no ErrorKind for EINPROGRESS :(
-            Err(ref e) if e.raw_os_error() == Some(libc::EINPROGRESS) => {}
-            Err(e) => return Err(e),
+            Err(ref e) if e.equal_to_os_error(libc::EINPROGRESS) => {}
+            Err(e) => return cvt_ocall(Err(e)),
         }
 
-        let mut pollfd = libc::pollfd { fd: self.0.raw(), events: libc::POLLOUT, revents: 0 };
+        let mut pollfds = [libc::pollfd {
+            fd: self.0.raw(),
+            events: libc::POLLOUT,
+            revents: 0,
+        }];
 
         if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
             return Err(io::Error::new(
@@ -150,7 +146,10 @@ impl Socket {
         loop {
             let elapsed = start.elapsed();
             if elapsed >= timeout {
-                return Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out"));
+                return Err(io::Error::new(
+                    io::ErrorKind::TimedOut,
+                    "connection timed out",
+                ));
             }
 
             let timeout = timeout - elapsed;
@@ -164,24 +163,17 @@ impl Socket {
 
             let timeout = cmp::min(timeout, c_int::max_value() as u64) as c_int;
 
-            match unsafe { libc::poll(&mut pollfd, 1, timeout) } {
-                -1 => {
-                    let err = io::Error::last_os_error();
-                    if err.kind() != io::ErrorKind::Interrupted {
-                        return Err(err);
-                    }
-                }
-                0 => {}
-                _ => {
+            match unsafe { cvt_ocall(libc::poll(&mut pollfds, timeout))? } {
+                PolledOk::TimeLimitExpired => {}
+                PolledOk::ReadyDescsCount(_) => {
                     // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
                     // for POLLHUP rather than read readiness
-                    if pollfd.revents & libc::POLLHUP != 0 {
+                    if pollfds[0].revents & libc::POLLHUP != 0 {
                         let e = self.take_error()?.unwrap_or_else(|| {
                             io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP")
                         });
                         return Err(e);
                     }
-
                     return Ok(());
                 }
             }
@@ -198,14 +190,10 @@ impl Socket {
     // This function is guarded by feature `net` and should only
     // be used on demand.
     // We don't support linux kernel < 2.6.28. So we only use accept4.
-    pub fn accept(&self, storage: *mut libc::sockaddr, len: *mut libc::socklen_t) -> io::Result<Socket> {
-        let res = cvt_r(|| unsafe {
-            libc::accept4(self.0.raw(), storage, len, libc::SOCK_CLOEXEC)
-        });
-        match res {
-            Ok(fd) => Ok(Socket(FileDesc::new(fd))),
-            Err(e) => Err(e),
-        }
+    pub fn accept(&self) -> io::Result<(Socket, libc::SockAddr)> {
+        let (fd, addr) =
+            cvt_ocall_r(|| unsafe { libc::accept4(self.0.raw(), libc::SOCK_CLOEXEC) })?;
+        Ok((Socket(FileDesc::new(fd)), addr))
     }
 
     pub fn raw(&self) -> c_int {
@@ -221,9 +209,7 @@ impl Socket {
     }
 
     fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
-        let ret = cvt(unsafe {
-            libc::recv(self.0.raw(), buf.as_mut_ptr() as *mut c_void, buf.len(), flags)
-        })?;
+        let ret = cvt_ocall(unsafe { libc::recv(self.0.raw(), buf, flags) })?;
         Ok(ret as usize)
     }
 
@@ -244,20 +230,8 @@ impl Socket {
         buf: &mut [u8],
         flags: c_int,
     ) -> io::Result<(usize, SocketAddr)> {
-        let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
-        let mut addrlen = mem::size_of_val(&storage) as libc::socklen_t;
-
-        let n = cvt(unsafe {
-            libc::recvfrom(
-                self.0.raw(),
-                buf.as_mut_ptr() as *mut c_void,
-                buf.len(),
-                flags,
-                &mut storage as *mut _ as *mut _,
-                &mut addrlen,
-            )
-        })?;
-        Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
+        let (n, addr) = cvt_ocall(unsafe { libc::recvfrom(self.0.raw(), buf, flags) })?;
+        Ok((n, addr.try_into()?))
     }
 
     pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
@@ -300,7 +274,10 @@ impl Socket {
                 }
                 timeout
             }
-            None => libc::timeval { tv_sec: 0, tv_usec: 0 },
+            None => libc::timeval {
+                tv_sec: 0,
+                tv_usec: 0,
+            },
         };
         setsockopt(self, libc::SOL_SOCKET, kind, timeout)
     }
@@ -322,7 +299,7 @@ impl Socket {
             Shutdown::Read => libc::SHUT_RD,
             Shutdown::Both => libc::SHUT_RDWR,
         };
-        cvt(unsafe { libc::shutdown(self.0.raw(), how) })?;
+        cvt_ocall(unsafe { libc::shutdown(self.0.raw(), how) })?;
         Ok(())
     }
 
@@ -337,12 +314,17 @@ impl Socket {
 
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         let mut nonblocking = nonblocking as c_int;
-        cvt(unsafe { libc::ioctl_arg1(*self.as_inner(), libc::FIONBIO, &mut nonblocking) }).map(drop)
+        cvt_ocall(unsafe { libc::ioctl_arg1(*self.as_inner(), libc::FIONBIO, &mut nonblocking) })
+            .map(drop)
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
         let raw: c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_ERROR)?;
-        if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) }
+        if raw == 0 {
+            Ok(None)
+        } else {
+            Ok(Some(io::Error::from_raw_os_error(raw as i32)))
+        }
     }
 }
 
@@ -365,7 +347,9 @@ impl IntoInner<c_int> for Socket {
 }
 
 mod libc {
+    pub use sgx_trts::libc::ocall::{
+        accept4, connect, ioctl_arg1, poll, recv, recvfrom, shutdown, socket,
+        socketpair,
+    };
     pub use sgx_trts::libc::*;
-    pub use sgx_trts::libc::ocall::{socket, socketpair, connect, accept4, recv, recvfrom, shutdown,
-                                    ioctl_arg1, poll, gai_strerror};
-}
\ No newline at end of file
+}
diff --git a/sgx_tstd/src/sys/os.rs b/sgx_tstd/src/sys/os.rs
index 9627cfe..49d9ef6 100644
--- a/sgx_tstd/src/sys/os.rs
+++ b/sgx_tstd/src/sys/os.rs
@@ -15,25 +15,23 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use sgx_trts::error as trts_error;
-use sgx_types::metadata;
-use crate::os::unix::prelude::*;
 use crate::error::Error as StdError;
 use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::io;
+use crate::memchr;
+use crate::os::unix::prelude::*;
 use crate::path::{self, PathBuf};
 use crate::sync::SgxThreadMutex;
-use crate::sys::cvt;
-use crate::memchr;
-use crate::io;
-use core::marker::PhantomData;
-use core::fmt;
-use core::iter;
-use core::ptr;
-use core::mem;
+use crate::sys::cvt_ocall;
 use alloc_crate::slice;
-use alloc_crate::string::String;
 use alloc_crate::str;
+use alloc_crate::string::String;
 use alloc_crate::vec::{self, Vec};
+use core::fmt;
+use core::iter;
+use core::marker::PhantomData;
+use sgx_trts::error as trts_error;
+use sgx_types::metadata;
 
 const TMPBUF_SZ: usize = 128;
 static ENV_LOCK: SgxThreadMutex = SgxThreadMutex::new();
@@ -54,47 +52,59 @@ pub fn error_string(error: i32) -> String {
         }
 
         let p = buf.as_ptr() as *const _;
-        str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
+        str::from_utf8(CStr::from_ptr(p).to_bytes())
+            .unwrap()
+            .to_owned()
     }
 }
 
 pub struct SplitPaths<'a> {
-    iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>,
-                    fn(&'a [u8]) -> PathBuf>,
+    iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>, fn(&'a [u8]) -> PathBuf>,
 }
 
 pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> {
     fn bytes_to_path(b: &[u8]) -> PathBuf {
         PathBuf::from(<OsStr as OsStrExt>::from_bytes(b))
     }
-    fn is_colon(b: &u8) -> bool { *b == b':' }
+    fn is_colon(b: &u8) -> bool {
+        *b == b':'
+    }
     let unparsed = unparsed.as_bytes();
     SplitPaths {
-        iter: unparsed.split(is_colon as fn(&u8) -> bool)
-                      .map(bytes_to_path as fn(&[u8]) -> PathBuf)
+        iter: unparsed
+            .split(is_colon as fn(&u8) -> bool)
+            .map(bytes_to_path as fn(&[u8]) -> PathBuf),
     }
 }
 
 impl<'a> Iterator for SplitPaths<'a> {
     type Item = PathBuf;
-    fn next(&mut self) -> Option<PathBuf> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+    fn next(&mut self) -> Option<PathBuf> {
+        self.iter.next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
 }
 
 #[derive(Debug)]
 pub struct JoinPathsError;
 
 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
-    where I: Iterator<Item=T>, T: AsRef<OsStr>
+where
+    I: Iterator<Item = T>,
+    T: AsRef<OsStr>,
 {
     let mut joined = Vec::new();
     let sep = b':';
 
     for (i, path) in paths.enumerate() {
         let path = path.as_ref().as_bytes();
-        if i > 0 { joined.push(sep) }
+        if i > 0 {
+            joined.push(sep)
+        }
         if path.contains(&sep) {
-            return Err(JoinPathsError)
+            return Err(JoinPathsError);
         }
         joined.extend_from_slice(path);
     }
@@ -108,17 +118,17 @@ impl fmt::Display for JoinPathsError {
 }
 
 impl StdError for JoinPathsError {
-    fn description(&self) -> &str { "failed to join paths" }
+    fn description(&self) -> &str {
+        "failed to join paths"
+    }
 }
 
 pub fn current_exe() -> io::Result<PathBuf> {
     match crate::fs::read_link("/proc/self/exe") {
-        Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
-            Err(io::Error::new(
-                io::ErrorKind::Other,
-                "no /proc/self/exe available. Is /proc mounted?"
-            ))
-        },
+        Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new(
+            io::ErrorKind::Other,
+            "no /proc/self/exe available. Is /proc mounted?",
+        )),
         other => other,
     }
 }
@@ -130,19 +140,26 @@ pub struct Env {
 
 impl Iterator for Env {
     type Item = (OsString, OsString);
-    fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+    fn next(&mut self) -> Option<(OsString, OsString)> {
+        self.iter.next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
 }
 
+/*
 pub unsafe fn environ() -> *const *const libc::c_char {
     libc::environ()
 }
+*/
 
 /// Returns a vector of (variable, value) byte-vector pairs for all the
 /// environment variables of the current process.
 pub fn env() -> Env {
     unsafe {
         ENV_LOCK.lock();
+        /*
         let mut environ = environ();
         let mut result = Vec::new();
         if !environ.is_null() {
@@ -153,6 +170,8 @@ pub fn env() -> Env {
                 environ = environ.add(1);
             }
         }
+        */
+        let result = Vec::new();
         let ret = Env {
             iter: result.into_iter(),
             _dont_send_or_sync_me: PhantomData,
@@ -183,40 +202,49 @@ pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
     // environment variables with a nul byte can't be set, so their value is
     // always None as well
     let k = CString::new(k.as_bytes())?;
+
     unsafe {
         ENV_LOCK.lock();
-        let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
-        let ret = if s.is_null() {
-            None
-        } else {
-            Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
-        };
+        let result_opt = cvt_ocall(libc::getenv(&k));
+        let ret = result_opt.map(|opt| opt.map(|v| OsString::from_vec(v)));
         ENV_LOCK.unlock();
-        Ok(ret)
+        ret
     }
 }
 
-pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
+pub fn setenv(_k: &OsStr, _v: &OsStr) -> io::Result<()> {
+    Err(io::Error::new(
+        io::ErrorKind::Other,
+        "To be implemented completely within trusted part",
+    ))
+    /*
     let k = CString::new(k.as_bytes())?;
     let v = CString::new(v.as_bytes())?;
 
     unsafe {
         ENV_LOCK.lock();
-        let ret = cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop);
+        let ret = cvt_ocall(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop);
         ENV_LOCK.unlock();
         ret
     }
+    */
 }
 
-pub fn unsetenv(n: &OsStr) -> io::Result<()> {
+pub fn unsetenv(_n: &OsStr) -> io::Result<()> {
+    Err(io::Error::new(
+        io::ErrorKind::Other,
+        "To be implemented completely within trusted part",
+    ))
+    /*
     let nbuf = CString::new(n.as_bytes())?;
 
     unsafe {
         ENV_LOCK.lock();
-        let ret = cvt(libc::unsetenv(nbuf.as_ptr())).map(drop);
+        let ret = cvt_ocall(libc::unsetenv(nbuf.as_ptr())).map(drop);
         ENV_LOCK.unlock();
         ret
     }
+    */
 }
 
 pub fn page_size() -> usize {
@@ -224,78 +252,28 @@ pub fn page_size() -> usize {
 }
 
 pub fn temp_dir() -> PathBuf {
-    crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| {
-        PathBuf::from("/tmp")
-    })
+    crate::env::var_os("TMPDIR")
+        .map(PathBuf::from)
+        .unwrap_or_else(|| PathBuf::from("/tmp"))
 }
 
 pub fn getcwd() -> io::Result<PathBuf> {
-    let mut buf = Vec::with_capacity(512);
-    loop {
-        unsafe {
-            let ptr = buf.as_mut_ptr() as *mut libc::c_char;
-            if !libc::getcwd(ptr, buf.capacity()).is_null() {
-                let len = CStr::from_ptr(buf.as_ptr() as *const libc::c_char).to_bytes().len();
-                buf.set_len(len);
-                buf.shrink_to_fit();
-                return Ok(PathBuf::from(OsString::from_vec(buf)));
-            } else {
-                let error = io::Error::last_os_error();
-                if error.raw_os_error() != Some(libc::ERANGE) {
-                    return Err(error);
-                }
-            }
-
-            // Trigger the internal buffer resizing logic of `Vec` by requiring
-            // more space than the current capacity.
-            let cap = buf.capacity();
-            buf.set_len(cap);
-            buf.reserve(1);
-        }
-    }
+    let v = cvt_ocall(unsafe { libc::getcwd() })?;
+    return Ok(PathBuf::from(OsString::from_vec(v)));
 }
 
 pub fn chdir(p: &path::Path) -> io::Result<()> {
     let p: &OsStr = p.as_ref();
     let p = CString::new(p.as_bytes())?;
-    unsafe {
-        match libc::chdir(p.as_ptr()) == (0 as libc::c_int) {
-            true => Ok(()),
-            false => Err(io::Error::last_os_error()),
-        }
-    }
+    unsafe { cvt_ocall(libc::chdir(&p)) }
 }
 
+// No fallback logic here for security reasons.
 pub fn home_dir() -> Option<PathBuf> {
-    return crate::env::var_os("HOME").or_else(|| unsafe {
-        fallback()
-    }).map(PathBuf::from);
-    unsafe fn fallback() -> Option<OsString> {
-        let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
-            n if n < 0 => 512 as usize,
-            n => n as usize,
-        };
-        let mut buf = Vec::with_capacity(amt);
-        let mut passwd: libc::passwd = mem::zeroed();
-        let mut result = ptr::null_mut();
-        match libc::getpwuid_r(
-            libc::getuid(),
-            &mut passwd,
-            buf.as_mut_ptr(),
-            buf.capacity(),
-            &mut result
-        ) {
-            0 if !result.is_null() => {
-                let ptr = passwd.pw_dir as *const _;
-                let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
-                Some(OsStringExt::from_vec(bytes))
-            }
-            _ => None,
-        }
-    }
+    return crate::env::var_os("HOME").map(PathBuf::from);
 }
 
 mod libc {
+    pub use sgx_trts::libc::ocall::{chdir, getcwd, getenv, getuid, sysconf};
     pub use sgx_trts::libc::*;
-    pub use sgx_trts::libc::ocall::{environ, getenv, setenv, unsetenv, getcwd, chdir, sysconf, getuid, getpwuid_r};
-}
\ No newline at end of file
+}
diff --git a/sgx_tstd/src/sys/pipe.rs b/sgx_tstd/src/sys/pipe.rs
index 3a5e249..637a4fc 100644
--- a/sgx_tstd/src/sys/pipe.rs
+++ b/sgx_tstd/src/sys/pipe.rs
@@ -17,10 +17,9 @@
 
 use crate::io::{self, IoSlice, IoSliceMut};
 use crate::sys::fd::FileDesc;
-use crate::sys::{cvt, cvt_r};
-use core::mem;
+use crate::sys::{cvt_ocall, cvt_ocall_r};
 use alloc_crate::vec::Vec;
-
+use core::mem;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Anonymous pipes
@@ -30,7 +29,7 @@ pub struct AnonPipe(FileDesc);
 
 pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
     let mut fds = [0; 2];
-    cvt(unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) })?;
+    cvt_ocall(unsafe { libc::pipe2(&mut fds, libc::O_CLOEXEC) })?;
 
     let fd0 = FileDesc::new(fds[0]);
     let fd1 = FileDesc::new(fds[1]);
@@ -77,7 +76,7 @@ pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) ->
     fds[1].events = libc::POLLIN;
     loop {
         // wait for either pipe to become readable using `poll`
-        cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;
+        cvt_ocall_r(|| unsafe { libc::poll(&mut fds, -1) })?;
 
         if fds[0].revents != 0 && read(&p1, v1)? {
             p2.set_nonblocking(false)?;
@@ -111,6 +110,6 @@ pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) ->
 }
 
 mod libc {
-    pub use sgx_trts::libc::*;
     pub use sgx_trts::libc::ocall::{pipe2, poll};
-}
\ No newline at end of file
+    pub use sgx_trts::libc::*;
+}
diff --git a/sgx_tstd/src/sys/thread.rs b/sgx_tstd/src/sys/thread.rs
index 91d20ec..d09d55a 100644
--- a/sgx_tstd/src/sys/thread.rs
+++ b/sgx_tstd/src/sys/thread.rs
@@ -21,7 +21,6 @@ use core::mem;
 use core::ptr;
 use crate::ffi::CStr;
 use crate::io;
-use crate::sys::os;
 use crate::time::Duration;
 
 pub struct Thread {
@@ -73,7 +72,7 @@ impl Thread {
 
     pub fn yield_now() {
         let ret = unsafe { libc::sched_yield() };
-        debug_assert_eq!(ret, 0);
+        debug_assert!(ret.is_ok());
     }
 
     pub fn sleep(dur: Duration) {
@@ -89,8 +88,8 @@ impl Thread {
                     tv_nsec: nsecs,
                 };
                 secs -= ts.tv_sec as u64;
-                if libc::nanosleep(&ts, &mut ts) == -1 {
-                    assert_eq!(os::errno(), libc::EINTR);
+                if let Err(e) = libc::nanosleep(&mut ts) {
+                    assert_eq!(e.equal_to_os_error(libc::EINTR), true);
                     secs += ts.tv_sec as u64;
                     nsecs = ts.tv_nsec;
                 } else {
diff --git a/sgx_tstd/src/sys/time.rs b/sgx_tstd/src/sys/time.rs
index 89940c4..55c001a 100644
--- a/sgx_tstd/src/sys/time.rs
+++ b/sgx_tstd/src/sys/time.rs
@@ -15,12 +15,12 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use sgx_trts::libc;
+pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};
+use crate::time::Duration;
 use core::cmp::Ordering;
-use core::hash::{Hash, Hasher};
 use core::convert::TryInto;
-use crate::time::Duration;
-pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};
+use core::hash::{Hash, Hasher};
+use sgx_trts::libc;
 
 const NSEC_PER_SEC: u64 = 1_000_000_000;
 
@@ -31,7 +31,12 @@ struct Timespec {
 
 impl Timespec {
     const fn zero() -> Timespec {
-        Timespec { t: libc::timespec { tv_sec: 0, tv_nsec: 0 } }
+        Timespec {
+            t: libc::timespec {
+                tv_sec: 0,
+                tv_nsec: 0,
+            },
+        }
     }
 
     fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
@@ -69,7 +74,12 @@ impl Timespec {
             nsec -= NSEC_PER_SEC as u32;
             secs = secs.checked_add(1)?;
         }
-        Some(Timespec { t: libc::timespec { tv_sec: secs, tv_nsec: nsec as _ } })
+        Some(Timespec {
+            t: libc::timespec {
+                tv_sec: secs,
+                tv_nsec: nsec as _,
+            },
+        })
     }
 
     fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
@@ -85,7 +95,12 @@ impl Timespec {
             nsec += NSEC_PER_SEC as i32;
             secs = secs.checked_sub(1)?;
         }
-        Some(Timespec { t: libc::timespec { tv_sec: secs, tv_nsec: nsec as _ } })
+        Some(Timespec {
+            t: libc::timespec {
+                tv_sec: secs,
+                tv_nsec: nsec as _,
+            },
+        })
     }
 }
 
@@ -119,9 +134,9 @@ impl Hash for Timespec {
 }
 
 mod inner {
-    use core::fmt;
-    use crate::sys::cvt;
+    use crate::sys::cvt_ocall;
     use crate::time::Duration;
+    use core::fmt;
 
     use super::Timespec;
 
@@ -141,7 +156,9 @@ mod inner {
 
     impl Instant {
         pub fn now() -> Instant {
-            Instant { t: now(libc::CLOCK_MONOTONIC) }
+            Instant {
+                t: now(libc::CLOCK_MONOTONIC),
+            }
         }
 
         pub const fn zero() -> Instant {
@@ -151,9 +168,9 @@ mod inner {
         }
 
         pub fn actually_monotonic() -> bool {
-            (cfg!(target_os = "linux") && cfg!(target_arch = "x86_64")) ||
-            (cfg!(target_os = "linux") && cfg!(target_arch = "x86")) ||
-            false // last clause, used so `||` is always trailing above
+            (cfg!(target_os = "linux") && cfg!(target_arch = "x86_64"))
+                || (cfg!(target_os = "linux") && cfg!(target_arch = "x86"))
+                || false // last clause, used so `||` is always trailing above
         }
 
         pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
@@ -161,11 +178,15 @@ mod inner {
         }
 
         pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
-            Some(Instant { t: self.t.checked_add_duration(other)? })
+            Some(Instant {
+                t: self.t.checked_add_duration(other)?,
+            })
         }
 
         pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
-            Some(Instant { t: self.t.checked_sub_duration(other)? })
+            Some(Instant {
+                t: self.t.checked_sub_duration(other)?,
+            })
         }
 
         pub fn get_tup(&self) -> (i64, i64) {
@@ -184,7 +205,9 @@ mod inner {
 
     impl SystemTime {
         pub fn now() -> SystemTime {
-            SystemTime { t: now(libc::CLOCK_REALTIME) }
+            SystemTime {
+                t: now(libc::CLOCK_REALTIME),
+            }
         }
 
         pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
@@ -192,11 +215,15 @@ mod inner {
         }
 
         pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
-            Some(SystemTime { t: self.t.checked_add_duration(other)? })
+            Some(SystemTime {
+                t: self.t.checked_add_duration(other)?,
+            })
         }
 
         pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
-            Some(SystemTime { t: self.t.checked_sub_duration(other)? })
+            Some(SystemTime {
+                t: self.t.checked_sub_duration(other)?,
+            })
         }
 
         pub fn get_tup(&self) -> (i64, i64) {
@@ -220,13 +247,18 @@ mod inner {
     }
 
     fn now(clock: libc::clockid_t) -> Timespec {
-        let mut t = Timespec { t: libc::timespec { tv_sec: 0, tv_nsec: 0 } };
-        cvt(unsafe { libc::clock_gettime(clock, &mut t.t) }).unwrap();
+        let mut t = Timespec {
+            t: libc::timespec {
+                tv_sec: 0,
+                tv_nsec: 0,
+            },
+        };
+        cvt_ocall(unsafe { libc::clock_gettime(clock, &mut t.t) }).unwrap();
         t
     }
 
     mod libc {
-        pub use sgx_trts::libc::*;
         pub use sgx_trts::libc::ocall::clock_gettime;
+        pub use sgx_trts::libc::*;
     }
-}
\ No newline at end of file
+}
diff --git a/sgx_tstd/src/sys_common/net.rs b/sgx_tstd/src/sys_common/net.rs
index 6e7f400..d086471 100644
--- a/sgx_tstd/src/sys_common/net.rs
+++ b/sgx_tstd/src/sys_common/net.rs
@@ -17,18 +17,18 @@
 
 #![allow(dead_code)]
 
-use sgx_trts::libc::{c_int, c_uint, c_void};
-use core::cmp;
-use core::fmt;
-use core::mem;
-use core::ptr;
-use core::convert::{TryFrom, TryInto};
 use crate::ffi::CString;
 use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut};
 use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
-use crate::sys::net::{cvt, cvt_gai, cvt_r, init, wrlen_t, Socket};
-use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys::net::{init, Socket};
+use crate::sys::{cvt_ocall, cvt_ocall_r};
+use crate::sys_common::{AsInner, FromInner};
 use crate::time::Duration;
+use alloc_crate::vec;
+use core::convert::{TryFrom, TryInto};
+use core::fmt;
+use core::mem;
+use sgx_trts::libc::{c_int, c_uint, c_void, SockAddr};
 
 ////////////////////////////////////////////////////////////////////////////////
 // sockaddr and misc bindings
@@ -37,7 +37,7 @@ use crate::time::Duration;
 pub fn setsockopt<T>(sock: &Socket, opt: c_int, val: c_int, payload: T) -> io::Result<()> {
     unsafe {
         let payload = &payload as *const T as *const c_void;
-        cvt(libc::setsockopt(
+        cvt_ocall(libc::setsockopt(
             *sock.as_inner(),
             opt,
             val,
@@ -52,7 +52,7 @@ pub fn getsockopt<T: Copy>(sock: &Socket, opt: c_int, val: c_int) -> io::Result<
     unsafe {
         let mut slot: T = mem::zeroed();
         let mut len = mem::size_of::<T>() as libc::socklen_t;
-        cvt(libc::getsockopt(
+        cvt_ocall(libc::getsockopt(
             *sock.as_inner(),
             opt,
             val,
@@ -66,16 +66,24 @@ pub fn getsockopt<T: Copy>(sock: &Socket, opt: c_int, val: c_int) -> io::Result<
 
 fn sockname<F>(f: F) -> io::Result<SocketAddr>
 where
-    F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> c_int,
+    F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::OCallResult<()>,
 {
     unsafe {
         let mut storage: libc::sockaddr_storage = mem::zeroed();
         let mut len = mem::size_of_val(&storage) as libc::socklen_t;
-        cvt(f(&mut storage as *mut _ as *mut _, &mut len))?;
+        cvt_ocall(f(&mut storage as *mut _ as *mut _, &mut len))?;
         sockaddr_to_addr(&storage, len as usize)
     }
 }
 
+fn sockname2<F>(f: F) -> io::Result<SocketAddr>
+where
+    F: FnOnce() -> libc::OCallResult<libc::SockAddr>,
+{
+    let sa = cvt_ocall(f())?;
+    sa.try_into()
+}
+
 pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage, len: usize) -> io::Result<SocketAddr> {
     match storage.ss_family as c_int {
         libc::AF_INET => {
@@ -103,8 +111,7 @@ fn to_ipv6mr_interface(value: u32) -> c_uint {
 ////////////////////////////////////////////////////////////////////////////////
 
 pub struct LookupHost {
-    original: *mut libc::addrinfo,
-    cur: *mut libc::addrinfo,
+    iter: vec::IntoIter<SockAddr>,
     port: u16,
 }
 
@@ -117,28 +124,17 @@ impl LookupHost {
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> {
-        loop {
-            unsafe {
-                let cur = self.cur.as_ref()?;
-                self.cur = cur.ai_next;
-                match sockaddr_to_addr(mem::transmute(cur.ai_addr), cur.ai_addrlen as usize) {
-                    Ok(addr) => return Some(addr),
-                    Err(_) => continue,
-                }
-            }
-        }
+        self.iter.next().map(|sai| match sai {
+            SockAddr::IN4(addr) => SocketAddr::V4(FromInner::from_inner(addr)),
+            SockAddr::IN6(addr) => SocketAddr::V6(FromInner::from_inner(addr)),
+            _ => unreachable!(),
+        })
     }
 }
 
 unsafe impl Sync for LookupHost {}
 unsafe impl Send for LookupHost {}
 
-impl Drop for LookupHost {
-    fn drop(&mut self) {
-        unsafe { libc::freeaddrinfo(self.original) }
-    }
-}
-
 impl TryFrom<&str> for LookupHost {
     type Error = io::Error;
 
@@ -169,13 +165,15 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
         init();
 
         let c_host = CString::new(host)?;
-        let mut hints: libc::addrinfo = unsafe { mem::zeroed() };
-        hints.ai_socktype = libc::SOCK_STREAM;
-        let mut res = ptr::null_mut();
-        unsafe {
-            cvt_gai(libc::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
-                .map(|_| LookupHost { original: res, cur: res, port })
-        }
+        let mut hints = libc::AddrInfoHints::default();
+        hints.socktype = libc::SOCK_STREAM;
+
+        let addr_vec = unsafe { cvt_ocall(libc::getaddrinfo(Some(&c_host), None, Some(hints)))? };
+
+        Ok(LookupHost {
+            iter: addr_vec.into_iter(),
+            port,
+        })
     }
 }
 
@@ -217,8 +215,8 @@ impl TcpStream {
         init();
 
         let sock = Socket::new_socket_addr_type(addr, libc::SOCK_STREAM)?;
-        let (addrp, len) = addr.into_inner();
-        cvt_r(|| unsafe { libc::connect(*sock.as_inner(), addrp, len) })?;
+        let sock_addr = addr.to_owned().into();
+        cvt_ocall_r(|| unsafe { libc::connect(*sock.as_inner(), &sock_addr) })?;
         Ok(TcpStream { inner: sock })
     }
 
@@ -227,8 +225,8 @@ impl TcpStream {
 
         init();
 
-        let (addrp, len) = addr.into_inner();
-        cvt_r(|| unsafe { libc::connect(*self.inner.as_inner(), addrp, len) }).map(drop)
+        let sock_addr = addr.to_owned().into();
+        cvt_ocall_r(|| unsafe { libc::connect(*self.inner.as_inner(), &sock_addr) }).map(drop)
     }
 
     pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
@@ -280,15 +278,8 @@ impl TcpStream {
     }
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
-        let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
-        let ret = cvt(unsafe {
-            libc::send(
-                *self.inner.as_inner(),
-                buf.as_ptr() as *const c_void,
-                len,
-                libc::MSG_NOSIGNAL,
-            )
-        })?;
+        let ret =
+            cvt_ocall(unsafe { libc::send(*self.inner.as_inner(), buf, libc::MSG_NOSIGNAL) })?;
         Ok(ret as usize)
     }
 
@@ -297,15 +288,11 @@ impl TcpStream {
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        sockname(|buf, len| unsafe {
-            libc::getpeername(*self.inner.as_inner(), buf, len)
-        })
+        sockname2(|| unsafe { libc::getpeername(*self.inner.as_inner()) })
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        sockname(|buf, len| unsafe {
-            libc::getsockname(*self.inner.as_inner(), buf, len)
-        })
+        sockname2(|| unsafe { libc::getsockname(*self.inner.as_inner()) })
     }
 
     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
@@ -334,7 +321,12 @@ impl TcpStream {
     }
 
     pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
-        setsockopt(&self.inner, libc::IPPROTO_IPV6, libc::IPV6_V6ONLY, only_v6 as c_int)
+        setsockopt(
+            &self.inner,
+            libc::IPPROTO_IPV6,
+            libc::IPV6_V6ONLY,
+            only_v6 as c_int,
+        )
     }
 
     pub fn only_v6(&self) -> io::Result<bool> {
@@ -419,11 +411,11 @@ impl TcpListener {
         setsockopt(&sock, libc::SOL_SOCKET, libc::SO_REUSEADDR, 1 as c_int)?;
 
         // Bind our new socket
-        let (addrp, len) = addr.into_inner();
-        cvt(unsafe { libc::bind(*sock.as_inner(), addrp, len as _) })?;
+        let sock_addr = addr.to_owned().into();
+        cvt_ocall(unsafe { libc::bind(*sock.as_inner(), &sock_addr) })?;
 
         // Start listening
-        cvt(unsafe { libc::listen(*sock.as_inner(), 128) })?;
+        cvt_ocall(unsafe { libc::listen(*sock.as_inner(), 128) })?;
         Ok(TcpListener { inner: sock })
     }
 
@@ -432,10 +424,15 @@ impl TcpListener {
 
         init();
 
-        setsockopt(&self.inner, libc::SOL_SOCKET, libc::SO_REUSEADDR, 1 as c_int)?;
-        let (addrp, len) = addr.into_inner();
-        cvt(unsafe { libc::bind(*self.inner.as_inner(), addrp, len as _) })?;
-        cvt(unsafe { libc::listen(*self.inner.as_inner(), 128) }).map(drop)
+        setsockopt(
+            &self.inner,
+            libc::SOL_SOCKET,
+            libc::SO_REUSEADDR,
+            1 as c_int,
+        )?;
+        let sock_addr = addr.to_owned().into();
+        cvt_ocall(unsafe { libc::bind(*self.inner.as_inner(), &sock_addr) })?;
+        cvt_ocall(unsafe { libc::listen(*self.inner.as_inner(), 128) })
     }
 
     pub fn socket(&self) -> &Socket {
@@ -447,16 +444,12 @@ impl TcpListener {
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        sockname(|buf, len| unsafe {
-            libc::getsockname(*self.inner.as_inner(), buf, len)
-        })
+        sockname2(|| unsafe { libc::getsockname(*self.inner.as_inner()) })
     }
 
     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
-        let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
-        let mut len = mem::size_of_val(&storage) as libc::socklen_t;
-        let sock = self.inner.accept(&mut storage as *mut _ as *mut _, &mut len)?;
-        let addr = sockaddr_to_addr(&storage, len as usize)?;
+        let (sock, addr) = self.inner.accept()?;
+        let addr = addr.try_into()?;
         Ok((TcpStream { inner: sock }, addr))
     }
 
@@ -474,7 +467,12 @@ impl TcpListener {
     }
 
     pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
-        setsockopt(&self.inner, libc::IPPROTO_IPV6, libc::IPV6_V6ONLY, only_v6 as c_int)
+        setsockopt(
+            &self.inner,
+            libc::IPPROTO_IPV6,
+            libc::IPV6_V6ONLY,
+            only_v6 as c_int,
+        )
     }
 
     pub fn only_v6(&self) -> io::Result<bool> {
@@ -519,7 +517,6 @@ pub struct UdpSocket {
 }
 
 impl UdpSocket {
-
     pub fn new(sockfd: c_int) -> io::Result<UdpSocket> {
         let sock = Socket::new(sockfd)?;
         Ok(UdpSocket { inner: sock })
@@ -549,8 +546,8 @@ impl UdpSocket {
         init();
 
         let sock = Socket::new_socket_addr_type(addr, libc::SOCK_DGRAM)?;
-        let (addrp, len) = addr.into_inner();
-        cvt(unsafe { libc::bind(*sock.as_inner(), addrp, len as _) })?;
+        let sock_addr = addr.to_owned().into();
+        cvt_ocall(unsafe { libc::bind(*sock.as_inner(), &sock_addr) })?;
         Ok(UdpSocket { inner: sock })
     }
 
@@ -559,8 +556,8 @@ impl UdpSocket {
 
         init();
 
-        let (addrp, len) = addr.into_inner();
-        cvt(unsafe { libc::bind(*self.inner.as_inner(), addrp, len as _) }).map(drop)
+        let sock_addr = addr.to_owned().into();
+        cvt_ocall(unsafe { libc::bind(*self.inner.as_inner(), &sock_addr) }).map(drop)
     }
 
     pub fn socket(&self) -> &Socket {
@@ -572,15 +569,11 @@ impl UdpSocket {
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        sockname(|buf, len| unsafe {
-            libc::getpeername(*self.inner.as_inner(), buf, len)
-        })
+        sockname2(|| unsafe { libc::getpeername(*self.inner.as_inner()) })
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        sockname(|buf, len| unsafe { 
-            libc::getsockname(*self.inner.as_inner(), buf, len) 
-        })
+        sockname2(|| unsafe { libc::getsockname(*self.inner.as_inner()) })
     }
 
     pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
@@ -592,17 +585,9 @@ impl UdpSocket {
     }
 
     pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
-        let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
-        let (dstp, dstlen) = dst.into_inner();
-        let ret = cvt(unsafe {
-            libc::sendto(
-                *self.inner.as_inner(),
-                buf.as_ptr() as *const c_void,
-                len,
-                libc::MSG_NOSIGNAL,
-                dstp,
-                dstlen,
-            )
+        let dst = dst.to_owned().into();
+        let ret = cvt_ocall(unsafe {
+            libc::sendto(*self.inner.as_inner(), &buf, libc::MSG_NOSIGNAL, &dst)
         })?;
         Ok(ret as usize)
     }
@@ -628,7 +613,12 @@ impl UdpSocket {
     }
 
     pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
-        setsockopt(&self.inner, libc::SOL_SOCKET, libc::SO_BROADCAST, broadcast as c_int)
+        setsockopt(
+            &self.inner,
+            libc::SOL_SOCKET,
+            libc::SO_BROADCAST,
+            broadcast as c_int,
+        )
     }
 
     pub fn broadcast(&self) -> io::Result<bool> {
@@ -637,7 +627,12 @@ impl UdpSocket {
     }
 
     pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
-        setsockopt(&self.inner, libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, multicast_loop_v4 as c_int)
+        setsockopt(
+            &self.inner,
+            libc::IPPROTO_IP,
+            libc::IP_MULTICAST_LOOP,
+            multicast_loop_v4 as c_int,
+        )
     }
 
     pub fn multicast_loop_v4(&self) -> io::Result<bool> {
@@ -646,7 +641,12 @@ impl UdpSocket {
     }
 
     pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
-        setsockopt(&self.inner, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, multicast_ttl_v4 as c_int)
+        setsockopt(
+            &self.inner,
+            libc::IPPROTO_IP,
+            libc::IP_MULTICAST_TTL,
+            multicast_ttl_v4 as c_int,
+        )
     }
 
     pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
@@ -655,7 +655,12 @@ impl UdpSocket {
     }
 
     pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
-        setsockopt(&self.inner, libc::IPPROTO_IPV6, libc::IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int)
+        setsockopt(
+            &self.inner,
+            libc::IPPROTO_IPV6,
+            libc::IPV6_MULTICAST_LOOP,
+            multicast_loop_v6 as c_int,
+        )
     }
 
     pub fn multicast_loop_v6(&self) -> io::Result<bool> {
@@ -676,7 +681,12 @@ impl UdpSocket {
             ipv6mr_multiaddr: *multiaddr.as_inner(),
             ipv6mr_interface: to_ipv6mr_interface(interface),
         };
-        setsockopt(&self.inner, libc::IPPROTO_IPV6, libc::IPV6_ADD_MEMBERSHIP, mreq)
+        setsockopt(
+            &self.inner,
+            libc::IPPROTO_IPV6,
+            libc::IPV6_ADD_MEMBERSHIP,
+            mreq,
+        )
     }
 
     pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
@@ -684,7 +694,12 @@ impl UdpSocket {
             imr_multiaddr: *multiaddr.as_inner(),
             imr_interface: *interface.as_inner(),
         };
-        setsockopt(&self.inner, libc::IPPROTO_IP, libc::IP_DROP_MEMBERSHIP, mreq)
+        setsockopt(
+            &self.inner,
+            libc::IPPROTO_IP,
+            libc::IP_DROP_MEMBERSHIP,
+            mreq,
+        )
     }
 
     pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
@@ -692,7 +707,12 @@ impl UdpSocket {
             ipv6mr_multiaddr: *multiaddr.as_inner(),
             ipv6mr_interface: to_ipv6mr_interface(interface),
         };
-        setsockopt(&self.inner, libc::IPPROTO_IPV6, libc::IPV6_DROP_MEMBERSHIP, mreq)
+        setsockopt(
+            &self.inner,
+            libc::IPPROTO_IPV6,
+            libc::IPV6_DROP_MEMBERSHIP,
+            mreq,
+        )
     }
 
     pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
@@ -721,21 +741,14 @@ impl UdpSocket {
     }
 
     pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
-        let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
-        let ret = cvt(unsafe {
-            libc::send(
-                *self.inner.as_inner(),
-                buf.as_ptr() as *const c_void,
-                len,
-                libc::MSG_NOSIGNAL,
-            )
-        })?;
+        let ret =
+            cvt_ocall(unsafe { libc::send(*self.inner.as_inner(), buf, libc::MSG_NOSIGNAL) })?;
         Ok(ret as usize)
     }
 
     pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
-        let (addrp, len) = addr?.into_inner();
-        cvt_r(|| unsafe { libc::connect(*self.inner.as_inner(), addrp, len) }).map(drop)
+        let sock_addr = addr?.to_owned().into();
+        cvt_ocall_r(|| unsafe { libc::connect(*self.inner.as_inner(), &sock_addr) }).map(drop)
     }
 }
 
@@ -759,7 +772,9 @@ impl fmt::Debug for UdpSocket {
 }
 
 mod libc {
+    pub use sgx_trts::libc::ocall::{
+        bind, connect, getaddrinfo, getpeername, getsockname, getsockopt, listen, send, sendto,
+        setsockopt,
+    };
     pub use sgx_trts::libc::*;
-    pub use sgx_trts::libc::ocall::{bind, listen, connect, setsockopt, getsockopt, send, sendto,
-                                    getpeername, getsockname, getaddrinfo, freeaddrinfo};
-}
\ No newline at end of file
+}
diff --git a/sgx_urts/src/env.rs b/sgx_urts/src/env.rs
index 3816d3f..973c862 100644
--- a/sgx_urts/src/env.rs
+++ b/sgx_urts/src/env.rs
@@ -17,6 +17,7 @@
 
 use libc::{self, c_char, c_int, passwd, size_t, uid_t};
 use std::io::Error;
+use std::ptr;
 
 #[no_mangle]
 pub extern "C" fn u_getuid_ocall() -> uid_t {
@@ -32,8 +33,39 @@ pub extern "C" fn u_environ_ocall() -> *const *const c_char {
 }
 
 #[no_mangle]
-pub extern "C" fn u_getenv_ocall(name: *const c_char) -> *const c_char {
-    unsafe { libc::getenv(name) }
+pub extern "C" fn u_getenv_ocall(
+    error: *mut c_int,
+    name: *const c_char,
+    buf: *mut c_char,
+    bufsz: size_t,
+    isset: *mut c_int
+) -> c_int {
+    unsafe {
+        if bufsz == 0 || buf.is_null() || isset.is_null() {
+            if !error.is_null() {
+                *error = libc::EINVAL;
+            }
+            return -1;
+        }
+
+        let rptr = libc::getenv(name);
+
+        if rptr.is_null() {
+            *isset = 0;
+            *buf = 0;
+        } else {
+            *isset = 1;
+            let sn = libc::strlen(rptr) + 1;
+            if sn > bufsz {
+                if !error.is_null() {
+                    *error = libc::ERANGE;
+                }
+                return -1;
+            }
+            ptr::copy_nonoverlapping(rptr, buf, sn);
+        };
+        0
+    }
 }
 
 #[no_mangle]
@@ -72,18 +104,18 @@ pub extern "C" fn u_unsetenv_ocall(error: *mut c_int, name: *const c_char) -> c_
 }
 
 #[no_mangle]
-pub extern "C" fn u_getcwd_ocall(error: *mut c_int, buf: *mut c_char, size: size_t) -> *mut c_char {
-    let mut errno = 0;
+pub extern "C" fn u_getcwd_ocall(error: *mut c_int, buf: *mut c_char, size: size_t) -> c_int {
     let ret = unsafe { libc::getcwd(buf, size) };
     if ret.is_null() {
-        errno = Error::last_os_error().raw_os_error().unwrap_or(0);
-    }
-    if !error.is_null() {
-        unsafe {
-            *error = errno;
+        let errno = Error::last_os_error().raw_os_error().unwrap_or(0);
+        if !error.is_null() {
+            unsafe {
+                *error = errno;
+            }
         }
+        return -1;
     }
-    ret
+    0
 }
 
 #[no_mangle]
diff --git a/sgx_urts/src/fd.rs b/sgx_urts/src/fd.rs
index cfbf5a3..a416867 100644
--- a/sgx_urts/src/fd.rs
+++ b/sgx_urts/src/fd.rs
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use libc::{self, c_int, c_ulong, c_void, iovec, off64_t, size_t, ssize_t};
+use libc::{self, c_int, c_ulong, c_void, off64_t, size_t, ssize_t};
 use std::io::Error;
 
 #[no_mangle]
@@ -60,47 +60,6 @@ pub extern "C" fn u_pread64_ocall(
 }
 
 #[no_mangle]
-pub extern "C" fn u_readv_ocall(
-    error: *mut c_int,
-    fd: c_int,
-    iov: *const iovec,
-    iovcnt: c_int,
-) -> ssize_t {
-    let mut errno = 0;
-    let ret = unsafe { libc::readv(fd, iov, iovcnt) };
-    if ret < 0 {
-        errno = Error::last_os_error().raw_os_error().unwrap_or(0);
-    }
-    if !error.is_null() {
-        unsafe {
-            *error = errno;
-        }
-    }
-    ret
-}
-
-#[no_mangle]
-pub extern "C" fn u_preadv64_ocall(
-    error: *mut c_int,
-    fd: c_int,
-    iov: *const iovec,
-    iovcnt: c_int,
-    offset: off64_t,
-) -> ssize_t {
-    let mut errno = 0;
-    let ret = unsafe { libc::preadv64(fd, iov, iovcnt, offset) };
-    if ret < 0 {
-        errno = Error::last_os_error().raw_os_error().unwrap_or(0);
-    }
-    if !error.is_null() {
-        unsafe {
-            *error = errno;
-        }
-    }
-    ret
-}
-
-#[no_mangle]
 pub extern "C" fn u_write_ocall(
     error: *mut c_int,
     fd: c_int,
@@ -142,47 +101,6 @@ pub extern "C" fn u_pwrite64_ocall(
 }
 
 #[no_mangle]
-pub extern "C" fn u_writev_ocall(
-    error: *mut c_int,
-    fd: c_int,
-    iov: *const iovec,
-    iovcnt: c_int,
-) -> ssize_t {
-    let mut errno = 0;
-    let ret = unsafe { libc::writev(fd, iov, iovcnt) };
-    if ret < 0 {
-        errno = Error::last_os_error().raw_os_error().unwrap_or(0);
-    }
-    if !error.is_null() {
-        unsafe {
-            *error = errno;
-        }
-    }
-    ret
-}
-
-#[no_mangle]
-pub extern "C" fn u_pwritev64_ocall(
-    error: *mut c_int,
-    fd: c_int,
-    iov: *const iovec,
-    iovcnt: c_int,
-    offset: off64_t,
-) -> ssize_t {
-    let mut errno = 0;
-    let ret = unsafe { libc::pwritev64(fd, iov, iovcnt, offset) };
-    if ret < 0 {
-        errno = Error::last_os_error().raw_os_error().unwrap_or(0);
-    }
-    if !error.is_null() {
-        unsafe {
-            *error = errno;
-        }
-    }
-    ret
-}
-
-#[no_mangle]
 pub extern "C" fn u_fcntl_arg0_ocall(error: *mut c_int, fd: c_int, cmd: c_int) -> c_int {
     let mut errno = 0;
     let ret = unsafe { libc::fcntl(fd, cmd) };
diff --git a/sgx_urts/src/file.rs b/sgx_urts/src/file.rs
index 85edd82..7b13e69 100644
--- a/sgx_urts/src/file.rs
+++ b/sgx_urts/src/file.rs
@@ -411,18 +411,25 @@ pub extern "C" fn u_symlink_ocall(
 }
 
 #[no_mangle]
-pub extern "C" fn u_realpath_ocall(error: *mut c_int, pathname: *const c_char) -> *mut c_char {
+pub extern "C" fn u_realpath_ocall(
+    error: *mut c_int,
+    pathname: *const c_char,
+    resolved_buf: *mut c_char,
+    _bufsz: size_t,
+) -> c_int {
     let mut errno = 0;
-    let ret = unsafe { libc::realpath(pathname, ptr::null_mut()) };
+    let mut result = 0;
+    let ret = unsafe { libc::realpath(pathname, resolved_buf) };
     if ret.is_null() {
         errno = Error::last_os_error().raw_os_error().unwrap_or(0);
+        result = -1;
     }
     if !error.is_null() {
         unsafe {
             *error = errno;
         }
     }
-    ret
+    result
 }
 
 #[no_mangle]
@@ -474,9 +481,17 @@ pub extern "C" fn u_opendir_ocall(error: *mut c_int, pathname: *const c_char) ->
 pub extern "C" fn u_readdir64_r_ocall(
     dirp: *mut DIR,
     entry: *mut dirent64,
-    result: *mut *mut dirent64,
+    eods: *mut c_int, // end of directory stream
 ) -> c_int {
-    unsafe { libc::readdir64_r(dirp, entry, result) }
+    let mut result_ptr = ptr::null_mut();
+    let result = unsafe { libc::readdir64_r(dirp, entry, &mut result_ptr) };
+    assert!(!eods.is_null());
+    if result_ptr.is_null() {
+        unsafe {
+            *eods= 1;
+        }
+    }
+    return result;
 }
 
 #[no_mangle]
diff --git a/sgx_urts/src/net.rs b/sgx_urts/src/net.rs
index 765da79..e641725 100644
--- a/sgx_urts/src/net.rs
+++ b/sgx_urts/src/net.rs
@@ -15,36 +15,57 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use libc::{self, addrinfo, c_char, c_int};
+use libc::{self, addrinfo, c_char, c_int, size_t};
 use std::io::Error;
 
+use core::ptr;
+
 #[no_mangle]
 pub extern "C" fn u_getaddrinfo_ocall(
     error: *mut c_int,
     node: *const c_char,
     service: *const c_char,
-    hints: *const addrinfo,
-    res: *mut *mut addrinfo,
+    hints: *mut addrinfo,
+    entry_size: size_t,
+    buf: *mut u8,
+    bufsz: size_t,
+    out_cnt: *mut size_t,
 ) -> c_int {
     let mut errno = 0;
-    let ret = unsafe { libc::getaddrinfo(node, service, hints, res) };
+    let mut res: *mut addrinfo = ptr::null_mut();
+
+    let ret = unsafe { libc::getaddrinfo(node, service, hints, &mut res) };
+
     if ret == libc::EAI_SYSTEM {
         errno = Error::last_os_error().raw_os_error().unwrap_or(0);
     }
+
     if !error.is_null() {
         unsafe {
             *error = errno;
         }
     }
-    ret
-}
 
-#[no_mangle]
-pub extern "C" fn u_freeaddrinfo_ocall(res: *mut addrinfo) {
-    unsafe { libc::freeaddrinfo(res) }
-}
+    if ret != 0 {
+        return ret;
+    }
 
-#[no_mangle]
-pub extern "C" fn u_gai_strerror_ocall(errcode: c_int) -> *const c_char {
-    unsafe { libc::gai_strerror(errcode) }
+    unsafe {
+        let mut i = 0;
+        let mut cur_ptr = res;
+        while cur_ptr != ptr::null_mut() && (i + entry_size) < bufsz {
+            let cur: &addrinfo = &*cur_ptr;
+            let len = cur.ai_addrlen as usize;
+            if len > entry_size {
+                return 1;
+            }
+            std::ptr::copy_nonoverlapping(cur.ai_addr as *const u8, buf.add(i), len);
+            i += entry_size;
+            cur_ptr = cur.ai_next;
+        }
+        *out_cnt = i / entry_size;
+    }
+
+    unsafe { libc::freeaddrinfo(res) };
+    return 0;
 }
diff --git a/sgx_urts/src/socket.rs b/sgx_urts/src/socket.rs
index d606a1c..c139f9d 100644
--- a/sgx_urts/src/socket.rs
+++ b/sgx_urts/src/socket.rs
@@ -95,28 +95,6 @@ pub extern "C" fn u_listen_ocall(error: *mut c_int, sockfd: c_int, backlog: c_in
 }
 
 #[no_mangle]
-pub extern "C" fn u_accept_ocall(
-    error: *mut c_int,
-    sockfd: c_int,
-    addr: *mut sockaddr,
-    addrlen_in: socklen_t,
-    addrlen_out: *mut socklen_t,
-) -> c_int {
-    let mut errno = 0;
-    unsafe { *addrlen_out = addrlen_in };
-    let ret = unsafe { libc::accept(sockfd, addr, addrlen_out) };
-    if ret < 0 {
-        errno = Error::last_os_error().raw_os_error().unwrap_or(0);
-    }
-    if !error.is_null() {
-        unsafe {
-            *error = errno;
-        }
-    }
-    ret
-}
-
-#[no_mangle]
 pub extern "C" fn u_accept4_ocall(
     error: *mut c_int,
     sockfd: c_int,
diff --git a/sgx_ustdc/net.c b/sgx_ustdc/net.c
index 1228eaa..1c0ccb6 100644
--- a/sgx_ustdc/net.c
+++ b/sgx_ustdc/net.c
@@ -37,8 +37,3 @@ void u_freeaddrinfo_ocall(struct addrinfo *res)
 {
     return freeaddrinfo(res);
 }
-
-const char *u_gai_strerror_ocall(int errcode)
-{
-    return gai_strerror(errcode);
-}
\ No newline at end of file
diff --git a/sgx_ustdc/socket.c b/sgx_ustdc/socket.c
index 9b8141a..83dccfe 100644
--- a/sgx_ustdc/socket.c
+++ b/sgx_ustdc/socket.c
@@ -59,19 +59,6 @@ int u_listen_ocall(int *error, int sockfd, int backlog)
     return ret;
 }
 
-int u_accept_ocall(int *error,
-                   int sockfd,
-                   struct sockaddr *addr,
-                   socklen_t addrlen_in,
-                   socklen_t *addrlen_out)
-{
-    *addrlen_out = addrlen_in;
-    int ret = accept(sockfd, addr, addrlen_out);
-     if (error) {
-        *error = ret == -1 ? errno : 0;
-    }
-    return ret;
-}
 
 int u_accept4_ocall(int *error,
                     int sockfd,

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org