Skip to content

Commit 26c894a

Browse files
author
Jakub Konka
committed
Make AsFile fallible
Return `EBADF` in `AsFile` in case a `Handle` cannot be made into a `std::fs::File`.
1 parent 068a699 commit 26c894a

File tree

13 files changed

+49
-45
lines changed

13 files changed

+49
-45
lines changed

crates/wasi-common/src/sys/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ use stdio::Stdio;
3737
use sys_impl::get_file_type;
3838

3939
pub(crate) trait AsFile {
40-
fn as_file(&self) -> ManuallyDrop<File>;
40+
fn as_file(&self) -> io::Result<ManuallyDrop<File>>;
4141
}
4242

4343
impl AsFile for dyn Handle + 'static {
44-
fn as_file(&self) -> ManuallyDrop<File> {
44+
fn as_file(&self) -> io::Result<ManuallyDrop<File>> {
4545
if let Some(file) = self.as_any().downcast_ref::<OsFile>() {
4646
file.as_file()
4747
} else if let Some(dir) = self.as_any().downcast_ref::<OsDir>() {
@@ -51,7 +51,8 @@ impl AsFile for dyn Handle + 'static {
5151
} else if let Some(other) = self.as_any().downcast_ref::<OsOther>() {
5252
other.as_file()
5353
} else {
54-
panic!("non-OS resource cannot be made into a File")
54+
log::error!("tried to make std::fs::File from non-OS handle");
55+
Err(io::Error::from_raw_os_error(libc::EBADF))
5556
}
5657
}
5758
}

crates/wasi-common/src/sys/osdir.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,24 @@ impl Handle for OsDir {
4040
}
4141
// FdOps
4242
fn fdstat_get(&self) -> Result<types::Fdflags> {
43-
fd::fdstat_get(&self.as_file())
43+
fd::fdstat_get(&*self.as_file()?)
4444
}
4545
fn fdstat_set_flags(&self, fdflags: types::Fdflags) -> Result<()> {
46-
if let Some(new_file) = fd::fdstat_set_flags(&self.as_file(), fdflags)? {
46+
if let Some(new_file) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? {
4747
self.handle.update_from(new_file);
4848
}
4949
Ok(())
5050
}
5151
fn filestat_get(&self) -> Result<types::Filestat> {
52-
fd::filestat_get(&self.as_file())
52+
fd::filestat_get(&*self.as_file()?)
5353
}
5454
fn filestat_set_times(
5555
&self,
5656
atim: types::Timestamp,
5757
mtim: types::Timestamp,
5858
fst_flags: types::Fstflags,
5959
) -> Result<()> {
60-
fd::filestat_set_times(&self.as_file(), atim, mtim, fst_flags)
60+
fd::filestat_set_times(&*self.as_file()?, atim, mtim, fst_flags)
6161
}
6262
fn readdir<'a>(
6363
&'a self,

crates/wasi-common/src/sys/osfile.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl Handle for OsFile {
5757
fd::advise(self, advice, offset, len)
5858
}
5959
fn allocate(&self, offset: types::Filesize, len: types::Filesize) -> Result<()> {
60-
let fd = self.as_file();
60+
let fd = self.as_file()?;
6161
let metadata = fd.metadata()?;
6262
let current_size = metadata.len();
6363
let wanted_size = offset.checked_add(len).ok_or(Errno::TooBig)?;
@@ -71,23 +71,23 @@ impl Handle for OsFile {
7171
Ok(())
7272
}
7373
fn datasync(&self) -> Result<()> {
74-
self.as_file().sync_data()?;
74+
self.as_file()?.sync_data()?;
7575
Ok(())
7676
}
7777
fn fdstat_get(&self) -> Result<types::Fdflags> {
78-
fd::fdstat_get(&self.as_file())
78+
fd::fdstat_get(&*self.as_file()?)
7979
}
8080
fn fdstat_set_flags(&self, fdflags: types::Fdflags) -> Result<()> {
81-
if let Some(new_handle) = fd::fdstat_set_flags(&self.as_file(), fdflags)? {
81+
if let Some(new_handle) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? {
8282
self.handle.update_from(new_handle);
8383
}
8484
Ok(())
8585
}
8686
fn filestat_get(&self) -> Result<types::Filestat> {
87-
fd::filestat_get(&self.as_file())
87+
fd::filestat_get(&*self.as_file()?)
8888
}
8989
fn filestat_set_size(&self, size: types::Filesize) -> Result<()> {
90-
self.as_file().set_len(size)?;
90+
self.as_file()?.set_len(size)?;
9191
Ok(())
9292
}
9393
fn filestat_set_times(
@@ -96,38 +96,38 @@ impl Handle for OsFile {
9696
mtim: types::Timestamp,
9797
fst_flags: types::Fstflags,
9898
) -> Result<()> {
99-
fd::filestat_set_times(&self.as_file(), atim, mtim, fst_flags)
99+
fd::filestat_set_times(&*self.as_file()?, atim, mtim, fst_flags)
100100
}
101101
fn preadv(&self, buf: &mut [io::IoSliceMut], offset: u64) -> Result<usize> {
102-
let mut fd: &File = &self.as_file();
102+
let mut fd: &File = &*self.as_file()?;
103103
let cur_pos = fd.seek(SeekFrom::Current(0))?;
104104
fd.seek(SeekFrom::Start(offset))?;
105105
let nread = self.read_vectored(buf)?;
106106
fd.seek(SeekFrom::Start(cur_pos))?;
107107
Ok(nread)
108108
}
109109
fn pwritev(&self, buf: &[io::IoSlice], offset: u64) -> Result<usize> {
110-
let mut fd: &File = &self.as_file();
110+
let mut fd: &File = &*self.as_file()?;
111111
let cur_pos = fd.seek(SeekFrom::Current(0))?;
112112
fd.seek(SeekFrom::Start(offset))?;
113113
let nwritten = self.write_vectored(&buf)?;
114114
fd.seek(SeekFrom::Start(cur_pos))?;
115115
Ok(nwritten)
116116
}
117117
fn read_vectored(&self, iovs: &mut [io::IoSliceMut]) -> Result<usize> {
118-
let nread = self.as_file().read_vectored(iovs)?;
118+
let nread = self.as_file()?.read_vectored(iovs)?;
119119
Ok(nread)
120120
}
121121
fn seek(&self, offset: SeekFrom) -> Result<u64> {
122-
let pos = self.as_file().seek(offset)?;
122+
let pos = self.as_file()?.seek(offset)?;
123123
Ok(pos)
124124
}
125125
fn sync(&self) -> Result<()> {
126-
self.as_file().sync_all()?;
126+
self.as_file()?.sync_all()?;
127127
Ok(())
128128
}
129129
fn write_vectored(&self, iovs: &[io::IoSlice]) -> Result<usize> {
130-
let nwritten = self.as_file().write_vectored(&iovs)?;
130+
let nwritten = self.as_file()?.write_vectored(&iovs)?;
131131
Ok(nwritten)
132132
}
133133
}

crates/wasi-common/src/sys/osother.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,20 @@ impl Handle for OsOther {
6666
}
6767
// FdOps
6868
fn fdstat_get(&self) -> Result<types::Fdflags> {
69-
fd::fdstat_get(&self.as_file())
69+
fd::fdstat_get(&*self.as_file()?)
7070
}
7171
fn fdstat_set_flags(&self, fdflags: types::Fdflags) -> Result<()> {
72-
if let Some(handle) = fd::fdstat_set_flags(&self.as_file(), fdflags)? {
72+
if let Some(handle) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? {
7373
self.handle.update_from(handle);
7474
}
7575
Ok(())
7676
}
7777
fn read_vectored(&self, iovs: &mut [io::IoSliceMut]) -> Result<usize> {
78-
let nread = self.as_file().read_vectored(iovs)?;
78+
let nread = self.as_file()?.read_vectored(iovs)?;
7979
Ok(nread)
8080
}
8181
fn write_vectored(&self, iovs: &[io::IoSlice]) -> Result<usize> {
82-
let mut fd: &File = &self.as_file();
82+
let mut fd: &File = &*self.as_file()?;
8383
let nwritten = if self.is_tty() {
8484
SandboxedTTYWriter::new(&mut fd).write_vectored(&iovs)?
8585
} else {

crates/wasi-common/src/sys/stdio.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ impl Handle for Stdio {
5050
}
5151
// FdOps
5252
fn fdstat_get(&self) -> Result<types::Fdflags> {
53-
fd::fdstat_get(&self.as_file())
53+
fd::fdstat_get(&*self.as_file()?)
5454
}
5555
fn fdstat_set_flags(&self, fdflags: types::Fdflags) -> Result<()> {
56-
if let Some(_) = fd::fdstat_set_flags(&self.as_file(), fdflags)? {
56+
if let Some(_) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? {
5757
// OK, this means we should somehow update the underlying os handle,
5858
// and we can't do that with `std::io::std{in, out, err}`, so we'll
5959
// panic for now.

crates/wasi-common/src/sys/unix/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ use yanix::file::{AtFlag, OFlag};
4040
pub(crate) use sys_impl::*;
4141

4242
impl<T: AsRawFd> AsFile for T {
43-
fn as_file(&self) -> ManuallyDrop<File> {
43+
fn as_file(&self) -> io::Result<ManuallyDrop<File>> {
4444
let file = unsafe { File::from_raw_fd(self.as_raw_fd()) };
45-
ManuallyDrop::new(file)
45+
Ok(ManuallyDrop::new(file))
4646
}
4747
}
4848

crates/wasi-common/src/sys/unix/oshandle.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub(crate) struct OsHandle(Cell<RawFd>);
1111
impl OsHandle {
1212
/// Tries clone `self`.
1313
pub(crate) fn try_clone(&self) -> io::Result<Self> {
14-
let fd = self.as_file().try_clone()?;
14+
let fd = self.as_file()?.try_clone()?;
1515
Ok(Self(Cell::new(fd.into_raw_fd())))
1616
}
1717
/// Consumes `other` taking the ownership of the underlying

crates/wasi-common/src/sys/unix/poll.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::entry::EntryHandle;
22
use crate::poll::{ClockEventData, FdEventData};
3-
use crate::sys::osfile::OsFile;
43
use crate::sys::AsFile;
54
use crate::wasi::{types, Errno, Result};
65
use std::io;
@@ -17,7 +16,7 @@ pub(crate) fn oneoff(
1716
return Ok(());
1817
}
1918

20-
let mut poll_fds: Vec<_> = fd_events
19+
let poll_fds: Result<Vec<_>> = fd_events
2120
.iter()
2221
.map(|event| {
2322
let mut flags = PollFlags::empty();
@@ -29,9 +28,11 @@ pub(crate) fn oneoff(
2928
// events we filtered before. If we get something else here, the code has a serious bug.
3029
_ => unreachable!(),
3130
};
32-
unsafe { PollFd::new(event.handle.as_file().as_raw_fd(), flags) }
31+
let file = event.handle.as_file()?;
32+
unsafe { Ok(PollFd::new(file.as_raw_fd(), flags)) }
3333
})
3434
.collect();
35+
let mut poll_fds = poll_fds?;
3536

3637
let poll_timeout = timeout.map_or(-1, |timeout| {
3738
let delay = timeout.delay / 1_000_000; // poll syscall requires delay to expressed in milliseconds
@@ -77,15 +78,16 @@ fn handle_fd_event(
7778
events: &mut Vec<types::Event>,
7879
) -> Result<()> {
7980
fn query_nbytes(handle: EntryHandle) -> Result<u64> {
80-
if let Some(file) = handle.as_any().downcast_ref::<OsFile>() {
81+
let file = handle.as_file()?;
82+
if handle.get_file_type() == types::Filetype::RegularFile {
8183
// fionread may overflow for large files, so use another way for regular files.
8284
use yanix::file::tell;
83-
let meta = file.as_file().metadata()?;
85+
let meta = file.metadata()?;
8486
let len = meta.len();
8587
let host_offset = unsafe { tell(file.as_raw_fd())? };
8688
return Ok(len - host_offset);
8789
}
88-
Ok(unsafe { fionread(handle.as_file().as_raw_fd())?.into() })
90+
Ok(unsafe { fionread(file.as_raw_fd())?.into() })
8991
}
9092

9193
for (fd_event, poll_fd) in ready_events {

crates/wasi-common/src/sys/windows/fd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ pub(crate) fn readdir(
128128
use winx::file::get_file_path;
129129

130130
let cookie = cookie.try_into()?;
131-
let path = get_file_path(&dirfd.as_file())?;
131+
let path = get_file_path(&*dirfd.as_file()?)?;
132132
// std::fs::ReadDir doesn't return . and .., so we need to emulate it
133133
let path = Path::new(&path);
134134
// The directory /.. is the same as / on Unix (at least on ext4), so emulate this behavior too

crates/wasi-common/src/sys/windows/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ use winapi::shared::winerror;
2121
use winx::file::{CreationDisposition, Flags};
2222

2323
impl<T: AsRawHandle> AsFile for T {
24-
fn as_file(&self) -> ManuallyDrop<File> {
24+
fn as_file(&self) -> io::Result<ManuallyDrop<File>> {
2525
let file = unsafe { File::from_raw_handle(self.as_raw_handle()) };
26-
ManuallyDrop::new(file)
26+
Ok(ManuallyDrop::new(file))
2727
}
2828
}
2929

@@ -35,7 +35,7 @@ pub(crate) fn get_file_type(file: &File) -> io::Result<types::Filetype> {
3535
types::Filetype::CharacterDevice
3636
} else if file_type.is_disk() {
3737
// disk file: file, dir or disk device
38-
let file = file.as_file();
38+
let file = file.as_file()?;
3939
let meta = file.metadata()?;
4040
if meta.is_dir() {
4141
types::Filetype::Directory

0 commit comments

Comments
 (0)