Stop returning NOTCAPABLE errors from WASI calls. (#4666)
* Stop returning `NOTCAPABLE` errors from WASI calls. `ENOTCAPABLE` was an error code that is used as part of the rights system, from CloudABI. There is a set of flags associated with each file descriptor listing which operations can be performed with the file descriptor, and if an attempt is made to perform an operation with a file descriptor that isn't permitted by its rights flags, it fails with `ENOTCAPABLE`. WASI is removing the rights system. For example, WebAssembly/wasi-libc#294 removed support for translating `ENOTCAPABLE` into POSIX error codes, on the assumption that engines should stop using it. So as another step to migrating away from the rights system, remove uses of the `ENOTCAPABLE` error. * Update crates/wasi-common/src/file.rs Co-authored-by: Jamey Sharp <jamey@minilop.net> * Update crates/wasi-common/src/dir.rs Co-authored-by: Jamey Sharp <jamey@minilop.net> Co-authored-by: Jamey Sharp <jamey@minilop.net>
This commit is contained in:
@@ -30,7 +30,7 @@ unsafe fn try_read_file(dir_fd: wasi::Fd) {
|
|||||||
wasi::fd_read(fd, &[iovec])
|
wasi::fd_read(fd, &[iovec])
|
||||||
.expect_err("reading bytes from file should fail")
|
.expect_err("reading bytes from file should fail")
|
||||||
.raw_error(),
|
.raw_error(),
|
||||||
wasi::ERRNO_NOTCAPABLE
|
wasi::ERRNO_BADF
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ unsafe fn test_truncation_rights(dir_fd: wasi::Fd) {
|
|||||||
wasi::path_open(dir_fd, 0, "file", wasi::OFLAGS_TRUNC, 0, 0, 0)
|
wasi::path_open(dir_fd, 0, "file", wasi::OFLAGS_TRUNC, 0, 0, 0)
|
||||||
.expect_err("truncating a file without path_filestat_set_size right")
|
.expect_err("truncating a file without path_filestat_set_size right")
|
||||||
.raw_error(),
|
.raw_error(),
|
||||||
wasi::ERRNO_NOTCAPABLE
|
wasi::ERRNO_PERM
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,15 +76,23 @@ impl DirEntry {
|
|||||||
if self.caps.contains(caps) {
|
if self.caps.contains(caps) {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::not_capable().context(format!("desired {:?}, has {:?}", caps, self.caps,)))
|
let missing = caps & !self.caps;
|
||||||
|
let err = if missing.intersects(DirCaps::READDIR) {
|
||||||
|
Error::not_dir()
|
||||||
|
} else {
|
||||||
|
Error::perm()
|
||||||
|
};
|
||||||
|
Err(err.context(format!("desired rights {:?}, has {:?}", caps, self.caps)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn capable_of_file(&self, caps: FileCaps) -> Result<(), Error> {
|
pub fn capable_of_file(&self, caps: FileCaps) -> Result<(), Error> {
|
||||||
if self.file_caps.contains(caps) {
|
if self.file_caps.contains(caps) {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::not_capable()
|
Err(Error::perm().context(format!(
|
||||||
.context(format!("desired {:?}, has {:?}", caps, self.file_caps)))
|
"desired rights {:?}, has {:?}",
|
||||||
|
caps, self.file_caps
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn drop_caps_to(&mut self, caps: DirCaps, file_caps: FileCaps) -> Result<(), Error> {
|
pub fn drop_caps_to(&mut self, caps: DirCaps, file_caps: FileCaps) -> Result<(), Error> {
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ pub enum ErrorKind {
|
|||||||
/// Errno::Spipe: Invalid seek
|
/// Errno::Spipe: Invalid seek
|
||||||
#[error("Spipe: Invalid seek")]
|
#[error("Spipe: Invalid seek")]
|
||||||
Spipe,
|
Spipe,
|
||||||
|
/// Errno::Perm: Permission denied
|
||||||
|
#[error("Permission denied")]
|
||||||
|
Perm,
|
||||||
/// Errno::NotCapable: Not capable
|
/// Errno::NotCapable: Not capable
|
||||||
#[error("Not capable")]
|
#[error("Not capable")]
|
||||||
NotCapable,
|
NotCapable,
|
||||||
@@ -92,7 +95,7 @@ pub trait ErrorExt {
|
|||||||
fn overflow() -> Self;
|
fn overflow() -> Self;
|
||||||
fn range() -> Self;
|
fn range() -> Self;
|
||||||
fn seek_pipe() -> Self;
|
fn seek_pipe() -> Self;
|
||||||
fn not_capable() -> Self;
|
fn perm() -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ErrorExt for Error {
|
impl ErrorExt for Error {
|
||||||
@@ -138,7 +141,7 @@ impl ErrorExt for Error {
|
|||||||
fn seek_pipe() -> Self {
|
fn seek_pipe() -> Self {
|
||||||
ErrorKind::Spipe.into()
|
ErrorKind::Spipe.into()
|
||||||
}
|
}
|
||||||
fn not_capable() -> Self {
|
fn perm() -> Self {
|
||||||
ErrorKind::NotCapable.into()
|
ErrorKind::Perm.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,7 +238,16 @@ impl FileEntry {
|
|||||||
if self.caps.contains(caps) {
|
if self.caps.contains(caps) {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::not_capable().context(format!("desired {:?}, has {:?}", caps, self.caps,)))
|
let missing = caps & !self.caps;
|
||||||
|
let err = if missing.intersects(FileCaps::READ | FileCaps::WRITE) {
|
||||||
|
// `EBADF` is a little surprising here because it's also used
|
||||||
|
// for unknown-file-descriptor errors, but it's what POSIX uses
|
||||||
|
// in this situation.
|
||||||
|
Error::badf()
|
||||||
|
} else {
|
||||||
|
Error::perm()
|
||||||
|
};
|
||||||
|
Err(err.context(format!("desired rights {:?}, has {:?}", caps, self.caps)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ impl From<ErrorKind> for types::Errno {
|
|||||||
ErrorKind::Range => Errno::Range,
|
ErrorKind::Range => Errno::Range,
|
||||||
ErrorKind::Spipe => Errno::Spipe,
|
ErrorKind::Spipe => Errno::Spipe,
|
||||||
ErrorKind::NotCapable => Errno::Notcapable,
|
ErrorKind::NotCapable => Errno::Notcapable,
|
||||||
|
ErrorKind::Perm => Errno::Perm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user