* Rewrite FdEntry reusing as much libstd as possible
* Use the new FdEntry, FdObject, Descriptor struct in *nix impl
* Adapt Windows impl
* Remove unnecessary check in fd_read
Check `host_nread == 0` caused premature FdEntry closure and removal
which ultimately was resulting in an attempt at "double closing" of
the same file descriptor at the end of the Wasm program:
...
fd_close(fd=4)
-> errno=WASI_ESUCCESS
fd_close(fd=4)
-> errno=WASI_EBADF
* Use libstd vectored IO
* Use std:🧵:yield_now to implement sched_yield
* Add logging to integration tests
* Add preliminary support for host-specific errors
* Operate on std::fs::File in path_get on *nix
* Add cross-platform RawString type encapsulating OsStrExt
* Fix Windows build
* Update Travis and README to Rust v1.36
* Remove unused winx::handle::close helper
* Refactor Descriptor into raw handles/fds
* Strip readlinkat in prep for path_get host-independent
* Strip openat in prep for path_get host-independent
* Move ManuallyDrop up one level from Descriptor to FdObject
* Make (c)iovec host fns unsafe
* Swap unwraps/expects for Results in fdentry_impl on nix
* Rewrite fd_pread/write and implement for Win
* Use File::sync_all to impl fd_sync
* Use File::sync_data to impl fd_datasync
* Rewind file cursor after fd_p{read, write} on Windows
* Add fd_p{read, write} tests
* Handle errors instead of panicking in path_get
* Use File::set_len to impl fd_allocate
* Add test for fd_allocate
* Replace all panics with Results
* Document the point of RawString
131 lines
4.3 KiB
Rust
131 lines
4.3 KiB
Rust
use crate::fdentry::Descriptor;
|
|
use crate::host;
|
|
use crate::sys::errno_from_host;
|
|
|
|
use std::io;
|
|
use std::os::unix::prelude::{AsRawFd, FileTypeExt, FromRawFd, RawFd};
|
|
|
|
impl AsRawFd for Descriptor {
|
|
fn as_raw_fd(&self) -> RawFd {
|
|
match self {
|
|
Descriptor::File(f) => f.as_raw_fd(),
|
|
Descriptor::Stdin => io::stdin().as_raw_fd(),
|
|
Descriptor::Stdout => io::stdout().as_raw_fd(),
|
|
Descriptor::Stderr => io::stderr().as_raw_fd(),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) fn determine_type_and_access_rights<Fd: AsRawFd>(
|
|
fd: &Fd,
|
|
) -> Result<
|
|
(
|
|
host::__wasi_filetype_t,
|
|
host::__wasi_rights_t,
|
|
host::__wasi_rights_t,
|
|
),
|
|
host::__wasi_errno_t,
|
|
> {
|
|
let (file_type, mut rights_base, rights_inheriting) = determine_type_rights(fd)?;
|
|
|
|
use nix::fcntl::{fcntl, OFlag, F_GETFL};
|
|
let flags_bits = fcntl(fd.as_raw_fd(), F_GETFL).map_err(|err| {
|
|
err.as_errno()
|
|
.map_or(host::__WASI_EIO, |e| errno_from_host(e as i32))
|
|
})?;
|
|
let flags = OFlag::from_bits_truncate(flags_bits);
|
|
let accmode = flags & OFlag::O_ACCMODE;
|
|
if accmode == OFlag::O_RDONLY {
|
|
rights_base &= !host::__WASI_RIGHT_FD_WRITE;
|
|
} else if accmode == OFlag::O_WRONLY {
|
|
rights_base &= !host::__WASI_RIGHT_FD_READ;
|
|
}
|
|
|
|
Ok((file_type, rights_base, rights_inheriting))
|
|
}
|
|
|
|
pub(crate) fn determine_type_rights<Fd: AsRawFd>(
|
|
fd: &Fd,
|
|
) -> Result<
|
|
(
|
|
host::__wasi_filetype_t,
|
|
host::__wasi_rights_t,
|
|
host::__wasi_rights_t,
|
|
),
|
|
host::__wasi_errno_t,
|
|
> {
|
|
let (file_type, rights_base, rights_inheriting) = {
|
|
// we just make a `File` here for convenience; we don't want it to close when it drops
|
|
let file =
|
|
std::mem::ManuallyDrop::new(unsafe { std::fs::File::from_raw_fd(fd.as_raw_fd()) });
|
|
let ft = file
|
|
.metadata()
|
|
.map_err(|err| err.raw_os_error().map_or(host::__WASI_EIO, errno_from_host))?
|
|
.file_type();
|
|
if ft.is_block_device() {
|
|
(
|
|
host::__WASI_FILETYPE_BLOCK_DEVICE,
|
|
host::RIGHTS_BLOCK_DEVICE_BASE,
|
|
host::RIGHTS_BLOCK_DEVICE_INHERITING,
|
|
)
|
|
} else if ft.is_char_device() {
|
|
if nix::unistd::isatty(fd.as_raw_fd()).map_err(|err| {
|
|
err.as_errno()
|
|
.map_or(host::__WASI_EIO, |e| errno_from_host(e as i32))
|
|
})? {
|
|
(
|
|
host::__WASI_FILETYPE_CHARACTER_DEVICE,
|
|
host::RIGHTS_TTY_BASE,
|
|
host::RIGHTS_TTY_BASE,
|
|
)
|
|
} else {
|
|
(
|
|
host::__WASI_FILETYPE_CHARACTER_DEVICE,
|
|
host::RIGHTS_CHARACTER_DEVICE_BASE,
|
|
host::RIGHTS_CHARACTER_DEVICE_INHERITING,
|
|
)
|
|
}
|
|
} else if ft.is_dir() {
|
|
(
|
|
host::__WASI_FILETYPE_DIRECTORY,
|
|
host::RIGHTS_DIRECTORY_BASE,
|
|
host::RIGHTS_DIRECTORY_INHERITING,
|
|
)
|
|
} else if ft.is_file() {
|
|
(
|
|
host::__WASI_FILETYPE_REGULAR_FILE,
|
|
host::RIGHTS_REGULAR_FILE_BASE,
|
|
host::RIGHTS_REGULAR_FILE_INHERITING,
|
|
)
|
|
} else if ft.is_socket() {
|
|
use nix::sys::socket;
|
|
match socket::getsockopt(fd.as_raw_fd(), socket::sockopt::SockType).map_err(|err| {
|
|
err.as_errno()
|
|
.map_or(host::__WASI_EIO, |e| errno_from_host(e as i32))
|
|
})? {
|
|
socket::SockType::Datagram => (
|
|
host::__WASI_FILETYPE_SOCKET_DGRAM,
|
|
host::RIGHTS_SOCKET_BASE,
|
|
host::RIGHTS_SOCKET_INHERITING,
|
|
),
|
|
socket::SockType::Stream => (
|
|
host::__WASI_FILETYPE_SOCKET_STREAM,
|
|
host::RIGHTS_SOCKET_BASE,
|
|
host::RIGHTS_SOCKET_INHERITING,
|
|
),
|
|
_ => return Err(host::__WASI_EINVAL),
|
|
}
|
|
} else if ft.is_fifo() {
|
|
(
|
|
host::__WASI_FILETYPE_SOCKET_STREAM,
|
|
host::RIGHTS_SOCKET_BASE,
|
|
host::RIGHTS_SOCKET_INHERITING,
|
|
)
|
|
} else {
|
|
return Err(host::__WASI_EINVAL);
|
|
}
|
|
};
|
|
|
|
Ok((file_type, rights_base, rights_inheriting))
|
|
}
|