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:35 UTC

[incubator-teaclave-sgx-sdk] branch sec-liboc created (now a1728f2)

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

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


      at a1728f2  Change sgx_libc interface.

This branch includes the following new commits:

     new a1728f2  Change sgx_libc interface.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


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


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

Posted by zf...@apache.org.
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