about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-04-05 22:56:15 +0000
committerbors <bors@rust-lang.org>2019-04-05 22:56:15 +0000
commit05b4554e77ef32a97060b1bfffd1f621bf15bb88 (patch)
tree245d505fa744308ff7ffd95a061c6c41f536638f /src/libstd
parentacd8dd6a50d505057a7d7ad8d0d7a4c2bd274200 (diff)
parent8455818b319f47bbe3505ff5307e21d9c4acb869 (diff)
downloadrust-05b4554e77ef32a97060b1bfffd1f621bf15bb88.tar.gz
rust-05b4554e77ef32a97060b1bfffd1f621bf15bb88.zip
Auto merge of #59741 - Centril:rollup-3us4b8q, r=Centril
Rollup of 6 pull requests

Successful merges:

 - #58894 (Fix invalid bounds string generation in rustdoc)
 - #59599 (Updated RELEASES.md for 1.34.0)
 - #59624 (SGX target: Use linker option to avoid code CGU assignment kludge)
 - #59696 (Remove invalid assertion back::link::from add_upstream_rust_crates().)
 - #59707 (Add missing tryfrom example)
 - #59727 (wasi: Use shared API for preopened fds)

Failed merges:

r? @ghost
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/sys/sgx/alloc.rs16
-rw-r--r--src/libstd/sys/sgx/mod.rs9
-rw-r--r--src/libstd/sys/sgx/rwlock.rs42
-rw-r--r--src/libstd/sys/sgx/stdio.rs18
-rw-r--r--src/libstd/sys/wasi/fs.rs173
5 files changed, 130 insertions, 128 deletions
diff --git a/src/libstd/sys/sgx/alloc.rs b/src/libstd/sys/sgx/alloc.rs
index 98eb8397436..b385d567dd8 100644
--- a/src/libstd/sys/sgx/alloc.rs
+++ b/src/libstd/sys/sgx/alloc.rs
@@ -1,4 +1,4 @@
-use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::alloc::{self, GlobalAlloc, Layout, System};
 
 use super::waitqueue::SpinMutex;
 
@@ -30,3 +30,17 @@ unsafe impl GlobalAlloc for System {
         DLMALLOC.lock().realloc(ptr, layout.size(), layout.align(), new_size)
     }
 }
+
+// The following functions are needed by libunwind. These symbols are named
+// in pre-link args for the target specification, so keep that in sync.
+#[cfg(not(test))]
+#[no_mangle]
+pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
+    alloc::alloc(Layout::from_size_align_unchecked(size, align))
+}
+
+#[cfg(not(test))]
+#[no_mangle]
+pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
+    alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
+}
diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs
index b0679f65f0d..a99a534f41e 100644
--- a/src/libstd/sys/sgx/mod.rs
+++ b/src/libstd/sys/sgx/mod.rs
@@ -130,6 +130,15 @@ pub unsafe fn abort_internal() -> ! {
     abi::usercalls::exit(true)
 }
 
+// This function is needed by the panic runtime. The symbol is named in
+// pre-link args for the target specification, so keep that in sync.
+#[cfg(not(test))]
+#[no_mangle]
+// NB. used by both libunwind and libpanic_abort
+pub unsafe extern "C" fn __rust_abort() {
+    abort_internal();
+}
+
 pub fn hashmap_random_keys() -> (u64, u64) {
     fn rdrand64() -> u64 {
         unsafe {
diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs
index 09b5ffb1996..30c47e44eef 100644
--- a/src/libstd/sys/sgx/rwlock.rs
+++ b/src/libstd/sys/sgx/rwlock.rs
@@ -1,10 +1,4 @@
-#[cfg(not(test))]
-use crate::alloc::{self, Layout};
 use crate::num::NonZeroUsize;
-#[cfg(not(test))]
-use crate::slice;
-#[cfg(not(test))]
-use crate::str;
 
 use super::waitqueue::{
     try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable,
@@ -165,10 +159,11 @@ impl RWLock {
     pub unsafe fn destroy(&self) {}
 }
 
+// The following functions are needed by libunwind. These symbols are named
+// in pre-link args for the target specification, so keep that in sync.
 #[cfg(not(test))]
 const EINVAL: i32 = 22;
 
-// used by libunwind port
 #[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
@@ -198,39 +193,6 @@ pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
     return 0;
 }
 
-// the following functions are also used by the libunwind port. They're
-// included here to make sure parallel codegen and LTO don't mess things up.
-#[cfg(not(test))]
-#[no_mangle]
-pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
-    if s < 0 {
-        return;
-    }
-    let buf = slice::from_raw_parts(m as *const u8, s as _);
-    if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) {
-        eprint!("{}", s);
-    }
-}
-
-#[cfg(not(test))]
-#[no_mangle]
-// NB. used by both libunwind and libpanic_abort
-pub unsafe extern "C" fn __rust_abort() {
-    crate::sys::abort_internal();
-}
-
-#[cfg(not(test))]
-#[no_mangle]
-pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
-    alloc::alloc(Layout::from_size_align_unchecked(size, align))
-}
-
-#[cfg(not(test))]
-#[no_mangle]
-pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
-    alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/src/libstd/sys/sgx/stdio.rs b/src/libstd/sys/sgx/stdio.rs
index f2c6892bfb7..a575401f5f6 100644
--- a/src/libstd/sys/sgx/stdio.rs
+++ b/src/libstd/sys/sgx/stdio.rs
@@ -2,6 +2,10 @@ use fortanix_sgx_abi as abi;
 
 use crate::io;
 use crate::sys::fd::FileDesc;
+#[cfg(not(test))]
+use crate::slice;
+#[cfg(not(test))]
+use crate::str;
 
 pub struct Stdin(());
 pub struct Stdout(());
@@ -62,3 +66,17 @@ pub fn is_ebadf(err: &io::Error) -> bool {
 pub fn panic_output() -> Option<impl io::Write> {
     super::abi::panic::SgxPanicOutput::new()
 }
+
+// This function is needed by libunwind. The symbol is named in pre-link args
+// for the target specification, so keep that in sync.
+#[cfg(not(test))]
+#[no_mangle]
+pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
+    if s < 0 {
+        return;
+    }
+    let buf = slice::from_raw_parts(m as *const u8, s as _);
+    if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) {
+        eprint!("{}", s);
+    }
+}
diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs
index 7b1c2bd79cc..589593299d6 100644
--- a/src/libstd/sys/wasi/fs.rs
+++ b/src/libstd/sys/wasi/fs.rs
@@ -1,5 +1,4 @@
-use crate::collections::HashMap;
-use crate::ffi::{OsStr, OsString};
+use crate::ffi::{CStr, CString, OsStr, OsString};
 use crate::fmt;
 use crate::io::{self, IoVec, IoVecMut, SeekFrom};
 use crate::iter;
@@ -7,11 +6,10 @@ use crate::mem::{self, ManuallyDrop};
 use crate::os::wasi::ffi::{OsStrExt, OsStringExt};
 use crate::path::{Path, PathBuf};
 use crate::ptr;
-use crate::sync::atomic::{AtomicPtr, Ordering::SeqCst};
 use crate::sync::Arc;
 use crate::sys::fd::{DirCookie, WasiFd};
 use crate::sys::time::SystemTime;
-use crate::sys::{cvt_wasi, unsupported};
+use crate::sys::unsupported;
 use crate::sys_common::FromInner;
 
 pub use crate::sys_common::fs::copy;
@@ -230,7 +228,11 @@ impl DirEntry {
     }
 
     pub fn metadata(&self) -> io::Result<FileAttr> {
-        metadata_at(&self.inner.dir.fd, 0, OsStr::from_bytes(&self.name).as_ref())
+        metadata_at(
+            &self.inner.dir.fd,
+            0,
+            OsStr::from_bytes(&self.name).as_ref(),
+        )
     }
 
     pub fn file_type(&self) -> io::Result<FileType> {
@@ -377,8 +379,8 @@ impl OpenOptions {
 
 impl File {
     pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
-        let (dir, file) = open_parent(path)?;
-        open_at(&dir, file, opts)
+        let (dir, file) = open_parent(path, libc::__WASI_RIGHT_PATH_OPEN)?;
+        open_at(&dir, &file, opts)
     }
 
     pub fn open_at(&self, path: &Path, opts: &OpenOptions) -> io::Result<File> {
@@ -475,7 +477,7 @@ impl DirBuilder {
     }
 
     pub fn mkdir(&self, p: &Path) -> io::Result<()> {
-        let (dir, file) = open_parent(p)?;
+        let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY)?;
         dir.create_directory(file.as_os_str().as_bytes())
     }
 }
@@ -506,13 +508,13 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
 }
 
 pub fn unlink(p: &Path) -> io::Result<()> {
-    let (dir, file) = open_parent(p)?;
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_UNLINK_FILE)?;
     dir.unlink_file(file.as_os_str().as_bytes())
 }
 
 pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
-    let (old, old_file) = open_parent(old)?;
-    let (new, new_file) = open_parent(new)?;
+    let (old, old_file) = open_parent(old, libc::__WASI_RIGHT_PATH_RENAME_SOURCE)?;
+    let (new, new_file) = open_parent(new, libc::__WASI_RIGHT_PATH_RENAME_TARGET)?;
     old.rename(
         old_file.as_os_str().as_bytes(),
         &new,
@@ -527,13 +529,13 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
 }
 
 pub fn rmdir(p: &Path) -> io::Result<()> {
-    let (dir, file) = open_parent(p)?;
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY)?;
     dir.remove_directory(file.as_os_str().as_bytes())
 }
 
 pub fn readlink(p: &Path) -> io::Result<PathBuf> {
-    let (dir, file) = open_parent(p)?;
-    read_link(&dir, file)
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_READLINK)?;
+    read_link(&dir, &file)
 }
 
 fn read_link(fd: &WasiFd, file: &Path) -> io::Result<PathBuf> {
@@ -568,13 +570,13 @@ fn read_link(fd: &WasiFd, file: &Path) -> io::Result<PathBuf> {
 }
 
 pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
-    let (dst, dst_file) = open_parent(dst)?;
+    let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_SYMLINK)?;
     dst.symlink(src.as_os_str().as_bytes(), dst_file.as_os_str().as_bytes())
 }
 
 pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
-    let (src, src_file) = open_parent(src)?;
-    let (dst, dst_file) = open_parent(dst)?;
+    let (src, src_file) = open_parent(src, libc::__WASI_RIGHT_PATH_LINK_SOURCE)?;
+    let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_LINK_TARGET)?;
     src.link(
         libc::__WASI_LOOKUP_SYMLINK_FOLLOW,
         src_file.as_os_str().as_bytes(),
@@ -584,13 +586,13 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
 }
 
 pub fn stat(p: &Path) -> io::Result<FileAttr> {
-    let (dir, file) = open_parent(p)?;
-    metadata_at(&dir, libc::__WASI_LOOKUP_SYMLINK_FOLLOW, file)
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?;
+    metadata_at(&dir, libc::__WASI_LOOKUP_SYMLINK_FOLLOW, &file)
 }
 
 pub fn lstat(p: &Path) -> io::Result<FileAttr> {
-    let (dir, file) = open_parent(p)?;
-    metadata_at(&dir, 0, file)
+    let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?;
+    metadata_at(&dir, 0, &file)
 }
 
 fn metadata_at(
@@ -621,72 +623,69 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
     Ok(File { fd })
 }
 
-// FIXME: we shouldn't implement this. It'd be much better to share this between
-// libc (the wasi-sysroot) and Rust as the logic here is likely far more tricky
-// than what we're executing below. For now this is a stopgap to enable this
-// module, but we should add an official API in upstream wasi-libc which looks
-// like this.
-//
-// In the meantime this is highly unlikely to be correct. It allows some basic
-// testing but is not at all robust.
-fn open_parent(p: &Path) -> io::Result<(&'static WasiFd, &Path)> {
-    let map = preopened_map();
-    for ancestor in p.ancestors() {
-        if let Some(fd) = map.get(ancestor) {
-            let tail = p.strip_prefix(ancestor).unwrap();
-            let tail = if tail == Path::new("") {
-                ".".as_ref()
-            } else {
-                tail
-            };
-            return Ok((fd, tail))
-        }
-    }
-    let msg = format!("failed to find a preopened file descriptor to open {:?}", p);
-    return Err(io::Error::new(io::ErrorKind::Other, msg));
-
-    type Preopened = HashMap<PathBuf, ManuallyDrop<WasiFd>>;
-    fn preopened_map() -> &'static Preopened {
-        static PTR: AtomicPtr<Preopened> = AtomicPtr::new(ptr::null_mut());
-        unsafe {
-            let ptr = PTR.load(SeqCst);
-            if !ptr.is_null() {
-                return &*ptr;
-            }
-
-            let mut map = Box::new(HashMap::new());
-            for fd in 3.. {
-                let mut buf = mem::zeroed();
-                if cvt_wasi(libc::__wasi_fd_prestat_get(fd, &mut buf)).is_err() {
-                    break;
-                }
-                if buf.pr_type != libc::__WASI_PREOPENTYPE_DIR {
-                    continue;
-                }
-                let len = buf.u.dir.pr_name_len;
-                let mut v = vec![0u8; len];
-                let res = cvt_wasi(libc::__wasi_fd_prestat_dir_name(
-                    fd,
-                    v.as_mut_ptr() as *mut i8,
-                    v.len(),
-                ));
-                if res.is_err() {
-                    continue;
-                }
-                let path = PathBuf::from(OsString::from_vec(v));
-                map.insert(path, ManuallyDrop::new(WasiFd::from_raw(fd)));
-            }
-            let ptr = Box::into_raw(map);
-            match PTR.compare_exchange(ptr::null_mut(), ptr, SeqCst, SeqCst) {
-                Ok(_) => &*ptr,
-
-                // If we lost the race for initialization clean up the map we
-                // made and just use the one that's already there
-                Err(other) => {
-                    drop(Box::from_raw(ptr));
-                    &*other
-                }
-            }
+/// Attempts to open a bare path `p`.
+///
+/// WASI has no fundamental capability to do this. All syscalls and operations
+/// are relative to already-open file descriptors. The C library, however,
+/// manages a map of preopened file descriptors to their path, and then the C
+/// library provides an API to look at this. In other words, when you want to
+/// open a path `p`, you have to find a previously opened file descriptor in a
+/// global table and then see if `p` is relative to that file descriptor.
+///
+/// This function, if successful, will return two items:
+///
+/// * The first is a `ManuallyDrop<WasiFd>`. This represents a preopened file
+///   descriptor which we don't have ownership of, but we can use. You shouldn't
+///   actually drop the `fd`.
+///
+/// * The second is a path that should be a part of `p` and represents a
+///   relative traversal from the file descriptor specified to the desired
+///   location `p`.
+///
+/// If successful you can use the returned file descriptor to perform
+/// file-descriptor-relative operations on the path returned as well. The
+/// `rights` argument indicates what operations are desired on the returned file
+/// descriptor, and if successful the returned file descriptor should have the
+/// appropriate rights for performing `rights` actions.
+///
+/// Note that this can fail if `p` doesn't look like it can be opened relative
+/// to any preopened file descriptor.
+fn open_parent(
+    p: &Path,
+    rights: libc::__wasi_rights_t,
+) -> 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(), rights, 0, &mut ret);
+        if fd == -1 {
+            let msg = format!(
+                "failed to find a preopened file descriptor \
+                 through which {:?} could be opened",
+                p
+            );
+            return Err(io::Error::new(io::ErrorKind::Other, msg));
         }
+        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));
+    }
+
+    // FIXME(rust-lang/libc#1314) use the `libc` crate for this when the API
+    // there is published
+    extern "C" {
+        pub fn __wasilibc_find_relpath(
+            path: *const libc::c_char,
+            rights_base: libc::__wasi_rights_t,
+            rights_inheriting: libc::__wasi_rights_t,
+            relative_path: *mut *const libc::c_char,
+        ) -> libc::c_int;
     }
 }