summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml2
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/sys/epoll.rs114
-rw-r--r--src/sys/statfs.rs6
-rw-r--r--test/sys/test_epoll.rs2
-rw-r--r--test/test_fcntl.rs4
6 files changed, 120 insertions, 10 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index d69716db..21369672 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -42,7 +42,7 @@ task:
matrix:
- name: FreeBSD 12 amd64 & i686
freebsd_instance:
- image: freebsd-12-3-release-amd64
+ image: freebsd-12-4-release-amd64
- name: FreeBSD 14 amd64 & i686
freebsd_instance:
image_family: freebsd-14-0-snap
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4f7855d3..f6ee0fc5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- The MSRV is now 1.63
([#1862](https://github.com/nix-rust/nix/pull/1862))
+- The epoll interface now uses a type.
+ ([#1882](https://github.com/nix-rust/nix/pull/1882))
### Fixed
### Removed
diff --git a/src/sys/epoll.rs b/src/sys/epoll.rs
index 58def2e7..02c25d4d 100644
--- a/src/sys/epoll.rs
+++ b/src/sys/epoll.rs
@@ -2,8 +2,7 @@ use crate::errno::Errno;
use crate::Result;
use libc::{self, c_int};
use std::mem;
-use std::os::unix::io::RawFd;
-use std::ptr;
+use std::os::unix::io::{FromRawFd,RawFd, OwnedFd, AsFd, AsRawFd};
libc_bitflags!(
pub struct EpollFlags: c_int {
@@ -70,6 +69,110 @@ impl EpollEvent {
}
}
+/// A safe wrapper around [`epoll`](https://man7.org/linux/man-pages/man7/epoll.7.html).
+/// ```
+/// # use nix::sys::{epoll::{Epoll, EpollEvent, EpollFlags, EpollCreateFlags}, eventfd::{eventfd, EfdFlags}};
+/// # use nix::unistd::write;
+/// # use std::os::unix::io::{OwnedFd, FromRawFd, AsRawFd, AsFd};
+/// # use std::time::{Instant, Duration};
+/// # fn main() -> nix::Result<()> {
+/// const DATA: u64 = 17;
+/// const MILLIS: u64 = 100;
+///
+/// // Create epoll
+/// let epoll = Epoll::new(EpollCreateFlags::empty())?;
+///
+/// // Create eventfd & Add event
+/// let eventfd = unsafe { OwnedFd::from_raw_fd(eventfd(0, EfdFlags::empty())?) };
+/// epoll.add(&eventfd, EpollEvent::new(EpollFlags::EPOLLIN,DATA))?;
+///
+/// // Arm eventfd & Time wait
+/// write(eventfd.as_raw_fd(), &1u64.to_ne_bytes())?;
+/// let now = Instant::now();
+///
+/// // Wait on event
+/// let mut events = [EpollEvent::empty()];
+/// epoll.wait(&mut events, MILLIS as isize)?;
+///
+/// // Assert data correct & timeout didn't occur
+/// assert_eq!(events[0].data(), DATA);
+/// assert!(now.elapsed() < Duration::from_millis(MILLIS));
+/// # Ok(())
+/// # }
+/// ```
+#[derive(Debug)]
+pub struct Epoll(pub OwnedFd);
+impl Epoll {
+ /// Creates a new epoll instance and returns a file descriptor referring to that instance.
+ ///
+ /// [`epoll_create1`](https://man7.org/linux/man-pages/man2/epoll_create1.2.html).
+ pub fn new(flags: EpollCreateFlags) -> Result<Self> {
+ let res = unsafe { libc::epoll_create1(flags.bits()) };
+ let fd = Errno::result(res)?;
+ let owned_fd = unsafe { OwnedFd::from_raw_fd(fd) };
+ Ok(Self(owned_fd))
+ }
+ /// Add an entry to the interest list of the epoll file descriptor for
+ /// specified in events.
+ ///
+ /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_ADD`.
+ pub fn add<Fd: AsFd>(&self, fd: Fd, mut event: EpollEvent) -> Result<()> {
+ self.epoll_ctl(EpollOp::EpollCtlAdd,fd,&mut event)
+ }
+ /// Remove (deregister) the target file descriptor `fd` from the interest list.
+ ///
+ /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_DEL` .
+ pub fn delete<Fd: AsFd>(&self, fd: Fd) -> Result<()> {
+ self.epoll_ctl(EpollOp::EpollCtlDel,fd,None)
+ }
+ /// Change the settings associated with `fd` in the interest list to the new settings specified
+ /// in `event`.
+ ///
+ /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_MOD`.
+ pub fn modify<Fd: AsFd>(&self,fd: Fd, event: &mut EpollEvent) -> Result<()> {
+ self.epoll_ctl(EpollOp::EpollCtlMod,fd,event)
+ }
+ /// Waits for I/O events, blocking the calling thread if no events are currently available.
+ /// (This can be thought of as fetching items from the ready list of the epoll instance.)
+ ///
+ /// [`epoll_wait`](https://man7.org/linux/man-pages/man2/epoll_wait.2.html)
+ pub fn wait(&self, events: &mut [EpollEvent], timeout: isize) -> Result<usize> {
+ let res = unsafe {
+ libc::epoll_wait(
+ self.0.as_raw_fd(),
+ events.as_mut_ptr() as *mut libc::epoll_event,
+ events.len() as c_int,
+ timeout as c_int,
+ )
+ };
+
+ Errno::result(res).map(|r| r as usize)
+ }
+ /// This system call is used to add, modify, or remove entries in the interest list of the epoll
+ /// instance referred to by `self`. It requests that the operation `op` be performed for the
+ /// target file descriptor, `fd`.
+ ///
+ /// When possible prefer [`Epoll::add`], [`Epoll::delete`] and [`Epoll::modify`].
+ ///
+ /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html)
+ fn epoll_ctl<'a, Fd: AsFd, T>(
+ &self,
+ op: EpollOp,
+ fd: Fd,
+ event: T,
+ ) -> Result<()>
+ where
+ T: Into<Option<&'a mut EpollEvent>>,
+ {
+ let event: Option<&mut EpollEvent> = event.into();
+ let ptr = event.map(|x|&mut x.event as *mut libc::epoll_event).unwrap_or(std::ptr::null_mut());
+ unsafe {
+ Errno::result(libc::epoll_ctl(self.0.as_raw_fd(), op as c_int, fd.as_fd().as_raw_fd(), ptr)).map(drop)
+ }
+ }
+}
+
+#[deprecated(since = "0.27.0", note = "Use Epoll::new() instead")]
#[inline]
pub fn epoll_create() -> Result<RawFd> {
let res = unsafe { libc::epoll_create(1024) };
@@ -77,6 +180,7 @@ pub fn epoll_create() -> Result<RawFd> {
Errno::result(res)
}
+#[deprecated(since = "0.27.0", note = "Use Epoll::new() instead")]
#[inline]
pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
let res = unsafe { libc::epoll_create1(flags.bits()) };
@@ -84,6 +188,7 @@ pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
Errno::result(res)
}
+#[deprecated(since = "0.27.0", note = "Use Epoll::epoll_ctl() instead")]
#[inline]
pub fn epoll_ctl<'a, T>(
epfd: RawFd,
@@ -102,13 +207,14 @@ where
if let Some(ref mut event) = event {
libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event)
} else {
- libc::epoll_ctl(epfd, op as c_int, fd, ptr::null_mut())
+ libc::epoll_ctl(epfd, op as c_int, fd, std::ptr::null_mut())
}
};
Errno::result(res).map(drop)
}
}
+#[deprecated(since = "0.27.0", note = "Use Epoll::wait() instead")]
#[inline]
pub fn epoll_wait(
epfd: RawFd,
@@ -125,4 +231,4 @@ pub fn epoll_wait(
};
Errno::result(res).map(|r| r as usize)
-}
+} \ No newline at end of file
diff --git a/src/sys/statfs.rs b/src/sys/statfs.rs
index 9be8ca66..721d45cb 100644
--- a/src/sys/statfs.rs
+++ b/src/sys/statfs.rs
@@ -5,7 +5,7 @@
use std::ffi::CStr;
use std::fmt::{self, Debug};
use std::mem;
-use std::os::unix::io::AsRawFd;
+use std::os::unix::io::{AsFd, AsRawFd};
use cfg_if::cfg_if;
@@ -740,10 +740,10 @@ pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
/// # Arguments
///
/// `fd` - File descriptor of any open file within the file system to describe
-pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
+pub fn fstatfs<Fd: AsFd>(fd: &Fd) -> Result<Statfs> {
unsafe {
let mut stat = mem::MaybeUninit::<type_of_statfs>::uninit();
- Errno::result(LIBC_FSTATFS(fd.as_raw_fd(), stat.as_mut_ptr()))
+ Errno::result(LIBC_FSTATFS(fd.as_fd().as_raw_fd(), stat.as_mut_ptr()))
.map(|_| Statfs(stat.assume_init()))
}
}
diff --git a/test/sys/test_epoll.rs b/test/sys/test_epoll.rs
index 91569159..84b100c1 100644
--- a/test/sys/test_epoll.rs
+++ b/test/sys/test_epoll.rs
@@ -1,3 +1,5 @@
+#![allow(deprecated)]
+
use nix::errno::Errno;
use nix::sys::epoll::{epoll_create1, epoll_ctl};
use nix::sys::epoll::{EpollCreateFlags, EpollEvent, EpollFlags, EpollOp};
diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs
index fb2a5e2e..8f50f16b 100644
--- a/test/test_fcntl.rs
+++ b/test/test_fcntl.rs
@@ -383,7 +383,7 @@ mod linux_android {
let tmp = NamedTempFile::new().unwrap();
let fd = tmp.as_raw_fd();
- let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap();
+ let statfs = nix::sys::statfs::fstatfs(tmp.as_file()).unwrap();
if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC {
// OverlayFS is a union file system. It returns one inode value in
// stat(2), but a different one shows up in /proc/locks. So we must
@@ -421,7 +421,7 @@ mod linux_android {
let tmp = NamedTempFile::new().unwrap();
let fd = tmp.as_raw_fd();
- let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap();
+ let statfs = nix::sys::statfs::fstatfs(tmp.as_file()).unwrap();
if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC {
// OverlayFS is a union file system. It returns one inode value in
// stat(2), but a different one shows up in /proc/locks. So we must