[wasi-common]: yanix now returns io::Error directly (#1242)
* Yanix now returns io::Error This commit may seem somewhat controversial at first, but hear me out first. Currently, Yanix would return a custom error that's a wrapper around three other error types returned by various entities inside Rust's `libstd`. In particular, Yanix's error type would wrap `io::Error`, `num::TryFromIntError` and `ffi::NulError`. It turns out that there is a natural conversion between the first and the last and provided by the standard library, i.e., `From<ffi::NulError> for io::Error` is provided. So at the surface it may seem that only the first two wrapped error types are worth keeping. Digging a little bit deeper into `libstd`, `num::TryFromIntError` is essentially speaking only a marker that the integral conversion went wrong. The struct implementing this error stores a unit type, and nothing more. It therefore seems like a waste to wrap this particular error when we could unify everything under `io::Error`. And so, whenever we perform an int conversion, I suggest we simply remap the error to `io::Error::from_raw_os_error(libc::EOVERFLOW)` since this carries a comparable amount of information. As a result of completely discarding `yanix::Error` custom error type, we are invariably simplifying `yanix` itself, but also allowing `wasi-common` to simplify in several places as well. * Adapt wasi-common to changes in yanix * Add Cargo.lock * Unwrap try_into's where possible * Remove unnecessary type annotation
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -2607,7 +2607,6 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"thiserror",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::old::snapshot_0::hostcalls_impl::PathGet;
|
use crate::old::snapshot_0::hostcalls_impl::PathGet;
|
||||||
use crate::old::snapshot_0::{Error, Result};
|
use crate::old::snapshot_0::{Error, Result};
|
||||||
use std::{io, os::unix::prelude::AsRawFd};
|
use std::os::unix::prelude::AsRawFd;
|
||||||
|
|
||||||
pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
||||||
use yanix::file::{unlinkat, AtFlag};
|
use yanix::file::{unlinkat, AtFlag};
|
||||||
@@ -12,8 +12,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
)
|
)
|
||||||
} {
|
} {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if let yanix::Error::Io(ref errno) = err {
|
let raw_errno = err.raw_os_error().unwrap();
|
||||||
let raw_errno = errno.raw_os_error().unwrap();
|
|
||||||
// Non-Linux implementations may return EPERM when attempting to remove a
|
// Non-Linux implementations may return EPERM when attempting to remove a
|
||||||
// directory without REMOVEDIR. While that's what POSIX specifies, it's
|
// directory without REMOVEDIR. While that's what POSIX specifies, it's
|
||||||
// less useful. Adjust this to EISDIR. It doesn't matter that this is not
|
// less useful. Adjust this to EISDIR. It doesn't matter that this is not
|
||||||
@@ -33,7 +32,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
} {
|
} {
|
||||||
Ok(stat) => {
|
Ok(stat) => {
|
||||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory {
|
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory {
|
||||||
return Err(io::Error::from_raw_os_error(libc::EISDIR).into());
|
return Err(Error::EISDIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -41,7 +40,6 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Err(err.into())
|
Err(err.into())
|
||||||
}
|
}
|
||||||
@@ -57,8 +55,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
|
|||||||
|
|
||||||
match unsafe { symlinkat(old_path, resolved.dirfd().as_raw_fd(), resolved.path()) } {
|
match unsafe { symlinkat(old_path, resolved.dirfd().as_raw_fd(), resolved.path()) } {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if let yanix::Error::Io(ref errno) = err {
|
if err.raw_os_error().unwrap() == libc::ENOTDIR {
|
||||||
if errno.raw_os_error().unwrap() == libc::ENOTDIR {
|
|
||||||
// On BSD, symlinkat returns ENOTDIR when it should in fact
|
// On BSD, symlinkat returns ENOTDIR when it should in fact
|
||||||
// return a EEXIST. It seems that it gets confused with by
|
// return a EEXIST. It seems that it gets confused with by
|
||||||
// the trailing slash in the target path. Thus, we strip
|
// the trailing slash in the target path. Thus, we strip
|
||||||
@@ -78,7 +75,6 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Err(err.into())
|
Err(err.into())
|
||||||
}
|
}
|
||||||
Ok(()) => Ok(()),
|
Ok(()) => Ok(()),
|
||||||
@@ -105,8 +101,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
//
|
//
|
||||||
// TODO
|
// TODO
|
||||||
// Verify on other BSD-based OSes.
|
// Verify on other BSD-based OSes.
|
||||||
if let yanix::Error::Io(ref errno) = err {
|
if err.raw_os_error().unwrap() == libc::ENOENT {
|
||||||
if errno.raw_os_error().unwrap() == libc::ENOENT {
|
|
||||||
// check if the source path exists
|
// check if the source path exists
|
||||||
match unsafe {
|
match unsafe {
|
||||||
fstatat(
|
fstatat(
|
||||||
@@ -128,7 +123,6 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Err(err.into())
|
Err(err.into())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,17 +12,6 @@ use yanix::file::OFlag;
|
|||||||
|
|
||||||
pub(crate) use sys_impl::host_impl::*;
|
pub(crate) use sys_impl::host_impl::*;
|
||||||
|
|
||||||
impl From<yanix::Error> for Error {
|
|
||||||
fn from(err: yanix::Error) -> Self {
|
|
||||||
use yanix::Error::*;
|
|
||||||
match err {
|
|
||||||
Io(err) => err.into(),
|
|
||||||
Nul(err) => err.into(),
|
|
||||||
IntConversion(err) => err.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromRawOsError for Error {
|
impl FromRawOsError for Error {
|
||||||
fn from_raw_os_error(code: i32) -> Self {
|
fn from_raw_os_error(code: i32) -> Self {
|
||||||
match code {
|
match code {
|
||||||
|
|||||||
@@ -124,8 +124,7 @@ pub(crate) fn path_open(
|
|||||||
} {
|
} {
|
||||||
Ok(fd) => fd,
|
Ok(fd) => fd,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let yanix::Error::Io(ref err) = e {
|
match e.raw_os_error().unwrap() {
|
||||||
match err.raw_os_error().unwrap() {
|
|
||||||
// Linux returns ENXIO instead of EOPNOTSUPP when opening a socket
|
// Linux returns ENXIO instead of EOPNOTSUPP when opening a socket
|
||||||
libc::ENXIO => {
|
libc::ENXIO => {
|
||||||
match unsafe {
|
match unsafe {
|
||||||
@@ -174,7 +173,6 @@ pub(crate) fn path_open(
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::hostcalls_impl::PathGet;
|
use crate::hostcalls_impl::PathGet;
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
use std::{io, os::unix::prelude::AsRawFd};
|
use std::os::unix::prelude::AsRawFd;
|
||||||
|
|
||||||
pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
||||||
use yanix::file::{unlinkat, AtFlag};
|
use yanix::file::{unlinkat, AtFlag};
|
||||||
@@ -12,8 +12,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
)
|
)
|
||||||
} {
|
} {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if let yanix::Error::Io(ref errno) = err {
|
let raw_errno = err.raw_os_error().unwrap();
|
||||||
let raw_errno = errno.raw_os_error().unwrap();
|
|
||||||
// Non-Linux implementations may return EPERM when attempting to remove a
|
// Non-Linux implementations may return EPERM when attempting to remove a
|
||||||
// directory without REMOVEDIR. While that's what POSIX specifies, it's
|
// directory without REMOVEDIR. While that's what POSIX specifies, it's
|
||||||
// less useful. Adjust this to EISDIR. It doesn't matter that this is not
|
// less useful. Adjust this to EISDIR. It doesn't matter that this is not
|
||||||
@@ -33,7 +32,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
} {
|
} {
|
||||||
Ok(stat) => {
|
Ok(stat) => {
|
||||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory {
|
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory {
|
||||||
return Err(io::Error::from_raw_os_error(libc::EISDIR).into());
|
return Err(Error::EISDIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -41,7 +40,6 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Err(err.into())
|
Err(err.into())
|
||||||
}
|
}
|
||||||
@@ -57,8 +55,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
|
|||||||
|
|
||||||
match unsafe { symlinkat(old_path, resolved.dirfd().as_raw_fd(), resolved.path()) } {
|
match unsafe { symlinkat(old_path, resolved.dirfd().as_raw_fd(), resolved.path()) } {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if let yanix::Error::Io(ref errno) = err {
|
if err.raw_os_error().unwrap() == libc::ENOTDIR {
|
||||||
if errno.raw_os_error().unwrap() == libc::ENOTDIR {
|
|
||||||
// On BSD, symlinkat returns ENOTDIR when it should in fact
|
// On BSD, symlinkat returns ENOTDIR when it should in fact
|
||||||
// return a EEXIST. It seems that it gets confused with by
|
// return a EEXIST. It seems that it gets confused with by
|
||||||
// the trailing slash in the target path. Thus, we strip
|
// the trailing slash in the target path. Thus, we strip
|
||||||
@@ -78,7 +75,6 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Err(err.into())
|
Err(err.into())
|
||||||
}
|
}
|
||||||
Ok(()) => Ok(()),
|
Ok(()) => Ok(()),
|
||||||
@@ -105,8 +101,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
//
|
//
|
||||||
// TODO
|
// TODO
|
||||||
// Verify on other BSD-based OSes.
|
// Verify on other BSD-based OSes.
|
||||||
if let yanix::Error::Io(ref errno) = err {
|
if err.raw_os_error().unwrap() == libc::ENOENT {
|
||||||
if errno.raw_os_error().unwrap() == libc::ENOENT {
|
|
||||||
// check if the source path exists
|
// check if the source path exists
|
||||||
match unsafe {
|
match unsafe {
|
||||||
fstatat(
|
fstatat(
|
||||||
@@ -128,7 +123,6 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Err(err.into())
|
Err(err.into())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,17 +10,6 @@ use yanix::file::OFlag;
|
|||||||
|
|
||||||
pub(crate) use sys_impl::host_impl::*;
|
pub(crate) use sys_impl::host_impl::*;
|
||||||
|
|
||||||
impl From<yanix::Error> for Error {
|
|
||||||
fn from(err: yanix::Error) -> Self {
|
|
||||||
use yanix::Error::*;
|
|
||||||
match err {
|
|
||||||
Io(err) => err.into(),
|
|
||||||
Nul(err) => err.into(),
|
|
||||||
IntConversion(err) => err.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromRawOsError for Error {
|
impl FromRawOsError for Error {
|
||||||
fn from_raw_os_error(code: i32) -> Self {
|
fn from_raw_os_error(code: i32) -> Self {
|
||||||
match code {
|
match code {
|
||||||
|
|||||||
@@ -124,8 +124,7 @@ pub(crate) fn path_open(
|
|||||||
let new_fd = match fd_no {
|
let new_fd = match fd_no {
|
||||||
Ok(fd) => fd,
|
Ok(fd) => fd,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let yanix::Error::Io(ref err) = e {
|
match e.raw_os_error().unwrap() {
|
||||||
match err.raw_os_error().unwrap() {
|
|
||||||
// Linux returns ENXIO instead of EOPNOTSUPP when opening a socket
|
// Linux returns ENXIO instead of EOPNOTSUPP when opening a socket
|
||||||
libc::ENXIO => {
|
libc::ENXIO => {
|
||||||
match unsafe {
|
match unsafe {
|
||||||
@@ -174,7 +173,6 @@ pub(crate) fn path_open(
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
libc = { version = "0.2", features = ["extra_traits"] }
|
libc = { version = "0.2", features = ["extra_traits"] }
|
||||||
thiserror = "1.0"
|
|
||||||
bitflags = "1.2"
|
bitflags = "1.2"
|
||||||
cfg-if = "0.1.9"
|
cfg-if = "0.1.9"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::{Error, Result};
|
use crate::from_success_code;
|
||||||
|
use std::io::Result;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@@ -22,16 +23,12 @@ impl ClockId {
|
|||||||
|
|
||||||
pub fn clock_getres(clock_id: ClockId) -> Result<libc::timespec> {
|
pub fn clock_getres(clock_id: ClockId) -> Result<libc::timespec> {
|
||||||
let mut timespec = MaybeUninit::<libc::timespec>::uninit();
|
let mut timespec = MaybeUninit::<libc::timespec>::uninit();
|
||||||
Error::from_success_code(unsafe {
|
from_success_code(unsafe { libc::clock_getres(clock_id.as_raw(), timespec.as_mut_ptr()) })?;
|
||||||
libc::clock_getres(clock_id.as_raw(), timespec.as_mut_ptr())
|
|
||||||
})?;
|
|
||||||
Ok(unsafe { timespec.assume_init() })
|
Ok(unsafe { timespec.assume_init() })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clock_gettime(clock_id: ClockId) -> Result<libc::timespec> {
|
pub fn clock_gettime(clock_id: ClockId) -> Result<libc::timespec> {
|
||||||
let mut timespec = MaybeUninit::<libc::timespec>::uninit();
|
let mut timespec = MaybeUninit::<libc::timespec>::uninit();
|
||||||
Error::from_success_code(unsafe {
|
from_success_code(unsafe { libc::clock_gettime(clock_id.as_raw(), timespec.as_mut_ptr()) })?;
|
||||||
libc::clock_gettime(clock_id.as_raw(), timespec.as_mut_ptr())
|
|
||||||
})?;
|
|
||||||
Ok(unsafe { timespec.assume_init() })
|
Ok(unsafe { timespec.assume_init() })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
file::FileType,
|
file::FileType,
|
||||||
sys::dir::{iter_impl, EntryImpl},
|
sys::dir::{iter_impl, EntryImpl},
|
||||||
Result,
|
|
||||||
};
|
};
|
||||||
|
use std::io::Result;
|
||||||
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
|
||||||
use std::{ffi::CStr, io, ops::Deref, ptr};
|
use std::{ffi::CStr, io, ops::Deref, ptr};
|
||||||
|
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
//! Error type
|
|
||||||
use crate::Result;
|
|
||||||
use std::{ffi, io, num};
|
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
pub enum Error {
|
|
||||||
#[error("I/O error {0}")]
|
|
||||||
Io(#[from] io::Error),
|
|
||||||
#[error("a nul byte was not found in the expected position")]
|
|
||||||
Nul(#[from] ffi::NulError),
|
|
||||||
#[error("integral type conversion failed")]
|
|
||||||
IntConversion(#[from] num::TryFromIntError),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error {
|
|
||||||
pub fn from_success_code<T: IsZero>(t: T) -> Result<()> {
|
|
||||||
if t.is_zero() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(Self::from(io::Error::last_os_error()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_result<T: IsMinusOne>(t: T) -> Result<T> {
|
|
||||||
if t.is_minus_one() {
|
|
||||||
Err(Self::from(io::Error::last_os_error()))
|
|
||||||
} else {
|
|
||||||
Ok(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub trait IsZero {
|
|
||||||
fn is_zero(&self) -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_is_zero {
|
|
||||||
($($t:ident)*) => ($(impl IsZero for $t {
|
|
||||||
fn is_zero(&self) -> bool {
|
|
||||||
*self == 0
|
|
||||||
}
|
|
||||||
})*)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_is_zero! { i32 i64 isize }
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub trait IsMinusOne {
|
|
||||||
fn is_minus_one(&self) -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_is_minus_one {
|
|
||||||
($($t:ident)*) => ($(impl IsMinusOne for $t {
|
|
||||||
fn is_minus_one(&self) -> bool {
|
|
||||||
*self == -1
|
|
||||||
}
|
|
||||||
})*)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_is_minus_one! { i32 i64 isize }
|
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
file::{FdFlag, OFlag},
|
file::{FdFlag, OFlag},
|
||||||
Error, Result,
|
from_result, from_success_code,
|
||||||
};
|
};
|
||||||
|
use std::io::Result;
|
||||||
use std::os::unix::prelude::*;
|
use std::os::unix::prelude::*;
|
||||||
|
|
||||||
pub unsafe fn dup_fd(fd: RawFd, close_on_exec: bool) -> Result<RawFd> {
|
pub unsafe fn dup_fd(fd: RawFd, close_on_exec: bool) -> Result<RawFd> {
|
||||||
@@ -9,7 +10,7 @@ pub unsafe fn dup_fd(fd: RawFd, close_on_exec: bool) -> Result<RawFd> {
|
|||||||
// the minimum duplicated RawFd number. In our case, I don't
|
// the minimum duplicated RawFd number. In our case, I don't
|
||||||
// think we have to worry about this that much, so passing in
|
// think we have to worry about this that much, so passing in
|
||||||
// the RawFd descriptor we want duplicated
|
// the RawFd descriptor we want duplicated
|
||||||
Error::from_result(if close_on_exec {
|
from_result(if close_on_exec {
|
||||||
libc::fcntl(fd, libc::F_DUPFD_CLOEXEC, fd)
|
libc::fcntl(fd, libc::F_DUPFD_CLOEXEC, fd)
|
||||||
} else {
|
} else {
|
||||||
libc::fcntl(fd, libc::F_DUPFD, fd)
|
libc::fcntl(fd, libc::F_DUPFD, fd)
|
||||||
@@ -17,17 +18,17 @@ pub unsafe fn dup_fd(fd: RawFd, close_on_exec: bool) -> Result<RawFd> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn get_fd_flags(fd: RawFd) -> Result<FdFlag> {
|
pub unsafe fn get_fd_flags(fd: RawFd) -> Result<FdFlag> {
|
||||||
Error::from_result(libc::fcntl(fd, libc::F_GETFD)).map(FdFlag::from_bits_truncate)
|
from_result(libc::fcntl(fd, libc::F_GETFD)).map(FdFlag::from_bits_truncate)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn set_fd_flags(fd: RawFd, flags: FdFlag) -> Result<()> {
|
pub unsafe fn set_fd_flags(fd: RawFd, flags: FdFlag) -> Result<()> {
|
||||||
Error::from_success_code(libc::fcntl(fd, libc::F_SETFD, flags.bits()))
|
from_success_code(libc::fcntl(fd, libc::F_SETFD, flags.bits()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn get_status_flags(fd: RawFd) -> Result<OFlag> {
|
pub unsafe fn get_status_flags(fd: RawFd) -> Result<OFlag> {
|
||||||
Error::from_result(libc::fcntl(fd, libc::F_GETFL)).map(OFlag::from_bits_truncate)
|
from_result(libc::fcntl(fd, libc::F_GETFL)).map(OFlag::from_bits_truncate)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn set_status_flags(fd: RawFd, flags: OFlag) -> Result<()> {
|
pub unsafe fn set_status_flags(fd: RawFd, flags: OFlag) -> Result<()> {
|
||||||
Error::from_success_code(libc::fcntl(fd, libc::F_SETFL, flags.bits()))
|
from_success_code(libc::fcntl(fd, libc::F_SETFL, flags.bits()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
use crate::{Error, Result};
|
use crate::{from_result, from_success_code};
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryInto,
|
convert::TryInto,
|
||||||
ffi::{CString, OsStr, OsString},
|
ffi::{CString, OsStr, OsString},
|
||||||
|
io::Result,
|
||||||
os::unix::prelude::*,
|
os::unix::prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -137,7 +138,7 @@ pub unsafe fn openat<P: AsRef<OsStr>>(
|
|||||||
mode: Mode,
|
mode: Mode,
|
||||||
) -> Result<RawFd> {
|
) -> Result<RawFd> {
|
||||||
let path = CString::new(path.as_ref().as_bytes())?;
|
let path = CString::new(path.as_ref().as_bytes())?;
|
||||||
Error::from_result(libc::openat(
|
from_result(libc::openat(
|
||||||
dirfd,
|
dirfd,
|
||||||
path.as_ptr(),
|
path.as_ptr(),
|
||||||
oflag.bits(),
|
oflag.bits(),
|
||||||
@@ -148,21 +149,23 @@ pub unsafe fn openat<P: AsRef<OsStr>>(
|
|||||||
pub unsafe fn readlinkat<P: AsRef<OsStr>>(dirfd: RawFd, path: P) -> Result<OsString> {
|
pub unsafe fn readlinkat<P: AsRef<OsStr>>(dirfd: RawFd, path: P) -> Result<OsString> {
|
||||||
let path = CString::new(path.as_ref().as_bytes())?;
|
let path = CString::new(path.as_ref().as_bytes())?;
|
||||||
let buffer = &mut [0u8; libc::PATH_MAX as usize + 1];
|
let buffer = &mut [0u8; libc::PATH_MAX as usize + 1];
|
||||||
Error::from_result(libc::readlinkat(
|
let nread = from_result(libc::readlinkat(
|
||||||
dirfd,
|
dirfd,
|
||||||
path.as_ptr(),
|
path.as_ptr(),
|
||||||
buffer.as_mut_ptr() as *mut _,
|
buffer.as_mut_ptr() as *mut _,
|
||||||
buffer.len(),
|
buffer.len(),
|
||||||
))
|
))?;
|
||||||
.and_then(|nread| {
|
// We can just unwrap() this, because readlinkat returns an ssize_t which is either -1
|
||||||
let link = OsStr::from_bytes(&buffer[0..nread.try_into()?]);
|
// (handled above) or non-negative and will fit in a size_t/usize, which is what we're
|
||||||
|
// converting it to here.
|
||||||
|
let nread = nread.try_into().unwrap();
|
||||||
|
let link = OsStr::from_bytes(&buffer[0..nread]);
|
||||||
Ok(link.into())
|
Ok(link.into())
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn mkdirat<P: AsRef<OsStr>>(dirfd: RawFd, path: P, mode: Mode) -> Result<()> {
|
pub unsafe fn mkdirat<P: AsRef<OsStr>>(dirfd: RawFd, path: P, mode: Mode) -> Result<()> {
|
||||||
let path = CString::new(path.as_ref().as_bytes())?;
|
let path = CString::new(path.as_ref().as_bytes())?;
|
||||||
Error::from_success_code(libc::mkdirat(dirfd, path.as_ptr(), mode.bits()))
|
from_success_code(libc::mkdirat(dirfd, path.as_ptr(), mode.bits()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn linkat<P: AsRef<OsStr>>(
|
pub unsafe fn linkat<P: AsRef<OsStr>>(
|
||||||
@@ -174,7 +177,7 @@ pub unsafe fn linkat<P: AsRef<OsStr>>(
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let old_path = CString::new(old_path.as_ref().as_bytes())?;
|
let old_path = CString::new(old_path.as_ref().as_bytes())?;
|
||||||
let new_path = CString::new(new_path.as_ref().as_bytes())?;
|
let new_path = CString::new(new_path.as_ref().as_bytes())?;
|
||||||
Error::from_success_code(libc::linkat(
|
from_success_code(libc::linkat(
|
||||||
old_dirfd,
|
old_dirfd,
|
||||||
old_path.as_ptr(),
|
old_path.as_ptr(),
|
||||||
new_dirfd,
|
new_dirfd,
|
||||||
@@ -185,7 +188,7 @@ pub unsafe fn linkat<P: AsRef<OsStr>>(
|
|||||||
|
|
||||||
pub unsafe fn unlinkat<P: AsRef<OsStr>>(dirfd: RawFd, path: P, flags: AtFlag) -> Result<()> {
|
pub unsafe fn unlinkat<P: AsRef<OsStr>>(dirfd: RawFd, path: P, flags: AtFlag) -> Result<()> {
|
||||||
let path = CString::new(path.as_ref().as_bytes())?;
|
let path = CString::new(path.as_ref().as_bytes())?;
|
||||||
Error::from_success_code(libc::unlinkat(dirfd, path.as_ptr(), flags.bits()))
|
from_success_code(libc::unlinkat(dirfd, path.as_ptr(), flags.bits()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn renameat<P: AsRef<OsStr>>(
|
pub unsafe fn renameat<P: AsRef<OsStr>>(
|
||||||
@@ -196,7 +199,7 @@ pub unsafe fn renameat<P: AsRef<OsStr>>(
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let old_path = CString::new(old_path.as_ref().as_bytes())?;
|
let old_path = CString::new(old_path.as_ref().as_bytes())?;
|
||||||
let new_path = CString::new(new_path.as_ref().as_bytes())?;
|
let new_path = CString::new(new_path.as_ref().as_bytes())?;
|
||||||
Error::from_success_code(libc::renameat(
|
from_success_code(libc::renameat(
|
||||||
old_dirfd,
|
old_dirfd,
|
||||||
old_path.as_ptr(),
|
old_path.as_ptr(),
|
||||||
new_dirfd,
|
new_dirfd,
|
||||||
@@ -207,7 +210,7 @@ pub unsafe fn renameat<P: AsRef<OsStr>>(
|
|||||||
pub unsafe fn symlinkat<P: AsRef<OsStr>>(old_path: P, new_dirfd: RawFd, new_path: P) -> Result<()> {
|
pub unsafe fn symlinkat<P: AsRef<OsStr>>(old_path: P, new_dirfd: RawFd, new_path: P) -> Result<()> {
|
||||||
let old_path = CString::new(old_path.as_ref().as_bytes())?;
|
let old_path = CString::new(old_path.as_ref().as_bytes())?;
|
||||||
let new_path = CString::new(new_path.as_ref().as_bytes())?;
|
let new_path = CString::new(new_path.as_ref().as_bytes())?;
|
||||||
Error::from_success_code(libc::symlinkat(
|
from_success_code(libc::symlinkat(
|
||||||
old_path.as_ptr(),
|
old_path.as_ptr(),
|
||||||
new_dirfd,
|
new_dirfd,
|
||||||
new_path.as_ptr(),
|
new_path.as_ptr(),
|
||||||
@@ -218,7 +221,7 @@ pub unsafe fn fstatat<P: AsRef<OsStr>>(dirfd: RawFd, path: P, flags: AtFlag) ->
|
|||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
let path = CString::new(path.as_ref().as_bytes())?;
|
let path = CString::new(path.as_ref().as_bytes())?;
|
||||||
let mut filestat = MaybeUninit::<libc::stat>::uninit();
|
let mut filestat = MaybeUninit::<libc::stat>::uninit();
|
||||||
Error::from_result(libc::fstatat(
|
from_result(libc::fstatat(
|
||||||
dirfd,
|
dirfd,
|
||||||
path.as_ptr(),
|
path.as_ptr(),
|
||||||
filestat.as_mut_ptr(),
|
filestat.as_mut_ptr(),
|
||||||
@@ -230,20 +233,26 @@ pub unsafe fn fstatat<P: AsRef<OsStr>>(dirfd: RawFd, path: P, flags: AtFlag) ->
|
|||||||
pub unsafe fn fstat(fd: RawFd) -> Result<libc::stat> {
|
pub unsafe fn fstat(fd: RawFd) -> Result<libc::stat> {
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
let mut filestat = MaybeUninit::<libc::stat>::uninit();
|
let mut filestat = MaybeUninit::<libc::stat>::uninit();
|
||||||
Error::from_result(libc::fstat(fd, filestat.as_mut_ptr()))?;
|
from_result(libc::fstat(fd, filestat.as_mut_ptr()))?;
|
||||||
Ok(filestat.assume_init())
|
Ok(filestat.assume_init())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `fionread()` function, equivalent to `ioctl(fd, FIONREAD, *bytes)`.
|
/// `fionread()` function, equivalent to `ioctl(fd, FIONREAD, *bytes)`.
|
||||||
pub unsafe fn fionread(fd: RawFd) -> Result<u32> {
|
pub unsafe fn fionread(fd: RawFd) -> Result<u32> {
|
||||||
let mut nread: libc::c_int = 0;
|
let mut nread: libc::c_int = 0;
|
||||||
Error::from_result(libc::ioctl(fd, libc::FIONREAD, &mut nread as *mut _))?;
|
from_result(libc::ioctl(fd, libc::FIONREAD, &mut nread as *mut _))?;
|
||||||
Ok(nread.try_into()?)
|
// FIONREAD returns a non-negative int if it doesn't fail, or it'll fit in a u32 if it does.
|
||||||
|
//
|
||||||
|
// For the future, if we want to be super cautious and avoid assuming int is 32-bit, we could
|
||||||
|
// widen fionread's return type here, since the one place that calls it wants a u64 anyway.
|
||||||
|
Ok(nread.try_into().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function is unsafe because it operates on a raw file descriptor.
|
/// This function is unsafe because it operates on a raw file descriptor.
|
||||||
/// It's provided, because std::io::Seek requires a mutable borrow.
|
/// It's provided, because std::io::Seek requires a mutable borrow.
|
||||||
pub unsafe fn tell(fd: RawFd) -> Result<u64> {
|
pub unsafe fn tell(fd: RawFd) -> Result<u64> {
|
||||||
let offset: i64 = Error::from_result(libc::lseek(fd, 0, libc::SEEK_CUR))?;
|
let offset = from_result(libc::lseek(fd, 0, libc::SEEK_CUR))?;
|
||||||
Ok(offset.try_into()?)
|
// lseek returns an off_t, which we can assume is a non-negative i64 if it doesn't fail.
|
||||||
|
// So we can unwrap() this conversion.
|
||||||
|
Ok(offset.try_into().unwrap())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,54 @@ pub mod file;
|
|||||||
pub mod poll;
|
pub mod poll;
|
||||||
pub mod socket;
|
pub mod socket;
|
||||||
|
|
||||||
mod error;
|
|
||||||
mod sys;
|
mod sys;
|
||||||
|
|
||||||
pub mod fadvise {
|
pub mod fadvise {
|
||||||
pub use super::sys::fadvise::*;
|
pub use super::sys::fadvise::*;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use error::Error;
|
use std::io::{Error, Result};
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
|
||||||
|
fn from_success_code<T: IsZero>(t: T) -> Result<()> {
|
||||||
|
if t.is_zero() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error::last_os_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_result<T: IsMinusOne>(t: T) -> Result<T> {
|
||||||
|
if t.is_minus_one() {
|
||||||
|
Err(Error::last_os_error())
|
||||||
|
} else {
|
||||||
|
Ok(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait IsZero {
|
||||||
|
fn is_zero(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_is_zero {
|
||||||
|
($($t:ident)*) => ($(impl IsZero for $t {
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
*self == 0
|
||||||
|
}
|
||||||
|
})*)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_is_zero! { i32 i64 isize }
|
||||||
|
|
||||||
|
trait IsMinusOne {
|
||||||
|
fn is_minus_one(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_is_minus_one {
|
||||||
|
($($t:ident)*) => ($(impl IsMinusOne for $t {
|
||||||
|
fn is_minus_one(&self) -> bool {
|
||||||
|
*self == -1
|
||||||
|
}
|
||||||
|
})*)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_is_minus_one! { i32 i64 isize }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::{Error, Result};
|
use crate::from_result;
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use std::{convert::TryInto, os::unix::prelude::*};
|
use std::{convert::TryInto, io::Result, os::unix::prelude::*};
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct PollFlags: libc::c_short {
|
pub struct PollFlags: libc::c_short {
|
||||||
@@ -36,12 +36,14 @@ impl PollFd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<usize> {
|
pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<usize> {
|
||||||
Error::from_result(unsafe {
|
let nready = from_result(unsafe {
|
||||||
libc::poll(
|
libc::poll(
|
||||||
fds.as_mut_ptr() as *mut libc::pollfd,
|
fds.as_mut_ptr() as *mut libc::pollfd,
|
||||||
fds.len() as libc::nfds_t,
|
fds.len() as libc::nfds_t,
|
||||||
timeout,
|
timeout,
|
||||||
)
|
)
|
||||||
})
|
})?;
|
||||||
.and_then(|nready| nready.try_into().map_err(Into::into))
|
// When poll doesn't fail, its return value is a non-negative int, which will
|
||||||
|
// always be convertable to usize, so we can unwrap() here.
|
||||||
|
Ok(nready.try_into().unwrap())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::{Error, Result};
|
use crate::from_success_code;
|
||||||
|
use std::io::Result;
|
||||||
use std::os::unix::prelude::*;
|
use std::os::unix::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
@@ -15,7 +16,7 @@ pub unsafe fn get_socket_type(fd: RawFd) -> Result<SockType> {
|
|||||||
use std::mem::{self, MaybeUninit};
|
use std::mem::{self, MaybeUninit};
|
||||||
let mut buffer = MaybeUninit::<SockType>::zeroed().assume_init();
|
let mut buffer = MaybeUninit::<SockType>::zeroed().assume_init();
|
||||||
let mut out_len = mem::size_of::<SockType>() as libc::socklen_t;
|
let mut out_len = mem::size_of::<SockType>() as libc::socklen_t;
|
||||||
Error::from_success_code(libc::getsockopt(
|
from_success_code(libc::getsockopt(
|
||||||
fd,
|
fd,
|
||||||
libc::SOL_SOCKET,
|
libc::SOL_SOCKET,
|
||||||
libc::SO_TYPE,
|
libc::SO_TYPE,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::{
|
use crate::dir::{Dir, Entry, EntryExt, SeekLoc};
|
||||||
dir::{Dir, Entry, EntryExt, SeekLoc},
|
use std::{
|
||||||
Result,
|
io::{Error, Result},
|
||||||
|
ops::Deref,
|
||||||
};
|
};
|
||||||
use std::{io, ops::Deref};
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub(crate) struct EntryImpl {
|
pub(crate) struct EntryImpl {
|
||||||
@@ -19,17 +19,17 @@ impl Deref for EntryImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
|
pub(crate) fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
|
||||||
let errno = io::Error::last_os_error();
|
let errno = Error::last_os_error();
|
||||||
let dirent = unsafe { libc::readdir(dir.as_raw().as_ptr()) };
|
let dirent = unsafe { libc::readdir(dir.as_raw().as_ptr()) };
|
||||||
if dirent.is_null() {
|
if dirent.is_null() {
|
||||||
let curr_errno = io::Error::last_os_error();
|
let curr_errno = Error::last_os_error();
|
||||||
if errno.raw_os_error() != curr_errno.raw_os_error() {
|
if errno.raw_os_error() != curr_errno.raw_os_error() {
|
||||||
// TODO This should be verified on different BSD-flavours.
|
// TODO This should be verified on different BSD-flavours.
|
||||||
//
|
//
|
||||||
// According to 4.3BSD/POSIX.1-2001 man pages, there was an error
|
// 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
|
// if the errno value has changed at some point during the sequence
|
||||||
// of readdir calls.
|
// of readdir calls.
|
||||||
Some(Err(curr_errno.into()))
|
Some(Err(curr_errno))
|
||||||
} else {
|
} else {
|
||||||
// Not an error. We've simply reached the end of the stream.
|
// Not an error. We've simply reached the end of the stream.
|
||||||
None
|
None
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::{Error, Result};
|
use crate::from_success_code;
|
||||||
use std::{convert::TryInto, os::unix::prelude::*};
|
use std::{convert::TryInto, io::Result, os::unix::prelude::*};
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "freebsd", target_os = "netbsd")))]
|
#[cfg(not(any(target_os = "freebsd", target_os = "netbsd")))]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@@ -44,11 +44,22 @@ pub unsafe fn posix_fadvise(
|
|||||||
// off_t ra_offset; /* offset into the file */
|
// off_t ra_offset; /* offset into the file */
|
||||||
// int ra_count; /* size of the read */
|
// int ra_count; /* size of the read */
|
||||||
// };
|
// };
|
||||||
|
let ra_count = match len.try_into() {
|
||||||
|
Ok(ra_count) => ra_count,
|
||||||
|
Err(_) => {
|
||||||
|
// This conversion can fail, because it's converting into int. But in that case, the user
|
||||||
|
// is providing a dubiously large hint. This is not confirmed (no helpful info in the man
|
||||||
|
// pages), but offhand, a 2+ GiB advisory read async seems unlikely to help with any kind
|
||||||
|
// of performance, so we log and exit early with a no-op.
|
||||||
|
log::warn!("`len` too big to fit in the host's command. Returning early with no-op!");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
let advisory = libc::radvisory {
|
let advisory = libc::radvisory {
|
||||||
ra_offset: offset,
|
ra_offset: offset,
|
||||||
ra_count: len.try_into()?,
|
ra_count,
|
||||||
};
|
};
|
||||||
Error::from_success_code(libc::fcntl(fd, libc::F_RDADVISE, &advisory))
|
from_success_code(libc::fcntl(fd, libc::F_RDADVISE, &advisory))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
|
#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
|
||||||
@@ -58,7 +69,7 @@ pub unsafe fn posix_fadvise(
|
|||||||
len: libc::off_t,
|
len: libc::off_t,
|
||||||
advice: PosixFadviseAdvice,
|
advice: PosixFadviseAdvice,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
Error::from_success_code(libc::posix_fadvise(fd, offset, len, advice as libc::c_int))
|
from_success_code(libc::posix_fadvise(fd, offset, len, advice as libc::c_int))
|
||||||
}
|
}
|
||||||
|
|
||||||
// On BSDs without support we leave it as no-op
|
// On BSDs without support we leave it as no-op
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
use crate::Result;
|
use std::{
|
||||||
use std::{io, os::unix::prelude::*};
|
io::{Error, Result},
|
||||||
|
os::unix::prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
pub unsafe fn isatty(fd: RawFd) -> Result<bool> {
|
pub unsafe fn isatty(fd: RawFd) -> Result<bool> {
|
||||||
let res = libc::isatty(fd);
|
let res = libc::isatty(fd);
|
||||||
@@ -8,15 +10,11 @@ pub unsafe fn isatty(fd: RawFd) -> Result<bool> {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
// ... otherwise 0 is returned, and errno is set to indicate the error.
|
// ... otherwise 0 is returned, and errno is set to indicate the error.
|
||||||
let errno = io::Error::last_os_error();
|
let errno = Error::last_os_error();
|
||||||
if let Some(raw_errno) = errno.raw_os_error() {
|
if errno.raw_os_error().unwrap() == libc::ENOTTY {
|
||||||
if raw_errno == libc::ENOTTY {
|
|
||||||
Ok(false)
|
Ok(false)
|
||||||
} else {
|
} else {
|
||||||
Err(errno.into())
|
Err(errno)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(errno.into())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,20 @@ pub(crate) mod fadvise;
|
|||||||
#[path = "../linux/file.rs"]
|
#[path = "../linux/file.rs"]
|
||||||
pub(crate) mod file;
|
pub(crate) mod file;
|
||||||
|
|
||||||
use crate::{dir::SeekLoc, Result};
|
use crate::dir::SeekLoc;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use std::io::{Error, Result};
|
||||||
|
|
||||||
impl SeekLoc {
|
impl SeekLoc {
|
||||||
pub unsafe fn from_raw(loc: i64) -> Result<Self> {
|
pub unsafe fn from_raw(loc: i64) -> Result<Self> {
|
||||||
let loc = loc.try_into()?;
|
// The cookie (or `loc`) is an opaque value, and applications aren't supposed to do
|
||||||
|
// arithmetic on them or pick their own values or have any awareness of the numeric
|
||||||
|
// range of the values. They're just supposed to pass back in the values that we
|
||||||
|
// give them. And any value we give them will be convertable back to `long`,
|
||||||
|
// because that's the type the OS gives them to us in. So return an `EINVAL`.
|
||||||
|
let loc = loc
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| Error::from_raw_os_error(libc::EINVAL))?;
|
||||||
Ok(Self(loc))
|
Ok(Self(loc))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::{
|
use crate::dir::{Dir, Entry, EntryExt, SeekLoc};
|
||||||
dir::{Dir, Entry, EntryExt, SeekLoc},
|
use std::{
|
||||||
Result,
|
io::{Error, Result},
|
||||||
|
ops::Deref,
|
||||||
};
|
};
|
||||||
use std::{io, ops::Deref};
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub(crate) struct EntryImpl(libc::dirent64);
|
pub(crate) struct EntryImpl(libc::dirent64);
|
||||||
@@ -26,17 +26,17 @@ impl EntryExt for Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
|
pub(crate) fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
|
||||||
let errno = io::Error::last_os_error();
|
let errno = Error::last_os_error();
|
||||||
let dirent = unsafe { libc::readdir64(dir.as_raw().as_ptr()) };
|
let dirent = unsafe { libc::readdir64(dir.as_raw().as_ptr()) };
|
||||||
if dirent.is_null() {
|
if dirent.is_null() {
|
||||||
let curr_errno = io::Error::last_os_error();
|
let curr_errno = Error::last_os_error();
|
||||||
if errno.raw_os_error() != curr_errno.raw_os_error() {
|
if errno.raw_os_error() != curr_errno.raw_os_error() {
|
||||||
// TODO This should be verified on different BSD-flavours.
|
// TODO This should be verified on different BSD-flavours.
|
||||||
//
|
//
|
||||||
// According to 4.3BSD/POSIX.1-2001 man pages, there was an error
|
// 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
|
// if the errno value has changed at some point during the sequence
|
||||||
// of readdir calls.
|
// of readdir calls.
|
||||||
Some(Err(curr_errno.into()))
|
Some(Err(curr_errno))
|
||||||
} else {
|
} else {
|
||||||
// Not an error. We've simply reached the end of the stream.
|
// Not an error. We've simply reached the end of the stream.
|
||||||
None
|
None
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::{Error, Result};
|
use crate::from_success_code;
|
||||||
|
use std::io::Result;
|
||||||
use std::os::unix::prelude::*;
|
use std::os::unix::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@@ -18,5 +19,5 @@ pub unsafe fn posix_fadvise(
|
|||||||
len: libc::off_t,
|
len: libc::off_t,
|
||||||
advice: PosixFadviseAdvice,
|
advice: PosixFadviseAdvice,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
Error::from_success_code(libc::posix_fadvise(fd, offset, len, advice as libc::c_int))
|
from_success_code(libc::posix_fadvise(fd, offset, len, advice as libc::c_int))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
use crate::Result;
|
use std::{
|
||||||
use std::{io, os::unix::prelude::*};
|
io::{Error, Result},
|
||||||
|
os::unix::prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
pub unsafe fn isatty(fd: RawFd) -> Result<bool> {
|
pub unsafe fn isatty(fd: RawFd) -> Result<bool> {
|
||||||
let res = libc::isatty(fd);
|
let res = libc::isatty(fd);
|
||||||
@@ -8,8 +10,8 @@ pub unsafe fn isatty(fd: RawFd) -> Result<bool> {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
// ... otherwise 0 is returned, and errno is set to indicate the error.
|
// ... otherwise 0 is returned, and errno is set to indicate the error.
|
||||||
let errno = io::Error::last_os_error();
|
let errno = Error::last_os_error();
|
||||||
if let Some(raw_errno) = errno.raw_os_error() {
|
let raw_errno = errno.raw_os_error().unwrap();
|
||||||
// While POSIX specifies ENOTTY if the passed
|
// While POSIX specifies ENOTTY if the passed
|
||||||
// fd is *not* a tty, on Linux, some implementations
|
// fd is *not* a tty, on Linux, some implementations
|
||||||
// may return EINVAL instead.
|
// may return EINVAL instead.
|
||||||
@@ -18,10 +20,7 @@ pub unsafe fn isatty(fd: RawFd) -> Result<bool> {
|
|||||||
if raw_errno == libc::ENOTTY || raw_errno == libc::EINVAL {
|
if raw_errno == libc::ENOTTY || raw_errno == libc::EINVAL {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
} else {
|
} else {
|
||||||
Err(errno.into())
|
Err(errno)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(errno.into())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ pub(crate) mod dir;
|
|||||||
pub(crate) mod fadvise;
|
pub(crate) mod fadvise;
|
||||||
pub(crate) mod file;
|
pub(crate) mod file;
|
||||||
|
|
||||||
use crate::{dir::SeekLoc, Result};
|
use crate::dir::SeekLoc;
|
||||||
|
use std::io::Result;
|
||||||
|
|
||||||
impl SeekLoc {
|
impl SeekLoc {
|
||||||
pub unsafe fn from_raw(loc: i64) -> Result<Self> {
|
pub unsafe fn from_raw(loc: i64) -> Result<Self> {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::{dir::SeekLoc, Result};
|
use crate::dir::SeekLoc;
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
|
use std::io::Result;
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(any(target_os = "linux",
|
if #[cfg(any(target_os = "linux",
|
||||||
|
|||||||
Reference in New Issue
Block a user