Initial error refactor
This commit is contained in:
committed by
Jakub Konka
parent
85a41d449c
commit
14aaffd46f
@@ -5,8 +5,8 @@ use crate::fdentry::{Descriptor, FdEntry};
|
||||
use crate::memory::*;
|
||||
use crate::sys::fdentry_impl::determine_type_rights;
|
||||
use crate::sys::hostcalls_impl::fs_helpers::path_open_rights;
|
||||
use crate::sys::{errno_from_ioerror, host_impl, hostcalls_impl};
|
||||
use crate::{host, wasm32, Result};
|
||||
use crate::sys::{host_impl, hostcalls_impl};
|
||||
use crate::{host, wasm32, Error, Result};
|
||||
use filetime::{set_file_handle_times, FileTime};
|
||||
use log::trace;
|
||||
use std::fs::File;
|
||||
@@ -20,11 +20,11 @@ pub(crate) fn fd_close(wasi_ctx: &mut WasiCtx, fd: wasm32::__wasi_fd_t) -> Resul
|
||||
if let Some(fdent) = wasi_ctx.fds.get(&fd) {
|
||||
// can't close preopened files
|
||||
if fdent.preopen_path.is_some() {
|
||||
return Err(host::__WASI_ENOTSUP);
|
||||
return Err(Error::ENOTSUP);
|
||||
}
|
||||
}
|
||||
|
||||
let mut fe = wasi_ctx.fds.remove(&fd).ok_or(host::__WASI_EBADF)?;
|
||||
let mut fe = wasi_ctx.fds.remove(&fd).ok_or(Error::EBADF)?;
|
||||
fe.fd_object.needs_close = true;
|
||||
|
||||
Ok(())
|
||||
@@ -38,7 +38,7 @@ pub(crate) fn fd_datasync(wasi_ctx: &WasiCtx, fd: wasm32::__wasi_fd_t) -> Result
|
||||
.get_fd_entry(fd, host::__WASI_RIGHT_FD_DATASYNC, 0)
|
||||
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
|
||||
|
||||
fd.sync_data().map_err(errno_from_ioerror)
|
||||
fd.sync_data().map_err(Into::into)
|
||||
}
|
||||
|
||||
pub(crate) fn fd_pread(
|
||||
@@ -68,7 +68,7 @@ pub(crate) fn fd_pread(
|
||||
|
||||
let offset = dec_filesize(offset);
|
||||
if offset > i64::max_value() as u64 {
|
||||
return Err(host::__WASI_EIO);
|
||||
return Err(Error::EIO);
|
||||
}
|
||||
let buf_size = iovs.iter().map(|v| v.buf_len).sum();
|
||||
let mut buf = vec![0; buf_size];
|
||||
@@ -117,7 +117,7 @@ pub(crate) fn fd_pwrite(
|
||||
|
||||
let offset = dec_filesize(offset);
|
||||
if offset > i64::max_value() as u64 {
|
||||
return Err(host::__WASI_EIO);
|
||||
return Err(Error::EIO);
|
||||
}
|
||||
let buf_size = iovs.iter().map(|v| v.buf_len).sum();
|
||||
let mut buf = Vec::with_capacity(buf_size);
|
||||
@@ -160,10 +160,10 @@ pub(crate) fn fd_read(
|
||||
let maybe_host_nread = match &mut *fe.fd_object.descriptor {
|
||||
Descriptor::File(f) => f.read_vectored(&mut iovs),
|
||||
Descriptor::Stdin => io::stdin().lock().read_vectored(&mut iovs),
|
||||
_ => return Err(host::__WASI_EBADF),
|
||||
_ => return Err(Error::EBADF),
|
||||
};
|
||||
|
||||
let host_nread = maybe_host_nread.map_err(errno_from_ioerror)?;
|
||||
let host_nread = maybe_host_nread?;
|
||||
|
||||
trace!(" | *nread={:?}", host_nread);
|
||||
|
||||
@@ -181,14 +181,14 @@ pub(crate) fn fd_renumber(
|
||||
let to = dec_fd(to);
|
||||
|
||||
if !wasi_ctx.contains_fd_entry(from) || !wasi_ctx.contains_fd_entry(to) {
|
||||
return Err(host::__WASI_EBADF);
|
||||
return Err(Error::EBADF);
|
||||
}
|
||||
|
||||
// Don't allow renumbering over a pre-opened resource.
|
||||
// TODO: Eventually, we do want to permit this, once libpreopen in
|
||||
// userspace is capable of removing entries from its tables as well.
|
||||
if wasi_ctx.fds[&from].preopen_path.is_some() || wasi_ctx.fds[&to].preopen_path.is_some() {
|
||||
return Err(host::__WASI_ENOTSUP);
|
||||
return Err(Error::ENOTSUP);
|
||||
}
|
||||
|
||||
// check if stdio fds
|
||||
@@ -196,7 +196,7 @@ pub(crate) fn fd_renumber(
|
||||
if !wasi_ctx.fds[&from].fd_object.descriptor.is_file()
|
||||
|| !wasi_ctx.fds[&to].fd_object.descriptor.is_file()
|
||||
{
|
||||
return Err(host::__WASI_EBADF);
|
||||
return Err(Error::EBADF);
|
||||
}
|
||||
|
||||
let fe_from_dup = wasi_ctx.fds[&from]
|
||||
@@ -244,9 +244,9 @@ pub(crate) fn fd_seek(
|
||||
host::__WASI_WHENCE_CUR => SeekFrom::Current(offset),
|
||||
host::__WASI_WHENCE_END => SeekFrom::End(offset),
|
||||
host::__WASI_WHENCE_SET => SeekFrom::Start(offset as u64),
|
||||
_ => return Err(host::__WASI_EINVAL),
|
||||
_ => return Err(Error::EINVAL),
|
||||
};
|
||||
let host_newoffset = fd.seek(pos).map_err(errno_from_ioerror)?;
|
||||
let host_newoffset = fd.seek(pos)?;
|
||||
|
||||
trace!(" | *newoffset={:?}", host_newoffset);
|
||||
|
||||
@@ -266,7 +266,7 @@ pub(crate) fn fd_tell(
|
||||
.get_fd_entry(fd, host::__WASI_RIGHT_FD_TELL, 0)
|
||||
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
|
||||
|
||||
let host_offset = fd.seek(SeekFrom::Current(0)).map_err(errno_from_ioerror)?;
|
||||
let host_offset = fd.seek(SeekFrom::Current(0))?;
|
||||
|
||||
trace!(" | *newoffset={:?}", host_offset);
|
||||
|
||||
@@ -328,12 +328,12 @@ pub(crate) fn fd_fdstat_set_rights(
|
||||
);
|
||||
|
||||
let fd = dec_fd(fd);
|
||||
let fe = wasi_ctx.fds.get_mut(&fd).ok_or(host::__WASI_EBADF)?;
|
||||
let fe = wasi_ctx.fds.get_mut(&fd).ok_or(Error::EBADF)?;
|
||||
|
||||
if fe.rights_base & fs_rights_base != fs_rights_base
|
||||
|| fe.rights_inheriting & fs_rights_inheriting != fs_rights_inheriting
|
||||
{
|
||||
return Err(host::__WASI_ENOTCAPABLE);
|
||||
return Err(Error::ENOTCAPABLE);
|
||||
}
|
||||
fe.rights_base = fs_rights_base;
|
||||
fe.rights_inheriting = fs_rights_inheriting;
|
||||
@@ -348,7 +348,7 @@ pub(crate) fn fd_sync(wasi_ctx: &WasiCtx, fd: wasm32::__wasi_fd_t) -> Result<()>
|
||||
let fd = wasi_ctx
|
||||
.get_fd_entry(fd, host::__WASI_RIGHT_FD_SYNC, 0)
|
||||
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
|
||||
fd.sync_all().map_err(errno_from_ioerror)
|
||||
fd.sync_all().map_err(Into::into)
|
||||
}
|
||||
|
||||
pub(crate) fn fd_write(
|
||||
@@ -377,20 +377,17 @@ pub(crate) fn fd_write(
|
||||
|
||||
// perform unbuffered writes
|
||||
let host_nwritten = match &mut *fe.fd_object.descriptor {
|
||||
Descriptor::File(f) => f.write_vectored(&iovs).map_err(errno_from_ioerror)?,
|
||||
Descriptor::Stdin => return Err(host::__WASI_EBADF),
|
||||
Descriptor::File(f) => f.write_vectored(&iovs)?,
|
||||
Descriptor::Stdin => return Err(Error::EBADF),
|
||||
Descriptor::Stdout => {
|
||||
// lock for the duration of the scope
|
||||
let stdout = io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
let nwritten = stdout.write_vectored(&iovs).map_err(errno_from_ioerror)?;
|
||||
stdout.flush().map_err(errno_from_ioerror)?;
|
||||
let nwritten = stdout.write_vectored(&iovs)?;
|
||||
stdout.flush()?;
|
||||
nwritten
|
||||
}
|
||||
Descriptor::Stderr => io::stderr()
|
||||
.lock()
|
||||
.write_vectored(&iovs)
|
||||
.map_err(errno_from_ioerror)?,
|
||||
Descriptor::Stderr => io::stderr().lock().write_vectored(&iovs)?,
|
||||
};
|
||||
|
||||
trace!(" | *nwritten={:?}", host_nwritten);
|
||||
@@ -439,17 +436,17 @@ pub(crate) fn fd_allocate(
|
||||
.get_fd_entry(fd, host::__WASI_RIGHT_FD_ALLOCATE, 0)
|
||||
.and_then(|fe| fe.fd_object.descriptor.as_file())?;
|
||||
|
||||
let metadata = fd.metadata().map_err(errno_from_ioerror)?;
|
||||
let metadata = fd.metadata()?;
|
||||
|
||||
let current_size = metadata.len();
|
||||
let wanted_size = offset.checked_add(len).ok_or(host::__WASI_E2BIG)?;
|
||||
let wanted_size = offset.checked_add(len).ok_or(Error::E2BIG)?;
|
||||
// This check will be unnecessary when rust-lang/rust#63326 is fixed
|
||||
if wanted_size > i64::max_value() as u64 {
|
||||
return Err(host::__WASI_E2BIG);
|
||||
return Err(Error::E2BIG);
|
||||
}
|
||||
|
||||
if wanted_size > current_size {
|
||||
fd.set_len(wanted_size).map_err(errno_from_ioerror)
|
||||
fd.set_len(wanted_size).map_err(Into::into)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@@ -782,7 +779,7 @@ pub(crate) fn fd_filestat_set_times_impl(
|
||||
let set_mtim_now = fst_flags & host::__WASI_FILESTAT_SET_MTIM_NOW != 0;
|
||||
|
||||
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
||||
return Err(host::__WASI_EINVAL);
|
||||
return Err(Error::EINVAL);
|
||||
}
|
||||
let atim = if set_atim {
|
||||
let time = UNIX_EPOCH + Duration::from_nanos(st_atim);
|
||||
@@ -803,7 +800,7 @@ pub(crate) fn fd_filestat_set_times_impl(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
set_file_handle_times(fd, atim, mtim).map_err(errno_from_ioerror)
|
||||
set_file_handle_times(fd, atim, mtim).map_err(Into::into)
|
||||
}
|
||||
|
||||
pub(crate) fn fd_filestat_set_size(
|
||||
@@ -821,9 +818,9 @@ pub(crate) fn fd_filestat_set_size(
|
||||
let st_size = dec_filesize(st_size);
|
||||
// This check will be unnecessary when rust-lang/rust#63326 is fixed
|
||||
if st_size > i64::max_value() as u64 {
|
||||
return Err(host::__WASI_E2BIG);
|
||||
return Err(Error::E2BIG);
|
||||
}
|
||||
fd.set_len(st_size).map_err(errno_from_ioerror)
|
||||
fd.set_len(st_size).map_err(Into::into)
|
||||
}
|
||||
|
||||
pub(crate) fn path_filestat_get(
|
||||
@@ -1006,9 +1003,9 @@ pub(crate) fn fd_prestat_get(
|
||||
wasi_ctx
|
||||
.get_fd_entry(fd, host::__WASI_RIGHT_PATH_OPEN, 0)
|
||||
.and_then(|fe| {
|
||||
let po_path = fe.preopen_path.as_ref().ok_or(host::__WASI_ENOTSUP)?;
|
||||
let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?;
|
||||
if fe.fd_object.file_type != host::__WASI_FILETYPE_DIRECTORY {
|
||||
return Err(host::__WASI_ENOTDIR);
|
||||
return Err(Error::ENOTDIR);
|
||||
}
|
||||
|
||||
let path = host_impl::path_from_host(po_path.as_os_str())?;
|
||||
@@ -1047,15 +1044,15 @@ pub(crate) fn fd_prestat_dir_name(
|
||||
wasi_ctx
|
||||
.get_fd_entry(fd, host::__WASI_RIGHT_PATH_OPEN, 0)
|
||||
.and_then(|fe| {
|
||||
let po_path = fe.preopen_path.as_ref().ok_or(host::__WASI_ENOTSUP)?;
|
||||
let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?;
|
||||
if fe.fd_object.file_type != host::__WASI_FILETYPE_DIRECTORY {
|
||||
return Err(host::__WASI_ENOTDIR);
|
||||
return Err(Error::ENOTDIR);
|
||||
}
|
||||
|
||||
let path = host_impl::path_from_host(po_path.as_os_str())?;
|
||||
|
||||
if path.len() > dec_usize(path_len) {
|
||||
return Err(host::__WASI_ENAMETOOLONG);
|
||||
return Err(Error::ENAMETOOLONG);
|
||||
}
|
||||
|
||||
trace!(" | (path_ptr,path_len)='{}'", path);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
use crate::sys::host_impl;
|
||||
use crate::sys::hostcalls_impl::fs_helpers::*;
|
||||
use crate::sys::{errno_from_host, host_impl};
|
||||
use crate::{host, Result};
|
||||
use crate::{host, Error, Result};
|
||||
use std::fs::File;
|
||||
use std::path::{Component, Path};
|
||||
|
||||
@@ -33,13 +33,10 @@ pub(crate) fn path_get(
|
||||
|
||||
if path.contains('\0') {
|
||||
// if contains NUL, return EILSEQ
|
||||
return Err(host::__WASI_EILSEQ);
|
||||
return Err(Error::EILSEQ);
|
||||
}
|
||||
|
||||
let dirfd = dirfd.try_clone().map_err(|err| {
|
||||
err.raw_os_error()
|
||||
.map_or(host::__WASI_EBADF, errno_from_host)
|
||||
})?;
|
||||
let dirfd = dirfd.try_clone()?;
|
||||
|
||||
// Stack of directory file descriptors. Index 0 always corresponds with the directory provided
|
||||
// to this function. Entering a directory causes a file descriptor to be pushed, while handling
|
||||
@@ -64,7 +61,7 @@ pub(crate) fn path_get(
|
||||
let ends_with_slash = cur_path.ends_with('/');
|
||||
let mut components = Path::new(&cur_path).components();
|
||||
let head = match components.next() {
|
||||
None => return Err(host::__WASI_ENOENT),
|
||||
None => return Err(Error::ENOENT),
|
||||
Some(p) => p,
|
||||
};
|
||||
let tail = components.as_path();
|
||||
@@ -80,18 +77,18 @@ pub(crate) fn path_get(
|
||||
match head {
|
||||
Component::Prefix(_) | Component::RootDir => {
|
||||
// path is absolute!
|
||||
return Err(host::__WASI_ENOTCAPABLE);
|
||||
return Err(Error::ENOTCAPABLE);
|
||||
}
|
||||
Component::CurDir => {
|
||||
// "." so skip
|
||||
}
|
||||
Component::ParentDir => {
|
||||
// ".." so pop a dir
|
||||
let _ = dir_stack.pop().ok_or(host::__WASI_ENOTCAPABLE)?;
|
||||
let _ = dir_stack.pop().ok_or(Error::ENOTCAPABLE)?;
|
||||
|
||||
// we're not allowed to pop past the original directory
|
||||
if dir_stack.is_empty() {
|
||||
return Err(host::__WASI_ENOTCAPABLE);
|
||||
return Err(Error::ENOTCAPABLE);
|
||||
}
|
||||
}
|
||||
Component::Normal(head) => {
|
||||
@@ -102,41 +99,44 @@ pub(crate) fn path_get(
|
||||
}
|
||||
|
||||
if !path_stack.is_empty() || (ends_with_slash && !needs_final_component) {
|
||||
match openat(dir_stack.last().ok_or(host::__WASI_ENOTCAPABLE)?, &head) {
|
||||
match openat(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head) {
|
||||
Ok(new_dir) => {
|
||||
dir_stack.push(new_dir);
|
||||
}
|
||||
Err(e)
|
||||
if e == host::__WASI_ELOOP
|
||||
|| e == host::__WASI_EMLINK
|
||||
|| e == host::__WASI_ENOTDIR =>
|
||||
// Check to see if it was a symlink. Linux indicates
|
||||
// this with ENOTDIR because of the O_DIRECTORY flag.
|
||||
{
|
||||
// attempt symlink expansion
|
||||
let mut link_path = readlinkat(
|
||||
dir_stack.last().ok_or(host::__WASI_ENOTCAPABLE)?,
|
||||
&head,
|
||||
)?;
|
||||
|
||||
symlink_expansions += 1;
|
||||
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
||||
return Err(host::__WASI_ELOOP);
|
||||
}
|
||||
|
||||
if head.ends_with('/') {
|
||||
link_path.push('/');
|
||||
}
|
||||
|
||||
log::debug!(
|
||||
"attempted symlink expansion link_path={:?}",
|
||||
link_path
|
||||
);
|
||||
|
||||
path_stack.push(link_path);
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
match e.as_wasi_errno() {
|
||||
host::__WASI_ELOOP
|
||||
| host::__WASI_EMLINK
|
||||
| host::__WASI_ENOTDIR =>
|
||||
// Check to see if it was a symlink. Linux indicates
|
||||
// this with ENOTDIR because of the O_DIRECTORY flag.
|
||||
{
|
||||
// attempt symlink expansion
|
||||
let mut link_path = readlinkat(
|
||||
dir_stack.last().ok_or(Error::ENOTCAPABLE)?,
|
||||
&head,
|
||||
)?;
|
||||
|
||||
symlink_expansions += 1;
|
||||
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
||||
return Err(Error::ELOOP);
|
||||
}
|
||||
|
||||
if head.ends_with('/') {
|
||||
link_path.push('/');
|
||||
}
|
||||
|
||||
log::debug!(
|
||||
"attempted symlink expansion link_path={:?}",
|
||||
link_path
|
||||
);
|
||||
|
||||
path_stack.push(link_path);
|
||||
}
|
||||
_ => {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,14 +146,11 @@ pub(crate) fn path_get(
|
||||
{
|
||||
// if there's a trailing slash, or if `LOOKUP_SYMLINK_FOLLOW` is set, attempt
|
||||
// symlink expansion
|
||||
match readlinkat(
|
||||
dir_stack.last().ok_or(host::__WASI_ENOTCAPABLE)?,
|
||||
&head,
|
||||
) {
|
||||
match readlinkat(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head) {
|
||||
Ok(mut link_path) => {
|
||||
symlink_expansions += 1;
|
||||
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
||||
return Err(host::__WASI_ELOOP);
|
||||
return Err(Error::ELOOP);
|
||||
}
|
||||
|
||||
if head.ends_with('/') {
|
||||
@@ -169,7 +166,9 @@ pub(crate) fn path_get(
|
||||
continue;
|
||||
}
|
||||
Err(e) => {
|
||||
if e != host::__WASI_EINVAL && e != host::__WASI_ENOENT {
|
||||
if e.as_wasi_errno() != host::__WASI_EINVAL
|
||||
&& e.as_wasi_errno() != host::__WASI_ENOENT
|
||||
{
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
@@ -178,7 +177,7 @@ pub(crate) fn path_get(
|
||||
|
||||
// not a symlink, so we're done;
|
||||
return Ok(PathGet {
|
||||
dirfd: dir_stack.pop().ok_or(host::__WASI_ENOTCAPABLE)?,
|
||||
dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?,
|
||||
path: head,
|
||||
});
|
||||
}
|
||||
@@ -188,7 +187,7 @@ pub(crate) fn path_get(
|
||||
// no further components to process. means we've hit a case like "." or "a/..", or if the
|
||||
// input path has trailing slashes and `needs_final_component` is not set
|
||||
return Ok(PathGet {
|
||||
dirfd: dir_stack.pop().ok_or(host::__WASI_ENOTCAPABLE)?,
|
||||
dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?,
|
||||
path: String::from("."),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
use crate::ctx::WasiCtx;
|
||||
use crate::memory::*;
|
||||
use crate::sys::hostcalls_impl;
|
||||
use crate::{host, wasm32, Result};
|
||||
use crate::{wasm32, Error, Result};
|
||||
use log::trace;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
@@ -29,11 +29,8 @@ pub(crate) fn args_get(
|
||||
|
||||
argv.push(arg_ptr);
|
||||
|
||||
let len =
|
||||
wasm32::uintptr_t::try_from(arg_bytes.len()).map_err(|_| host::__WASI_EOVERFLOW)?;
|
||||
argv_buf_offset = argv_buf_offset
|
||||
.checked_add(len)
|
||||
.ok_or(host::__WASI_EOVERFLOW)?;
|
||||
let len = wasm32::uintptr_t::try_from(arg_bytes.len()).map_err(|_| Error::EOVERFLOW)?;
|
||||
argv_buf_offset = argv_buf_offset.checked_add(len).ok_or(Error::EOVERFLOW)?;
|
||||
}
|
||||
|
||||
enc_slice_of(memory, argv.as_slice(), argv_ptr)
|
||||
@@ -90,11 +87,10 @@ pub(crate) fn environ_get(
|
||||
|
||||
environ.push(env_ptr);
|
||||
|
||||
let len =
|
||||
wasm32::uintptr_t::try_from(env_bytes.len()).map_err(|_| host::__WASI_EOVERFLOW)?;
|
||||
let len = wasm32::uintptr_t::try_from(env_bytes.len()).map_err(|_| Error::EOVERFLOW)?;
|
||||
environ_buf_offset = environ_buf_offset
|
||||
.checked_add(len)
|
||||
.ok_or(host::__WASI_EOVERFLOW)?;
|
||||
.ok_or(Error::EOVERFLOW)?;
|
||||
}
|
||||
|
||||
enc_slice_of(memory, environ.as_slice(), environ_ptr)
|
||||
@@ -119,7 +115,7 @@ pub(crate) fn environ_sizes_get(
|
||||
.try_fold(0, |acc: u32, pair| {
|
||||
acc.checked_add(pair.as_bytes_with_nul().len() as u32)
|
||||
})
|
||||
.ok_or(host::__WASI_EOVERFLOW)?;
|
||||
.ok_or(Error::EOVERFLOW)?;
|
||||
|
||||
trace!(" | *environ_count_ptr={:?}", environ_count);
|
||||
|
||||
@@ -202,7 +198,7 @@ pub(crate) fn poll_oneoff(
|
||||
);
|
||||
|
||||
if nsubscriptions as u64 > wasm32::__wasi_filesize_t::max_value() {
|
||||
return Err(host::__WASI_EINVAL);
|
||||
return Err(Error::EINVAL);
|
||||
}
|
||||
|
||||
enc_pointee(memory, nevents, 0)?;
|
||||
|
||||
Reference in New Issue
Block a user