diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/sched.rs | 6 | ||||
-rw-r--r-- | src/sys/inotify.rs | 28 | ||||
-rw-r--r-- | src/sys/sendfile.rs | 62 | ||||
-rw-r--r-- | src/sys/statvfs.rs | 6 | ||||
-rw-r--r-- | src/sys/timerfd.rs | 44 | ||||
-rw-r--r-- | src/sys/uio.rs | 28 |
6 files changed, 90 insertions, 84 deletions
diff --git a/src/sched.rs b/src/sched.rs index d5b1233c..0515e30f 100644 --- a/src/sched.rs +++ b/src/sched.rs @@ -16,7 +16,7 @@ mod sched_linux_like { use libc::{self, c_int, c_void}; use std::mem; use std::option::Option; - use std::os::unix::io::RawFd; + use std::os::unix::io::{AsFd, AsRawFd}; // For some functions taking with a parameter of type CloneFlags, // only a subset of these flags have an effect. @@ -136,8 +136,8 @@ mod sched_linux_like { /// reassociate thread with a namespace /// /// See also [setns(2)](https://man7.org/linux/man-pages/man2/setns.2.html) - pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> { - let res = unsafe { libc::setns(fd, nstype.bits()) }; + pub fn setns<Fd: AsFd>(fd: Fd, nstype: CloneFlags) -> Result<()> { + let res = unsafe { libc::setns(fd.as_fd().as_raw_fd(), nstype.bits()) }; Errno::result(res).map(drop) } diff --git a/src/sys/inotify.rs b/src/sys/inotify.rs index 84356ec7..2398c16e 100644 --- a/src/sys/inotify.rs +++ b/src/sys/inotify.rs @@ -32,7 +32,7 @@ use libc::{c_char, c_int}; use std::ffi::{CStr, OsStr, OsString}; use std::mem::{size_of, MaybeUninit}; use std::os::unix::ffi::OsStrExt; -use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; +use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd, RawFd}; use std::ptr; libc_bitflags! { @@ -101,9 +101,9 @@ libc_bitflags! { /// An inotify instance. This is also a file descriptor, you can feed it to /// other interfaces consuming file descriptors, epoll for example. -#[derive(Debug, Clone, Copy)] +#[derive(Debug)] pub struct Inotify { - fd: RawFd, + fd: OwnedFd, } /// This object is returned when you create a new watch on an inotify instance. @@ -143,7 +143,7 @@ impl Inotify { pub fn init(flags: InitFlags) -> Result<Inotify> { let res = Errno::result(unsafe { libc::inotify_init1(flags.bits()) }); - res.map(|fd| Inotify { fd }) + res.map(|fd| Inotify { fd: unsafe { OwnedFd::from_raw_fd(fd) } }) } /// Adds a new watch on the target file or directory. @@ -152,12 +152,12 @@ impl Inotify { /// /// For more information see, [inotify_add_watch(2)](https://man7.org/linux/man-pages/man2/inotify_add_watch.2.html). pub fn add_watch<P: ?Sized + NixPath>( - self, + &self, path: &P, mask: AddWatchFlags, ) -> Result<WatchDescriptor> { let res = path.with_nix_path(|cstr| unsafe { - libc::inotify_add_watch(self.fd, cstr.as_ptr(), mask.bits()) + libc::inotify_add_watch(self.fd.as_raw_fd(), cstr.as_ptr(), mask.bits()) })?; Errno::result(res).map(|wd| WatchDescriptor { wd }) @@ -169,7 +169,7 @@ impl Inotify { /// Returns an EINVAL error if the watch descriptor is invalid. /// /// For more information see, [inotify_rm_watch(2)](https://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html). - pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> { + pub fn rm_watch(&self, wd: WatchDescriptor) -> Result<()> { cfg_if! { if #[cfg(target_os = "linux")] { let arg = wd.wd; @@ -177,7 +177,7 @@ impl Inotify { let arg = wd.wd as u32; } } - let res = unsafe { libc::inotify_rm_watch(self.fd, arg) }; + let res = unsafe { libc::inotify_rm_watch(self.fd.as_raw_fd(), arg) }; Errno::result(res).map(drop) } @@ -188,14 +188,14 @@ impl Inotify { /// /// Returns as many events as available. If the call was non blocking and no /// events could be read then the EAGAIN error is returned. - pub fn read_events(self) -> Result<Vec<InotifyEvent>> { + pub fn read_events(&self) -> Result<Vec<InotifyEvent>> { let header_size = size_of::<libc::inotify_event>(); const BUFSIZ: usize = 4096; let mut buffer = [0u8; BUFSIZ]; let mut events = Vec::new(); let mut offset = 0; - let nread = read(self.fd, &mut buffer)?; + let nread = read(self.fd.as_raw_fd(), &mut buffer)?; while (nread - offset) >= header_size { let event = unsafe { @@ -235,14 +235,8 @@ impl Inotify { } } -impl AsRawFd for Inotify { - fn as_raw_fd(&self) -> RawFd { - self.fd - } -} - impl FromRawFd for Inotify { unsafe fn from_raw_fd(fd: RawFd) -> Self { - Inotify { fd } + Inotify { fd: OwnedFd::from_raw_fd(fd) } } } diff --git a/src/sys/sendfile.rs b/src/sys/sendfile.rs index fb293a4e..9f3c333f 100644 --- a/src/sys/sendfile.rs +++ b/src/sys/sendfile.rs @@ -1,7 +1,7 @@ //! Send data from a file to a socket, bypassing userland. use cfg_if::cfg_if; -use std::os::unix::io::RawFd; +use std::os::unix::io::{AsFd, AsRawFd}; use std::ptr; use libc::{self, off_t}; @@ -23,16 +23,23 @@ use crate::Result; /// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html) #[cfg(any(target_os = "android", target_os = "linux"))] #[cfg_attr(docsrs, doc(cfg(all())))] -pub fn sendfile( - out_fd: RawFd, - in_fd: RawFd, +pub fn sendfile<F1: AsFd, F2: AsFd>( + out_fd: F1, + in_fd: F2, offset: Option<&mut off_t>, count: usize, ) -> Result<usize> { let offset = offset .map(|offset| offset as *mut _) .unwrap_or(ptr::null_mut()); - let ret = unsafe { libc::sendfile(out_fd, in_fd, offset, count) }; + let ret = unsafe { + libc::sendfile( + out_fd.as_fd().as_raw_fd(), + in_fd.as_fd().as_raw_fd(), + offset, + count, + ) + }; Errno::result(ret).map(|r| r as usize) } @@ -50,16 +57,23 @@ pub fn sendfile( /// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html) #[cfg(target_os = "linux")] #[cfg_attr(docsrs, doc(cfg(all())))] -pub fn sendfile64( - out_fd: RawFd, - in_fd: RawFd, +pub fn sendfile64<F1: AsFd, F2: AsFd>( + out_fd: F1, + in_fd: F2, offset: Option<&mut libc::off64_t>, count: usize, ) -> Result<usize> { let offset = offset .map(|offset| offset as *mut _) .unwrap_or(ptr::null_mut()); - let ret = unsafe { libc::sendfile64(out_fd, in_fd, offset, count) }; + let ret = unsafe { + libc::sendfile64( + out_fd.as_fd().as_raw_fd(), + in_fd.as_fd().as_raw_fd(), + offset, + count, + ) + }; Errno::result(ret).map(|r| r as usize) } @@ -156,9 +170,9 @@ cfg_if! { /// For more information, see /// [the sendfile(2) man page.](https://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2) #[allow(clippy::too_many_arguments)] - pub fn sendfile( - in_fd: RawFd, - out_sock: RawFd, + pub fn sendfile<F1: AsFd, F2: AsFd>( + in_fd: F1, + out_sock: F2, offset: off_t, count: Option<usize>, headers: Option<&[&[u8]]>, @@ -175,8 +189,8 @@ cfg_if! { let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers)); let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr); let return_code = unsafe { - libc::sendfile(in_fd, - out_sock, + libc::sendfile(in_fd.as_fd().as_raw_fd(), + out_sock.as_fd().as_raw_fd(), offset, count.unwrap_or(0), hdtr_ptr as *mut libc::sf_hdtr, @@ -206,9 +220,9 @@ cfg_if! { /// /// For more information, see /// [the sendfile(2) man page.](https://leaf.dragonflybsd.org/cgi/web-man?command=sendfile§ion=2) - pub fn sendfile( - in_fd: RawFd, - out_sock: RawFd, + pub fn sendfile<F1: AsFd, F2: AsFd>( + in_fd: F1, + out_sock: F2, offset: off_t, count: Option<usize>, headers: Option<&[&[u8]]>, @@ -218,8 +232,8 @@ cfg_if! { let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers)); let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr); let return_code = unsafe { - libc::sendfile(in_fd, - out_sock, + libc::sendfile(in_fd.as_fd().as_raw_fd(), + out_sock.as_fd().as_raw_fd(), offset, count.unwrap_or(0), hdtr_ptr as *mut libc::sf_hdtr, @@ -252,9 +266,9 @@ cfg_if! { /// /// For more information, see /// [the sendfile(2) man page.](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man2/sendfile.2.html) - pub fn sendfile( - in_fd: RawFd, - out_sock: RawFd, + pub fn sendfile<F1: AsFd, F2: AsFd>( + in_fd: F1, + out_sock: F2, offset: off_t, count: Option<off_t>, headers: Option<&[&[u8]]>, @@ -264,8 +278,8 @@ cfg_if! { let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers)); let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr); let return_code = unsafe { - libc::sendfile(in_fd, - out_sock, + libc::sendfile(in_fd.as_fd().as_raw_fd(), + out_sock.as_fd().as_raw_fd(), offset, &mut len as *mut off_t, hdtr_ptr as *mut libc::sf_hdtr, diff --git a/src/sys/statvfs.rs b/src/sys/statvfs.rs index 8de369f4..c2c86624 100644 --- a/src/sys/statvfs.rs +++ b/src/sys/statvfs.rs @@ -3,7 +3,7 @@ //! See [the man pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html) //! for more details. use std::mem; -use std::os::unix::io::AsRawFd; +use std::os::unix::io::{AsFd, AsRawFd}; use libc::{self, c_ulong}; @@ -146,11 +146,11 @@ pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> { } /// Return a `Statvfs` object with information about `fd` -pub fn fstatvfs<T: AsRawFd>(fd: &T) -> Result<Statvfs> { +pub fn fstatvfs<Fd: AsFd>(fd: Fd) -> Result<Statvfs> { unsafe { Errno::clear(); let mut stat = mem::MaybeUninit::<libc::statvfs>::uninit(); - Errno::result(libc::fstatvfs(fd.as_raw_fd(), stat.as_mut_ptr())) + Errno::result(libc::fstatvfs(fd.as_fd().as_raw_fd(), stat.as_mut_ptr())) .map(|_| Statvfs(stat.assume_init())) } } diff --git a/src/sys/timerfd.rs b/src/sys/timerfd.rs index a35fc927..90a05a8c 100644 --- a/src/sys/timerfd.rs +++ b/src/sys/timerfd.rs @@ -33,24 +33,28 @@ pub use crate::sys::time::timer::{Expiration, TimerSetTimeFlags}; use crate::unistd::read; use crate::{errno::Errno, Result}; use libc::c_int; -use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; +use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd}; /// A timerfd instance. This is also a file descriptor, you can feed it to -/// other interfaces consuming file descriptors, epoll for example. +/// other interfaces taking file descriptors as arguments, [`epoll`] for example. +/// +/// [`epoll`]: crate::sys::epoll #[derive(Debug)] pub struct TimerFd { - fd: RawFd, + fd: OwnedFd, } -impl AsRawFd for TimerFd { - fn as_raw_fd(&self) -> RawFd { - self.fd +impl AsFd for TimerFd { + fn as_fd(&self) -> BorrowedFd<'_> { + self.fd.as_fd() } } impl FromRawFd for TimerFd { unsafe fn from_raw_fd(fd: RawFd) -> Self { - TimerFd { fd } + TimerFd { + fd: OwnedFd::from_raw_fd(fd), + } } } @@ -97,7 +101,9 @@ impl TimerFd { Errno::result(unsafe { libc::timerfd_create(clockid as i32, flags.bits()) }) - .map(|fd| Self { fd }) + .map(|fd| Self { + fd: unsafe { OwnedFd::from_raw_fd(fd) }, + }) } /// Sets a new alarm on the timer. @@ -145,7 +151,7 @@ impl TimerFd { let timerspec: TimerSpec = expiration.into(); Errno::result(unsafe { libc::timerfd_settime( - self.fd, + self.fd.as_fd().as_raw_fd(), flags.bits(), timerspec.as_ref(), std::ptr::null_mut(), @@ -159,7 +165,10 @@ impl TimerFd { pub fn get(&self) -> Result<Option<Expiration>> { let mut timerspec = TimerSpec::none(); Errno::result(unsafe { - libc::timerfd_gettime(self.fd, timerspec.as_mut()) + libc::timerfd_gettime( + self.fd.as_fd().as_raw_fd(), + timerspec.as_mut(), + ) }) .map(|_| { if timerspec.as_ref().it_interval.tv_sec == 0 @@ -179,7 +188,7 @@ impl TimerFd { pub fn unset(&self) -> Result<()> { Errno::result(unsafe { libc::timerfd_settime( - self.fd, + self.fd.as_fd().as_raw_fd(), TimerSetTimeFlags::empty().bits(), TimerSpec::none().as_ref(), std::ptr::null_mut(), @@ -192,7 +201,7 @@ impl TimerFd { /// /// Note: If the alarm is unset, then you will wait forever. pub fn wait(&self) -> Result<()> { - while let Err(e) = read(self.fd, &mut [0u8; 8]) { + while let Err(e) = read(self.fd.as_fd().as_raw_fd(), &mut [0u8; 8]) { if e != Errno::EINTR { return Err(e); } @@ -201,14 +210,3 @@ impl TimerFd { Ok(()) } } - -impl Drop for TimerFd { - fn drop(&mut self) { - if !std::thread::panicking() { - let result = Errno::result(unsafe { libc::close(self.fd) }); - if let Err(Errno::EBADF) = result { - panic!("close of TimerFd encountered EBADF"); - } - } - } -} diff --git a/src/sys/uio.rs b/src/sys/uio.rs index 7248bd0c..ce0fb54d 100644 --- a/src/sys/uio.rs +++ b/src/sys/uio.rs @@ -4,12 +4,12 @@ use crate::errno::Errno; use crate::Result; use libc::{self, c_int, c_void, off_t, size_t}; use std::io::{IoSlice, IoSliceMut}; -use std::os::unix::io::RawFd; +use std::os::unix::io::{AsFd, AsRawFd}; /// Low-level vectored write to a raw file descriptor /// /// See also [writev(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html) -pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result<usize> { +pub fn writev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>]) -> Result<usize> { // SAFETY: to quote the documentation for `IoSlice`: // // [IoSlice] is semantically a wrapper around a &[u8], but is @@ -18,7 +18,7 @@ pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result<usize> { // // Because it is ABI compatible, a pointer cast here is valid let res = unsafe { - libc::writev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) + libc::writev(fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len() as c_int) }; Errno::result(res).map(|r| r as usize) @@ -27,10 +27,10 @@ pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result<usize> { /// Low-level vectored read from a raw file descriptor /// /// See also [readv(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html) -pub fn readv(fd: RawFd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> { +pub fn readv<Fd: AsFd>(fd: Fd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> { // SAFETY: same as in writev(), IoSliceMut is ABI-compatible with iovec let res = unsafe { - libc::readv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) + libc::readv(fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len() as c_int) }; Errno::result(res).map(|r| r as usize) @@ -44,14 +44,14 @@ pub fn readv(fd: RawFd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> { /// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html) #[cfg(not(any(target_os = "redox", target_os = "haiku")))] #[cfg_attr(docsrs, doc(cfg(all())))] -pub fn pwritev(fd: RawFd, iov: &[IoSlice<'_>], offset: off_t) -> Result<usize> { +pub fn pwritev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>], offset: off_t) -> Result<usize> { #[cfg(target_env = "uclibc")] let offset = offset as libc::off64_t; // uclibc doesn't use off_t // SAFETY: same as in writev() let res = unsafe { libc::pwritev( - fd, + fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset, @@ -70,8 +70,8 @@ pub fn pwritev(fd: RawFd, iov: &[IoSlice<'_>], offset: off_t) -> Result<usize> { /// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html) #[cfg(not(any(target_os = "redox", target_os = "haiku")))] #[cfg_attr(docsrs, doc(cfg(all())))] -pub fn preadv( - fd: RawFd, +pub fn preadv<Fd: AsFd>( + fd: Fd, iov: &mut [IoSliceMut<'_>], offset: off_t, ) -> Result<usize> { @@ -81,7 +81,7 @@ pub fn preadv( // SAFETY: same as in readv() let res = unsafe { libc::preadv( - fd, + fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset, @@ -95,10 +95,10 @@ pub fn preadv( /// /// See also [pwrite(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html) // TODO: move to unistd -pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> { +pub fn pwrite<Fd: AsFd>(fd: Fd, buf: &[u8], offset: off_t) -> Result<usize> { let res = unsafe { libc::pwrite( - fd, + fd.as_fd().as_raw_fd(), buf.as_ptr() as *const c_void, buf.len() as size_t, offset, @@ -112,10 +112,10 @@ pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> { /// /// See also [pread(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html) // TODO: move to unistd -pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize> { +pub fn pread<Fd: AsFd>(fd: Fd, buf: &mut [u8], offset: off_t) -> Result<usize> { let res = unsafe { libc::pread( - fd, + fd.as_fd().as_raw_fd(), buf.as_mut_ptr() as *mut c_void, buf.len() as size_t, offset, |