diff --git a/changelog/2283.added.md b/changelog/2283.added.md new file mode 100644 index 0000000000..fbf357d0f3 --- /dev/null +++ b/changelog/2283.added.md @@ -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 diff --git a/changelog/2283.changed.md b/changelog/2283.changed.md new file mode 100644 index 0000000000..44bb1d5405 --- /dev/null +++ b/changelog/2283.changed.md @@ -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()`) diff --git a/src/errno.rs b/src/errno.rs index cde462d958..114a4a1eab 100644 --- a/src/errno.rs +++ b/src/errno.rs @@ -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}; @@ -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 @@ -135,14 +191,10 @@ impl TryFrom for Errno { type Error = io::Error; fn try_from(ioerror: io::Error) -> std::result::Result { - 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 { @@ -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::*; @@ -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::*; @@ -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::*; @@ -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::*; @@ -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::*; @@ -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::*; @@ -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::*; @@ -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::*; @@ -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::*; @@ -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::*; @@ -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::*; diff --git a/src/fcntl.rs b/src/fcntl.rs index 638d6f6ea6..e4a2d73c41 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -1109,7 +1109,7 @@ mod posix_fadvise { if res == 0 { Ok(()) } else { - Err(Errno::from_i32(res)) + Err(Errno::from_raw(res)) } } } @@ -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)), } } } diff --git a/src/sys/aio.rs b/src/sys/aio.rs index e3c44db654..e9213c6434 100644 --- a/src/sys/aio.rs +++ b/src/sys/aio.rs @@ -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:?}"), } diff --git a/src/time.rs b/src/time.rs index 72915c25df..d50324ddd3 100644 --- a/src/time.rs +++ b/src/time.rs @@ -196,7 +196,7 @@ pub fn clock_getcpuclockid(pid: Pid) -> Result { let res = unsafe { clk_id.assume_init() }; Ok(ClockId::from(res)) } else { - Err(Errno::from_i32(ret)) + Err(Errno::from_raw(ret)) } } @@ -248,6 +248,6 @@ pub fn clock_nanosleep( if ret == 0 { Ok(remain) } else { - Err(Errno::from_i32(ret)) + Err(Errno::from_raw(ret)) } } diff --git a/src/unistd.rs b/src/unistd.rs index a7f784eae4..564dafbb3e 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -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")), @@ -2148,7 +2148,7 @@ pub fn fpathconf(fd: F, var: PathconfVar) -> Result> { 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()) @@ -2188,7 +2188,7 @@ pub fn pathconf( 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()) @@ -2787,7 +2787,7 @@ pub fn sysconf(var: SysconfVar) -> Result> { libc::sysconf(var as c_int) }; if raw == -1 { - if errno::errno() == 0 { + if Errno::last_raw() == 0 { Ok(None) } else { Err(Errno::last()) @@ -3543,7 +3543,7 @@ pub fn ttyname(fd: F) -> Result { 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[..]) diff --git a/test/test.rs b/test/test.rs index 205ae3329c..00f0e74efb 100644 --- a/test/test.rs +++ b/test/test.rs @@ -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; diff --git a/test/test_errno.rs b/test/test_errno.rs new file mode 100644 index 0000000000..750fc924ff --- /dev/null +++ b/test/test_errno.rs @@ -0,0 +1,16 @@ +use nix::errno::Errno; + +#[test] +fn errno_set_and_read() { + Errno::ENFILE.set(); + assert_eq!(Errno::last(), Errno::ENFILE); +} + +#[test] +fn errno_set_and_clear() { + Errno::ENFILE.set(); + assert_eq!(Errno::last(), Errno::ENFILE); + + Errno::clear(); + assert_eq!(Errno::last(), Errno::from_raw(0)); +} diff --git a/test/test_mount.rs b/test/test_mount.rs index 5cf00408e8..09d80bcc6a 100644 --- a/test/test_mount.rs +++ b/test/test_mount.rs @@ -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