Skip to content

Commit 8d06b01

Browse files
committed
Fix cap-std compilation on WASI.
This gets cap-primitives and cap-std to the point where they compile on WASI. There are a few TODOs, and some of this will need to be revisited as WASI evolves and adds `chmod` support, but this should suffice for now. Fixes #195.
1 parent e79f37f commit 8d06b01

18 files changed

+277
-54
lines changed

cap-primitives/src/fs/dir_options.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#[cfg(not(target_os = "wasi"))]
12
use crate::fs::DirOptionsExt;
23

34
/// Options and flags which can be used to configure how a directory is
@@ -6,6 +7,7 @@ use crate::fs::DirOptionsExt;
67
/// This is to `create_dir` what to `OpenOptions` is to `open`.
78
#[derive(Debug, Clone)]
89
pub struct DirOptions {
10+
#[cfg(not(target_os = "wasi"))]
911
#[allow(dead_code)]
1012
pub(crate) ext: DirOptionsExt,
1113
}
@@ -16,6 +18,7 @@ impl DirOptions {
1618
#[inline]
1719
pub const fn new() -> Self {
1820
Self {
21+
#[cfg(not(target_os = "wasi"))]
1922
ext: DirOptionsExt::new(),
2023
}
2124
}

cap-primitives/src/fs/metadata.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,44 @@ impl std::os::unix::fs::MetadataExt for Metadata {
259259
}
260260
}
261261

262+
#[cfg(target_os = "wasi")]
263+
impl std::os::wasi::fs::MetadataExt for Metadata {
264+
#[inline]
265+
fn dev(&self) -> u64 {
266+
self.ext.dev()
267+
}
268+
269+
#[inline]
270+
fn ino(&self) -> u64 {
271+
self.ext.ino()
272+
}
273+
274+
#[inline]
275+
fn nlink(&self) -> u64 {
276+
self.ext.nlink()
277+
}
278+
279+
#[inline]
280+
fn size(&self) -> u64 {
281+
self.ext.size()
282+
}
283+
284+
#[inline]
285+
fn atim(&self) -> u64 {
286+
self.ext.atim()
287+
}
288+
289+
#[inline]
290+
fn mtim(&self) -> u64 {
291+
self.ext.mtim()
292+
}
293+
294+
#[inline]
295+
fn ctim(&self) -> u64 {
296+
self.ext.ctim()
297+
}
298+
}
299+
262300
#[cfg(target_os = "vxworks")]
263301
impl std::os::vxworks::fs::MetadataExt for Metadata {
264302
#[inline]

cap-primitives/src/fs/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ mod remove_file;
3232
mod remove_open_dir;
3333
mod rename;
3434
mod reopen;
35+
#[cfg(not(target_os = "wasi"))]
3536
mod set_permissions;
3637
mod set_times;
3738
mod stat;
@@ -85,6 +86,7 @@ pub use remove_file::remove_file;
8586
pub use remove_open_dir::{remove_open_dir, remove_open_dir_all};
8687
pub use rename::rename;
8788
pub use reopen::reopen;
89+
#[cfg(not(target_os = "wasi"))]
8890
pub use set_permissions::set_permissions;
8991
pub use set_times::{set_times, set_times_nofollow};
9092
pub use stat::stat;

cap-primitives/src/fs/open_options.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,41 @@ impl std::os::unix::fs::OpenOptionsExt for OpenOptions {
178178
}
179179
}
180180

181+
#[cfg(target_os = "wasi")]
182+
impl std::os::wasi::fs::OpenOptionsExt for OpenOptions {
183+
fn lookup_flags(&mut self, _: u32) -> &mut Self {
184+
todo!()
185+
}
186+
fn directory(&mut self, dir_required: bool) -> &mut Self {
187+
self.dir_required = dir_required;
188+
self
189+
}
190+
fn dsync(&mut self, _: bool) -> &mut Self {
191+
todo!()
192+
}
193+
fn nonblock(&mut self, _: bool) -> &mut Self {
194+
todo!()
195+
}
196+
fn rsync(&mut self, _: bool) -> &mut Self {
197+
todo!()
198+
}
199+
fn sync(&mut self, _: bool) -> &mut Self {
200+
todo!()
201+
}
202+
fn fs_rights_base(&mut self, _: u64) -> &mut Self {
203+
todo!()
204+
}
205+
fn fs_rights_inheriting(&mut self, _: u64) -> &mut Self {
206+
todo!()
207+
}
208+
fn open_at<P>(&self, dirfd: &std::fs::File, path: P) -> Result<std::fs::File, std::io::Error>
209+
where
210+
P: AsRef<std::path::Path>,
211+
{
212+
crate::fs::open(dirfd, path.as_ref(), self)
213+
}
214+
}
215+
181216
#[cfg(target_os = "vxworks")]
182217
impl std::os::vxworks::fs::OpenOptionsExt for OpenOptions {
183218
#[inline]

cap-primitives/src/fs/permissions.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[cfg(any(unix, target_os = "vxworks"))]
1+
#[cfg(not(windows))]
22
use crate::fs::PermissionsExt;
33
#[cfg(unix)]
44
use rustix::fs::RawMode;
@@ -52,6 +52,15 @@ impl Permissions {
5252
Ok(fs::Permissions::from_mode(self.ext.mode()))
5353
}
5454

55+
#[cfg(target_os = "wasi")]
56+
#[inline]
57+
#[allow(clippy::unnecessary_wraps)]
58+
fn _into_std(self, file: &fs::File) -> io::Result<fs::Permissions> {
59+
let mut permissions = file.metadata()?.permissions();
60+
permissions.set_readonly(self.readonly());
61+
Ok(permissions)
62+
}
63+
5564
#[cfg(windows)]
5665
#[inline]
5766
fn _into_std(self, file: &fs::File) -> io::Result<fs::Permissions> {

cap-primitives/src/rustix/fs/copy_impl.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ fn open_from(start: &fs::File, path: &Path) -> io::Result<(fs::File, fs::Metadat
2525
Ok((reader, metadata))
2626
}
2727

28+
#[cfg(not(target_os = "wasi"))]
2829
fn open_to_and_set_permissions(
2930
start: &fs::File,
3031
path: &Path,
@@ -54,6 +55,25 @@ fn open_to_and_set_permissions(
5455
Ok((writer, writer_metadata))
5556
}
5657

58+
#[cfg(target_os = "wasi")]
59+
fn open_to_and_set_permissions(
60+
start: &fs::File,
61+
path: &Path,
62+
reader_metadata: fs::Metadata,
63+
) -> io::Result<(fs::File, fs::Metadata)> {
64+
let writer = open(
65+
start,
66+
path,
67+
OpenOptions::new()
68+
// create the file with the correct mode right away
69+
.write(true)
70+
.create(true)
71+
.truncate(true),
72+
)?;
73+
let writer_metadata = writer.metadata()?;
74+
Ok((writer, writer_metadata))
75+
}
76+
5777
#[cfg(not(any(
5878
target_os = "linux",
5979
target_os = "android",

cap-primitives/src/rustix/fs/create_dir_unchecked.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ pub(crate) fn create_dir_unchecked(
1010
path: &Path,
1111
options: &DirOptions,
1212
) -> io::Result<()> {
13-
Ok(mkdirat(
14-
start,
15-
path,
16-
Mode::from_bits(options.ext.mode as RawMode).unwrap(),
17-
)?)
13+
#[cfg(not(target_os = "wasi"))]
14+
let raw_mode = options.ext.mode as RawMode;
15+
#[cfg(target_os = "wasi")]
16+
let raw_mode = 0;
17+
18+
Ok(mkdirat(start, path, Mode::from_bits(raw_mode).unwrap())?)
1819
}

cap-primitives/src/rustix/fs/dir_utils.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::ops::Deref;
66
#[cfg(unix)]
77
use std::os::unix::{ffi::OsStrExt, fs::OpenOptionsExt};
88
#[cfg(target_os = "wasi")]
9-
use std::os::wasi::{ffi::OsStrExt, fs::OpenOptionsExt};
9+
use std::os::wasi::ffi::OsStrExt;
1010
use std::path::Path;
1111
#[cfg(racy_asserts)]
1212
use std::{ffi::OsString, os::unix::ffi::OsStringExt, path::PathBuf};
@@ -104,10 +104,13 @@ pub(crate) fn open_ambient_dir_impl(path: &Path, _: AmbientAuthority) -> io::Res
104104
// `O_DIRECTORY` manually.
105105
let flags = OFlags::DIRECTORY | target_o_path();
106106

107-
fs::OpenOptions::new()
108-
.read(true)
109-
.custom_flags(flags.bits() as i32)
110-
.open(&path)
107+
let mut options = fs::OpenOptions::new();
108+
options.read(true);
109+
110+
#[cfg(not(target_os = "wasi"))]
111+
options.custom_flags(flags.bits() as i32);
112+
113+
options.open(&path)
111114
}
112115

113116
/// Use `O_PATH` on platforms which have it, or none otherwise.
@@ -131,6 +134,7 @@ pub(crate) const fn target_o_path() -> OFlags {
131134
target_os = "macos",
132135
target_os = "netbsd",
133136
target_os = "openbsd",
137+
target_os = "wasi",
134138
))]
135139
{
136140
OFlags::empty()

cap-primitives/src/rustix/fs/file_path.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ use std::ffi::OsString;
66
use std::fs;
77
#[cfg(unix)]
88
use std::os::unix::ffi::OsStringExt;
9-
#[cfg(target_os = "wasi")]
10-
use std::os::wasi::ffi::OsStringExt;
119
use std::path::PathBuf;
1210

1311
pub(crate) fn file_path_by_ttyname_or_seaching(file: &fs::File) -> Option<PathBuf> {

cap-primitives/src/rustix/fs/file_type_ext.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,16 @@ impl FileTypeExt {
4444
FileType::ext(Self::BlockDevice)
4545
} else if std.is_char_device() {
4646
FileType::ext(Self::CharDevice)
47-
} else if std.is_fifo() {
48-
FileType::ext(Self::Fifo)
49-
} else if std.is_socket() {
50-
FileType::ext(Self::Socket)
5147
} else {
52-
FileType::unknown()
48+
#[cfg(not(target_os = "wasi"))]
49+
if std.is_fifo() {
50+
return FileType::ext(Self::Fifo);
51+
}
52+
if std.is_socket() {
53+
FileType::ext(Self::Socket)
54+
} else {
55+
FileType::unknown()
56+
}
5357
}
5458
}
5559

0 commit comments

Comments
 (0)