Skip to content

Commit 09c5c44

Browse files
committed
Pass Fd by reference.
Make handles non-`Copy` and non-`Clone`. Pass them by reference, and store them instructs as raw `u32` values. And make `Fd::from_raw` unsafe so that we're careful about where we get handles from. This also obviates the `Fd` trait. With `EntryTable`, it's now straightforward to let `FdPool` just operate on `u32` values.
1 parent 07bd973 commit 09c5c44

8 files changed

Lines changed: 98 additions & 154 deletions

File tree

crates/wasi-common/src/ctx.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ impl WasiCtxBuilder {
381381
#[derive(Debug)]
382382
struct EntryTable {
383383
fd_pool: FdPool,
384-
entries: HashMap<types::Fd, Entry>,
384+
entries: HashMap<u32, Entry>,
385385
}
386386

387387
impl EntryTable {
@@ -393,30 +393,30 @@ impl EntryTable {
393393
}
394394

395395
fn contains(&self, fd: &types::Fd) -> bool {
396-
self.entries.contains_key(fd)
396+
self.entries.contains_key(&fd.as_raw())
397397
}
398398

399399
fn insert(&mut self, entry: Entry) -> Option<types::Fd> {
400400
let fd = self.fd_pool.allocate()?;
401401
self.entries.insert(fd, entry);
402-
Some(fd)
402+
Some(unsafe { types::Fd::from_raw(fd) })
403403
}
404404

405405
fn insert_at(&mut self, fd: &types::Fd, entry: Entry) {
406-
self.entries.insert(*fd, entry);
406+
self.entries.insert(fd.as_raw(), entry);
407407
}
408408

409409
fn get(&self, fd: &types::Fd) -> Option<&Entry> {
410-
self.entries.get(fd)
410+
self.entries.get(&fd.as_raw())
411411
}
412412

413413
fn get_mut(&mut self, fd: &types::Fd) -> Option<&mut Entry> {
414-
self.entries.get_mut(fd)
414+
self.entries.get_mut(&fd.as_raw())
415415
}
416416

417-
fn remove(&mut self, fd: types::Fd) -> Option<Entry> {
418-
let entry = self.entries.remove(&fd)?;
419-
self.fd_pool.deallocate(fd);
417+
fn remove(&mut self, fd: &types::Fd) -> Option<Entry> {
418+
let entry = self.entries.remove(&fd.as_raw())?;
419+
self.fd_pool.deallocate(fd.as_raw());
420420
Some(entry)
421421
}
422422
}
@@ -444,13 +444,13 @@ impl WasiCtx {
444444
.build()
445445
}
446446

447-
/// Check if `WasiCtx` contains the specified raw WASI `fd`.
448-
pub(crate) fn contains_entry(&self, fd: types::Fd) -> bool {
447+
/// Check if `WasiCtx` contains the specified WASI `Fd`.
448+
pub(crate) fn contains_entry(&self, fd: &types::Fd) -> bool {
449449
self.entries.borrow().contains(&fd)
450450
}
451451

452-
/// Get an immutable `Entry` corresponding to the specified raw WASI `fd`.
453-
pub(crate) fn get_entry(&self, fd: types::Fd) -> Result<Ref<Entry>> {
452+
/// Get an immutable `Entry` corresponding to the specified WASI `Fd`.
453+
pub(crate) fn get_entry(&self, fd: &types::Fd) -> Result<Ref<Entry>> {
454454
if !self.contains_entry(fd) {
455455
return Err(Errno::Badf);
456456
}
@@ -459,9 +459,9 @@ impl WasiCtx {
459459
}))
460460
}
461461

462-
/// Get a mutable `Entry` corresponding to the specified raw WASI `fd`.
462+
/// Get a mutable `Entry` corresponding to the specified WASI `Fd`.
463463
// TODO This runs the risk of a potential difficult-to-predict panic down-the-line.
464-
pub(crate) fn get_entry_mut(&self, fd: types::Fd) -> Result<RefMut<Entry>> {
464+
pub(crate) fn get_entry_mut(&self, fd: &types::Fd) -> Result<RefMut<Entry>> {
465465
if !self.contains_entry(fd) {
466466
return Err(Errno::Badf);
467467
}
@@ -472,20 +472,20 @@ impl WasiCtx {
472472

473473
/// Insert the specified `Entry` into the `WasiCtx` object.
474474
///
475-
/// The `Entry` will automatically get another free raw WASI `fd` assigned. Note that
476-
/// the two subsequent free raw WASI `fd`s do not have to be stored contiguously.
475+
/// The `Entry` will automatically get another free WASI `Fd` assigned. Note that
476+
/// the two subsequent free WASI `Fd`s do not have to be stored contiguously.
477477
pub(crate) fn insert_entry(&self, entry: Entry) -> Result<types::Fd> {
478478
self.entries.borrow_mut().insert(entry).ok_or(Errno::Mfile)
479479
}
480480

481-
/// Insert the specified `Entry` with the specified raw WASI `fd` key into the `WasiCtx`
481+
/// Insert the specified `Entry` with the specified WASI `Fd` key into the `WasiCtx`
482482
/// object.
483-
pub(crate) fn insert_entry_at(&self, fd: types::Fd, entry: Entry) {
483+
pub(crate) fn insert_entry_at(&self, fd: &types::Fd, entry: Entry) {
484484
self.entries.borrow_mut().insert_at(&fd, entry)
485485
}
486486

487-
/// Remove `Entry` corresponding to the specified raw WASI `fd` from the `WasiCtx` object.
488-
pub(crate) fn remove_entry(&self, fd: types::Fd) -> Result<Entry> {
487+
/// Remove `Entry` corresponding to the specified WASI `Fd` from the `WasiCtx` object.
488+
pub(crate) fn remove_entry(&self, fd: &types::Fd) -> Result<Entry> {
489489
self.entries.borrow_mut().remove(fd).ok_or(Errno::Badf)
490490
}
491491
}

crates/wasi-common/src/fdpool.rs

Lines changed: 12 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,8 @@
22
//! pool. It's intended to be mainly used within the `WasiCtx`
33
//! object(s).
44
5-
/// Any type wishing to be treated as a valid WASI file descriptor
6-
/// should implement this trait.
7-
///
8-
/// This trait is required as internally we use `u32` to represent
9-
/// and manage raw file descriptors.
10-
pub(crate) trait Fd {
11-
/// Convert to `u32`.
12-
fn as_raw(&self) -> u32;
13-
/// Convert from `u32`.
14-
fn from_raw(raw_fd: u32) -> Self;
15-
}
16-
175
/// This container tracks and manages all file descriptors that
186
/// were already allocated.
19-
/// Internally, we use `u32` to represent the file descriptors;
20-
/// however, the caller may supply any type `T` such that it
21-
/// implements the `Fd` trait when requesting a new descriptor
22-
/// via the `allocate` method, or when returning one back via
23-
/// the `deallocate` method.
247
#[derive(Debug)]
258
pub(crate) struct FdPool {
269
next_alloc: Option<u32>,
@@ -41,11 +24,11 @@ impl FdPool {
4124
/// descriptors (which would be equal to `2^32 + 1` accounting for `0`),
4225
/// then this method will return `None` to signal that case.
4326
/// Otherwise, a new file descriptor is return as `Some(fd)`.
44-
pub fn allocate<T: Fd>(&mut self) -> Option<T> {
27+
pub fn allocate(&mut self) -> Option<u32> {
4528
if let Some(fd) = self.available.pop() {
4629
// Since we've had free, unclaimed handle in the pool,
4730
// simply claim it and return.
48-
return Some(T::from_raw(fd));
31+
return Some(fd);
4932
}
5033
// There are no free handles available in the pool, so try
5134
// allocating an additional one into the pool. If we've
@@ -55,16 +38,15 @@ impl FdPool {
5538
// It's OK to not unpack the result of `fd.checked_add()` here which
5639
// can fail since we check for `None` in the snippet above.
5740
self.next_alloc = fd.checked_add(1);
58-
Some(T::from_raw(fd))
41+
Some(fd)
5942
}
6043

6144
/// Return a file descriptor back to the pool.
6245
///
6346
/// If the caller tries to return a file descriptor that was
6447
/// not yet allocated (via spoofing, etc.), this method
6548
/// will panic.
66-
pub fn deallocate<T: Fd>(&mut self, fd: T) {
67-
let fd = fd.as_raw();
49+
pub fn deallocate(&mut self, fd: u32) {
6850
if let Some(next_alloc) = self.next_alloc {
6951
assert!(fd < next_alloc);
7052
}
@@ -76,44 +58,24 @@ impl FdPool {
7658
#[cfg(test)]
7759
mod test {
7860
use super::FdPool;
79-
use std::ops::Deref;
80-
81-
#[derive(Debug)]
82-
struct Fd(u32);
83-
84-
impl super::Fd for Fd {
85-
fn as_raw(&self) -> u32 {
86-
self.0
87-
}
88-
fn from_raw(raw_fd: u32) -> Self {
89-
Self(raw_fd)
90-
}
91-
}
92-
93-
impl Deref for Fd {
94-
type Target = u32;
95-
fn deref(&self) -> &Self::Target {
96-
&self.0
97-
}
98-
}
9961

10062
#[test]
10163
fn basics() {
10264
let mut fd_pool = FdPool::new();
103-
let mut fd: Fd = fd_pool.allocate().expect("success allocating 0");
104-
assert_eq!(*fd, 0);
65+
let mut fd = fd_pool.allocate().expect("success allocating 0");
66+
assert_eq!(fd, 0);
10567
fd = fd_pool.allocate().expect("success allocating 1");
106-
assert_eq!(*fd, 1);
68+
assert_eq!(fd, 1);
10769
fd = fd_pool.allocate().expect("success allocating 2");
108-
assert_eq!(*fd, 2);
70+
assert_eq!(fd, 2);
10971
fd_pool.deallocate(1u32);
11072
fd_pool.deallocate(0u32);
11173
fd = fd_pool.allocate().expect("success reallocating 0");
112-
assert_eq!(*fd, 0);
74+
assert_eq!(fd, 0);
11375
fd = fd_pool.allocate().expect("success reallocating 1");
114-
assert_eq!(*fd, 1);
76+
assert_eq!(fd, 1);
11577
fd = fd_pool.allocate().expect("success allocating 3");
116-
assert_eq!(*fd, 3);
78+
assert_eq!(fd, 3);
11779
}
11880

11981
#[test]
@@ -128,6 +90,6 @@ mod test {
12890
let mut fd_pool = FdPool::new();
12991
// Spoof reaching the limit of allocs.
13092
fd_pool.next_alloc = None;
131-
assert!(fd_pool.allocate::<Fd>().is_none());
93+
assert!(fd_pool.allocate().is_none());
13294
}
13395
}

crates/wasi-common/src/fs/dir.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ use std::{io, path::Path};
1818
/// don't interoperate well with the capability-oriented security model.
1919
pub struct Dir<'ctx> {
2020
ctx: &'ctx WasiCtx,
21-
fd: types::Fd,
21+
fd: &'ctx types::Fd,
2222
}
2323

2424
impl<'ctx> Dir<'ctx> {
2525
/// Constructs a new instance of `Self` from the given raw WASI file descriptor.
26-
pub unsafe fn from_raw_wasi_fd(ctx: &'ctx WasiCtx, fd: types::Fd) -> Self {
26+
pub unsafe fn from_raw_wasi_fd(ctx: &'ctx WasiCtx, fd: &'ctx types::Fd) -> Self {
2727
Self { ctx, fd }
2828
}
2929

@@ -38,9 +38,6 @@ impl<'ctx> Dir<'ctx> {
3838
///
3939
/// [`std::fs::File::open`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.open
4040
pub fn open_file<P: AsRef<Path>>(&mut self, path: P) -> io::Result<File> {
41-
let path = path.as_ref();
42-
let mut fd = types::Fd::from(0);
43-
4441
// TODO: Refactor the hostcalls functions to split out the encoding/decoding
4542
// parts from the underlying functionality, so that we can call into the
4643
// underlying functionality directly.
@@ -51,6 +48,9 @@ impl<'ctx> Dir<'ctx> {
5148
// on `OsStrExt`.
5249
unimplemented!("Dir::open_file");
5350
/*
51+
let path = path.as_ref();
52+
let mut fd = types::Fd { raw: types::RawFd::from(0) };
53+
5454
wasi_errno_to_io_error(hostcalls::path_open(
5555
self.ctx,
5656
self.fd,
@@ -63,10 +63,10 @@ impl<'ctx> Dir<'ctx> {
6363
0,
6464
&mut fd,
6565
))?;
66-
*/
6766
6867
let ctx = self.ctx;
6968
Ok(unsafe { File::from_raw_wasi_fd(ctx, fd) })
69+
*/
7070
}
7171

7272
/// Opens a file at `path` with the options specified by `self`.
@@ -91,12 +91,12 @@ impl<'ctx> Dir<'ctx> {
9191
///
9292
/// TODO: Not yet implemented. See the comment in `open_file`.
9393
pub fn open_dir<P: AsRef<Path>>(&mut self, path: P) -> io::Result<Self> {
94-
let path = path.as_ref();
95-
let mut fd = types::Fd::from(0);
96-
9794
// TODO: See the comment in `open_file`.
9895
unimplemented!("Dir::open_dir");
9996
/*
97+
let path = path.as_ref();
98+
let mut fd = types::Fd { raw: types::RawFd::from(0) };
99+
100100
wasi_errno_to_io_error(hostcalls::path_open(
101101
self.ctx,
102102
self.fd,
@@ -108,10 +108,10 @@ impl<'ctx> Dir<'ctx> {
108108
0,
109109
&mut fd,
110110
))?;
111-
*/
112111
113112
let ctx = self.ctx;
114113
Ok(unsafe { Dir::from_raw_wasi_fd(ctx, fd) })
114+
*/
115115
}
116116

117117
/// Opens a file in write-only mode.
@@ -123,14 +123,14 @@ impl<'ctx> Dir<'ctx> {
123123
///
124124
/// [`std::fs::File::create`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.create
125125
pub fn create_file<P: AsRef<Path>>(&mut self, path: P) -> io::Result<File> {
126-
let path = path.as_ref();
127-
let mut fd = types::Fd::from(0);
128-
129126
// TODO: See the comments in `open_file`.
130127
//
131128
// TODO: Set the requested rights to be read+write.
132129
unimplemented!("Dir::create_file");
133130
/*
131+
let path = path.as_ref();
132+
let mut fd = types::Fd { raw: types::RawFd::from(0) };
133+
134134
wasi_errno_to_io_error(hostcalls::path_open(
135135
self.ctx,
136136
self.fd,
@@ -143,10 +143,10 @@ impl<'ctx> Dir<'ctx> {
143143
0,
144144
&mut fd,
145145
))?;
146-
*/
147146
148147
let ctx = self.ctx;
149148
Ok(unsafe { File::from_raw_wasi_fd(ctx, fd) })
149+
*/
150150
}
151151

152152
/// Returns an iterator over the entries within a directory.
@@ -159,13 +159,13 @@ impl<'ctx> Dir<'ctx> {
159159
/// now, use `into_read` instead.
160160
///
161161
/// [`std::fs::read_dir`]: https://doc.rust-lang.org/std/fs/fn.read_dir.html
162-
pub fn read(&mut self) -> io::Result<ReadDir> {
162+
pub fn read(&mut self) -> io::Result<ReadDir<'ctx>> {
163163
unimplemented!("Dir::read")
164164
}
165165

166166
/// Consumes self and returns an iterator over the entries within a directory
167167
/// in the manner of `read`.
168-
pub fn into_read(self) -> ReadDir {
168+
pub fn into_read(self) -> ReadDir<'ctx> {
169169
unsafe { ReadDir::from_raw_wasi_fd(self.fd) }
170170
}
171171

@@ -189,7 +189,7 @@ impl<'ctx> Dir<'ctx> {
189189
/// relative to and within `self`.
190190
///
191191
/// [`std::fs::read_dir`]: https://doc.rust-lang.org/std/fs/fn.read_dir.html
192-
pub fn read_dir<P: AsRef<Path>>(&mut self, path: P) -> io::Result<ReadDir> {
192+
pub fn read_dir<P: AsRef<Path>>(&mut self, path: P) -> io::Result<ReadDir<'ctx>> {
193193
self.open_dir(path)?.read()
194194
}
195195
}

crates/wasi-common/src/fs/file.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::io;
1818
/// [`Dir::create_file`]: struct.Dir.html#method.create_file
1919
pub struct File<'ctx> {
2020
ctx: &'ctx WasiCtx,
21-
fd: types::Fd,
21+
fd: &'ctx types::Fd,
2222
}
2323

2424
impl<'ctx> File<'ctx> {
@@ -27,7 +27,7 @@ impl<'ctx> File<'ctx> {
2727
/// This corresponds to [`std::fs::File::from_raw_fd`].
2828
///
2929
/// [`std::fs::File::from_raw_fd`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.from_raw_fd
30-
pub unsafe fn from_raw_wasi_fd(ctx: &'ctx WasiCtx, fd: types::Fd) -> Self {
30+
pub unsafe fn from_raw_wasi_fd(ctx: &'ctx WasiCtx, fd: &'ctx types::Fd) -> Self {
3131
Self { ctx, fd }
3232
}
3333

crates/wasi-common/src/fs/readdir.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ use crate::wasi::types;
88
/// TODO: Not yet implemented.
99
///
1010
/// [`std::fs::ReadDir`]: https://doc.rust-lang.org/std/fs/struct.ReadDir.html
11-
pub struct ReadDir {
12-
fd: types::Fd,
11+
pub struct ReadDir<'ctx> {
12+
fd: &'ctx types::Fd,
1313
}
1414

15-
impl ReadDir {
15+
impl<'ctx> ReadDir<'ctx> {
1616
/// Constructs a new instance of `Self` from the given raw WASI file descriptor.
17-
pub unsafe fn from_raw_wasi_fd(fd: types::Fd) -> Self {
17+
pub unsafe fn from_raw_wasi_fd(fd: &'ctx types::Fd) -> Self {
1818
Self { fd }
1919
}
2020
}
2121

2222
/// TODO: Not yet implemented.
23-
impl Iterator for ReadDir {
23+
impl<'ctx> Iterator for ReadDir<'ctx> {
2424
type Item = DirEntry;
2525

2626
/// TODO: Not yet implemented.

0 commit comments

Comments
 (0)