Skip to content

Commit 2d06571

Browse files
committed
Auto merge of #59619 - alexcrichton:wasi-fs, r=fitzgen
wasi: Implement more of the standard library This commit fills out more of the `wasm32-unknown-wasi` target's standard library, notably the `std::fs` module and all of its internals. A few tweaks were made along the way to non-`fs` modules, but the last commit contains the bulk of the work which is to wire up all APIs to their equivalent on WASI targets instead of unconditionally returning "unsupported". After this some basic filesystem operations and such should all be working in WASI!
2 parents e43f99c + 61b487c commit 2d06571

File tree

16 files changed

+1189
-304
lines changed

16 files changed

+1189
-304
lines changed

src/libstd/fs.rs

+8
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,10 @@ impl OpenOptions {
881881
}
882882
}
883883

884+
impl AsInner<fs_imp::OpenOptions> for OpenOptions {
885+
fn as_inner(&self) -> &fs_imp::OpenOptions { &self.0 }
886+
}
887+
884888
impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
885889
fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 }
886890
}
@@ -1104,6 +1108,10 @@ impl AsInner<fs_imp::FileAttr> for Metadata {
11041108
fn as_inner(&self) -> &fs_imp::FileAttr { &self.0 }
11051109
}
11061110

1111+
impl FromInner<fs_imp::FileAttr> for Metadata {
1112+
fn from_inner(attr: fs_imp::FileAttr) -> Metadata { Metadata(attr) }
1113+
}
1114+
11071115
impl Permissions {
11081116
/// Returns `true` if these permissions describe a readonly (unwritable) file.
11091117
///

src/libstd/sys/redox/fs.rs

+4-38
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ use crate::os::unix::prelude::*;
22

33
use crate::ffi::{OsString, OsStr};
44
use crate::fmt;
5-
use crate::io::{self, Error, ErrorKind, SeekFrom};
5+
use crate::io::{self, Error, SeekFrom};
66
use crate::path::{Path, PathBuf};
77
use crate::sync::Arc;
88
use crate::sys::fd::FileDesc;
99
use crate::sys::time::SystemTime;
1010
use crate::sys::{cvt, syscall};
1111
use crate::sys_common::{AsInner, FromInner};
1212

13+
pub use crate::sys_common::fs::copy;
14+
pub use crate::sys_common::fs::remove_dir_all;
15+
1316
pub struct File(FileDesc);
1417

1518
#[derive(Clone)]
@@ -392,27 +395,6 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
392395
Ok(())
393396
}
394397

395-
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
396-
let filetype = lstat(path)?.file_type();
397-
if filetype.is_symlink() {
398-
unlink(path)
399-
} else {
400-
remove_dir_all_recursive(path)
401-
}
402-
}
403-
404-
fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
405-
for child in readdir(path)? {
406-
let child = child?;
407-
if child.file_type()?.is_dir() {
408-
remove_dir_all_recursive(&child.path())?;
409-
} else {
410-
unlink(&child.path())?;
411-
}
412-
}
413-
rmdir(path)
414-
}
415-
416398
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
417399
let fd = cvt(syscall::open(p.to_str().unwrap(),
418400
syscall::O_CLOEXEC | syscall::O_SYMLINK | syscall::O_RDONLY))?;
@@ -455,19 +437,3 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
455437
let file = File(FileDesc::new(fd));
456438
file.path()
457439
}
458-
459-
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
460-
use crate::fs::{File, set_permissions};
461-
if !from.is_file() {
462-
return Err(Error::new(ErrorKind::InvalidInput,
463-
"the source path is not an existing regular file"))
464-
}
465-
466-
let mut reader = File::open(from)?;
467-
let mut writer = File::create(to)?;
468-
let perm = reader.metadata()?.permissions();
469-
470-
let ret = io::copy(&mut reader, &mut writer)?;
471-
set_permissions(to, perm)?;
472-
Ok(ret)
473-
}

src/libstd/sys/unix/fs.rs

+2-21
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, off_t as off64_t,
3636
target_os = "fuchsia")))]
3737
use libc::{readdir_r as readdir64_r};
3838

39+
pub use crate::sys_common::fs::remove_dir_all;
40+
3941
pub struct File(FileDesc);
4042

4143
#[derive(Clone)]
@@ -734,27 +736,6 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
734736
Ok(())
735737
}
736738

737-
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
738-
let filetype = lstat(path)?.file_type();
739-
if filetype.is_symlink() {
740-
unlink(path)
741-
} else {
742-
remove_dir_all_recursive(path)
743-
}
744-
}
745-
746-
fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
747-
for child in readdir(path)? {
748-
let child = child?;
749-
if child.file_type()?.is_dir() {
750-
remove_dir_all_recursive(&child.path())?;
751-
} else {
752-
unlink(&child.path())?;
753-
}
754-
}
755-
rmdir(path)
756-
}
757-
758739
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
759740
let c_path = cstr(p)?;
760741
let p = c_path.as_ptr();

src/libstd/sys/wasi/args.rs

+24-26
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,15 @@
1-
use crate::any::Any;
21
use crate::ffi::CStr;
2+
use crate::io;
3+
use crate::sys::cvt_wasi;
34
use crate::ffi::OsString;
45
use crate::marker::PhantomData;
56
use crate::os::wasi::ffi::OsStringExt;
6-
use crate::ptr;
77
use crate::vec;
88

9-
static mut ARGC: isize = 0;
10-
static mut ARGV: *const *const u8 = ptr::null();
11-
12-
#[cfg(not(target_feature = "atomics"))]
13-
pub unsafe fn args_lock() -> impl Any {
14-
// No need for a lock if we're single-threaded, but this function will need
15-
// to get implemented for multi-threaded scenarios
16-
}
17-
18-
pub unsafe fn init(argc: isize, argv: *const *const u8) {
19-
let _guard = args_lock();
20-
ARGC = argc;
21-
ARGV = argv;
9+
pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
2210
}
2311

2412
pub unsafe fn cleanup() {
25-
let _guard = args_lock();
26-
ARGC = 0;
27-
ARGV = ptr::null();
2813
}
2914

3015
pub struct Args {
@@ -34,18 +19,31 @@ pub struct Args {
3419

3520
/// Returns the command line arguments
3621
pub fn args() -> Args {
22+
maybe_args().unwrap_or_else(|_| {
23+
Args {
24+
iter: Vec::new().into_iter(),
25+
_dont_send_or_sync_me: PhantomData
26+
}
27+
})
28+
}
29+
30+
fn maybe_args() -> io::Result<Args> {
3731
unsafe {
38-
let _guard = args_lock();
39-
let args = (0..ARGC)
40-
.map(|i| {
41-
let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char);
42-
OsStringExt::from_vec(cstr.to_bytes().to_vec())
43-
})
32+
let (mut argc, mut argv_buf_size) = (0, 0);
33+
cvt_wasi(libc::__wasi_args_sizes_get(&mut argc, &mut argv_buf_size))?;
34+
35+
let mut argc = vec![0 as *mut libc::c_char; argc];
36+
let mut argv_buf = vec![0; argv_buf_size];
37+
cvt_wasi(libc::__wasi_args_get(argc.as_mut_ptr(), argv_buf.as_mut_ptr()))?;
38+
39+
let args = argc.into_iter()
40+
.map(|ptr| CStr::from_ptr(ptr).to_bytes().to_vec())
41+
.map(|bytes| OsString::from_vec(bytes))
4442
.collect::<Vec<_>>();
45-
Args {
43+
Ok(Args {
4644
iter: args.into_iter(),
4745
_dont_send_or_sync_me: PhantomData,
48-
}
46+
})
4947
}
5048
}
5149

src/libstd/sys/wasi/ext/ffi.rs

+1-56
Original file line numberDiff line numberDiff line change
@@ -2,60 +2,5 @@
22
33
#![stable(feature = "rust1", since = "1.0.0")]
44

5-
use crate::ffi::{OsStr, OsString};
6-
use crate::mem;
7-
use crate::sys::os_str::Buf;
8-
use crate::sys_common::{FromInner, IntoInner, AsInner};
9-
10-
/// WASI-specific extensions to [`OsString`].
11-
///
12-
/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
13-
#[stable(feature = "rust1", since = "1.0.0")]
14-
pub trait OsStringExt {
15-
/// Creates an `OsString` from a byte vector.
16-
#[stable(feature = "rust1", since = "1.0.0")]
17-
fn from_vec(vec: Vec<u8>) -> Self;
18-
19-
/// Yields the underlying byte vector of this `OsString`.
20-
#[stable(feature = "rust1", since = "1.0.0")]
21-
fn into_vec(self) -> Vec<u8>;
22-
}
23-
24-
#[stable(feature = "rust1", since = "1.0.0")]
25-
impl OsStringExt for OsString {
26-
fn from_vec(vec: Vec<u8>) -> OsString {
27-
FromInner::from_inner(Buf { inner: vec })
28-
}
29-
fn into_vec(self) -> Vec<u8> {
30-
self.into_inner().inner
31-
}
32-
}
33-
34-
/// WASI-specific extensions to [`OsStr`].
35-
///
36-
/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
375
#[stable(feature = "rust1", since = "1.0.0")]
38-
pub trait OsStrExt {
39-
#[stable(feature = "rust1", since = "1.0.0")]
40-
/// Creates an [`OsStr`] from a byte slice.
41-
///
42-
/// [`OsStr`]: ../../../ffi/struct.OsStr.html
43-
fn from_bytes(slice: &[u8]) -> &Self;
44-
45-
/// Gets the underlying byte view of the [`OsStr`] slice.
46-
///
47-
/// [`OsStr`]: ../../../ffi/struct.OsStr.html
48-
#[stable(feature = "rust1", since = "1.0.0")]
49-
fn as_bytes(&self) -> &[u8];
50-
}
51-
52-
#[stable(feature = "rust1", since = "1.0.0")]
53-
impl OsStrExt for OsStr {
54-
fn from_bytes(slice: &[u8]) -> &OsStr {
55-
unsafe { mem::transmute(slice) }
56-
}
57-
fn as_bytes(&self) -> &[u8] {
58-
&self.as_inner().inner
59-
}
60-
}
61-
6+
pub use crate::sys_common::os_str_bytes::*;

0 commit comments

Comments
 (0)