Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce set_errno #2283

Merged
merged 15 commits into from
Jan 8, 2024
4 changes: 4 additions & 0 deletions changelog/2283.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- Added `errno::Errno::set` function
- Added `errno::Errno::set_raw` function
- Added `errno::Errno::last_raw` function
- Added `errno::Errno::from_raw` function
3 changes: 3 additions & 0 deletions changelog/2283.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Deprecated `errno::errno()` function (use `Errno::last_raw()`)
- Deprecated `errno::from_i32()` function (use `Errno::from_raw()`)
- Deprecated `errno::Errno::from_i32()` function (use `Errno::from_raw()`)
132 changes: 114 additions & 18 deletions src/errno.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
//! Safe wrappers around errno functions
//!
//! # Example
//! ```
//! use nix::errno::Errno;
//!
//! Errno::EIO.set();
//! assert_eq!(Errno::last(), Errno::EIO);
//!
//! Errno::clear();
//! assert_eq!(Errno::last(), Errno::from_raw(0));
//! ```

use crate::Result;
use cfg_if::cfg_if;
use libc::{c_int, c_void};
Expand Down Expand Up @@ -39,34 +52,77 @@ cfg_if! {
}
}

/// Sets the platform-specific errno to no-error
fn clear() {
// Safe because errno is a thread-local variable
unsafe {
*errno_location() = 0;
}
}

/// Returns the platform-specific value of errno
#[deprecated(since = "0.28.0", note = "please use `Errno::last_raw()` instead")]
pub fn errno() -> i32 {
unsafe { *errno_location() }
Errno::last_raw()
}

impl Errno {
/// Returns the current value of errno
pub fn last() -> Self {
last()
Self::from_raw(Self::last_raw())
}

pub fn desc(self) -> &'static str {
desc(self)
/// Returns the current raw i32 value of errno
pub fn last_raw() -> i32 {
unsafe { *errno_location() }
}

/// Sets the value of errno.
///
/// # Example
/// ```
/// use nix::errno::Errno;
///
/// Errno::EIO.set();
///
/// assert_eq!(Errno::last(), Errno::EIO);
/// ```
pub fn set(self) {
Self::set_raw(self as i32)
}

/// Sets the raw i32 value of errno.
pub fn set_raw(errno: i32) {
// Safe because errno is a thread-local variable
unsafe {
*errno_location() = errno;
}
}

#[deprecated(
since = "0.28.0",
note = "please use `Errno::from_raw()` instead"
)]
pub const fn from_i32(err: i32) -> Errno {
Self::from_raw(err)
}

pub const fn from_raw(err: i32) -> Errno {
#[allow(deprecated)]
from_i32(err)
}

pub fn desc(self) -> &'static str {
desc(self)
}

/// Sets the platform-specific errno to no-error
///
/// ```
/// use nix::errno::Errno;
///
/// Errno::EIO.set();
///
/// Errno::clear();
///
/// let err = Errno::last();
/// assert_ne!(err, Errno::EIO);
/// assert_eq!(err, Errno::from_raw(0));
/// ```
pub fn clear() {
clear()
Self::set_raw(0)
}

/// Returns `Ok(value)` if it does not contain the sentinel value. This
Expand Down Expand Up @@ -135,14 +191,10 @@ impl TryFrom<io::Error> for Errno {
type Error = io::Error;

fn try_from(ioerror: io::Error) -> std::result::Result<Self, io::Error> {
ioerror.raw_os_error().map(Errno::from_i32).ok_or(ioerror)
ioerror.raw_os_error().map(Errno::from_raw).ok_or(ioerror)
}
}

fn last() -> Errno {
Errno::from_i32(errno())
}

fn desc(errno: Errno) -> &'static str {
use self::Errno::*;
match errno {
Expand Down Expand Up @@ -929,6 +981,10 @@ mod consts {
pub const ENOTSUP: Errno = Errno::EOPNOTSUPP;
}

#[deprecated(
since = "0.28.0",
note = "please use `Errno::from_raw()` instead"
)]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;

Expand Down Expand Up @@ -1192,6 +1248,10 @@ mod consts {
pub const EDEADLOCK: Errno = Errno::EDEADLK;
}

#[deprecated(
since = "0.28.0",
note = "please use `Errno::from_raw()` instead"
)]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;

Expand Down Expand Up @@ -1419,6 +1479,10 @@ mod consts {
pub const EOPNOTSUPP: Errno = Errno::ENOTSUP;
}

#[deprecated(
since = "0.28.0",
note = "please use `Errno::from_raw()` instead"
)]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;

Expand Down Expand Up @@ -1636,6 +1700,10 @@ mod consts {
pub const EOPNOTSUPP: Errno = Errno::ENOTSUP;
}

#[deprecated(
since = "0.28.0",
note = "please use `Errno::from_raw()` instead"
)]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;

Expand Down Expand Up @@ -1848,6 +1916,10 @@ mod consts {
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
}

#[deprecated(
since = "0.28.0",
note = "please use `Errno::from_raw()` instead"
)]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;

Expand Down Expand Up @@ -2062,6 +2134,10 @@ mod consts {
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
}

#[deprecated(
since = "0.28.0",
note = "please use `Errno::from_raw()` instead"
)]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;

Expand Down Expand Up @@ -2265,6 +2341,10 @@ mod consts {
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
}

#[deprecated(
since = "0.28.0",
note = "please use `Errno::from_raw()` instead"
)]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;

Expand Down Expand Up @@ -2494,6 +2574,10 @@ mod consts {
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
}

#[deprecated(
since = "0.28.0",
note = "please use `Errno::from_raw()` instead"
)]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;

Expand Down Expand Up @@ -2714,6 +2798,10 @@ mod consts {
pub const EOPNOTSUPP: Errno = Errno::ENOTSUP;
}

#[deprecated(
since = "0.28.0",
note = "please use `Errno::from_raw()` instead"
)]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;

Expand Down Expand Up @@ -2905,6 +2993,10 @@ mod consts {
EOPNOTSUPP = libc::EOPNOTSUPP,
}

#[deprecated(
since = "0.28.0",
note = "please use `Errno::from_raw()` instead"
)]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;

Expand Down Expand Up @@ -3128,6 +3220,10 @@ mod consts {
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
}

#[deprecated(
since = "0.28.0",
note = "please use `Errno::from_raw()` instead"
)]
pub const fn from_i32(e: i32) -> Errno {
use self::Errno::*;

Expand Down
4 changes: 2 additions & 2 deletions src/fcntl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1109,7 +1109,7 @@ mod posix_fadvise {
if res == 0 {
Ok(())
} else {
Err(Errno::from_i32(res))
Err(Errno::from_raw(res))
}
}
}
Expand All @@ -1131,7 +1131,7 @@ pub fn posix_fallocate(
match Errno::result(res) {
Err(err) => Err(err),
Ok(0) => Ok(()),
Ok(errno) => Err(Errno::from_i32(errno)),
Ok(errno) => Err(Errno::from_raw(errno)),
}
}
}
2 changes: 1 addition & 1 deletion src/sys/aio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ impl AioCb {
let r = unsafe { libc::aio_error(&self.aiocb().0) };
match r {
0 => Ok(()),
num if num > 0 => Err(Errno::from_i32(num)),
num if num > 0 => Err(Errno::from_raw(num)),
-1 => Err(Errno::last()),
num => panic!("unknown aio_error return value {num:?}"),
}
Expand Down
4 changes: 2 additions & 2 deletions src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ pub fn clock_getcpuclockid(pid: Pid) -> Result<ClockId> {
let res = unsafe { clk_id.assume_init() };
Ok(ClockId::from(res))
} else {
Err(Errno::from_i32(ret))
Err(Errno::from_raw(ret))
}
}

Expand Down Expand Up @@ -248,6 +248,6 @@ pub fn clock_nanosleep(
if ret == 0 {
Ok(remain)
} else {
Err(Errno::from_i32(ret))
Err(Errno::from_raw(ret))
}
}
10 changes: 5 additions & 5 deletions src/unistd.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Safe wrappers around functions found in libc "unistd.h" header

use crate::errno::{self, Errno};
use crate::errno::Errno;

#[cfg(any(
all(feature = "fs", not(target_os = "redox")),
Expand Down Expand Up @@ -2148,7 +2148,7 @@ pub fn fpathconf<F: AsFd>(fd: F, var: PathconfVar) -> Result<Option<c_long>> {
libc::fpathconf(fd.as_fd().as_raw_fd(), var as c_int)
};
if raw == -1 {
if errno::errno() == 0 {
if Errno::last_raw() == 0 {
Ok(None)
} else {
Err(Errno::last())
Expand Down Expand Up @@ -2188,7 +2188,7 @@ pub fn pathconf<P: ?Sized + NixPath>(
libc::pathconf(cstr.as_ptr(), var as c_int)
})?;
if raw == -1 {
if errno::errno() == 0 {
if Errno::last_raw() == 0 {
Ok(None)
} else {
Err(Errno::last())
Expand Down Expand Up @@ -2787,7 +2787,7 @@ pub fn sysconf(var: SysconfVar) -> Result<Option<c_long>> {
libc::sysconf(var as c_int)
};
if raw == -1 {
if errno::errno() == 0 {
if Errno::last_raw() == 0 {
Ok(None)
} else {
Err(Errno::last())
Expand Down Expand Up @@ -3543,7 +3543,7 @@ pub fn ttyname<F: AsFd>(fd: F) -> Result<PathBuf> {

let ret = unsafe { libc::ttyname_r(fd.as_fd().as_raw_fd(), c_buf, buf.len()) };
if ret != 0 {
return Err(Errno::from_i32(ret));
return Err(Errno::from_raw(ret));
}

CStr::from_bytes_until_nul(&buf[..])
Expand Down
1 change: 1 addition & 0 deletions test/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod common;
mod sys;
#[cfg(not(target_os = "redox"))]
mod test_dir;
mod test_errno;
mod test_fcntl;
#[cfg(linux_android)]
mod test_kmod;
Expand Down
8 changes: 8 additions & 0 deletions test/test_errno.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use nix::errno::Errno;

#[test]
fn errno_set_and_read() {
Errno::clear();
PolyMeilex marked this conversation as resolved.
Show resolved Hide resolved
Errno::ENFILE.set();
assert_eq!(Errno::last(), Errno::ENFILE);
}
2 changes: 1 addition & 1 deletion test/test_mount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ exit 23";
.mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
.open(&test_path)
.or_else(|e| {
if Errno::from_i32(e.raw_os_error().unwrap())
if Errno::from_raw(e.raw_os_error().unwrap())
== Errno::EOVERFLOW
{
// Skip tests on certain Linux kernels which have a bug
Expand Down