Add yanix crate and replace nix with yanix in wasi-common (#649)

* Add yanix crate

This commit adds `yanix` crate as a Unix dependency for `wasi-common`.
`yanix` stands for Yet Another Nix crate and is exactly what the name
suggests: a crate in the spirit of the `nix` crate, but which takes a different
approach, using lower-level interfaces with less abstraction, so that it fits
better with its main use case, implementation of WASI syscalls.

* Replace nix with yanix crate

Having introduced `yanix` crate as an in-house replacement for the
`nix` crate, this commit makes the necessary changes to `wasi-common`
to depend _only_ on `yanix` crate.

* Address review comments

* make `fd_dup` unsafe
* rename `get_fd` to `get_fd_flags`, etc.
* reuse `io::Error::last_os_error()` to get the last errno value

* Address more comments

* make all `fcntl` fns unsafe
* adjust `wasi-common` impl appropriately

* Make all fns operating on RawFd unsafe

* Fix linux build

* Address more comments
This commit is contained in:
Jakub Konka
2019-12-09 01:40:05 +01:00
committed by Dan Gohman
parent ec8144b87d
commit 51f880f625
54 changed files with 2383 additions and 2031 deletions

View File

@@ -0,0 +1,52 @@
use crate::{
dir::{Dir, Entry, EntryExt, SeekLoc},
Errno, Result,
};
use std::ops::Deref;
#[derive(Copy, Clone, Debug)]
pub(crate) struct EntryImpl {
dirent: libc::dirent,
loc: SeekLoc,
}
impl Deref for EntryImpl {
type Target = libc::dirent;
fn deref(&self) -> &Self::Target {
&self.dirent
}
}
pub(crate) unsafe fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
let errno = Errno::last();
let dirent = libc::readdir(dir.0.as_ptr());
if dirent.is_null() {
if errno != Errno::last() {
// TODO This should be verified on different BSD-flavours.
//
// According to 4.3BSD/POSIX.1-2001 man pages, there was an error
// if the errno value has changed at some point during the sequence
// of readdir calls.
Some(Err(Errno::last().into()))
} else {
// Not an error. We've simply reached the end of the stream.
None
}
} else {
Some(Ok(EntryImpl {
dirent: *dirent,
loc: dir.tell(),
}))
}
}
impl EntryExt for Entry {
fn ino(&self) -> u64 {
self.0.d_ino.into()
}
fn seek_loc(&self) -> SeekLoc {
self.0.loc
}
}

View File

@@ -0,0 +1,51 @@
use crate::{Errno, Result};
use std::{convert::TryInto, os::unix::prelude::*};
#[derive(Debug, Copy, Clone)]
#[repr(i32)]
pub enum PosixFadviseAdvice {
Normal,
Sequential,
Random,
NoReuse,
WillNeed,
DontNeed,
}
// There's no posix_fadvise on macOS but we can use fcntl with F_RDADVISE
// command instead to achieve the same
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub unsafe fn posix_fadvise(
fd: RawFd,
offset: libc::off_t,
len: libc::off_t,
_advice: PosixFadviseAdvice,
) -> Result<()> {
// From macOS man pages:
// F_RDADVISE Issue an advisory read async with no copy to user.
//
// The F_RDADVISE command operates on the following structure which holds information passed from
// the user to the system:
//
// struct radvisory {
// off_t ra_offset; /* offset into the file */
// int ra_count; /* size of the read */
// };
let advisory = libc::radvisory {
ra_offset: offset,
ra_count: len.try_into()?,
};
Errno::from_success_code(libc::fcntl(fd, libc::F_RDADVISE, &advisory))
}
// TODO
// On non-macOS BSD's we leave it as no-op for now
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
pub unsafe fn posix_fadvise(
_fd: RawFd,
_offset: libc::off_t,
_len: libc::off_t,
_advice: PosixFadviseAdvice,
) -> Result<()> {
Ok(())
}

View File

@@ -0,0 +1,18 @@
use crate::{Errno, Result};
use std::os::unix::prelude::*;
pub unsafe fn isatty(fd: RawFd) -> Result<bool> {
let res = libc::isatty(fd);
if res == 1 {
// isatty() returns 1 if fd is an open file descriptor referring to a terminal...
Ok(true)
} else {
// ... otherwise 0 is returned, and errno is set to indicate the error.
let errno = Errno::last();
if errno == Errno::ENOTTY {
Ok(false)
} else {
Err(errno.into())
}
}
}

View File

@@ -0,0 +1,3 @@
pub(crate) mod dir;
pub(crate) mod fadvise;
pub(crate) mod file;