about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2020-11-30 13:19:48 -0800
committerAlex Crichton <alex@alexcrichton.com>2021-01-14 10:40:10 -0800
commit5756bd7f2daaa1acf486f911f7246498c7ee6881 (patch)
tree79dd8f8e43f5d527015b3fe6da0d4146b2229853
parentfc9944fe84a683f0450c0921a935456e51b1c3ae (diff)
downloadrust-5756bd7f2daaa1acf486f911f7246498c7ee6881.tar.gz
rust-5756bd7f2daaa1acf486f911f7246498c7ee6881.zip
std: Update wasi-libc commit of the wasm32-wasi target
This brings in an implementation of `current_dir` and `set_current_dir`
(emulation in `wasi-libc`) as well as an updated version of finding
relative paths. This also additionally updates clang to the latest
release to build wasi-libc with.
-rw-r--r--library/std/src/sys/wasi/fs.rs55
-rw-r--r--library/std/src/sys/wasi/os.rs45
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh10
3 files changed, 82 insertions, 28 deletions
diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index 120b9f59f1e..4134ef67671 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -627,33 +627,50 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
 /// to any pre-opened file descriptor.
 fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
     let p = CString::new(p.as_os_str().as_bytes())?;
-    unsafe {
-        let mut ret = ptr::null();
-        let fd = __wasilibc_find_relpath(p.as_ptr(), &mut ret);
-        if fd == -1 {
-            let msg = format!(
-                "failed to find a pre-opened file descriptor \
-                 through which {:?} could be opened",
-                p
+    let mut buf = Vec::<u8>::with_capacity(512);
+    loop {
+        unsafe {
+            let mut relative_path = buf.as_ptr().cast();
+            let mut abs_prefix = ptr::null();
+            let fd = __wasilibc_find_relpath(
+                p.as_ptr(),
+                &mut abs_prefix,
+                &mut relative_path,
+                buf.capacity(),
             );
-            return Err(io::Error::new(io::ErrorKind::Other, msg));
+            if fd == -1 {
+                if io::Error::last_os_error().raw_os_error() == Some(libc::ENOMEM) {
+                    // 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);
+                    continue;
+                }
+                let msg = format!(
+                    "failed to find a pre-opened file descriptor \
+                     through which {:?} could be opened",
+                    p
+                );
+                return Err(io::Error::new(io::ErrorKind::Other, msg));
+            }
+            let len = CStr::from_ptr(buf.as_ptr().cast()).to_bytes().len();
+            buf.set_len(len);
+            buf.shrink_to_fit();
+
+            return Ok((
+                ManuallyDrop::new(WasiFd::from_raw(fd as u32)),
+                PathBuf::from(OsString::from_vec(buf)),
+            ));
         }
-        let path = Path::new(OsStr::from_bytes(CStr::from_ptr(ret).to_bytes()));
-
-        // FIXME: right now `path` is a pointer into `p`, the `CString` above.
-        // When we return `p` is deallocated and we can't use it, so we need to
-        // currently separately allocate `path`. If this becomes an issue though
-        // we should probably turn this into a closure-taking interface or take
-        // `&CString` and then pass off `&Path` tied to the same lifetime.
-        let path = path.to_path_buf();
-
-        return Ok((ManuallyDrop::new(WasiFd::from_raw(fd as u32)), path));
     }
 
     extern "C" {
         pub fn __wasilibc_find_relpath(
             path: *const libc::c_char,
+            abs_prefix: *mut *const libc::c_char,
             relative_path: *mut *const libc::c_char,
+            relative_path_len: libc::size_t,
         ) -> libc::c_int;
     }
 }
diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs
index 33c796ae941..185d6109cb9 100644
--- a/library/std/src/sys/wasi/os.rs
+++ b/library/std/src/sys/wasi/os.rs
@@ -13,6 +13,16 @@ use crate::sys::memchr;
 use crate::sys::{unsupported, Void};
 use crate::vec;
 
+// Add a few symbols not in upstream `libc` just yet.
+mod libc {
+    pub use libc::*;
+
+    extern "C" {
+        pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
+        pub fn chdir(dir: *const c_char) -> c_int;
+    }
+}
+
 #[cfg(not(target_feature = "atomics"))]
 pub unsafe fn env_lock() -> impl Any {
     // No need for a lock if we're single-threaded, but this function will need
@@ -41,11 +51,40 @@ pub fn error_string(errno: i32) -> String {
 }
 
 pub fn getcwd() -> io::Result<PathBuf> {
-    unsupported()
+    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);
+        }
+    }
 }
 
-pub fn chdir(_: &path::Path) -> io::Result<()> {
-    unsupported()
+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()),
+        }
+    }
 }
 
 pub struct SplitPaths<'a>(&'a Void);
diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
index c6db200f866..82d0f7dc471 100755
--- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
+++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
@@ -1,18 +1,16 @@
 #!/bin/sh
-#
-# ignore-tidy-linelength
 
 set -ex
 
-# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz
-curl https://ci-mirrors.rust-lang.org/rustc/clang%2Bllvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz | \
+# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-11.0.0/clang+llvm-11.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
+curl https://ci-mirrors.rust-lang.org/rustc/2021-01-14-clang%2Bllvm-11.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz | \
   tar xJf -
-export PATH=`pwd`/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04/bin:$PATH
+export PATH=`pwd`/clang+llvm-11.0.1-x86_64-linux-gnu-ubuntu-16.04/bin:$PATH
 
 git clone https://github.com/WebAssembly/wasi-libc
 
 cd wasi-libc
-git reset --hard 215adc8ac9f91eb055311acc72683fd2eb1ae15a
+git reset --hard 58795582905e08fa7748846c1971b4ab911d1e16
 make -j$(nproc) INSTALL_DIR=/wasm32-wasi install
 
 cd ..