From c05a907042e12cc0a8b5c164a48a193a3f8a0eeb Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Thu, 6 Jun 2024 09:10:32 -0700 Subject: [PATCH 1/3] Move `sys_fill_exact` from `util_libc` to `util_unix`. Prepare for removing the libc dependency from it. --- src/getrandom.rs | 2 +- src/lib.rs | 2 ++ src/linux_android.rs | 4 ++-- src/netbsd.rs | 2 +- src/use_file.rs | 5 +---- src/util_libc.rs | 28 ---------------------------- src/util_unix.rs | 30 ++++++++++++++++++++++++++++++ 7 files changed, 37 insertions(+), 36 deletions(-) create mode 100644 src/util_unix.rs diff --git a/src/getrandom.rs b/src/getrandom.rs index 88c077c6..743e5477 100644 --- a/src/getrandom.rs +++ b/src/getrandom.rs @@ -15,7 +15,7 @@ //! GRND_RANDOM is not recommended. On NetBSD/FreeBSD/Dragonfly/3ds, it does //! nothing. On illumos, the default pool is used to implement getentropy(2), //! so we assume it is acceptable here. -use crate::{util_libc::sys_fill_exact, Error}; +use crate::{util_unix::sys_fill_exact, Error}; use core::{ffi::c_void, mem::MaybeUninit}; pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { diff --git a/src/lib.rs b/src/lib.rs index d1e9ef09..c1f36377 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -217,6 +217,8 @@ use core::mem::MaybeUninit; mod error; mod util; +#[cfg(unix)] +mod util_unix; // To prevent a breaking change when targets are added, we always export the // register_custom_getrandom macro, so old Custom RNG crates continue to build. #[cfg(feature = "custom")] diff --git a/src/linux_android.rs b/src/linux_android.rs index 7c1fede4..90b2edf3 100644 --- a/src/linux_android.rs +++ b/src/linux_android.rs @@ -1,9 +1,9 @@ //! Implementation for Linux / Android without `/dev/urandom` fallback -use crate::{util_libc, Error}; +use crate::{util_unix::sys_fill_exact, Error}; use core::mem::MaybeUninit; pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { - util_libc::sys_fill_exact(dest, getrandom_syscall) + sys_fill_exact(dest, getrandom_syscall) } // Also used by linux_android_with_fallback to check if the syscall is available. diff --git a/src/netbsd.rs b/src/netbsd.rs index c4ea75e4..991e095b 100644 --- a/src/netbsd.rs +++ b/src/netbsd.rs @@ -1,5 +1,5 @@ //! Implementation for NetBSD -use crate::{lazy::LazyPtr, util_libc::sys_fill_exact, Error}; +use crate::{lazy::LazyPtr, util_unix::sys_fill_exact, Error}; use core::{ffi::c_void, mem::MaybeUninit, ptr}; fn kern_arnd(buf: &mut [MaybeUninit]) -> libc::ssize_t { diff --git a/src/use_file.rs b/src/use_file.rs index 36210dee..0ce276ab 100644 --- a/src/use_file.rs +++ b/src/use_file.rs @@ -1,8 +1,5 @@ //! Implementations that just need to read from a file -use crate::{ - util_libc::{open_readonly, sys_fill_exact}, - Error, -}; +use crate::{util_libc::open_readonly, util_unix::sys_fill_exact, Error}; use core::{ cell::UnsafeCell, ffi::c_void, diff --git a/src/util_libc.rs b/src/util_libc.rs index 7708bfcc..a2c07e7d 100644 --- a/src/util_libc.rs +++ b/src/util_libc.rs @@ -1,6 +1,5 @@ #![allow(dead_code)] use crate::Error; -use core::mem::MaybeUninit; cfg_if! { if #[cfg(any(target_os = "netbsd", target_os = "openbsd", target_os = "android"))] { @@ -46,33 +45,6 @@ pub fn last_os_error() -> Error { } } -// Fill a buffer by repeatedly invoking a system call. The `sys_fill` function: -// - should return -1 and set errno on failure -// - should return the number of bytes written on success -pub fn sys_fill_exact( - mut buf: &mut [MaybeUninit], - sys_fill: impl Fn(&mut [MaybeUninit]) -> libc::ssize_t, -) -> Result<(), Error> { - while !buf.is_empty() { - let res = sys_fill(buf); - match res { - res if res > 0 => buf = buf.get_mut(res as usize..).ok_or(Error::UNEXPECTED)?, - -1 => { - let err = last_os_error(); - // We should try again if the call was interrupted. - if err.raw_os_error() != Some(libc::EINTR) { - return Err(err); - } - } - // Negative return codes not equal to -1 should be impossible. - // EOF (ret = 0) should be impossible, as the data we are reading - // should be an infinite stream of random bytes. - _ => return Err(Error::UNEXPECTED), - } - } - Ok(()) -} - /// Open a file in read-only mode. /// /// # Panics diff --git a/src/util_unix.rs b/src/util_unix.rs new file mode 100644 index 00000000..d6e7baea --- /dev/null +++ b/src/util_unix.rs @@ -0,0 +1,30 @@ +#![allow(dead_code)] +use crate::{util_libc::last_os_error, Error}; +use core::mem::MaybeUninit; + +// Fill a buffer by repeatedly invoking a system call. The `sys_fill` function: +// - should return -1 and set errno on failure +// - should return the number of bytes written on success +pub fn sys_fill_exact( + mut buf: &mut [MaybeUninit], + sys_fill: impl Fn(&mut [MaybeUninit]) -> libc::ssize_t, +) -> Result<(), Error> { + while !buf.is_empty() { + let res = sys_fill(buf); + match res { + res if res > 0 => buf = buf.get_mut(res as usize..).ok_or(Error::UNEXPECTED)?, + -1 => { + let err = last_os_error(); + // We should try again if the call was interrupted. + if err.raw_os_error() != Some(libc::EINTR) { + return Err(err); + } + } + // Negative return codes not equal to -1 should be impossible. + // EOF (ret = 0) should be impossible, as the data we are reading + // should be an infinite stream of random bytes. + _ => return Err(Error::UNEXPECTED), + } + } + Ok(()) +} From f9f7af932645525cce908be39ee14066b7bae0c4 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Thu, 6 Jun 2024 10:24:12 -0700 Subject: [PATCH 2/3] util_unix: Move dependency on libc's `errno` to callers. Make progress on reoving the libc dependency from util_unix, so we can remove the libc dependency for x86_64-unknown-linux-none. --- src/getrandom.rs | 5 +++-- src/linux_android.rs | 12 ++++++++---- src/linux_android_with_fallback.rs | 22 +++++++++------------- src/netbsd.rs | 11 ++++++----- src/use_file.rs | 9 +++++++-- src/util_unix.rs | 18 ++++++++---------- 6 files changed, 41 insertions(+), 36 deletions(-) diff --git a/src/getrandom.rs b/src/getrandom.rs index 743e5477..5b66e568 100644 --- a/src/getrandom.rs +++ b/src/getrandom.rs @@ -15,11 +15,12 @@ //! GRND_RANDOM is not recommended. On NetBSD/FreeBSD/Dragonfly/3ds, it does //! nothing. On illumos, the default pool is used to implement getentropy(2), //! so we assume it is acceptable here. -use crate::{util_unix::sys_fill_exact, Error}; +use crate::{util_libc::last_os_error, util_unix::sys_fill_exact, Error}; use core::{ffi::c_void, mem::MaybeUninit}; pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { sys_fill_exact(dest, |buf| unsafe { - libc::getrandom(buf.as_mut_ptr().cast::(), buf.len(), 0) + let ret: isize = libc::getrandom(buf.as_mut_ptr().cast::(), buf.len(), 0); + usize::try_from(ret).map_err(|_| last_os_error()) }) } diff --git a/src/linux_android.rs b/src/linux_android.rs index 90b2edf3..151f7c5c 100644 --- a/src/linux_android.rs +++ b/src/linux_android.rs @@ -7,13 +7,17 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { } // Also used by linux_android_with_fallback to check if the syscall is available. -pub fn getrandom_syscall(buf: &mut [MaybeUninit]) -> libc::ssize_t { - unsafe { +pub fn getrandom_syscall(buf: &mut [MaybeUninit]) -> Result { + use crate::util_libc::last_os_error; + + let ret: libc::c_long = unsafe { libc::syscall( libc::SYS_getrandom, buf.as_mut_ptr().cast::(), buf.len(), 0, - ) as libc::ssize_t - } + ) + }; + const _: () = assert!(core::mem::size_of::() == core::mem::size_of::()); + usize::try_from(ret as isize).map_err(|_| last_os_error()) } diff --git a/src/linux_android_with_fallback.rs b/src/linux_android_with_fallback.rs index 98fa15e8..3a7d1bad 100644 --- a/src/linux_android_with_fallback.rs +++ b/src/linux_android_with_fallback.rs @@ -1,5 +1,5 @@ //! Implementation for Linux / Android with `/dev/urandom` fallback -use crate::{lazy::LazyBool, linux_android, use_file, util_libc::last_os_error, Error}; +use crate::{lazy::LazyBool, linux_android, use_file, Error}; use core::mem::MaybeUninit; pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { @@ -13,17 +13,13 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { } fn is_getrandom_available() -> bool { - if linux_android::getrandom_syscall(&mut []) < 0 { - match last_os_error().raw_os_error() { - Some(libc::ENOSYS) => false, // No kernel support - // The fallback on EPERM is intentionally not done on Android since this workaround - // seems to be needed only for specific Linux-based products that aren't based - // on Android. See https://github.com/rust-random/getrandom/issues/229. - #[cfg(target_os = "linux")] - Some(libc::EPERM) => false, // Blocked by seccomp - _ => true, - } - } else { - true + match linux_android::getrandom_syscall(&mut []) { + Err(err) if err.raw_os_error() == Some(libc::ENOSYS) => false, // No kernel support + // The fallback on EPERM is intentionally not done on Android since this workaround + // seems to be needed only for specific Linux-based products that aren't based + // on Android. See https://github.com/rust-random/getrandom/issues/229. + #[cfg(target_os = "linux")] + Err(err) if err.raw_os_error() == Some(libc::EPERM) => false, // Blocked by seccomp + _ => true, } } diff --git a/src/netbsd.rs b/src/netbsd.rs index 991e095b..8f71ab97 100644 --- a/src/netbsd.rs +++ b/src/netbsd.rs @@ -1,8 +1,8 @@ //! Implementation for NetBSD -use crate::{lazy::LazyPtr, util_unix::sys_fill_exact, Error}; +use crate::{lazy::LazyPtr, util_libc::last_os_error, util_unix::sys_fill_exact, Error}; use core::{ffi::c_void, mem::MaybeUninit, ptr}; -fn kern_arnd(buf: &mut [MaybeUninit]) -> libc::ssize_t { +fn kern_arnd(buf: &mut [MaybeUninit]) -> Result { static MIB: [libc::c_int; 2] = [libc::CTL_KERN, libc::KERN_ARND]; let mut len = buf.len(); let ret = unsafe { @@ -16,9 +16,9 @@ fn kern_arnd(buf: &mut [MaybeUninit]) -> libc::ssize_t { ) }; if ret == -1 { - -1 + Err(last_os_error()) } else { - len as libc::ssize_t + Ok(len) } } @@ -38,7 +38,8 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { if !fptr.is_null() { let func: GetRandomFn = unsafe { core::mem::transmute(fptr) }; return sys_fill_exact(dest, |buf| unsafe { - func(buf.as_mut_ptr().cast::(), buf.len(), 0) + let ret: isize = func(buf.as_mut_ptr().cast::(), buf.len(), 0); + usize::try_from(ret as isize).map_err(|_| last_os_error()) }); } diff --git a/src/use_file.rs b/src/use_file.rs index 0ce276ab..dae3c790 100644 --- a/src/use_file.rs +++ b/src/use_file.rs @@ -1,5 +1,9 @@ //! Implementations that just need to read from a file -use crate::{util_libc::open_readonly, util_unix::sys_fill_exact, Error}; +use crate::{ + util_libc::{last_os_error, open_readonly}, + util_unix::sys_fill_exact, + Error, +}; use core::{ cell::UnsafeCell, ffi::c_void, @@ -22,7 +26,8 @@ const FD_UNINIT: usize = usize::max_value(); pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { let fd = get_rng_fd()?; sys_fill_exact(dest, |buf| unsafe { - libc::read(fd, buf.as_mut_ptr().cast::(), buf.len()) + let ret: isize = libc::read(fd, buf.as_mut_ptr().cast::(), buf.len()); + usize::try_from(ret).map_err(|_| last_os_error()) }) } diff --git a/src/util_unix.rs b/src/util_unix.rs index d6e7baea..67513507 100644 --- a/src/util_unix.rs +++ b/src/util_unix.rs @@ -1,20 +1,18 @@ #![allow(dead_code)] -use crate::{util_libc::last_os_error, Error}; +use crate::Error; use core::mem::MaybeUninit; -// Fill a buffer by repeatedly invoking a system call. The `sys_fill` function: -// - should return -1 and set errno on failure -// - should return the number of bytes written on success +// Fill a buffer by repeatedly invoking a system call. The `sys_fill` function +// must return `Ok(written)` where `written` is the number of bytes written, +// or otherwise an error. pub fn sys_fill_exact( mut buf: &mut [MaybeUninit], - sys_fill: impl Fn(&mut [MaybeUninit]) -> libc::ssize_t, + sys_fill: impl Fn(&mut [MaybeUninit]) -> Result, ) -> Result<(), Error> { while !buf.is_empty() { - let res = sys_fill(buf); - match res { - res if res > 0 => buf = buf.get_mut(res as usize..).ok_or(Error::UNEXPECTED)?, - -1 => { - let err = last_os_error(); + match sys_fill(buf) { + Ok(res) if res > 0 => buf = buf.get_mut(res..).ok_or(Error::UNEXPECTED)?, + Err(err) => { // We should try again if the call was interrupted. if err.raw_os_error() != Some(libc::EINTR) { return Err(err); From 86c13827e8fde2d920936add7ef39f29d013a2ac Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Thu, 6 Jun 2024 09:00:45 -0700 Subject: [PATCH 3/3] linux_android: Use direct syscall on x86-64 to support x86_64-*-linux-none. Remove the last libc dependency from `linux_android`, as a step towards supporting x86_64-unknown-linux-none. This requires bumping the MSRV to 1.59. --- .clippy.toml | 2 +- .github/workflows/tests.yml | 6 ++- Cargo.toml | 8 ++- README.md | 2 +- src/lib.rs | 11 ++-- src/linux_android.rs | 85 +++++++++++++++++++++++++----- src/linux_android_with_fallback.rs | 3 ++ src/util_unix.rs | 8 ++- 8 files changed, 104 insertions(+), 21 deletions(-) diff --git a/.clippy.toml b/.clippy.toml index 5cccb362..abe19b3a 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1 +1 @@ -msrv = "1.57" +msrv = "1.59" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f3831d5c..54af9750 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -44,7 +44,7 @@ jobs: strategy: matrix: os: [ubuntu-22.04, windows-2022] - toolchain: [nightly, beta, stable, 1.57] + toolchain: [nightly, beta, stable, 1.59] # Only Test macOS on stable to reduce macOS CI jobs include: # x86_64-apple-darwin. @@ -61,6 +61,8 @@ jobs: - uses: Swatinem/rust-cache@v2 - run: cargo test - run: cargo test --features=std + # This is assumed to be the same code path as x86_64-*-linux-none, since + # we don't/can't run tests for that target yet. - run: cargo test --features=linux_disable_fallback - run: cargo test --features=custom # custom should do nothing here - if: ${{ matrix.toolchain == 'nightly' }} @@ -361,6 +363,8 @@ jobs: features: ["rdrand"] - target: i686-unknown-hurd-gnu features: ["std"] + - target: x86_64-unknown-linux-none + features: ["rdrand"] steps: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly # Required to build libcore diff --git a/Cargo.toml b/Cargo.toml index b9357bce..5995cf06 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "getrandom" version = "0.2.15" # Also update html_root_url in lib.rs when bumping this edition = "2021" -rust-version = "1.57" # Sync .clippy.toml, tests.yml, and README.md. +rust-version = "1.59" # Sync .clippy.toml, tests.yml, and README.md. authors = ["The Rand Project Developers"] license = "MIT OR Apache-2.0" description = "A small cross-platform library for retrieving random data from system source" @@ -18,7 +18,11 @@ cfg-if = "1" compiler_builtins = { version = "0.1", optional = true } core = { version = "1.0", optional = true, package = "rustc-std-workspace-core" } -[target.'cfg(unix)'.dependencies] +# XXX: Additionally, we don't use libc when feature `linux_disable_fallback` is +# enabled on `x86_64-{*-linux-*,linux-android}`, but we can't express this. In +# that case, we require libc to be built, and we force it to be linked, but we +# don't actually use anything from it. +[target.'cfg(all(unix, not(all(target_arch = "x86_64", target_os = "linux", target_env = ""))))'.dependencies] libc = { version = "0.2.154", default-features = false } [target.'cfg(target_os = "wasi")'.dependencies] diff --git a/README.md b/README.md index 56af89dd..608d5dc8 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ crate features, WASM support and Custom RNGs see the ## Minimum Supported Rust Version -This crate requires Rust 1.57.0 or later. +This crate requires Rust 1.59.0 or later. ## Platform Support diff --git a/src/lib.rs b/src/lib.rs index c1f36377..a4fcd556 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -259,7 +259,12 @@ cfg_if! { mod util_libc; #[path = "getrandom.rs"] mod imp; } else if #[cfg(all( - not(feature = "linux_disable_fallback"), + // Always treat feature="linux_disable_fallback" identically to + // all(target_os = "linux", target_env="") to ensure the code paths are + // the same. This is important because we can't run tests for + // *-*-linux-none (yet). Note that target_env="" for common Android + // targets. + not(any(feature = "linux_disable_fallback", all(target_os = "linux", target_env=""))), any( // Rust supports Android API level 19 (KitKat) [0] and the next upgrade targets // level 21 (Lollipop) [1], while `getrandom(2)` was added only in @@ -304,8 +309,8 @@ cfg_if! { mod linux_android; #[path = "linux_android_with_fallback.rs"] mod imp; } else if #[cfg(any(target_os = "android", target_os = "linux"))] { - mod util_libc; - #[path = "linux_android.rs"] mod imp; + mod linux_android; + use linux_android as imp; } else if #[cfg(target_os = "solaris")] { mod util_libc; #[path = "solaris.rs"] mod imp; diff --git a/src/linux_android.rs b/src/linux_android.rs index 151f7c5c..c7b041c8 100644 --- a/src/linux_android.rs +++ b/src/linux_android.rs @@ -6,18 +6,79 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { sys_fill_exact(dest, getrandom_syscall) } +// The value of `EINTR` is not architecture-specific. It is checked against +// `libc::EINTR` by linux_android_with_fallback.rs. +pub const EINTR: i32 = 4; + // Also used by linux_android_with_fallback to check if the syscall is available. -pub fn getrandom_syscall(buf: &mut [MaybeUninit]) -> Result { - use crate::util_libc::last_os_error; +cfg_if! { + // TODO: Expand inilne assembly to other architectures to avoid depending + // on libc on Linux. + if #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] { + type Word = u64; + type IWord = i64; + + // TODO(MSRV(1.78 feature(target_abi))): Enable this and remove `target_pointer_width` + // restriction above. + // + // #[cfg(target_abi = "x32")] + // const __X32_SYSCALL_BIT: Word = 0x40000000; + // + // #[cfg(target_abi = "x832")] + // #[allow(non_upper_case_globals)] + // pub const SYS_getrandom: IWord = 318 | __X32_SYSCALL_BIT; + + // #[cfg(not(target_abi = "x832"))] + #[allow(non_upper_case_globals)] + pub const SYS_getrandom: IWord = 318; + + pub fn getrandom_syscall(buf: &mut [MaybeUninit]) -> Result { + // Clamp request length to word size; no-op on regular (non-x32) x86_64. + assert!(core::mem::size_of::() <= core::mem::size_of::()); + let buflen: Word = buf.len() as Word; + let mut ret: IWord; + let flags = 0; + unsafe { + core::arch::asm!( + "syscall", + inout("rax") SYS_getrandom => ret, + in("rdi") buf.as_mut_ptr(), + in("rsi") buflen, + in("rdx") flags, + lateout("rcx") _, + lateout("r11") _, + options(nostack), + ); + } + match Word::try_from(ret) { + Ok(written) => { + // `buflen` can from a usize and the return value won't be + // larger than what we requested (otherwise that would be a + // buffer overflow), so this cast is lossless even if + // `usize` is smaller. + Ok(written as usize) + }, + Err(_) => { + Err(u32::try_from(ret.unsigned_abs()).map_or( + Error::UNEXPECTED, Error::from_os_error)) + } + } + } + } else { + use crate::util_libc::last_os_error; + pub use libc::SYS_getrandom; - let ret: libc::c_long = unsafe { - libc::syscall( - libc::SYS_getrandom, - buf.as_mut_ptr().cast::(), - buf.len(), - 0, - ) - }; - const _: () = assert!(core::mem::size_of::() == core::mem::size_of::()); - usize::try_from(ret as isize).map_err(|_| last_os_error()) + pub fn getrandom_syscall(buf: &mut [MaybeUninit]) -> Result { + let ret: libc::c_long = unsafe { + libc::syscall( + SYS_getrandom, + buf.as_mut_ptr().cast::(), + buf.len(), + 0, + ) + }; + const _:() = assert!(core::mem::size_of::() == core::mem::size_of::()); + usize::try_from(ret as isize).map_err(|_| last_os_error()) + } + } } diff --git a/src/linux_android_with_fallback.rs b/src/linux_android_with_fallback.rs index 3a7d1bad..3c3f134b 100644 --- a/src/linux_android_with_fallback.rs +++ b/src/linux_android_with_fallback.rs @@ -2,6 +2,9 @@ use crate::{lazy::LazyBool, linux_android, use_file, Error}; use core::mem::MaybeUninit; +const _: () = assert!(linux_android::EINTR == libc::EINTR); +const _: () = assert!(linux_android::SYS_getrandom == libc::SYS_getrandom); + pub fn getrandom_inner(dest: &mut [MaybeUninit]) -> Result<(), Error> { // getrandom(2) was introduced in Linux 3.17 static HAS_GETRANDOM: LazyBool = LazyBool::new(); diff --git a/src/util_unix.rs b/src/util_unix.rs index 67513507..2b81f921 100644 --- a/src/util_unix.rs +++ b/src/util_unix.rs @@ -9,12 +9,18 @@ pub fn sys_fill_exact( mut buf: &mut [MaybeUninit], sys_fill: impl Fn(&mut [MaybeUninit]) -> Result, ) -> Result<(), Error> { + // Avoid depending on libc for Linux/Android. + #[cfg(any(target_os = "android", target_os = "linux"))] + use crate::linux_android::EINTR; + #[cfg(not(any(target_os = "android", target_os = "linux")))] + use libc::EINTR; + while !buf.is_empty() { match sys_fill(buf) { Ok(res) if res > 0 => buf = buf.get_mut(res..).ok_or(Error::UNEXPECTED)?, Err(err) => { // We should try again if the call was interrupted. - if err.raw_os_error() != Some(libc::EINTR) { + if err.raw_os_error() != Some(EINTR) { return Err(err); } }