Skip to content

Commit 458013d

Browse files
authored
refactor: I/O safety for unistd.rs (#2440)
* refactor: I/O safety for sys/unistd.rs * chore: changelog entry * remove link to dup3_raw() since it is not available on all OSes * fix: imports * fix test * fix test on FreeBSD & update docs
1 parent c86548e commit 458013d

17 files changed

+610
-293
lines changed

changelog/2440.changed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Module unistd now adopts I/O safety.

src/fcntl.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ use std::ffi::CStr;
1313
use std::ffi::OsString;
1414
#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
1515
use std::ops::{Deref, DerefMut};
16-
#[cfg(not(target_os = "redox"))]
17-
use std::os::raw;
1816
use std::os::unix::ffi::OsStringExt;
1917
#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
2018
use std::os::unix::io::OwnedFd;
@@ -234,12 +232,8 @@ libc_bitflags!(
234232
);
235233

236234
/// Computes the raw fd consumed by a function of the form `*at`.
237-
#[cfg(any(
238-
all(feature = "fs", not(target_os = "redox")),
239-
all(feature = "process", linux_android),
240-
all(feature = "fanotify", target_os = "linux")
241-
))]
242-
pub(crate) fn at_rawfd(fd: Option<RawFd>) -> raw::c_int {
235+
#[cfg(all(feature = "fanotify", target_os = "linux"))]
236+
pub(crate) fn at_rawfd(fd: Option<RawFd>) -> RawFd {
243237
fd.unwrap_or(libc::AT_FDCWD)
244238
}
245239

src/poll.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl<'fd> PollFd<'fd> {
3636
/// let mut fds = [pfd];
3737
/// poll(&mut fds, PollTimeout::NONE).unwrap();
3838
/// let mut buf = [0u8; 80];
39-
/// read(r.as_raw_fd(), &mut buf[..]);
39+
/// read(&r, &mut buf[..]);
4040
/// ```
4141
// Unlike I/O functions, constructors like this must take `BorrowedFd`
4242
// instead of AsFd or &AsFd. Otherwise, an `OwnedFd` argument would be

src/pty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl IntoRawFd for PtyMaster {
7373

7474
impl io::Read for PtyMaster {
7575
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
76-
unistd::read(self.0.as_raw_fd(), buf).map_err(io::Error::from)
76+
unistd::read(&self.0, buf).map_err(io::Error::from)
7777
}
7878
}
7979

@@ -88,7 +88,7 @@ impl io::Write for PtyMaster {
8888

8989
impl io::Read for &PtyMaster {
9090
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
91-
unistd::read(self.0.as_raw_fd(), buf).map_err(io::Error::from)
91+
unistd::read(&self.0, buf).map_err(io::Error::from)
9292
}
9393
}
9494

src/sys/eventfd.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::errno::Errno;
2-
use crate::{Result,unistd};
3-
use std::os::unix::io::{FromRawFd, OwnedFd, AsRawFd, AsFd, RawFd, BorrowedFd};
2+
use crate::{unistd, Result};
3+
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
44

55
libc_bitflags! {
66
pub struct EfdFlags: libc::c_int {
@@ -10,7 +10,10 @@ libc_bitflags! {
1010
}
1111
}
1212

13-
#[deprecated(since = "0.28.0", note = "Use EventFd::from_value_and_flags() instead")]
13+
#[deprecated(
14+
since = "0.28.0",
15+
note = "Use EventFd::from_value_and_flags() instead"
16+
)]
1417
pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<OwnedFd> {
1518
let res = unsafe { libc::eventfd(initval, flags.bits()) };
1619

@@ -26,9 +29,12 @@ impl EventFd {
2629
Self::from_value_and_flags(0, EfdFlags::empty())
2730
}
2831
/// Constructs [`EventFd`] with the given `init_val` and `flags`.
29-
///
32+
///
3033
/// Wrapper around [`libc::eventfd`].
31-
pub fn from_value_and_flags(init_val: u32, flags: EfdFlags) -> Result<Self> {
34+
pub fn from_value_and_flags(
35+
init_val: u32,
36+
flags: EfdFlags,
37+
) -> Result<Self> {
3238
let res = unsafe { libc::eventfd(init_val, flags.bits()) };
3339
Errno::result(res).map(|r| Self(unsafe { OwnedFd::from_raw_fd(r) }))
3440
}
@@ -41,29 +47,29 @@ impl EventFd {
4147
Self::from_value_and_flags(init_val, EfdFlags::empty())
4248
}
4349
/// Arms `self`, a following call to `poll`, `select` or `epoll` will return immediately.
44-
///
50+
///
4551
/// [`EventFd::write`] with `1`.
4652
pub fn arm(&self) -> Result<usize> {
4753
self.write(1)
4854
}
4955
/// Defuses `self`, a following call to `poll`, `select` or `epoll` will block.
50-
///
56+
///
5157
/// [`EventFd::write`] with `0`.
5258
pub fn defuse(&self) -> Result<usize> {
5359
self.write(0)
5460
}
5561
/// Enqueues `value` triggers.
56-
///
62+
///
5763
/// The next `value` calls to `poll`, `select` or `epoll` will return immediately.
58-
///
64+
///
5965
/// [`EventFd::write`] with `value`.
60-
pub fn write(&self, value: u64) -> Result<usize> {
61-
unistd::write(&self.0,&value.to_ne_bytes())
66+
pub fn write(&self, value: u64) -> Result<usize> {
67+
unistd::write(&self.0, &value.to_ne_bytes())
6268
}
6369
// Reads the value from the file descriptor.
6470
pub fn read(&self) -> Result<u64> {
6571
let mut arr = [0; std::mem::size_of::<u64>()];
66-
unistd::read(self.0.as_raw_fd(),&mut arr)?;
72+
unistd::read(&self.0, &mut arr)?;
6773
Ok(u64::from_ne_bytes(arr))
6874
}
6975
}

src/sys/fanotify.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,11 @@ impl Drop for FanotifyEvent {
252252
if self.0.fd == libc::FAN_NOFD {
253253
return;
254254
}
255-
let e = close(self.0.fd);
255+
// SAFETY:
256+
//
257+
// If this fd is not `FAN_NOFD`, then it should be a valid, owned file
258+
// descriptor, which means we can safely close it.
259+
let e = unsafe { close(self.0.fd) };
256260
if !std::thread::panicking() && e == Err(Errno::EBADF) {
257261
panic!("Closing an invalid file descriptor!");
258262
};
@@ -362,7 +366,7 @@ impl Fanotify {
362366
let mut events = Vec::new();
363367
let mut offset = 0;
364368

365-
let nread = read(self.fd.as_raw_fd(), &mut buffer)?;
369+
let nread = read(&self.fd, &mut buffer)?;
366370

367371
while (nread - offset) >= metadata_size {
368372
let metadata = unsafe {

src/sys/inotify.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ impl Inotify {
201201
let mut events = Vec::new();
202202
let mut offset = 0;
203203

204-
let nread = read(self.fd.as_raw_fd(), &mut buffer)?;
204+
let nread = read(&self.fd, &mut buffer)?;
205205

206206
while (nread - offset) >= header_size {
207207
let event = unsafe {

src/sys/timerfd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ impl TimerFd {
208208
///
209209
/// Note: If the alarm is unset, then you will wait forever.
210210
pub fn wait(&self) -> Result<()> {
211-
while let Err(e) = read(self.fd.as_fd().as_raw_fd(), &mut [0u8; 8]) {
211+
while let Err(e) = read(&self.fd, &mut [0u8; 8]) {
212212
if e == Errno::ECANCELED {
213213
break;
214214
}

0 commit comments

Comments
 (0)