diff --git a/src/dir.rs b/src/dir.rs index e1854c35e8..ea93c5f8bd 100644 --- a/src/dir.rs +++ b/src/dir.rs @@ -6,6 +6,7 @@ use crate::sys; use crate::{Error, NixPath, Result}; use cfg_if::cfg_if; use std::ffi; +use std::os::unix::io::AsFd; use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd}; use std::ptr; @@ -39,18 +40,18 @@ impl Dir { mode: sys::stat::Mode, ) -> Result { let fd = fcntl::open(path, oflag, mode)?; - Dir::from_fd(fd) + Dir::from_fd(fd.into_raw_fd()) } /// Opens the given path as with `fcntl::openat`. - pub fn openat( - dirfd: RawFd, + pub fn openat( + dirfd: &Fd, path: &P, oflag: OFlag, mode: sys::stat::Mode, ) -> Result { let fd = fcntl::openat(dirfd, path, oflag, mode)?; - Dir::from_fd(fd) + Dir::from_fd(fd.into_raw_fd()) } /// Converts from a descriptor-based object, closing the descriptor on success or failure. diff --git a/src/fcntl.rs b/src/fcntl.rs index 65bbd4ca7a..0490a022e0 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -1,9 +1,12 @@ use crate::errno::Errno; use libc::{self, c_char, c_int, c_uint, size_t, ssize_t}; use std::ffi::OsString; -#[cfg(not(target_os = "redox"))] -use std::os::raw; use std::os::unix::ffi::OsStringExt; +use std::os::unix::io::AsFd; +#[cfg(not(target_os = "redox"))] +use std::os::unix::io::AsRawFd; +use std::os::unix::io::FromRawFd; +use std::os::unix::io::OwnedFd; use std::os::unix::io::RawFd; #[cfg(feature = "fs")] @@ -193,42 +196,52 @@ feature! { // The conversion is not identical on all operating systems. #[allow(clippy::useless_conversion)] -pub fn open(path: &P, oflag: OFlag, mode: Mode) -> Result { - let fd = path.with_nix_path(|cstr| { - unsafe { libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) } +pub fn open( + path: &P, + oflag: OFlag, + mode: Mode, +) -> Result { + let fd = path.with_nix_path(|cstr| unsafe { + libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) })?; - Errno::result(fd) + Errno::result(fd).map(|fd| unsafe { OwnedFd::from_raw_fd(fd) }) } // The conversion is not identical on all operating systems. #[allow(clippy::useless_conversion)] #[cfg(not(target_os = "redox"))] -pub fn openat( - dirfd: RawFd, +pub fn openat( + dirfd: &Fd, path: &P, oflag: OFlag, mode: Mode, -) -> Result { - let fd = path.with_nix_path(|cstr| { - unsafe { libc::openat(dirfd, cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) } +) -> Result { + let fd = path.with_nix_path(|cstr| unsafe { + libc::openat( + dirfd.as_fd().as_raw_fd(), + cstr.as_ptr(), + oflag.bits(), + mode.bits() as c_uint, + ) })?; - Errno::result(fd) + + Errno::result(fd).map(|fd| unsafe { OwnedFd::from_raw_fd(fd) }) } #[cfg(not(target_os = "redox"))] -pub fn renameat( - old_dirfd: Option, +pub fn renameat( + old_dirfd: &Fd1, old_path: &P1, - new_dirfd: Option, + new_dirfd: &Fd2, new_path: &P2, ) -> Result<()> { let res = old_path.with_nix_path(|old_cstr| { new_path.with_nix_path(|new_cstr| unsafe { libc::renameat( - at_rawfd(old_dirfd), + old_dirfd.as_fd().as_raw_fd(), old_cstr.as_ptr(), - at_rawfd(new_dirfd), + new_dirfd.as_fd().as_raw_fd(), new_cstr.as_ptr(), ) }) @@ -251,19 +264,19 @@ libc_bitflags! { feature! { #![feature = "fs"] #[cfg(all(target_os = "linux", target_env = "gnu"))] -pub fn renameat2( - old_dirfd: Option, +pub fn renameat2( + old_dirfd: &Fd1, old_path: &P1, - new_dirfd: Option, + new_dirfd: &Fd2, new_path: &P2, flags: RenameFlags, ) -> Result<()> { let res = old_path.with_nix_path(|old_cstr| { new_path.with_nix_path(|new_cstr| unsafe { libc::renameat2( - at_rawfd(old_dirfd), + old_dirfd.as_fd().as_raw_fd(), old_cstr.as_ptr(), - at_rawfd(new_dirfd), + new_dirfd.as_fd().as_raw_fd(), new_cstr.as_ptr(), flags.bits(), ) @@ -275,21 +288,21 @@ pub fn renameat2( fn wrap_readlink_result(mut v: Vec, len: ssize_t) -> Result { unsafe { v.set_len(len as usize) } v.shrink_to_fit(); - Ok(OsString::from_vec(v.to_vec())) + Ok(OsString::from_vec(v)) } -fn readlink_maybe_at( - dirfd: Option, +fn readlink_maybe_at( + dirfd: Option<&Fd>, path: &P, v: &mut Vec, -) -> Result { +) -> Result { path.with_nix_path(|cstr| unsafe { match dirfd { #[cfg(target_os = "redox")] Some(_) => unreachable!(), #[cfg(not(target_os = "redox"))] Some(dirfd) => libc::readlinkat( - dirfd, + dirfd.as_fd().as_raw_fd(), cstr.as_ptr(), v.as_mut_ptr() as *mut c_char, v.capacity() as size_t, @@ -303,7 +316,10 @@ fn readlink_maybe_at( }) } -fn inner_readlink(dirfd: Option, path: &P) -> Result { +fn inner_readlink( + dirfd: Option<&Fd>, + path: &P, +) -> Result { let mut v = Vec::with_capacity(libc::PATH_MAX as usize); { @@ -383,22 +399,16 @@ fn inner_readlink(dirfd: Option, path: &P) -> Result } pub fn readlink(path: &P) -> Result { - inner_readlink(None, path) + inner_readlink(None::<&OwnedFd>, path) } #[cfg(not(target_os = "redox"))] -pub fn readlinkat(dirfd: RawFd, path: &P) -> Result { +pub fn readlinkat( + dirfd: &Fd, + path: &P, +) -> Result { inner_readlink(Some(dirfd), path) } - -/// Computes the raw fd consumed by a function of the form `*at`. -#[cfg(not(target_os = "redox"))] -pub(crate) fn at_rawfd(fd: Option) -> raw::c_int { - match fd { - None => libc::AT_FDCWD, - Some(fd) => fd, - } -} } #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] @@ -588,10 +598,10 @@ feature! { /// On successful completion the number of bytes actually copied will be /// returned. #[cfg(any(target_os = "android", target_os = "linux"))] -pub fn copy_file_range( - fd_in: RawFd, +pub fn copy_file_range( + fd_in: &Fd1, off_in: Option<&mut libc::loff_t>, - fd_out: RawFd, + fd_out: &Fd2, off_out: Option<&mut libc::loff_t>, len: usize, ) -> Result { @@ -605,9 +615,9 @@ pub fn copy_file_range( let ret = unsafe { libc::syscall( libc::SYS_copy_file_range, - fd_in, + fd_in.as_fd().as_raw_fd(), off_in, - fd_out, + fd_out.as_fd().as_raw_fd(), off_out, len, 0, @@ -617,10 +627,10 @@ pub fn copy_file_range( } #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn splice( - fd_in: RawFd, +pub fn splice( + fd_in: &Fd1, off_in: Option<&mut libc::loff_t>, - fd_out: RawFd, + fd_out: &Fd2, off_out: Option<&mut libc::loff_t>, len: usize, flags: SpliceFFlags, @@ -632,26 +642,46 @@ pub fn splice( .map(|offset| offset as *mut libc::loff_t) .unwrap_or(ptr::null_mut()); - let ret = unsafe { libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits()) }; + let ret = unsafe { + libc::splice( + fd_in.as_fd().as_raw_fd(), + off_in, + fd_out.as_fd().as_raw_fd(), + off_out, + len, + flags.bits(), + ) + }; Errno::result(ret).map(|r| r as usize) } #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn tee(fd_in: RawFd, fd_out: RawFd, len: usize, flags: SpliceFFlags) -> Result { - let ret = unsafe { libc::tee(fd_in, fd_out, len, flags.bits()) }; +pub fn tee( + fd_in: &Fd1, + fd_out: &Fd2, + len: usize, + flags: SpliceFFlags, +) -> Result { + let ret = unsafe { + libc::tee( + fd_in.as_fd().as_raw_fd(), + fd_out.as_fd().as_raw_fd(), + len, + flags.bits(), + ) + }; Errno::result(ret).map(|r| r as usize) } #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn vmsplice( - fd: RawFd, +pub fn vmsplice( + fd: &Fd, iov: &[std::io::IoSlice<'_>], - flags: SpliceFFlags - ) -> Result -{ + flags: SpliceFFlags, +) -> Result { let ret = unsafe { libc::vmsplice( - fd, + fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len(), flags.bits(), @@ -703,13 +733,15 @@ feature! { /// file referred to by fd. #[cfg(any(target_os = "linux"))] #[cfg(feature = "fs")] -pub fn fallocate( - fd: RawFd, +pub fn fallocate( + fd: &Fd, mode: FallocateFlags, offset: libc::off_t, len: libc::off_t, ) -> Result<()> { - let res = unsafe { libc::fallocate(fd, mode.bits(), offset, len) }; + let res = unsafe { + libc::fallocate(fd.as_fd().as_raw_fd(), mode.bits(), offset, len) + }; Errno::result(res).map(drop) } @@ -762,30 +794,38 @@ impl SpacectlRange { #[cfg_attr(not(fbsd14), doc = " ```no_run")] /// # use std::io::Write; /// # use std::os::unix::fs::FileExt; -/// # use std::os::unix::io::AsRawFd; /// # use nix::fcntl::*; /// # use tempfile::tempfile; +/// /// const INITIAL: &[u8] = b"0123456789abcdef"; /// let mut f = tempfile().unwrap(); /// f.write_all(INITIAL).unwrap(); /// let mut range = SpacectlRange(3, 6); /// while (!range.is_empty()) { -/// range = fspacectl(f.as_raw_fd(), range).unwrap(); +/// range = fspacectl(&f, range).unwrap(); /// } /// let mut buf = vec![0; INITIAL.len()]; /// f.read_exact_at(&mut buf, 0).unwrap(); /// assert_eq!(buf, b"012\0\0\0\0\0\09abcdef"); /// ``` #[cfg(target_os = "freebsd")] -pub fn fspacectl(fd: RawFd, range: SpacectlRange) -> Result { - let mut rqsr = libc::spacectl_range{r_offset: range.0, r_len: range.1}; - let res = unsafe { libc::fspacectl( - fd, +pub fn fspacectl( + fd: &Fd, + range: SpacectlRange, +) -> Result { + let mut rqsr = libc::spacectl_range { + r_offset: range.0, + r_len: range.1, + }; + let res = unsafe { + libc::fspacectl( + fd.as_fd().as_raw_fd(), libc::SPACECTL_DEALLOC, // Only one command is supported ATM &rqsr, - 0, // No flags are currently supported - &mut rqsr - )}; + 0, // No flags are currently supported + &mut rqsr, + ) + }; Errno::result(res).map(|_| SpacectlRange(rqsr.r_offset, rqsr.r_len)) } @@ -808,30 +848,37 @@ pub fn fspacectl(fd: RawFd, range: SpacectlRange) -> Result { #[cfg_attr(not(fbsd14), doc = " ```no_run")] /// # use std::io::Write; /// # use std::os::unix::fs::FileExt; -/// # use std::os::unix::io::AsRawFd; /// # use nix::fcntl::*; /// # use tempfile::tempfile; +/// /// const INITIAL: &[u8] = b"0123456789abcdef"; /// let mut f = tempfile().unwrap(); /// f.write_all(INITIAL).unwrap(); -/// fspacectl_all(f.as_raw_fd(), 3, 6).unwrap(); +/// fspacectl_all(&f, 3, 6).unwrap(); /// let mut buf = vec![0; INITIAL.len()]; /// f.read_exact_at(&mut buf, 0).unwrap(); /// assert_eq!(buf, b"012\0\0\0\0\0\09abcdef"); /// ``` #[cfg(target_os = "freebsd")] -pub fn fspacectl_all(fd: RawFd, offset: libc::off_t, len: libc::off_t) - -> Result<()> -{ - let mut rqsr = libc::spacectl_range{r_offset: offset, r_len: len}; +pub fn fspacectl_all( + fd: &Fd, + offset: libc::off_t, + len: libc::off_t, +) -> Result<()> { + let mut rqsr = libc::spacectl_range { + r_offset: offset, + r_len: len, + }; while rqsr.r_len > 0 { - let res = unsafe { libc::fspacectl( - fd, + let res = unsafe { + libc::fspacectl( + fd.as_fd().as_raw_fd(), libc::SPACECTL_DEALLOC, // Only one command is supported ATM &rqsr, - 0, // No flags are currently supported - &mut rqsr - )}; + 0, // No flags are currently supported + &mut rqsr, + ) + }; Errno::result(res)?; } Ok(()) @@ -848,8 +895,9 @@ pub fn fspacectl_all(fd: RawFd, offset: libc::off_t, len: libc::off_t) ))] mod posix_fadvise { use crate::errno::Errno; - use std::os::unix::io::RawFd; use crate::Result; + use std::os::unix::io::AsFd; + use std::os::unix::io::AsRawFd; #[cfg(feature = "fs")] libc_enum! { @@ -868,13 +916,20 @@ mod posix_fadvise { feature! { #![feature = "fs"] - pub fn posix_fadvise( - fd: RawFd, + pub fn posix_fadvise( + fd: &Fd, offset: libc::off_t, len: libc::off_t, advice: PosixFadviseAdvice, ) -> Result<()> { - let res = unsafe { libc::posix_fadvise(fd, offset, len, advice as libc::c_int) }; + let res = unsafe { + libc::posix_fadvise( + fd.as_fd().as_raw_fd(), + offset, + len, + advice as libc::c_int, + ) + }; if res == 0 { Ok(()) @@ -894,8 +949,13 @@ mod posix_fadvise { target_os = "wasi", target_os = "freebsd" ))] -pub fn posix_fallocate(fd: RawFd, offset: libc::off_t, len: libc::off_t) -> Result<()> { - let res = unsafe { libc::posix_fallocate(fd, offset, len) }; +pub fn posix_fallocate( + fd: &Fd, + offset: libc::off_t, + len: libc::off_t, +) -> Result<()> { + let res = + unsafe { libc::posix_fallocate(fd.as_fd().as_raw_fd(), offset, len) }; match Errno::result(res) { Err(err) => Err(err), Ok(0) => Ok(()), diff --git a/src/lib.rs b/src/lib.rs index 6349d37e0f..5b5d8ce921 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -162,6 +162,8 @@ pub mod unistd; use std::ffi::{CStr, CString, OsStr}; use std::mem::MaybeUninit; use std::os::unix::ffi::OsStrExt; +#[cfg(not(target_os = "redox"))] +use std::os::unix::io::BorrowedFd; use std::path::{Path, PathBuf}; use std::{ptr, result, slice}; @@ -182,6 +184,17 @@ pub type Result = result::Result; /// ones. pub type Error = Errno; +/// A file descriptor representing the current working directory. +#[cfg(not(target_os = "redox"))] +pub const AT_FDCWD: &BorrowedFd<'static> = unsafe { + &BorrowedFd::borrow_raw(if cfg!(target_os = "haiku") { + // Hack to work around BorrowedFd not allowing -1 + -2 + } else { + libc::AT_FDCWD + }) +}; + /// Common trait used to represent file system paths by many Nix functions. pub trait NixPath { /// Is the path empty? diff --git a/src/pty.rs b/src/pty.rs index 28ae5e924b..384750de92 100644 --- a/src/pty.rs +++ b/src/pty.rs @@ -81,13 +81,15 @@ impl Drop for PtyMaster { impl io::Read for PtyMaster { fn read(&mut self, buf: &mut [u8]) -> io::Result { - unistd::read(self.0, buf).map_err(io::Error::from) + unistd::read(unsafe { &BorrowedFd::borrow_raw(self.0) }, buf) + .map_err(io::Error::from) } } impl io::Write for PtyMaster { fn write(&mut self, buf: &[u8]) -> io::Result { - unistd::write(self.0, buf).map_err(io::Error::from) + unistd::write(unsafe { &BorrowedFd::borrow_raw(self.0) }, buf) + .map_err(io::Error::from) } fn flush(&mut self) -> io::Result<()> { Ok(()) @@ -96,13 +98,15 @@ impl io::Write for PtyMaster { impl io::Read for &PtyMaster { fn read(&mut self, buf: &mut [u8]) -> io::Result { - unistd::read(self.0, buf).map_err(io::Error::from) + unistd::read(unsafe { &BorrowedFd::borrow_raw(self.0) }, buf) + .map_err(io::Error::from) } } impl io::Write for &PtyMaster { fn write(&mut self, buf: &[u8]) -> io::Result { - unistd::write(self.0, buf).map_err(io::Error::from) + unistd::write(unsafe { &BorrowedFd::borrow_raw(self.0) }, buf) + .map_err(io::Error::from) } fn flush(&mut self) -> io::Result<()> { Ok(()) diff --git a/src/sys/inotify.rs b/src/sys/inotify.rs index 84356ec70f..b12f9cfca3 100644 --- a/src/sys/inotify.rs +++ b/src/sys/inotify.rs @@ -32,6 +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::BorrowedFd; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use std::ptr; @@ -195,7 +196,8 @@ impl Inotify { let mut events = Vec::new(); let mut offset = 0; - let nread = read(self.fd, &mut buffer)?; + let nread = + read(unsafe { &BorrowedFd::borrow_raw(self.fd) }, &mut buffer)?; while (nread - offset) >= header_size { let event = unsafe { diff --git a/src/sys/select.rs b/src/sys/select.rs index 7a94cff87e..cbbb48fe13 100644 --- a/src/sys/select.rs +++ b/src/sys/select.rs @@ -304,6 +304,7 @@ mod tests { use super::*; use crate::sys::time::{TimeVal, TimeValLike}; use crate::unistd::{pipe, write}; + use std::os::unix::io::AsRawFd; use std::os::unix::io::RawFd; #[test] @@ -385,31 +386,31 @@ mod tests { #[test] fn test_select() { let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); + write(&w1, b"hi!").unwrap(); let (r2, _w2) = pipe().unwrap(); let mut fd_set = FdSet::new(); - fd_set.insert(r1); - fd_set.insert(r2); + fd_set.insert(r1.as_raw_fd()); + fd_set.insert(r2.as_raw_fd()); let mut timeout = TimeVal::seconds(10); assert_eq!( 1, select(None, &mut fd_set, None, None, &mut timeout).unwrap() ); - assert!(fd_set.contains(r1)); - assert!(!fd_set.contains(r2)); + assert!(fd_set.contains(r1.as_raw_fd())); + assert!(!fd_set.contains(r2.as_raw_fd())); } #[test] fn test_select_nfds() { let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); + write(&w1, b"hi!").unwrap(); let (r2, _w2) = pipe().unwrap(); let mut fd_set = FdSet::new(); - fd_set.insert(r1); - fd_set.insert(r2); + fd_set.insert(r1.as_raw_fd()); + fd_set.insert(r2.as_raw_fd()); let mut timeout = TimeVal::seconds(10); assert_eq!( @@ -423,25 +424,25 @@ mod tests { ) .unwrap() ); - assert!(fd_set.contains(r1)); - assert!(!fd_set.contains(r2)); + assert!(fd_set.contains(r1.as_raw_fd())); + assert!(!fd_set.contains(r2.as_raw_fd())); } #[test] fn test_select_nfds2() { let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); + write(&w1, b"hi!").unwrap(); let (r2, _w2) = pipe().unwrap(); let mut fd_set = FdSet::new(); - fd_set.insert(r1); - fd_set.insert(r2); + fd_set.insert(r1.as_raw_fd()); + fd_set.insert(r2.as_raw_fd()); let mut timeout = TimeVal::seconds(10); assert_eq!( 1, select( - ::std::cmp::max(r1, r2) + 1, + std::cmp::max(r1.as_raw_fd(), r2.as_raw_fd()) + 1, &mut fd_set, None, None, @@ -449,7 +450,7 @@ mod tests { ) .unwrap() ); - assert!(fd_set.contains(r1)); - assert!(!fd_set.contains(r2)); + assert!(fd_set.contains(r1.as_raw_fd())); + assert!(!fd_set.contains(r2.as_raw_fd())); } } diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 5dac869899..b26bbbaefe 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -1437,13 +1437,15 @@ impl<'a> ControlMessage<'a> { /// # use nix::sys::socket::*; /// # use nix::unistd::pipe; /// # use std::io::IoSlice; +/// # use std::os::unix::io::AsRawFd; +/// /// let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, /// SockFlag::empty()) /// .unwrap(); /// let (r, w) = pipe().unwrap(); /// /// let iov = [IoSlice::new(b"hello")]; -/// let fds = [r]; +/// let fds = [r.as_raw_fd()]; /// let cmsg = ControlMessage::ScmRights(&fds); /// sendmsg::<()>(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(); /// ``` @@ -1452,14 +1454,16 @@ impl<'a> ControlMessage<'a> { /// # use nix::sys::socket::*; /// # use nix::unistd::pipe; /// # use std::io::IoSlice; +/// # use std::os::unix::io::AsRawFd; /// # use std::str::FromStr; +/// /// let localhost = SockaddrIn::from_str("1.2.3.4:8080").unwrap(); /// let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), /// None).unwrap(); /// let (r, w) = pipe().unwrap(); /// /// let iov = [IoSlice::new(b"hello")]; -/// let fds = [r]; +/// let fds = [r.as_raw_fd()]; /// let cmsg = ControlMessage::ScmRights(&fds); /// sendmsg(fd, &iov, &[cmsg], MsgFlags::empty(), Some(&localhost)).unwrap(); /// ``` diff --git a/src/sys/stat.rs b/src/sys/stat.rs index 78203bfbe3..f2b33a06f7 100644 --- a/src/sys/stat.rs +++ b/src/sys/stat.rs @@ -10,11 +10,11 @@ pub use libc::stat as FileStat; pub use libc::{dev_t, mode_t}; #[cfg(not(target_os = "redox"))] -use crate::fcntl::{at_rawfd, AtFlags}; +use crate::fcntl::AtFlags; use crate::sys::time::{TimeSpec, TimeVal}; use crate::{errno::Errno, NixPath, Result}; use std::mem; -use std::os::unix::io::RawFd; +use std::os::unix::io::{AsFd, AsRawFd}; libc_bitflags!( /// "File type" flags for `mknod` and related functions. @@ -191,8 +191,8 @@ pub fn mknod( target_os = "haiku" )))] #[cfg_attr(docsrs, doc(cfg(all())))] -pub fn mknodat( - dirfd: RawFd, +pub fn mknodat( + dirfd: &Fd, path: &P, kind: SFlag, perm: Mode, @@ -200,7 +200,7 @@ pub fn mknodat( ) -> Result<()> { let res = path.with_nix_path(|cstr| unsafe { libc::mknodat( - dirfd, + dirfd.as_fd().as_raw_fd(), cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev, @@ -258,9 +258,9 @@ pub fn lstat(path: &P) -> Result { Ok(unsafe { dst.assume_init() }) } -pub fn fstat(fd: RawFd) -> Result { +pub fn fstat(fd: &Fd) -> Result { let mut dst = mem::MaybeUninit::uninit(); - let res = unsafe { libc::fstat(fd, dst.as_mut_ptr()) }; + let res = unsafe { libc::fstat(fd.as_fd().as_raw_fd(), dst.as_mut_ptr()) }; Errno::result(res)?; @@ -269,15 +269,15 @@ pub fn fstat(fd: RawFd) -> Result { #[cfg(not(target_os = "redox"))] #[cfg_attr(docsrs, doc(cfg(all())))] -pub fn fstatat( - dirfd: RawFd, +pub fn fstatat( + dirfd: &Fd, pathname: &P, f: AtFlags, ) -> Result { let mut dst = mem::MaybeUninit::uninit(); let res = pathname.with_nix_path(|cstr| unsafe { libc::fstatat( - dirfd, + dirfd.as_fd().as_raw_fd(), cstr.as_ptr(), dst.as_mut_ptr(), f.bits() as libc::c_int, @@ -294,8 +294,9 @@ pub fn fstatat( /// # References /// /// [fchmod(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html). -pub fn fchmod(fd: RawFd, mode: Mode) -> Result<()> { - let res = unsafe { libc::fchmod(fd, mode.bits() as mode_t) }; +pub fn fchmod(fd: &Fd, mode: Mode) -> Result<()> { + let res = + unsafe { libc::fchmod(fd.as_fd().as_raw_fd(), mode.bits() as mode_t) }; Errno::result(res).map(drop) } @@ -325,8 +326,8 @@ pub enum FchmodatFlags { /// [fchmodat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html). #[cfg(not(target_os = "redox"))] #[cfg_attr(docsrs, doc(cfg(all())))] -pub fn fchmodat( - dirfd: Option, +pub fn fchmodat( + dirfd: &Fd, path: &P, mode: Mode, flag: FchmodatFlags, @@ -337,7 +338,7 @@ pub fn fchmodat( }; let res = path.with_nix_path(|cstr| unsafe { libc::fchmodat( - at_rawfd(dirfd), + dirfd.as_fd().as_raw_fd(), cstr.as_ptr(), mode.bits() as mode_t, atflag.bits() as libc::c_int, @@ -408,9 +409,13 @@ pub fn lutimes( /// /// [futimens(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html). #[inline] -pub fn futimens(fd: RawFd, atime: &TimeSpec, mtime: &TimeSpec) -> Result<()> { +pub fn futimens( + fd: &Fd, + atime: &TimeSpec, + mtime: &TimeSpec, +) -> Result<()> { let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()]; - let res = unsafe { libc::futimens(fd, ×[0]) }; + let res = unsafe { libc::futimens(fd.as_fd().as_raw_fd(), ×[0]) }; Errno::result(res).map(drop) } @@ -441,8 +446,8 @@ pub enum UtimensatFlags { /// [utimensat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html). #[cfg(not(target_os = "redox"))] #[cfg_attr(docsrs, doc(cfg(all())))] -pub fn utimensat( - dirfd: Option, +pub fn utimensat( + dirfd: &Fd, path: &P, atime: &TimeSpec, mtime: &TimeSpec, @@ -455,7 +460,7 @@ pub fn utimensat( let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()]; let res = path.with_nix_path(|cstr| unsafe { libc::utimensat( - at_rawfd(dirfd), + dirfd.as_fd().as_raw_fd(), cstr.as_ptr(), ×[0], atflag.bits() as libc::c_int, @@ -467,13 +472,17 @@ pub fn utimensat( #[cfg(not(target_os = "redox"))] #[cfg_attr(docsrs, doc(cfg(all())))] -pub fn mkdirat( - fd: RawFd, +pub fn mkdirat( + fd: &Fd, path: &P, mode: Mode, ) -> Result<()> { let res = path.with_nix_path(|cstr| unsafe { - libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t) + libc::mkdirat( + fd.as_fd().as_raw_fd(), + cstr.as_ptr(), + mode.bits() as mode_t, + ) })?; Errno::result(res).map(drop) diff --git a/src/sys/timerfd.rs b/src/sys/timerfd.rs index a35fc927f4..0514d2497a 100644 --- a/src/sys/timerfd.rs +++ b/src/sys/timerfd.rs @@ -33,24 +33,27 @@ 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::OwnedFd; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; /// A timerfd instance. This is also a file descriptor, you can feed it to /// other interfaces consuming file descriptors, epoll for example. #[derive(Debug)] pub struct TimerFd { - fd: RawFd, + fd: OwnedFd, } impl AsRawFd for TimerFd { fn as_raw_fd(&self) -> RawFd { - self.fd + self.fd.as_raw_fd() } } impl FromRawFd for TimerFd { unsafe fn from_raw_fd(fd: RawFd) -> Self { - TimerFd { fd } + TimerFd { + fd: OwnedFd::from_raw_fd(fd), + } } } @@ -97,6 +100,7 @@ impl TimerFd { Errno::result(unsafe { libc::timerfd_create(clockid as i32, flags.bits()) }) + .map(|fd| unsafe { OwnedFd::from_raw_fd(fd) }) .map(|fd| Self { fd }) } @@ -145,7 +149,7 @@ impl TimerFd { let timerspec: TimerSpec = expiration.into(); Errno::result(unsafe { libc::timerfd_settime( - self.fd, + self.fd.as_raw_fd(), flags.bits(), timerspec.as_ref(), std::ptr::null_mut(), @@ -159,7 +163,7 @@ impl TimerFd { pub fn get(&self) -> Result> { let mut timerspec = TimerSpec::none(); Errno::result(unsafe { - libc::timerfd_gettime(self.fd, timerspec.as_mut()) + libc::timerfd_gettime(self.fd.as_raw_fd(), timerspec.as_mut()) }) .map(|_| { if timerspec.as_ref().it_interval.tv_sec == 0 @@ -179,7 +183,7 @@ impl TimerFd { pub fn unset(&self) -> Result<()> { Errno::result(unsafe { libc::timerfd_settime( - self.fd, + self.fd.as_raw_fd(), TimerSetTimeFlags::empty().bits(), TimerSpec::none().as_ref(), std::ptr::null_mut(), @@ -192,7 +196,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, &mut [0u8; 8]) { if e != Errno::EINTR { return Err(e); } @@ -201,14 +205,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/unistd.rs b/src/unistd.rs index 1bfeb7b94f..29a2cac67f 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -3,7 +3,7 @@ use crate::errno::{self, Errno}; #[cfg(not(target_os = "redox"))] #[cfg(feature = "fs")] -use crate::fcntl::{at_rawfd, AtFlags}; +use crate::fcntl::AtFlags; #[cfg(feature = "fs")] use crate::fcntl::{fcntl, FcntlArg::F_SETFD, FdFlag, OFlag}; #[cfg(all( @@ -34,7 +34,10 @@ use std::ffi::{CString, OsStr}; #[cfg(not(target_os = "redox"))] use std::os::unix::ffi::OsStrExt; use std::os::unix::ffi::OsStringExt; +use std::os::unix::io::AsFd; +use std::os::unix::io::IntoRawFd; use std::os::unix::io::RawFd; +use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd}; use std::path::PathBuf; use std::{fmt, mem, ptr}; @@ -252,19 +255,30 @@ impl ForkResult { /// return value of this function. As an example: /// /// ``` -/// use nix::{sys::wait::waitpid,unistd::{fork, ForkResult, write}}; -/// -/// match unsafe{fork()} { -/// Ok(ForkResult::Parent { child, .. }) => { -/// println!("Continuing execution in parent process, new child has pid: {}", child); -/// waitpid(child, None).unwrap(); -/// } -/// Ok(ForkResult::Child) => { -/// // Unsafe to use `println!` (or `unwrap`) here. See Safety. -/// write(libc::STDOUT_FILENO, "I'm a new child process\n".as_bytes()).ok(); -/// unsafe { libc::_exit(0) }; -/// } -/// Err(_) => println!("Fork failed"), +/// use nix::{ +/// sys::wait::waitpid, +/// unistd::{fork, write, ForkResult}, +/// }; +/// use std::os::unix::io::BorrowedFd; +/// +/// match unsafe { fork() } { +/// Ok(ForkResult::Parent { child, .. }) => { +/// println!( +/// "Continuing execution in parent process, new child has pid: {}", +/// child +/// ); +/// waitpid(child, None).unwrap(); +/// } +/// Ok(ForkResult::Child) => { +/// // Unsafe to use `println!` (or `unwrap`) here. See Safety. +/// write( +/// unsafe { &BorrowedFd::borrow_raw(libc::STDOUT_FILENO) }, +/// "I'm a new child process\n".as_bytes(), +/// ) +/// .ok(); +/// unsafe { libc::_exit(0) }; +/// } +/// Err(_) => println!("Fork failed"), /// } /// ``` /// @@ -425,10 +439,10 @@ feature! { /// /// The two file descriptors do not share file descriptor flags (e.g. `OFlag::FD_CLOEXEC`). #[inline] -pub fn dup(oldfd: RawFd) -> Result { - let res = unsafe { libc::dup(oldfd) }; +pub fn dup(oldfd: &Fd) -> Result { + let res = unsafe { libc::dup(oldfd.as_fd().as_raw_fd()) }; - Errno::result(res) + Errno::result(res).map(|fd| unsafe { OwnedFd::from_raw_fd(fd) }) } /// Create a copy of the specified file descriptor using the specified fd (see @@ -438,10 +452,11 @@ pub fn dup(oldfd: RawFd) -> Result { /// specified fd instead of allocating a new one. See the man pages for more /// detail on the exact behavior of this function. #[inline] -pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result { - let res = unsafe { libc::dup2(oldfd, newfd) }; +pub fn dup2(oldfd: &Fd, newfd: &mut OwnedFd) -> Result<()> { + let res = + unsafe { libc::dup2(oldfd.as_fd().as_raw_fd(), newfd.as_raw_fd()) }; - Errno::result(res) + Errno::result(res).map(drop) } /// Create a new copy of the specified file descriptor using the specified fd @@ -449,26 +464,31 @@ pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result { /// /// This function behaves similar to `dup2()` but allows for flags to be /// specified. -pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { +pub fn dup3( + oldfd: &Fd, + newfd: &mut OwnedFd, + flags: OFlag, +) -> Result<()> { dup3_polyfill(oldfd, newfd, flags) } #[inline] -fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { - if oldfd == newfd { +fn dup3_polyfill( + oldfd: &Fd, + newfd: &mut OwnedFd, + flags: OFlag, +) -> Result<()> { + if oldfd.as_fd().as_raw_fd() == newfd.as_raw_fd() { return Err(Errno::EINVAL); } - let fd = dup2(oldfd, newfd)?; + dup2(oldfd, newfd)?; if flags.contains(OFlag::O_CLOEXEC) { - if let Err(e) = fcntl(fd, F_SETFD(FdFlag::FD_CLOEXEC)) { - let _ = close(fd); - return Err(e); - } + fcntl(newfd.as_raw_fd(), F_SETFD(FdFlag::FD_CLOEXEC))?; } - Ok(fd) + Ok(()) } /// Change the current working directory of the calling process (see @@ -478,9 +498,8 @@ fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { /// pages for additional details on possible failure cases. #[inline] pub fn chdir(path: &P) -> Result<()> { - let res = path.with_nix_path(|cstr| { - unsafe { libc::chdir(cstr.as_ptr()) } - })?; + let res = + path.with_nix_path(|cstr| unsafe { libc::chdir(cstr.as_ptr()) })?; Errno::result(res).map(drop) } @@ -493,8 +512,8 @@ pub fn chdir(path: &P) -> Result<()> { /// pages for additional details on possible failure cases. #[inline] #[cfg(not(target_os = "fuchsia"))] -pub fn fchdir(dirfd: RawFd) -> Result<()> { - let res = unsafe { libc::fchdir(dirfd) }; +pub fn fchdir(dirfd: &Fd) -> Result<()> { + let res = unsafe { libc::fchdir(dirfd.as_fd().as_raw_fd()) }; Errno::result(res).map(drop) } @@ -527,8 +546,8 @@ pub fn fchdir(dirfd: RawFd) -> Result<()> { /// ``` #[inline] pub fn mkdir(path: &P, mode: Mode) -> Result<()> { - let res = path.with_nix_path(|cstr| { - unsafe { libc::mkdir(cstr.as_ptr(), mode.bits() as mode_t) } + let res = path.with_nix_path(|cstr| unsafe { + libc::mkdir(cstr.as_ptr(), mode.bits() as mode_t) })?; Errno::result(res).map(drop) @@ -566,8 +585,8 @@ pub fn mkdir(path: &P, mode: Mode) -> Result<()> { #[inline] #[cfg(not(target_os = "redox"))] // RedoxFS does not support fifo yet pub fn mkfifo(path: &P, mode: Mode) -> Result<()> { - let res = path.with_nix_path(|cstr| { - unsafe { libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t) } + let res = path.with_nix_path(|cstr| unsafe { + libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t) })?; Errno::result(res).map(drop) @@ -591,9 +610,17 @@ pub fn mkfifo(path: &P, mode: Mode) -> Result<()> { target_os = "android", target_os = "redox" )))] -pub fn mkfifoat(dirfd: Option, path: &P, mode: Mode) -> Result<()> { +pub fn mkfifoat( + dirfd: &Fd, + path: &P, + mode: Mode, +) -> Result<()> { let res = path.with_nix_path(|cstr| unsafe { - libc::mkfifoat(at_rawfd(dirfd), cstr.as_ptr(), mode.bits() as mode_t) + libc::mkfifoat( + dirfd.as_fd().as_raw_fd(), + cstr.as_ptr(), + mode.bits() as mode_t, + ) })?; Errno::result(res).map(drop) @@ -609,22 +636,20 @@ pub fn mkfifoat(dirfd: Option, path: &P, mode: Mode) /// /// See also [symlinkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html). #[cfg(not(target_os = "redox"))] -pub fn symlinkat( +pub fn symlinkat( path1: &P1, - dirfd: Option, - path2: &P2) -> Result<()> { - let res = - path1.with_nix_path(|path1| { - path2.with_nix_path(|path2| { - unsafe { - libc::symlinkat( - path1.as_ptr(), - dirfd.unwrap_or(libc::AT_FDCWD), - path2.as_ptr() - ) - } - }) - })??; + dirfd: &Fd, + path2: &P2, +) -> Result<()> { + let res = path1.with_nix_path(|path1| { + path2.with_nix_path(|path2| unsafe { + libc::symlinkat( + path1.as_ptr(), + dirfd.as_fd().as_raw_fd(), + path2.as_ptr(), + ) + }) + })??; Errno::result(res).map(drop) } } @@ -744,9 +769,13 @@ pub fn chown( /// provided for that argument. Ownership change will be attempted for the path /// only if `Some` owner/group is provided. #[inline] -pub fn fchown(fd: RawFd, owner: Option, group: Option) -> Result<()> { +pub fn fchown( + fd: &Fd, + owner: Option, + group: Option, +) -> Result<()> { let (uid, gid) = chown_raw_ids(owner, group); - let res = unsafe { libc::fchown(fd, uid, gid) }; + let res = unsafe { libc::fchown(fd.as_fd().as_raw_fd(), uid, gid) }; Errno::result(res).map(drop) } @@ -779,8 +808,8 @@ pub enum FchownatFlags { /// /// [fchownat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html). #[cfg(not(target_os = "redox"))] -pub fn fchownat( - dirfd: Option, +pub fn fchownat( + dirfd: &Fd, path: &P, owner: Option, group: Option, @@ -792,8 +821,13 @@ pub fn fchownat( }; let res = path.with_nix_path(|cstr| unsafe { let (uid, gid) = chown_raw_ids(owner, group); - libc::fchownat(at_rawfd(dirfd), cstr.as_ptr(), uid, gid, - atflag.bits() as libc::c_int) + libc::fchownat( + dirfd.as_fd().as_raw_fd(), + cstr.as_ptr(), + uid, + gid, + atflag.bits() as c_int, + ) })?; Errno::result(res).map(drop) @@ -912,13 +946,15 @@ pub fn execvpe, SE: AsRef>( target_os = "freebsd" ))] #[inline] -pub fn fexecve ,SE: AsRef>(fd: RawFd, args: &[SA], env: &[SE]) -> Result { +pub fn fexecve, SE: AsRef>( + fd: &Fd, + args: &[SA], + env: &[SE], +) -> Result { let args_p = to_exec_array(args); let env_p = to_exec_array(env); - unsafe { - libc::fexecve(fd, args_p.as_ptr(), env_p.as_ptr()) - }; + unsafe { libc::fexecve(fd.as_fd().as_raw_fd(), args_p.as_ptr(), env_p.as_ptr()) }; Err(Errno::last()) } @@ -935,14 +971,25 @@ pub fn fexecve ,SE: AsRef>(fd: RawFd, args: &[SA], env: &[ /// is referenced as a file descriptor to the base directory plus a path. #[cfg(any(target_os = "android", target_os = "linux"))] #[inline] -pub fn execveat,SE: AsRef>(dirfd: RawFd, pathname: &CStr, args: &[SA], - env: &[SE], flags: super::fcntl::AtFlags) -> Result { +pub fn execveat, SE: AsRef>( + dirfd: &Fd, + pathname: &CStr, + args: &[SA], + env: &[SE], + flags: super::fcntl::AtFlags, +) -> Result { let args_p = to_exec_array(args); let env_p = to_exec_array(env); unsafe { - libc::syscall(libc::SYS_execveat, dirfd, pathname.as_ptr(), - args_p.as_ptr(), env_p.as_ptr(), flags); + libc::syscall( + libc::SYS_execveat, + dirfd.as_fd().as_raw_fd(), + pathname.as_ptr(), + args_p.as_ptr(), + env_p.as_ptr(), + flags, + ); }; Err(Errno::last()) @@ -1063,32 +1110,28 @@ pub fn gethostname() -> Result { /// /// # Examples /// -/// ```no_run -/// use std::os::unix::io::AsRawFd; -/// use nix::unistd::close; -/// -/// let f = tempfile::tempfile().unwrap(); -/// close(f.as_raw_fd()).unwrap(); // Bad! f will also close on drop! -/// ``` -/// /// ```rust -/// use std::os::unix::io::IntoRawFd; +/// use std::os::unix::io::AsFd; /// use nix::unistd::close; /// /// let f = tempfile::tempfile().unwrap(); -/// close(f.into_raw_fd()).unwrap(); // Good. into_raw_fd consumes f +/// close(f).unwrap(); /// ``` -pub fn close(fd: RawFd) -> Result<()> { - let res = unsafe { libc::close(fd) }; +pub fn close(fd: Fd) -> Result<()> { + let res = unsafe { libc::close(fd.into_raw_fd()) }; Errno::result(res).map(drop) } /// Read from a raw file descriptor. /// /// See also [read(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html) -pub fn read(fd: RawFd, buf: &mut [u8]) -> Result { +pub fn read(fd: &Fd, buf: &mut [u8]) -> Result { let res = unsafe { - libc::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) + libc::read( + fd.as_fd().as_raw_fd(), + buf.as_mut_ptr() as *mut c_void, + buf.len() as size_t, + ) }; Errno::result(res).map(|r| r as usize) @@ -1097,9 +1140,13 @@ pub fn read(fd: RawFd, buf: &mut [u8]) -> Result { /// Write to a raw file descriptor. /// /// See also [write(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html) -pub fn write(fd: RawFd, buf: &[u8]) -> Result { +pub fn write(fd: &Fd, buf: &[u8]) -> Result { let res = unsafe { - libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) + libc::write( + fd.as_fd().as_raw_fd(), + buf.as_ptr() as *const c_void, + buf.len() as size_t, + ) }; Errno::result(res).map(|r| r as usize) @@ -1150,15 +1197,21 @@ pub enum Whence { /// Move the read/write file offset. /// /// See also [lseek(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html) -pub fn lseek(fd: RawFd, offset: off_t, whence: Whence) -> Result { - let res = unsafe { libc::lseek(fd, offset, whence as i32) }; +pub fn lseek(fd: &Fd, offset: off_t, whence: Whence) -> Result { + let res = + unsafe { libc::lseek(fd.as_fd().as_raw_fd(), offset, whence as i32) }; Errno::result(res).map(|r| r as off_t) } #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result { - let res = unsafe { libc::lseek64(fd, offset, whence as i32) }; +pub fn lseek64( + fd: &Fd, + offset: libc::off64_t, + whence: Whence, +) -> Result { + let res = + unsafe { libc::lseek64(fd.as_fd().as_raw_fd(), offset, whence as i32) }; Errno::result(res).map(|r| r as libc::off64_t) } @@ -1167,14 +1220,18 @@ pub fn lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result std::result::Result<(RawFd, RawFd), Error> { +pub fn pipe() -> std::result::Result<(OwnedFd, OwnedFd), Error> { let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); let res = unsafe { libc::pipe(fds.as_mut_ptr() as *mut c_int) }; Error::result(res)?; - unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) } + unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) }.map( + |fds| unsafe { + (OwnedFd::from_raw_fd(fds.0), OwnedFd::from_raw_fd(fds.1)) + }, + ) } feature! { @@ -1208,16 +1265,19 @@ feature! { target_os = "openbsd", target_os = "solaris" ))] -pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> { +pub fn pipe2(flags: OFlag) -> Result<(OwnedFd, OwnedFd)> { let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); - let res = unsafe { - libc::pipe2(fds.as_mut_ptr() as *mut c_int, flags.bits()) - }; + let res = + unsafe { libc::pipe2(fds.as_mut_ptr() as *mut c_int, flags.bits()) }; Errno::result(res)?; - unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) } + unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) }.map( + |fds| unsafe { + (OwnedFd::from_raw_fd(fds.0), OwnedFd::from_raw_fd(fds.1)) + }, + ) } /// Truncate a file to a specified length @@ -1236,15 +1296,16 @@ pub fn truncate(path: &P, len: off_t) -> Result<()> { /// /// See also /// [ftruncate(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html) -pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> { - Errno::result(unsafe { libc::ftruncate(fd, len) }).map(drop) +pub fn ftruncate(fd: &Fd, len: off_t) -> Result<()> { + Errno::result(unsafe { libc::ftruncate(fd.as_fd().as_raw_fd(), len) }) + .map(drop) } -pub fn isatty(fd: RawFd) -> Result { +pub fn isatty(fd: &Fd) -> Result { unsafe { // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so // we return `Ok(false)` - if libc::isatty(fd) == 1 { + if libc::isatty(fd.as_fd().as_raw_fd()) == 1 { Ok(true) } else { match Errno::last() { @@ -1276,34 +1337,29 @@ pub enum LinkatFlags { /// # References /// See also [linkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html) #[cfg(not(target_os = "redox"))] // RedoxFS does not support symlinks yet -pub fn linkat( - olddirfd: Option, - oldpath: &P, - newdirfd: Option, - newpath: &P, +pub fn linkat( + olddirfd: &Fd1, + oldpath: &P1, + newdirfd: &Fd2, + newpath: &P2, flag: LinkatFlags, ) -> Result<()> { + let atflag = match flag { + LinkatFlags::SymlinkFollow => AtFlags::AT_SYMLINK_FOLLOW, + LinkatFlags::NoSymlinkFollow => AtFlags::empty(), + }; - let atflag = - match flag { - LinkatFlags::SymlinkFollow => AtFlags::AT_SYMLINK_FOLLOW, - LinkatFlags::NoSymlinkFollow => AtFlags::empty(), - }; - - let res = - oldpath.with_nix_path(|oldcstr| { - newpath.with_nix_path(|newcstr| { - unsafe { - libc::linkat( - at_rawfd(olddirfd), - oldcstr.as_ptr(), - at_rawfd(newdirfd), - newcstr.as_ptr(), - atflag.bits() as libc::c_int - ) - } - }) - })??; + let res = oldpath.with_nix_path(|oldcstr| { + newpath.with_nix_path(|newcstr| unsafe { + libc::linkat( + olddirfd.as_fd().as_raw_fd(), + oldcstr.as_ptr(), + newdirfd.as_fd().as_raw_fd(), + newcstr.as_ptr(), + atflag.bits() as c_int, + ) + }) + })??; Errno::result(res).map(drop) } @@ -1334,20 +1390,21 @@ pub enum UnlinkatFlags { /// # References /// See also [unlinkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html) #[cfg(not(target_os = "redox"))] -pub fn unlinkat( - dirfd: Option, +pub fn unlinkat( + dirfd: &Fd, path: &P, flag: UnlinkatFlags, ) -> Result<()> { - let atflag = - match flag { - UnlinkatFlags::RemoveDir => AtFlags::AT_REMOVEDIR, - UnlinkatFlags::NoRemoveDir => AtFlags::empty(), - }; - let res = path.with_nix_path(|cstr| { - unsafe { - libc::unlinkat(at_rawfd(dirfd), cstr.as_ptr(), atflag.bits() as libc::c_int) - } + let atflag = match flag { + UnlinkatFlags::RemoveDir => AtFlags::AT_REMOVEDIR, + UnlinkatFlags::NoRemoveDir => AtFlags::empty(), + }; + let res = path.with_nix_path(|cstr| unsafe { + libc::unlinkat( + dirfd.as_fd().as_raw_fd(), + cstr.as_ptr(), + atflag.bits() as c_int, + ) })?; Errno::result(res).map(drop) } @@ -1380,8 +1437,8 @@ pub fn sync() { /// /// See also [syncfs(2)](https://man7.org/linux/man-pages/man2/sync.2.html) #[cfg(target_os = "linux")] -pub fn syncfs(fd: RawFd) -> Result<()> { - let res = unsafe { libc::syncfs(fd) }; +pub fn syncfs(fd: &Fd) -> Result<()> { + let res = unsafe { libc::syncfs(fd.as_fd().as_raw_fd()) }; Errno::result(res).map(drop) } @@ -1390,8 +1447,8 @@ pub fn syncfs(fd: RawFd) -> Result<()> { /// /// See also [fsync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html) #[inline] -pub fn fsync(fd: RawFd) -> Result<()> { - let res = unsafe { libc::fsync(fd) }; +pub fn fsync(fd: &Fd) -> Result<()> { + let res = unsafe { libc::fsync(fd.as_fd().as_raw_fd()) }; Errno::result(res).map(drop) } @@ -1412,8 +1469,8 @@ pub fn fsync(fd: RawFd) -> Result<()> { target_os = "solaris" ))] #[inline] -pub fn fdatasync(fd: RawFd) -> Result<()> { - let res = unsafe { libc::fdatasync(fd) }; +pub fn fdatasync(fd: &Fd) -> Result<()> { + let res = unsafe { libc::fdatasync(fd.as_fd().as_raw_fd()) }; Errno::result(res).map(drop) } @@ -2945,11 +3002,19 @@ pub fn access(path: &P, amode: AccessFlags) -> Result<()> { /// [faccessat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/faccessat.html) // redox: does not appear to support the *at family of syscalls. #[cfg(not(target_os = "redox"))] -pub fn faccessat(dirfd: Option, path: &P, mode: AccessFlags, flags: AtFlags) -> Result<()> { - let res = path.with_nix_path(|cstr| { - unsafe { - libc::faccessat(at_rawfd(dirfd), cstr.as_ptr(), mode.bits(), flags.bits()) - } +pub fn faccessat( + dirfd: &Fd, + path: &P, + mode: AccessFlags, + flags: AtFlags, +) -> Result<()> { + let res = path.with_nix_path(|cstr| unsafe { + libc::faccessat( + dirfd.as_fd().as_raw_fd(), + cstr.as_ptr(), + mode.bits(), + flags.bits(), + ) })?; Errno::result(res).map(drop) } diff --git a/test/sys/test_select.rs b/test/sys/test_select.rs index 40bda4d90a..a1fb19a0f6 100644 --- a/test/sys/test_select.rs +++ b/test/sys/test_select.rs @@ -2,18 +2,19 @@ use nix::sys::select::*; use nix::sys::signal::SigSet; use nix::sys::time::{TimeSpec, TimeValLike}; use nix::unistd::{pipe, write}; +use std::os::unix::io::AsRawFd; #[test] pub fn test_pselect() { let _mtx = crate::SIGNAL_MTX.lock(); let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); + write(&w1, b"hi!").unwrap(); let (r2, _w2) = pipe().unwrap(); let mut fd_set = FdSet::new(); - fd_set.insert(r1); - fd_set.insert(r2); + fd_set.insert(r1.as_raw_fd()); + fd_set.insert(r2.as_raw_fd()); let timeout = TimeSpec::seconds(10); let sigmask = SigSet::empty(); @@ -21,25 +22,25 @@ pub fn test_pselect() { 1, pselect(None, &mut fd_set, None, None, &timeout, &sigmask).unwrap() ); - assert!(fd_set.contains(r1)); - assert!(!fd_set.contains(r2)); + assert!(fd_set.contains(r1.as_raw_fd())); + assert!(!fd_set.contains(r2.as_raw_fd())); } #[test] pub fn test_pselect_nfds2() { let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); + write(&w1, b"hi!").unwrap(); let (r2, _w2) = pipe().unwrap(); let mut fd_set = FdSet::new(); - fd_set.insert(r1); - fd_set.insert(r2); + fd_set.insert(r1.as_raw_fd()); + fd_set.insert(r2.as_raw_fd()); let timeout = TimeSpec::seconds(10); assert_eq!( 1, pselect( - ::std::cmp::max(r1, r2) + 1, + ::std::cmp::max(r1.as_raw_fd(), r2.as_raw_fd()) + 1, &mut fd_set, None, None, @@ -48,8 +49,8 @@ pub fn test_pselect_nfds2() { ) .unwrap() ); - assert!(fd_set.contains(r1)); - assert!(!fd_set.contains(r2)); + assert!(fd_set.contains(r1.as_raw_fd())); + assert!(!fd_set.contains(r2.as_raw_fd())); } macro_rules! generate_fdset_bad_fd_tests { diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 2ab6c54f6e..03dc351cbb 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -5,6 +5,8 @@ use nix::sys::socket::{getsockname, AddressFamily, UnixAddr}; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use std::net::{SocketAddrV4, SocketAddrV6}; +use std::os::unix::io::AsRawFd; +use std::os::unix::io::BorrowedFd; use std::os::unix::io::RawFd; use std::path::Path; use std::slice; @@ -195,9 +197,9 @@ pub fn test_socketpair() { SockFlag::empty(), ) .unwrap(); - write(fd1, b"hello").unwrap(); + write(unsafe { &BorrowedFd::borrow_raw(fd1) }, b"hello").unwrap(); let mut buf = [0; 5]; - read(fd2, &mut buf).unwrap(); + read(unsafe { &BorrowedFd::borrow_raw(fd2) }, &mut buf).unwrap(); assert_eq!(&buf[..], b"hello"); } @@ -691,7 +693,7 @@ pub fn test_scm_rights() { { let iov = [IoSlice::new(b"hello")]; - let fds = [r]; + let fds = [r.as_raw_fd()]; let cmsg = ControlMessage::ScmRights(&fds); assert_eq!( sendmsg::<()>(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), @@ -732,12 +734,11 @@ pub fn test_scm_rights() { let received_r = received_r.expect("Did not receive passed fd"); // Ensure that the received file descriptor works - write(w, b"world").unwrap(); + write(&w, b"world").unwrap(); let mut buf = [0u8; 5]; - read(received_r, &mut buf).unwrap(); + read(unsafe { &BorrowedFd::borrow_raw(received_r) }, &mut buf).unwrap(); assert_eq!(&buf[..], b"world"); close(received_r).unwrap(); - close(w).unwrap(); } // Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross @@ -796,7 +797,11 @@ pub fn test_af_alg_cipher() { // allocate buffer for encrypted data let mut encrypted = vec![0u8; payload_len]; - let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt"); + let num_bytes = read( + unsafe { &BorrowedFd::borrow_raw(session_socket) }, + &mut encrypted, + ) + .expect("read encrypt"); assert_eq!(num_bytes, payload_len); let iov = IoSlice::new(&encrypted); @@ -812,7 +817,11 @@ pub fn test_af_alg_cipher() { // allocate buffer for decrypted data let mut decrypted = vec![0u8; payload_len]; - let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt"); + let num_bytes = read( + unsafe { &BorrowedFd::borrow_raw(session_socket) }, + &mut decrypted, + ) + .expect("read decrypt"); assert_eq!(num_bytes, payload_len); assert_eq!(decrypted, payload); @@ -893,7 +902,11 @@ pub fn test_af_alg_aead() { // allocate buffer for encrypted data let mut encrypted = vec![0u8; (assoc_size as usize) + payload_len + auth_size]; - let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt"); + let num_bytes = read( + unsafe { &BorrowedFd::borrow_raw(session_socket) }, + &mut encrypted, + ) + .expect("read encrypt"); assert_eq!(num_bytes, payload_len + auth_size + (assoc_size as usize)); close(session_socket).expect("close"); @@ -924,7 +937,11 @@ pub fn test_af_alg_aead() { // Do not block on read, as we may have fewer bytes than buffer size fcntl(session_socket, FcntlArg::F_SETFL(OFlag::O_NONBLOCK)) .expect("fcntl non_blocking"); - let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt"); + let num_bytes = read( + unsafe { &BorrowedFd::borrow_raw(session_socket) }, + &mut decrypted, + ) + .expect("read decrypt"); assert!(num_bytes >= payload_len + (assoc_size as usize)); assert_eq!( @@ -1344,7 +1361,7 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec) { gid: getgid().as_raw(), } .into(); - let fds = [r]; + let fds = [r.as_raw_fd()]; let cmsgs = [ ControlMessage::ScmCredentials(&cred), ControlMessage::ScmRights(&fds), @@ -1394,12 +1411,11 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec) { let received_r = received_r.expect("Did not receive passed fd"); // Ensure that the received file descriptor works - write(w, b"world").unwrap(); + write(&w, b"world").unwrap(); let mut buf = [0u8; 5]; - read(received_r, &mut buf).unwrap(); + read(unsafe { &BorrowedFd::borrow_raw(received_r) }, &mut buf).unwrap(); assert_eq!(&buf[..], b"world"); close(received_r).unwrap(); - close(w).unwrap(); } // Test creating and using named unix domain sockets @@ -1432,14 +1448,15 @@ pub fn test_named_unixdomain() { ) .expect("socket failed"); connect(s2, &sockaddr).expect("connect failed"); - write(s2, b"hello").expect("write failed"); + write(unsafe { &BorrowedFd::borrow_raw(s2) }, b"hello") + .expect("write failed"); close(s2).unwrap(); }); let s3 = accept(s1).expect("accept failed"); let mut buf = [0; 5]; - read(s3, &mut buf).unwrap(); + read(unsafe { &BorrowedFd::borrow_raw(s3) }, &mut buf).unwrap(); close(s3).unwrap(); close(s1).unwrap(); thr.join().unwrap(); diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs index 34bef945e1..2ef3d0708c 100644 --- a/test/sys/test_sockopt.rs +++ b/test/sys/test_sockopt.rs @@ -96,6 +96,7 @@ fn test_so_tcp_maxseg() { use nix::sys::socket::{accept, bind, connect, listen, SockaddrIn}; use nix::unistd::{close, write}; use std::net::SocketAddrV4; + use std::os::unix::io::BorrowedFd; use std::str::FromStr; let std_sa = SocketAddrV4::from_str("127.0.0.1:4001").unwrap(); @@ -134,7 +135,7 @@ fn test_so_tcp_maxseg() { .unwrap(); connect(ssock, &sock_addr).unwrap(); let rsess = accept(rsock).unwrap(); - write(rsess, b"hello").unwrap(); + write(unsafe { &BorrowedFd::borrow_raw(rsess) }, b"hello").unwrap(); let actual = getsockopt(ssock, sockopt::TcpMaxSeg).unwrap(); // Actual max segment size takes header lengths into account, max IPv4 options (60 bytes) + max // TCP options (40 bytes) are subtracted from the requested maximum as a lower boundary. diff --git a/test/sys/test_stat.rs b/test/sys/test_stat.rs index 426b4b6588..19c1f69da0 100644 --- a/test/sys/test_stat.rs +++ b/test/sys/test_stat.rs @@ -7,13 +7,12 @@ fn test_chflags() { sys::stat::{fstat, FileFlag}, unistd::chflags, }; - use std::os::unix::io::AsRawFd; use tempfile::NamedTempFile; let f = NamedTempFile::new().unwrap(); let initial = FileFlag::from_bits_truncate( - fstat(f.as_raw_fd()).unwrap().st_flags.into(), + fstat(f.as_file()).unwrap().st_flags.into(), ); // UF_OFFLINE is preserved by all FreeBSD file systems, but not interpreted // in any way, so it's handy for testing. @@ -22,7 +21,7 @@ fn test_chflags() { chflags(f.path(), commanded).unwrap(); let changed = FileFlag::from_bits_truncate( - fstat(f.as_raw_fd()).unwrap().st_flags.into(), + fstat(f.as_file()).unwrap().st_flags.into(), ); assert_eq!(commanded, changed); diff --git a/test/sys/test_termios.rs b/test/sys/test_termios.rs index aaf00084fa..cf41071ae8 100644 --- a/test/sys/test_termios.rs +++ b/test/sys/test_termios.rs @@ -11,7 +11,8 @@ use nix::unistd::{close, read, write}; fn write_all(f: RawFd, buf: &[u8]) { let mut len = 0; while len < buf.len() { - len += write(f, &buf[len..]).unwrap(); + len += + write(unsafe { &BorrowedFd::borrow_raw(f) }, &buf[len..]).unwrap(); } } @@ -129,7 +130,8 @@ fn test_local_flags() { // Try to read from the master, which should not have anything as echoing was disabled. let mut buf = [0u8; 10]; - let read = read(pty.master, &mut buf).unwrap_err(); + let read = read(unsafe { &BorrowedFd::borrow_raw(pty.master) }, &mut buf) + .unwrap_err(); close(pty.master).unwrap(); close(pty.slave).unwrap(); assert_eq!(read, Errno::EAGAIN); diff --git a/test/sys/test_uio.rs b/test/sys/test_uio.rs index 0f4b8a6568..5aad6fa982 100644 --- a/test/sys/test_uio.rs +++ b/test/sys/test_uio.rs @@ -45,18 +45,16 @@ fn test_writev() { // FileDesc will close its filedesc (reader). let mut read_buf: Vec = iter::repeat(0u8).take(128 * 16).collect(); // Blocking io, should write all data. - let write_res = writev(writer, &iovecs); + let write_res = writev(writer.as_raw_fd(), &iovecs); let written = write_res.expect("couldn't write"); // Check whether we written all data assert_eq!(to_write.len(), written); - let read_res = read(reader, &mut read_buf[..]); + let read_res = read(&reader, &mut read_buf[..]); let read = read_res.expect("couldn't read"); // Check we have read as much as we written assert_eq!(read, written); // Check equality of written and read data assert_eq!(&to_write, &read_buf); - close(writer).expect("closed writer"); - close(reader).expect("closed reader"); } #[test] @@ -87,8 +85,8 @@ fn test_readv() { } let (reader, writer) = pipe().expect("couldn't create pipe"); // Blocking io, should write all data. - write(writer, &to_write).expect("write failed"); - let read = readv(reader, &mut iovecs[..]).expect("read failed"); + write(&writer, &to_write).expect("write failed"); + let read = readv(reader.as_raw_fd(), &mut iovecs[..]).expect("read failed"); // Check whether we've read all data assert_eq!(to_write.len(), read); // Cccumulate data from iovecs @@ -100,8 +98,6 @@ fn test_readv() { assert_eq!(read_buf.len(), to_write.len()); // Check equality of written and read data assert_eq!(&read_buf, &to_write); - close(reader).expect("couldn't close reader"); - close(writer).expect("couldn't close writer"); } #[test] @@ -236,8 +232,8 @@ fn test_process_vm_readv() { Parent { child } => { close(w).unwrap(); // wait for child - read(r, &mut [0u8]).unwrap(); - close(r).unwrap(); + read(&r, &mut [0u8]).unwrap(); + drop(r); let ptr = vector.as_ptr() as usize; let remote_iov = RemoteIoVec { base: ptr, len: 5 }; @@ -260,8 +256,8 @@ fn test_process_vm_readv() { for i in &mut vector { *i += 1; } - let _ = write(w, b"\0"); - let _ = close(w); + let _ = write(&w, b"\0"); + drop(w); loop { pause(); } diff --git a/test/test.rs b/test/test.rs index 6b42aad950..27934afd82 100644 --- a/test/test.rs +++ b/test/test.rs @@ -66,6 +66,7 @@ mod test_unistd; use nix::unistd::{chdir, getcwd, read}; use parking_lot::{Mutex, RwLock, RwLockWriteGuard}; +use std::os::unix::io::BorrowedFd; use std::os::unix::io::RawFd; use std::path::PathBuf; @@ -75,7 +76,7 @@ fn read_exact(f: RawFd, buf: &mut [u8]) { while len < buf.len() { // get_mut would be better than split_at_mut, but it requires nightly let (_, remaining) = buf.split_at_mut(len); - len += read(f, remaining).unwrap(); + len += read(unsafe { &BorrowedFd::borrow_raw(f) }, remaining).unwrap(); } } diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs index fb2a5e2ea0..354c50ec35 100644 --- a/test/test_fcntl.rs +++ b/test/test_fcntl.rs @@ -18,7 +18,7 @@ use nix::fcntl::{renameat2, RenameFlags}; #[cfg(not(target_os = "redox"))] use nix::sys::stat::Mode; #[cfg(not(target_os = "redox"))] -use nix::unistd::{close, read}; +use nix::unistd::read; #[cfg(not(target_os = "redox"))] use std::fs::File; #[cfg(not(target_os = "redox"))] @@ -42,7 +42,7 @@ fn test_openat() { open(tmp.path().parent().unwrap(), OFlag::empty(), Mode::empty()) .unwrap(); let fd = openat( - dirfd, + &dirfd, tmp.path().file_name().unwrap(), OFlag::O_RDONLY, Mode::empty(), @@ -50,11 +50,8 @@ fn test_openat() { .unwrap(); let mut buf = [0u8; 1024]; - assert_eq!(4, read(fd, &mut buf).unwrap()); + assert_eq!(4, read(&fd, &mut buf).unwrap()); assert_eq!(CONTENTS, &buf[0..4]); - - close(fd).unwrap(); - close(dirfd).unwrap(); } #[test] @@ -68,13 +65,11 @@ fn test_renameat() { let new_dir = tempfile::tempdir().unwrap(); let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); - renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap(); + renameat(&old_dirfd, "old", &new_dirfd, "new").unwrap(); assert_eq!( - renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap_err(), + renameat(&old_dirfd, "old", &new_dirfd, "new").unwrap_err(), Errno::ENOENT ); - close(old_dirfd).unwrap(); - close(new_dirfd).unwrap(); assert!(new_dir.path().join("new").exists()); } @@ -98,27 +93,13 @@ fn test_renameat2_behaves_like_renameat_with_no_flags() { let new_dir = tempfile::tempdir().unwrap(); let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); - renameat2( - Some(old_dirfd), - "old", - Some(new_dirfd), - "new", - RenameFlags::empty(), - ) - .unwrap(); + renameat2(&old_dirfd, "old", &new_dirfd, "new", RenameFlags::empty()) + .unwrap(); assert_eq!( - renameat2( - Some(old_dirfd), - "old", - Some(new_dirfd), - "new", - RenameFlags::empty() - ) - .unwrap_err(), + renameat2(&old_dirfd, "old", &new_dirfd, "new", RenameFlags::empty()) + .unwrap_err(), Errno::ENOENT ); - close(old_dirfd).unwrap(); - close(new_dirfd).unwrap(); assert!(new_dir.path().join("new").exists()); } @@ -151,9 +132,9 @@ fn test_renameat2_exchange() { new_f.write_all(b"new").unwrap(); } renameat2( - Some(old_dirfd), + &old_dirfd, "old", - Some(new_dirfd), + &new_dirfd, "new", RenameFlags::RENAME_EXCHANGE, ) @@ -166,8 +147,6 @@ fn test_renameat2_exchange() { let mut old_f = File::open(&old_path).unwrap(); old_f.read_to_string(&mut buf).unwrap(); assert_eq!(buf, "new"); - close(old_dirfd).unwrap(); - close(new_dirfd).unwrap(); } #[test] @@ -194,17 +173,15 @@ fn test_renameat2_noreplace() { File::create(new_path).unwrap(); assert_eq!( renameat2( - Some(old_dirfd), + &old_dirfd, "old", - Some(new_dirfd), + &new_dirfd, "new", RenameFlags::RENAME_NOREPLACE ) .unwrap_err(), Errno::EEXIST ); - close(old_dirfd).unwrap(); - close(new_dirfd).unwrap(); assert!(new_dir.path().join("new").exists()); assert!(old_dir.path().join("old").exists()); } @@ -222,7 +199,7 @@ fn test_readlink() { assert_eq!(readlink(&dst).unwrap().to_str().unwrap(), expected_dir); assert_eq!( - readlinkat(dirfd, "b").unwrap().to_str().unwrap(), + readlinkat(&dirfd, "b").unwrap().to_str().unwrap(), expected_dir ); } @@ -232,10 +209,9 @@ mod linux_android { use libc::loff_t; use std::io::prelude::*; use std::io::IoSlice; - use std::os::unix::prelude::*; use nix::fcntl::*; - use nix::unistd::{close, pipe, read, write}; + use nix::unistd::{pipe, read, write}; use tempfile::tempfile; #[cfg(any(target_os = "linux"))] @@ -262,14 +238,7 @@ mod linux_android { tmp1.flush().unwrap(); let mut from_offset: i64 = 3; - copy_file_range( - tmp1.as_raw_fd(), - Some(&mut from_offset), - tmp2.as_raw_fd(), - None, - 3, - ) - .unwrap(); + copy_file_range(&tmp1, Some(&mut from_offset), &tmp2, None, 3).unwrap(); let mut res: String = String::new(); tmp2.rewind().unwrap(); @@ -288,9 +257,9 @@ mod linux_android { let (rd, wr) = pipe().unwrap(); let mut offset: loff_t = 5; let res = splice( - tmp.as_raw_fd(), + &tmp, Some(&mut offset), - wr, + &wr, None, 2, SpliceFFlags::empty(), @@ -300,12 +269,9 @@ mod linux_android { assert_eq!(2, res); let mut buf = [0u8; 1024]; - assert_eq!(2, read(rd, &mut buf).unwrap()); + assert_eq!(2, read(&rd, &mut buf).unwrap()); assert_eq!(b"f1", &buf[0..2]); assert_eq!(7, offset); - - close(rd).unwrap(); - close(wr).unwrap(); } #[test] @@ -313,25 +279,20 @@ mod linux_android { let (rd1, wr1) = pipe().unwrap(); let (rd2, wr2) = pipe().unwrap(); - write(wr1, b"abc").unwrap(); - let res = tee(rd1, wr2, 2, SpliceFFlags::empty()).unwrap(); + write(&wr1, b"abc").unwrap(); + let res = tee(&rd1, &wr2, 2, SpliceFFlags::empty()).unwrap(); assert_eq!(2, res); let mut buf = [0u8; 1024]; // Check the tee'd bytes are at rd2. - assert_eq!(2, read(rd2, &mut buf).unwrap()); + assert_eq!(2, read(&rd2, &mut buf).unwrap()); assert_eq!(b"ab", &buf[0..2]); // Check all the bytes are still at rd1. - assert_eq!(3, read(rd1, &mut buf).unwrap()); + assert_eq!(3, read(&rd1, &mut buf).unwrap()); assert_eq!(b"abc", &buf[0..3]); - - close(rd1).unwrap(); - close(wr1).unwrap(); - close(rd2).unwrap(); - close(wr2).unwrap(); } #[test] @@ -342,17 +303,14 @@ mod linux_android { let buf2 = b"defghi"; let iovecs = vec![IoSlice::new(&buf1[0..3]), IoSlice::new(&buf2[0..3])]; - let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap(); + let res = vmsplice(&wr, &iovecs[..], SpliceFFlags::empty()).unwrap(); assert_eq!(6, res); // Check the bytes can be read at rd. let mut buf = [0u8; 32]; - assert_eq!(6, read(rd, &mut buf).unwrap()); + assert_eq!(6, read(&rd, &mut buf).unwrap()); assert_eq!(b"abcdef", &buf[0..6]); - - close(rd).unwrap(); - close(wr).unwrap(); } #[cfg(any(target_os = "linux"))] @@ -360,12 +318,11 @@ mod linux_android { fn test_fallocate() { let tmp = NamedTempFile::new().unwrap(); - let fd = tmp.as_raw_fd(); - fallocate(fd, FallocateFlags::empty(), 0, 100).unwrap(); + fallocate(tmp.as_file(), FallocateFlags::empty(), 0, 100).unwrap(); // Check if we read exactly 100 bytes let mut buf = [0u8; 200]; - assert_eq!(100, read(fd, &mut buf).unwrap()); + assert_eq!(100, read(tmp.as_file(), &mut buf).unwrap()); } // The tests below are disabled for the listed targets @@ -379,10 +336,10 @@ mod linux_android { fn test_ofd_write_lock() { use nix::sys::stat::fstat; use std::mem; + use std::os::unix::prelude::*; let tmp = NamedTempFile::new().unwrap(); - let fd = tmp.as_raw_fd(); let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap(); if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC { // OverlayFS is a union file system. It returns one inode value in @@ -390,7 +347,7 @@ mod linux_android { // skip the test. skip!("/proc/locks does not work on overlayfs"); } - let inode = fstat(fd).expect("fstat failed").st_ino as usize; + let inode = fstat(tmp.as_file()).expect("fstat failed").st_ino as usize; let mut flock: libc::flock = unsafe { mem::zeroed() // required for Linux/mips @@ -400,14 +357,16 @@ mod linux_android { flock.l_start = 0; flock.l_len = 0; flock.l_pid = 0; - fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write lock failed"); + fcntl(tmp.as_raw_fd(), F_OFD_SETLKW(&flock)) + .expect("write lock failed"); assert_eq!( Some(("OFDLCK".to_string(), "WRITE".to_string())), lock_info(inode) ); flock.l_type = libc::F_UNLCK as libc::c_short; - fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write unlock failed"); + fcntl(tmp.as_raw_fd(), F_OFD_SETLKW(&flock)) + .expect("write unlock failed"); assert_eq!(None, lock_info(inode)); } @@ -417,10 +376,10 @@ mod linux_android { fn test_ofd_read_lock() { use nix::sys::stat::fstat; use std::mem; + use std::os::unix::prelude::*; let tmp = NamedTempFile::new().unwrap(); - let fd = tmp.as_raw_fd(); let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap(); if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC { // OverlayFS is a union file system. It returns one inode value in @@ -428,7 +387,7 @@ mod linux_android { // skip the test. skip!("/proc/locks does not work on overlayfs"); } - let inode = fstat(fd).expect("fstat failed").st_ino as usize; + let inode = fstat(tmp.as_file()).expect("fstat failed").st_ino as usize; let mut flock: libc::flock = unsafe { mem::zeroed() // required for Linux/mips @@ -438,14 +397,15 @@ mod linux_android { flock.l_start = 0; flock.l_len = 0; flock.l_pid = 0; - fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read lock failed"); + fcntl(tmp.as_raw_fd(), F_OFD_SETLKW(&flock)).expect("read lock failed"); assert_eq!( Some(("OFDLCK".to_string(), "READ".to_string())), lock_info(inode) ); flock.l_type = libc::F_UNLCK as libc::c_short; - fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read unlock failed"); + fcntl(tmp.as_raw_fd(), F_OFD_SETLKW(&flock)) + .expect("read unlock failed"); assert_eq!(None, lock_info(inode)); } @@ -481,30 +441,28 @@ mod linux_android { target_os = "freebsd" ))] mod test_posix_fadvise { - use nix::errno::Errno; use nix::fcntl::*; use nix::unistd::pipe; - use std::os::unix::io::{AsRawFd, RawFd}; use tempfile::NamedTempFile; #[test] fn test_success() { let tmp = NamedTempFile::new().unwrap(); - let fd = tmp.as_raw_fd(); - posix_fadvise(fd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED) - .expect("posix_fadvise failed"); + posix_fadvise( + tmp.as_file(), + 0, + 100, + PosixFadviseAdvice::POSIX_FADV_WILLNEED, + ) + .expect("posix_fadvise failed"); } #[test] fn test_errno() { let (rd, _wr) = pipe().unwrap(); - let res = posix_fadvise( - rd as RawFd, - 0, - 100, - PosixFadviseAdvice::POSIX_FADV_WILLNEED, - ); + let res = + posix_fadvise(&rd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED); assert_eq!(res, Err(Errno::ESPIPE)); } } @@ -523,18 +481,14 @@ mod test_posix_fallocate { use nix::errno::Errno; use nix::fcntl::*; use nix::unistd::pipe; - use std::{ - io::Read, - os::unix::io::{AsRawFd, RawFd}, - }; + use std::io::Read; use tempfile::NamedTempFile; #[test] fn success() { const LEN: usize = 100; let mut tmp = NamedTempFile::new().unwrap(); - let fd = tmp.as_raw_fd(); - let res = posix_fallocate(fd, 0, LEN as libc::off_t); + let res = posix_fallocate(tmp.as_file(), 0, LEN as libc::off_t); match res { Ok(_) => { let mut data = [1u8; LEN]; @@ -556,7 +510,7 @@ mod test_posix_fallocate { #[test] fn errno() { let (rd, _wr) = pipe().unwrap(); - let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err(); + let err = posix_fallocate(&rd, 0, 100).unwrap_err(); match err { Errno::EINVAL | Errno::ENODEV | Errno::ESPIPE | Errno::EBADF => (), errno => panic!("unexpected errno {errno}",), diff --git a/test/test_poll.rs b/test/test_poll.rs index 53964e26bb..67586eccd4 100644 --- a/test/test_poll.rs +++ b/test/test_poll.rs @@ -3,6 +3,7 @@ use nix::{ poll::{poll, PollFd, PollFlags}, unistd::{pipe, write}, }; +use std::os::unix::io::AsRawFd; macro_rules! loop_while_eintr { ($poll_expr: expr) => { @@ -19,14 +20,14 @@ macro_rules! loop_while_eintr { #[test] fn test_poll() { let (r, w) = pipe().unwrap(); - let mut fds = [PollFd::new(r, PollFlags::POLLIN)]; + let mut fds = [PollFd::new(r.as_raw_fd(), PollFlags::POLLIN)]; // Poll an idle pipe. Should timeout let nfds = loop_while_eintr!(poll(&mut fds, 100)); assert_eq!(nfds, 0); assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN)); - write(w, b".").unwrap(); + write(&w, b".").unwrap(); // Poll a readable pipe. Should return an event. let nfds = poll(&mut fds, 100).unwrap(); @@ -51,7 +52,7 @@ fn test_ppoll() { let timeout = TimeSpec::milliseconds(1); let (r, w) = pipe().unwrap(); - let mut fds = [PollFd::new(r, PollFlags::POLLIN)]; + let mut fds = [PollFd::new(r.as_raw_fd(), PollFlags::POLLIN)]; // Poll an idle pipe. Should timeout let sigset = SigSet::empty(); @@ -59,7 +60,7 @@ fn test_ppoll() { assert_eq!(nfds, 0); assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN)); - write(w, b".").unwrap(); + write(&w, b".").unwrap(); // Poll a readable pipe. Should return an event. let nfds = ppoll(&mut fds, Some(timeout), None).unwrap(); diff --git a/test/test_pty.rs b/test/test_pty.rs index 5c27e2d632..1d24f35b03 100644 --- a/test/test_pty.rs +++ b/test/test_pty.rs @@ -125,22 +125,23 @@ fn open_ptty_pair() -> (PtyMaster, File) { // after opening a device path returned from ptsname(). let ptem = b"ptem\0"; let ldterm = b"ldterm\0"; - let r = unsafe { ioctl(slave_fd, I_FIND, ldterm.as_ptr()) }; + let r = unsafe { ioctl(slave_fd.as_raw_fd(), I_FIND, ldterm.as_ptr()) }; if r < 0 { panic!("I_FIND failure"); } else if r == 0 { - if unsafe { ioctl(slave_fd, I_PUSH, ptem.as_ptr()) } < 0 { + if unsafe { ioctl(slave_fd.as_raw_fd(), I_PUSH, ptem.as_ptr()) } < 0 + { panic!("I_PUSH ptem failure"); } - if unsafe { ioctl(slave_fd, I_PUSH, ldterm.as_ptr()) } < 0 { + if unsafe { ioctl(slave_fd.as_raw_fd(), I_PUSH, ldterm.as_ptr()) } + < 0 + { panic!("I_PUSH ldterm failure"); } } } - let slave = unsafe { File::from_raw_fd(slave_fd) }; - - (master, slave) + (master, File::from(slave_fd)) } /// Test opening a master/slave PTTY pair @@ -208,7 +209,11 @@ fn test_openpty() { // Writing to one should be readable on the other one let string = "foofoofoo\n"; let mut buf = [0u8; 10]; - write(pty.master, string.as_bytes()).unwrap(); + write( + unsafe { &BorrowedFd::borrow_raw(pty.master) }, + string.as_bytes(), + ) + .unwrap(); crate::read_exact(pty.slave, &mut buf); assert_eq!(&buf, string.as_bytes()); @@ -222,7 +227,11 @@ fn test_openpty() { let string2 = "barbarbarbar\n"; let echoed_string2 = "barbarbarbar\r\n"; let mut buf = [0u8; 14]; - write(pty.slave, string2.as_bytes()).unwrap(); + write( + unsafe { &BorrowedFd::borrow_raw(pty.slave) }, + string2.as_bytes(), + ) + .unwrap(); crate::read_exact(pty.master, &mut buf); assert_eq!(&buf, echoed_string2.as_bytes()); @@ -257,7 +266,11 @@ fn test_openpty_with_termios() { // Writing to one should be readable on the other one let string = "foofoofoo\n"; let mut buf = [0u8; 10]; - write(pty.master, string.as_bytes()).unwrap(); + write( + unsafe { &BorrowedFd::borrow_raw(pty.master) }, + string.as_bytes(), + ) + .unwrap(); crate::read_exact(pty.slave, &mut buf); assert_eq!(&buf, string.as_bytes()); @@ -270,7 +283,11 @@ fn test_openpty_with_termios() { let string2 = "barbarbarbar\n"; let echoed_string2 = "barbarbarbar\n"; let mut buf = [0u8; 13]; - write(pty.slave, string2.as_bytes()).unwrap(); + write( + unsafe { &BorrowedFd::borrow_raw(pty.slave) }, + string2.as_bytes(), + ) + .unwrap(); crate::read_exact(pty.master, &mut buf); assert_eq!(&buf, echoed_string2.as_bytes()); @@ -294,7 +311,11 @@ fn test_forkpty() { let pty = unsafe { forkpty(None, None).unwrap() }; match pty.fork_result { Child => { - write(STDOUT_FILENO, string.as_bytes()).unwrap(); + write( + unsafe { &BorrowedFd::borrow_raw(STDOUT_FILENO) }, + string.as_bytes(), + ) + .unwrap(); pause(); // we need the child to stay alive until the parent calls read unsafe { _exit(0); diff --git a/test/test_sendfile.rs b/test/test_sendfile.rs index f73a3b56c3..4b931111f9 100644 --- a/test/test_sendfile.rs +++ b/test/test_sendfile.rs @@ -7,7 +7,7 @@ use tempfile::tempfile; cfg_if! { if #[cfg(any(target_os = "android", target_os = "linux"))] { - use nix::unistd::{close, pipe, read}; + use nix::unistd::{pipe, read}; } else if #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos"))] { use std::net::Shutdown; use std::os::unix::net::UnixStream; @@ -23,17 +23,15 @@ fn test_sendfile_linux() { let (rd, wr) = pipe().unwrap(); let mut offset: off_t = 5; - let res = sendfile(wr, tmp.as_raw_fd(), Some(&mut offset), 2).unwrap(); + let res = sendfile(wr.as_raw_fd(), tmp.as_raw_fd(), Some(&mut offset), 2) + .unwrap(); assert_eq!(2, res); let mut buf = [0u8; 1024]; - assert_eq!(2, read(rd, &mut buf).unwrap()); + assert_eq!(2, read(&rd, &mut buf).unwrap()); assert_eq!(b"f1", &buf[0..2]); assert_eq!(7, offset); - - close(rd).unwrap(); - close(wr).unwrap(); } #[cfg(target_os = "linux")] @@ -45,17 +43,15 @@ fn test_sendfile64_linux() { let (rd, wr) = pipe().unwrap(); let mut offset: libc::off64_t = 5; - let res = sendfile64(wr, tmp.as_raw_fd(), Some(&mut offset), 2).unwrap(); + let res = sendfile64(wr.as_raw_fd(), tmp.as_raw_fd(), Some(&mut offset), 2) + .unwrap(); assert_eq!(2, res); let mut buf = [0u8; 1024]; - assert_eq!(2, read(rd, &mut buf).unwrap()); + assert_eq!(2, read(&rd, &mut buf).unwrap()); assert_eq!(b"f1", &buf[0..2]); assert_eq!(7, offset); - - close(rd).unwrap(); - close(wr).unwrap(); } #[cfg(target_os = "freebsd")] diff --git a/test/test_stat.rs b/test/test_stat.rs index 55f15c0771..c30778f98f 100644 --- a/test/test_stat.rs +++ b/test/test_stat.rs @@ -5,7 +5,6 @@ use std::fs::File; use std::os::unix::fs::symlink; #[cfg(not(any(target_os = "redox", target_os = "haiku")))] use std::os::unix::fs::PermissionsExt; -use std::os::unix::prelude::AsRawFd; #[cfg(not(target_os = "redox"))] use std::path::Path; #[cfg(not(any(target_os = "redox", target_os = "haiku")))] @@ -14,6 +13,8 @@ use std::time::{Duration, UNIX_EPOCH}; use libc::mode_t; #[cfg(not(any(target_os = "netbsd", target_os = "redox")))] use libc::{S_IFLNK, S_IFMT}; +#[cfg(not(target_os = "redox"))] +use nix::AT_FDCWD; #[cfg(not(target_os = "redox"))] use nix::errno::Errno; @@ -103,7 +104,7 @@ fn test_stat_and_fstat() { let stat_result = stat(&filename); assert_stat_results(stat_result); - let fstat_result = fstat(file.as_raw_fd()); + let fstat_result = fstat(&file); assert_stat_results(fstat_result); } @@ -114,10 +115,10 @@ fn test_fstatat() { let filename = tempdir.path().join("foo.txt"); File::create(&filename).unwrap(); let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()); + fcntl::open(tempdir.path(), fcntl::OFlag::empty(), Mode::empty()) + .unwrap(); - let result = - stat::fstatat(dirfd.unwrap(), &filename, fcntl::AtFlags::empty()); + let result = stat::fstatat(&dirfd, &filename, fcntl::AtFlags::empty()); assert_stat_results(result); } @@ -142,7 +143,7 @@ fn test_stat_fstat_lstat() { let lstat_result = lstat(&linkname); assert_lstat_results(lstat_result); - let fstat_result = fstat(link.as_raw_fd()); + let fstat_result = fstat(&link); assert_stat_results(fstat_result); } @@ -155,14 +156,14 @@ fn test_fchmod() { let mut mode1 = Mode::empty(); mode1.insert(Mode::S_IRUSR); mode1.insert(Mode::S_IWUSR); - fchmod(file.as_raw_fd(), mode1).unwrap(); + fchmod(&file, mode1).unwrap(); let file_stat1 = stat(&filename).unwrap(); assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits()); let mut mode2 = Mode::empty(); mode2.insert(Mode::S_IROTH); - fchmod(file.as_raw_fd(), mode2).unwrap(); + fchmod(&file, mode2).unwrap(); let file_stat2 = stat(&filename).unwrap(); assert_eq!(file_stat2.st_mode as mode_t & 0o7777, mode2.bits()); @@ -178,14 +179,13 @@ fn test_fchmodat() { File::create(&fullpath).unwrap(); let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) + fcntl::open(tempdir.path(), fcntl::OFlag::empty(), Mode::empty()) .unwrap(); let mut mode1 = Mode::empty(); mode1.insert(Mode::S_IRUSR); mode1.insert(Mode::S_IWUSR); - fchmodat(Some(dirfd), filename, mode1, FchmodatFlags::FollowSymlink) - .unwrap(); + fchmodat(&dirfd, filename, mode1, FchmodatFlags::FollowSymlink).unwrap(); let file_stat1 = stat(&fullpath).unwrap(); assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits()); @@ -194,7 +194,7 @@ fn test_fchmodat() { let mut mode2 = Mode::empty(); mode2.insert(Mode::S_IROTH); - fchmodat(None, filename, mode2, FchmodatFlags::FollowSymlink).unwrap(); + fchmodat(AT_FDCWD, filename, mode2, FchmodatFlags::FollowSymlink).unwrap(); let file_stat2 = stat(&fullpath).unwrap(); assert_eq!(file_stat2.st_mode as mode_t & 0o7777, mode2.bits()); @@ -272,10 +272,10 @@ fn test_futimens() { let fullpath = tempdir.path().join("file"); drop(File::create(&fullpath).unwrap()); - let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); + let fd = + fcntl::open(&fullpath, fcntl::OFlag::empty(), Mode::empty()).unwrap(); - futimens(fd, &TimeSpec::seconds(10), &TimeSpec::seconds(20)).unwrap(); + futimens(&fd, &TimeSpec::seconds(10), &TimeSpec::seconds(20)).unwrap(); assert_times_eq(10, 20, &fs::metadata(&fullpath).unwrap()); } @@ -289,11 +289,11 @@ fn test_utimensat() { drop(File::create(&fullpath).unwrap()); let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) + fcntl::open(tempdir.path(), fcntl::OFlag::empty(), Mode::empty()) .unwrap(); utimensat( - Some(dirfd), + &dirfd, filename, &TimeSpec::seconds(12345), &TimeSpec::seconds(678), @@ -305,7 +305,7 @@ fn test_utimensat() { chdir(tempdir.path()).unwrap(); utimensat( - None, + AT_FDCWD, filename, &TimeSpec::seconds(500), &TimeSpec::seconds(800), @@ -321,23 +321,22 @@ fn test_mkdirat_success_path() { let tempdir = tempfile::tempdir().unwrap(); let filename = "example_subdir"; let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) + fcntl::open(tempdir.path(), fcntl::OFlag::empty(), Mode::empty()) .unwrap(); - mkdirat(dirfd, filename, Mode::S_IRWXU).expect("mkdirat failed"); + mkdirat(&dirfd, filename, Mode::S_IRWXU).expect("mkdirat failed"); assert!(Path::exists(&tempdir.path().join(filename))); } #[test] #[cfg(not(any(target_os = "redox", target_os = "haiku")))] fn test_mkdirat_success_mode() { - let expected_bits = - stat::SFlag::S_IFDIR.bits() | stat::Mode::S_IRWXU.bits(); + let expected_bits = stat::SFlag::S_IFDIR.bits() | Mode::S_IRWXU.bits(); let tempdir = tempfile::tempdir().unwrap(); let filename = "example_subdir"; let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) + fcntl::open(tempdir.path(), fcntl::OFlag::empty(), Mode::empty()) .unwrap(); - mkdirat(dirfd, filename, Mode::S_IRWXU).expect("mkdirat failed"); + mkdirat(&dirfd, filename, Mode::S_IRWXU).expect("mkdirat failed"); let permissions = fs::metadata(tempdir.path().join(filename)) .unwrap() .permissions(); @@ -354,10 +353,10 @@ fn test_mkdirat_fail() { let dirfd = fcntl::open( &tempdir.path().join(not_dir_filename), fcntl::OFlag::O_CREAT, - stat::Mode::empty(), + Mode::empty(), ) .unwrap(); - let result = mkdirat(dirfd, filename, Mode::S_IRWXU).unwrap_err(); + let result = mkdirat(&dirfd, filename, Mode::S_IRWXU).unwrap_err(); assert_eq!(result, Errno::ENOTDIR); } @@ -396,13 +395,15 @@ fn test_mknodat() { use fcntl::{AtFlags, OFlag}; use nix::dir::Dir; use stat::{fstatat, mknodat, SFlag}; + use std::os::unix::io::AsRawFd; + use std::os::unix::io::BorrowedFd; let file_name = "test_file"; let tempdir = tempfile::tempdir().unwrap(); let target_dir = Dir::open(tempdir.path(), OFlag::O_DIRECTORY, Mode::S_IRWXU).unwrap(); mknodat( - target_dir.as_raw_fd(), + unsafe { &BorrowedFd::borrow_raw(target_dir.as_raw_fd()) }, file_name, SFlag::S_IFREG, Mode::S_IRWXU, @@ -410,7 +411,7 @@ fn test_mknodat() { ) .unwrap(); let mode = fstatat( - target_dir.as_raw_fd(), + unsafe { &BorrowedFd::borrow_raw(target_dir.as_raw_fd()) }, file_name, AtFlags::AT_SYMLINK_NOFOLLOW, ) diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 6619262e93..006824bceb 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -1,10 +1,10 @@ use libc::{_exit, mode_t, off_t}; use nix::errno::Errno; +#[cfg(not(target_os = "redox"))] +use nix::fcntl::open; #[cfg(not(any(target_os = "redox", target_os = "haiku")))] use nix::fcntl::readlink; use nix::fcntl::OFlag; -#[cfg(not(target_os = "redox"))] -use nix::fcntl::{self, open}; #[cfg(not(any( target_os = "redox", target_os = "fuchsia", @@ -19,6 +19,8 @@ use nix::sys::stat::{self, Mode, SFlag}; use nix::sys::wait::*; use nix::unistd::ForkResult::*; use nix::unistd::*; +#[cfg(not(target_os = "redox"))] +use nix::AT_FDCWD; use std::env; #[cfg(not(any(target_os = "fuchsia", target_os = "redox")))] use std::ffi::CString; @@ -47,7 +49,7 @@ fn test_fork_and_waitpid() { Child => unsafe { _exit(0) }, Parent { child } => { // assert that child was created and pid > 0 - let child_raw: ::libc::pid_t = child.into(); + let child_raw: libc::pid_t = child.into(); assert!(child_raw > 0); let wait_status = waitpid(child, None); match wait_status { @@ -113,7 +115,7 @@ fn test_mkfifo() { mkfifo(&mkfifo_fifo, Mode::S_IRUSR).unwrap(); let stats = stat::stat(&mkfifo_fifo).unwrap(); - let typ = stat::SFlag::from_bits_truncate(stats.st_mode as mode_t); + let typ = SFlag::from_bits_truncate(stats.st_mode as mode_t); assert_eq!(typ, SFlag::S_IFIFO); } @@ -138,10 +140,10 @@ fn test_mkfifoat_none() { let tempdir = tempdir().unwrap(); let mkfifoat_fifo = tempdir.path().join("mkfifoat_fifo"); - mkfifoat(None, &mkfifoat_fifo, Mode::S_IRUSR).unwrap(); + mkfifoat(AT_FDCWD, &mkfifoat_fifo, Mode::S_IRUSR).unwrap(); let stats = stat::stat(&mkfifoat_fifo).unwrap(); - let typ = stat::SFlag::from_bits_truncate(stats.st_mode); + let typ = SFlag::from_bits_truncate(stats.st_mode); assert_eq!(typ, SFlag::S_IFIFO); } @@ -154,17 +156,16 @@ fn test_mkfifoat_none() { target_os = "haiku" )))] fn test_mkfifoat() { - use nix::fcntl; + use nix::fcntl::AtFlags; let tempdir = tempdir().unwrap(); let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); let mkfifoat_name = "mkfifoat_name"; - mkfifoat(Some(dirfd), mkfifoat_name, Mode::S_IRUSR).unwrap(); + mkfifoat(&dirfd, mkfifoat_name, Mode::S_IRUSR).unwrap(); - let stats = - stat::fstatat(dirfd, mkfifoat_name, fcntl::AtFlags::empty()).unwrap(); - let typ = stat::SFlag::from_bits_truncate(stats.st_mode); + let stats = stat::fstatat(&dirfd, mkfifoat_name, AtFlags::empty()).unwrap(); + let typ = SFlag::from_bits_truncate(stats.st_mode); assert_eq!(typ, SFlag::S_IFIFO); } @@ -180,7 +181,7 @@ fn test_mkfifoat_directory_none() { let _m = crate::CWD_LOCK.read(); // mkfifoat should fail if a directory is given - mkfifoat(None, &env::temp_dir(), Mode::S_IRUSR) + mkfifoat(AT_FDCWD, &env::temp_dir(), Mode::S_IRUSR) .expect_err("assertion failed"); } @@ -197,16 +198,16 @@ fn test_mkfifoat_directory() { let tempdir = tempdir().unwrap(); let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); let mkfifoat_dir = "mkfifoat_dir"; - stat::mkdirat(dirfd, mkfifoat_dir, Mode::S_IRUSR).unwrap(); + stat::mkdirat(&dirfd, mkfifoat_dir, Mode::S_IRUSR).unwrap(); - mkfifoat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR) + mkfifoat(&dirfd, mkfifoat_dir, Mode::S_IRUSR) .expect_err("assertion failed"); } #[test] fn test_getpid() { - let pid: ::libc::pid_t = getpid().into(); - let ppid: ::libc::pid_t = getppid().into(); + let pid: libc::pid_t = getpid().into(); + let ppid: libc::pid_t = getppid().into(); assert!(pid > 0); assert!(ppid > 0); } @@ -214,8 +215,8 @@ fn test_getpid() { #[test] #[cfg(not(target_os = "redox"))] fn test_getsid() { - let none_sid: ::libc::pid_t = getsid(None).unwrap().into(); - let pid_sid: ::libc::pid_t = getsid(Some(getpid())).unwrap().into(); + let none_sid: libc::pid_t = getsid(None).unwrap().into(); + let pid_sid: libc::pid_t = getsid(Some(getpid())).unwrap().into(); assert!(none_sid > 0); assert_eq!(none_sid, pid_sid); } @@ -226,7 +227,7 @@ mod linux_android { #[test] fn test_gettid() { - let tid: ::libc::pid_t = gettid().into(); + let tid: libc::pid_t = gettid().into(); assert!(tid > 0); } } @@ -315,8 +316,9 @@ macro_rules! execve_test_factory ( const BAZ: &'static [u8] = b"baz=quux\0"; fn syscall_cstr_ref() -> Result { + let exe = $exe; $syscall( - $exe, + &exe, $(CString::new($pathname).unwrap().as_c_str(), )* &[CStr::from_bytes_with_nul(EMPTY).unwrap(), CStr::from_bytes_with_nul(DASH_C).unwrap(), @@ -327,8 +329,9 @@ macro_rules! execve_test_factory ( } fn syscall_cstring() -> Result { + let exe = $exe; $syscall( - $exe, + &exe, $(CString::new($pathname).unwrap().as_c_str(), )* &[CString::from(CStr::from_bytes_with_nul(EMPTY).unwrap()), CString::from(CStr::from_bytes_with_nul(DASH_C).unwrap()), @@ -356,7 +359,8 @@ macro_rules! execve_test_factory ( match unsafe{fork()}.unwrap() { Child => { // Make `writer` be the stdout of the new process. - dup2(writer, 1).unwrap(); + let mut stdout = std::mem::ManuallyDrop::new(unsafe { OwnedFd::from_raw_fd(libc::STDOUT_FILENO) }); + dup2(&writer, &mut stdout).unwrap(); let r = syscall(); let _ = std::io::stderr() .write_all(format!("{:?}", r).as_bytes()); @@ -370,7 +374,7 @@ macro_rules! execve_test_factory ( assert_eq!(ws, Ok(WaitStatus::Exited(child, 0))); // Read 1024 bytes. let mut buf = [0u8; 1024]; - read(reader, &mut buf).unwrap(); + read(&reader, &mut buf).unwrap(); // It should contain the things we printed using `/bin/sh`. let string = String::from_utf8_lossy(&buf); assert!(string.contains("nix!!!")); @@ -402,48 +406,48 @@ macro_rules! execve_test_factory ( cfg_if! { if #[cfg(target_os = "android")] { - execve_test_factory!(test_execve, execve, CString::new("/system/bin/sh").unwrap().as_c_str()); - execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd()); + execve_test_factory!(test_execve, execve, CString::new("/system/bin/sh").unwrap()); + execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap()); } else if #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] { // These tests frequently fail on musl, probably due to // https://github.com/nix-rust/nix/issues/555 - execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str()); - execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd()); + execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap()); + execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap()); } else if #[cfg(any(target_os = "illumos", target_os = "ios", target_os = "macos", target_os = "netbsd", target_os = "openbsd", target_os = "solaris"))] { - execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str()); + execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap()); // No fexecve() on ios, macos, NetBSD, OpenBSD. } } #[cfg(any(target_os = "haiku", target_os = "linux", target_os = "openbsd"))] -execve_test_factory!(test_execvpe, execvpe, &CString::new("sh").unwrap()); +execve_test_factory!(test_execvpe, execvpe, CString::new("sh").unwrap()); cfg_if! { if #[cfg(target_os = "android")] { use nix::fcntl::AtFlags; execve_test_factory!(test_execveat_empty, execveat, - File::open("/system/bin/sh").unwrap().into_raw_fd(), + File::open("/system/bin/sh").unwrap(), "", AtFlags::AT_EMPTY_PATH); execve_test_factory!(test_execveat_relative, execveat, - File::open("/system/bin/").unwrap().into_raw_fd(), + File::open("/system/bin/").unwrap(), "./sh", AtFlags::empty()); execve_test_factory!(test_execveat_absolute, execveat, - File::open("/").unwrap().into_raw_fd(), + File::open("/").unwrap(), "/system/bin/sh", AtFlags::empty()); } else if #[cfg(all(target_os = "linux", any(target_arch ="x86_64", target_arch ="x86")))] { use nix::fcntl::AtFlags; - execve_test_factory!(test_execveat_empty, execveat, File::open("/bin/sh").unwrap().into_raw_fd(), + execve_test_factory!(test_execveat_empty, execveat, File::open("/bin/sh").unwrap(), "", AtFlags::AT_EMPTY_PATH); - execve_test_factory!(test_execveat_relative, execveat, File::open("/bin/").unwrap().into_raw_fd(), + execve_test_factory!(test_execveat_relative, execveat, File::open("/bin/").unwrap(), "./sh", AtFlags::empty()); - execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(), + execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap(), "/bin/sh", AtFlags::empty()); } } @@ -452,22 +456,20 @@ cfg_if! { #[cfg(not(target_os = "fuchsia"))] fn test_fchdir() { // fchdir changes the process's cwd - let _dr = crate::DirRestore::new(); + let _dr = DirRestore::new(); let tmpdir = tempdir().unwrap(); let tmpdir_path = tmpdir.path().canonicalize().unwrap(); - let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd(); + let tmpdir_fd = File::open(&tmpdir_path).unwrap(); - fchdir(tmpdir_fd).expect("assertion failed"); + fchdir(&tmpdir_fd).expect("assertion failed"); assert_eq!(getcwd().unwrap(), tmpdir_path); - - close(tmpdir_fd).expect("assertion failed"); } #[test] fn test_getcwd() { // chdir changes the process's cwd - let _dr = crate::DirRestore::new(); + let _dr = DirRestore::new(); let tmpdir = tempdir().unwrap(); let tmpdir_path = tmpdir.path().canonicalize().unwrap(); @@ -516,18 +518,18 @@ fn test_fchown() { let gid = Some(getgid()); let path = tempfile().unwrap(); - let fd = path.as_raw_fd(); - fchown(fd, uid, gid).unwrap(); - fchown(fd, uid, None).unwrap(); - fchown(fd, None, gid).unwrap(); - fchown(999999999, uid, gid).unwrap_err(); + fchown(&path, uid, gid).unwrap(); + fchown(&path, uid, None).unwrap(); + fchown(&path, None, gid).unwrap(); + fchown(unsafe { &BorrowedFd::borrow_raw(999999999) }, uid, gid) + .unwrap_err(); } #[test] #[cfg(not(target_os = "redox"))] fn test_fchownat() { - let _dr = crate::DirRestore::new(); + let _dr = DirRestore::new(); // Testing for anything other than our own UID/GID is hard. let uid = Some(getuid()); let gid = Some(getgid()); @@ -540,14 +542,14 @@ fn test_fchownat() { let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); - fchownat(Some(dirfd), "file", uid, gid, FchownatFlags::FollowSymlink) - .unwrap(); + fchownat(&dirfd, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap(); chdir(tempdir.path()).unwrap(); - fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap(); + fchownat(AT_FDCWD, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap(); fs::remove_file(&path).unwrap(); - fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap_err(); + fchownat(AT_FDCWD, "file", uid, gid, FchownatFlags::FollowSymlink) + .unwrap_err(); } #[test] @@ -555,16 +557,13 @@ fn test_lseek() { const CONTENTS: &[u8] = b"abcdef123456"; let mut tmp = tempfile().unwrap(); tmp.write_all(CONTENTS).unwrap(); - let tmpfd = tmp.into_raw_fd(); let offset: off_t = 5; - lseek(tmpfd, offset, Whence::SeekSet).unwrap(); + lseek(&tmp, offset, Whence::SeekSet).unwrap(); let mut buf = [0u8; 7]; - crate::read_exact(tmpfd, &mut buf); + read_exact(tmp.as_raw_fd(), &mut buf); assert_eq!(b"f123456", &buf); - - close(tmpfd).unwrap(); } #[cfg(any(target_os = "linux", target_os = "android"))] @@ -573,15 +572,12 @@ fn test_lseek64() { const CONTENTS: &[u8] = b"abcdef123456"; let mut tmp = tempfile().unwrap(); tmp.write_all(CONTENTS).unwrap(); - let tmpfd = tmp.into_raw_fd(); - lseek64(tmpfd, 5, Whence::SeekSet).unwrap(); + lseek64(&tmp, 5, Whence::SeekSet).unwrap(); let mut buf = [0u8; 7]; - crate::read_exact(tmpfd, &mut buf); + read_exact(tmp.as_raw_fd(), &mut buf); assert_eq!(b"f123456", &buf); - - close(tmpfd).unwrap(); } cfg_if! { @@ -719,14 +715,12 @@ fn test_getresgid() { #[test] fn test_pipe() { let (fd0, fd1) = pipe().unwrap(); - let m0 = stat::SFlag::from_bits_truncate( - stat::fstat(fd0).unwrap().st_mode as mode_t, - ); + let m0 = + SFlag::from_bits_truncate(stat::fstat(&fd0).unwrap().st_mode as mode_t); // S_IFIFO means it's a pipe assert_eq!(m0, SFlag::S_IFIFO); - let m1 = stat::SFlag::from_bits_truncate( - stat::fstat(fd1).unwrap().st_mode as mode_t, - ); + let m1 = + SFlag::from_bits_truncate(stat::fstat(&fd1).unwrap().st_mode as mode_t); assert_eq!(m1, SFlag::S_IFIFO); } @@ -749,9 +743,13 @@ fn test_pipe2() { use nix::fcntl::{fcntl, FcntlArg, FdFlag}; let (fd0, fd1) = pipe2(OFlag::O_CLOEXEC).unwrap(); - let f0 = FdFlag::from_bits_truncate(fcntl(fd0, FcntlArg::F_GETFD).unwrap()); + let f0 = FdFlag::from_bits_truncate( + fcntl(fd0.as_raw_fd(), FcntlArg::F_GETFD).unwrap(), + ); assert!(f0.contains(FdFlag::FD_CLOEXEC)); - let f1 = FdFlag::from_bits_truncate(fcntl(fd1, FcntlArg::F_GETFD).unwrap()); + let f1 = FdFlag::from_bits_truncate( + fcntl(fd1.as_raw_fd(), FcntlArg::F_GETFD).unwrap(), + ); assert!(f1.contains(FdFlag::FD_CLOEXEC)); } @@ -778,15 +776,11 @@ fn test_ftruncate() { let tempdir = tempdir().unwrap(); let path = tempdir.path().join("file"); - let tmpfd = { - let mut tmp = File::create(&path).unwrap(); - const CONTENTS: &[u8] = b"12345678"; - tmp.write_all(CONTENTS).unwrap(); - tmp.into_raw_fd() - }; + let mut tmp = File::create(&path).unwrap(); + const CONTENTS: &[u8] = b"12345678"; + tmp.write_all(CONTENTS).unwrap(); - ftruncate(tmpfd, 2).unwrap(); - close(tmpfd).unwrap(); + ftruncate(&tmp, 2).unwrap(); let metadata = fs::metadata(&path).unwrap(); assert_eq!(2, metadata.len()); @@ -868,7 +862,7 @@ fn test_symlinkat() { let target = tempdir.path().join("a"); let linkpath = tempdir.path().join("b"); - symlinkat(&target, None, &linkpath).unwrap(); + symlinkat(&target, AT_FDCWD, &linkpath).unwrap(); assert_eq!( readlink(&linkpath).unwrap().to_str().unwrap(), target.to_str().unwrap() @@ -877,7 +871,7 @@ fn test_symlinkat() { let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); let target = "c"; let linkpath = "d"; - symlinkat(target, Some(dirfd), linkpath).unwrap(); + symlinkat(target, &dirfd, linkpath).unwrap(); assert_eq!( readlink(&tempdir.path().join(linkpath)) .unwrap() @@ -901,15 +895,13 @@ fn test_linkat_file() { File::create(oldfilepath).unwrap(); // Get file descriptor for base directory - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); + let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); // Attempt hard link file at relative path linkat( - Some(dirfd), + &dirfd, oldfilename, - Some(dirfd), + &dirfd, newfilename, LinkatFlags::SymlinkFollow, ) @@ -920,7 +912,7 @@ fn test_linkat_file() { #[test] #[cfg(not(any(target_os = "redox", target_os = "haiku")))] fn test_linkat_olddirfd_none() { - let _dr = crate::DirRestore::new(); + let _dr = DirRestore::new(); let tempdir_oldfile = tempdir().unwrap(); let oldfilename = "foo.txt"; @@ -934,19 +926,15 @@ fn test_linkat_olddirfd_none() { File::create(oldfilepath).unwrap(); // Get file descriptor for base directory of new file - let dirfd = fcntl::open( - tempdir_newfile.path(), - fcntl::OFlag::empty(), - stat::Mode::empty(), - ) - .unwrap(); + let dirfd = + open(tempdir_newfile.path(), OFlag::empty(), Mode::empty()).unwrap(); // Attempt hard link file using curent working directory as relative path for old file path chdir(tempdir_oldfile.path()).unwrap(); linkat( - None, + AT_FDCWD, oldfilename, - Some(dirfd), + &dirfd, newfilename, LinkatFlags::SymlinkFollow, ) @@ -957,7 +945,7 @@ fn test_linkat_olddirfd_none() { #[test] #[cfg(not(any(target_os = "redox", target_os = "haiku")))] fn test_linkat_newdirfd_none() { - let _dr = crate::DirRestore::new(); + let _dr = DirRestore::new(); let tempdir_oldfile = tempdir().unwrap(); let oldfilename = "foo.txt"; @@ -971,19 +959,15 @@ fn test_linkat_newdirfd_none() { File::create(oldfilepath).unwrap(); // Get file descriptor for base directory of old file - let dirfd = fcntl::open( - tempdir_oldfile.path(), - fcntl::OFlag::empty(), - stat::Mode::empty(), - ) - .unwrap(); + let dirfd = + open(tempdir_oldfile.path(), OFlag::empty(), Mode::empty()).unwrap(); // Attempt hard link file using current working directory as relative path for new file path chdir(tempdir_newfile.path()).unwrap(); linkat( - Some(dirfd), + &dirfd, oldfilename, - None, + AT_FDCWD, newfilename, LinkatFlags::SymlinkFollow, ) @@ -1015,18 +999,16 @@ fn test_linkat_no_follow_symlink() { File::create(&oldfilepath).unwrap(); // Create symlink to file - symlinkat(&oldfilepath, None, &symoldfilepath).unwrap(); + symlinkat(&oldfilepath, AT_FDCWD, &symoldfilepath).unwrap(); // Get file descriptor for base directory - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); + let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); // Attempt link symlink of file at relative path linkat( - Some(dirfd), + &dirfd, symoldfilename, - Some(dirfd), + &dirfd, newfilename, LinkatFlags::NoSymlinkFollow, ) @@ -1058,18 +1040,16 @@ fn test_linkat_follow_symlink() { File::create(&oldfilepath).unwrap(); // Create symlink to file - symlinkat(&oldfilepath, None, &symoldfilepath).unwrap(); + symlinkat(&oldfilepath, AT_FDCWD, &symoldfilepath).unwrap(); // Get file descriptor for base directory - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); + let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); // Attempt link target of symlink of file at relative path linkat( - Some(dirfd), + &dirfd, symoldfilename, - Some(dirfd), + &dirfd, newfilename, LinkatFlags::SymlinkFollow, ) @@ -1079,7 +1059,7 @@ fn test_linkat_follow_symlink() { // Check the file type of the new link assert_eq!( - (stat::SFlag::from_bits_truncate(newfilestat.st_mode as mode_t) + (SFlag::from_bits_truncate(newfilestat.st_mode as mode_t) & SFlag::S_IFMT), SFlag::S_IFREG ); @@ -1099,13 +1079,11 @@ fn test_unlinkat_dir_noremovedir() { DirBuilder::new().recursive(true).create(dirpath).unwrap(); // Get file descriptor for base directory - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); + let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); // Attempt unlink dir at relative path without proper flag let err_result = - unlinkat(Some(dirfd), dirname, UnlinkatFlags::NoRemoveDir).unwrap_err(); + unlinkat(&dirfd, dirname, UnlinkatFlags::NoRemoveDir).unwrap_err(); assert!(err_result == Errno::EISDIR || err_result == Errno::EPERM); } @@ -1120,12 +1098,10 @@ fn test_unlinkat_dir_removedir() { DirBuilder::new().recursive(true).create(&dirpath).unwrap(); // Get file descriptor for base directory - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); + let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); // Attempt unlink dir at relative path with proper flag - unlinkat(Some(dirfd), dirname, UnlinkatFlags::RemoveDir).unwrap(); + unlinkat(&dirfd, dirname, UnlinkatFlags::RemoveDir).unwrap(); assert!(!dirpath.exists()); } @@ -1140,12 +1116,10 @@ fn test_unlinkat_file() { File::create(&filepath).unwrap(); // Get file descriptor for base directory - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); + let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); // Attempt unlink file at relative path - unlinkat(Some(dirfd), filename, UnlinkatFlags::NoRemoveDir).unwrap(); + unlinkat(&dirfd, filename, UnlinkatFlags::NoRemoveDir).unwrap(); assert!(!filepath.exists()); } @@ -1208,7 +1182,7 @@ fn test_setfsuid() { // set filesystem UID let fuid = setfsuid(nobody.uid); // trying to open the temporary file should fail with EACCES - let res = fs::File::open(&temp_path); + let res = File::open(&temp_path); let err = res.expect_err("assertion failed"); assert_eq!(err.kind(), io::ErrorKind::PermissionDenied); @@ -1220,7 +1194,7 @@ fn test_setfsuid() { .unwrap(); // open the temporary file with the current thread filesystem UID - fs::File::open(temp_path_2).unwrap(); + File::open(temp_path_2).unwrap(); } #[test] @@ -1239,11 +1213,11 @@ fn test_ttyname() { grantpt(&fd).expect("grantpt failed"); unlockpt(&fd).expect("unlockpt failed"); let sname = unsafe { ptsname(&fd) }.expect("ptsname failed"); - let fds = open(Path::new(&sname), OFlag::O_RDWR, stat::Mode::empty()) + let fds = open(Path::new(&sname), OFlag::O_RDWR, Mode::empty()) .expect("open failed"); - assert!(fds > 0); + assert!(fds.as_raw_fd() > 0); - let name = ttyname(fds).expect("ttyname failed"); + let name = ttyname(fds.as_raw_fd()).expect("ttyname failed"); assert!(name.starts_with("/dev")); } @@ -1308,10 +1282,10 @@ fn test_getpeereid_invalid_fd() { #[cfg(not(target_os = "redox"))] fn test_faccessat_none_not_existing() { use nix::fcntl::AtFlags; - let tempdir = tempfile::tempdir().unwrap(); + let tempdir = tempdir().unwrap(); let dir = tempdir.path().join("does_not_exist.txt"); assert_eq!( - faccessat(None, &dir, AccessFlags::F_OK, AtFlags::empty()) + faccessat(AT_FDCWD, &dir, AccessFlags::F_OK, AtFlags::empty()) .err() .unwrap(), Errno::ENOENT @@ -1322,18 +1296,13 @@ fn test_faccessat_none_not_existing() { #[cfg(not(target_os = "redox"))] fn test_faccessat_not_existing() { use nix::fcntl::AtFlags; - let tempdir = tempfile::tempdir().unwrap(); + let tempdir = tempdir().unwrap(); let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); let not_exist_file = "does_not_exist.txt"; assert_eq!( - faccessat( - Some(dirfd), - not_exist_file, - AccessFlags::F_OK, - AtFlags::empty(), - ) - .err() - .unwrap(), + faccessat(&dirfd, not_exist_file, AccessFlags::F_OK, AtFlags::empty()) + .err() + .unwrap(), Errno::ENOENT ); } @@ -1342,11 +1311,11 @@ fn test_faccessat_not_existing() { #[cfg(not(target_os = "redox"))] fn test_faccessat_none_file_exists() { use nix::fcntl::AtFlags; - let tempdir = tempfile::tempdir().unwrap(); + let tempdir = tempdir().unwrap(); let path = tempdir.path().join("does_exist.txt"); let _file = File::create(path.clone()).unwrap(); assert!(faccessat( - None, + AT_FDCWD, &path, AccessFlags::R_OK | AccessFlags::W_OK, AtFlags::empty(), @@ -1358,13 +1327,13 @@ fn test_faccessat_none_file_exists() { #[cfg(not(target_os = "redox"))] fn test_faccessat_file_exists() { use nix::fcntl::AtFlags; - let tempdir = tempfile::tempdir().unwrap(); + let tempdir = tempdir().unwrap(); let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); let exist_file = "does_exist.txt"; let path = tempdir.path().join(exist_file); let _file = File::create(path.clone()).unwrap(); assert!(faccessat( - Some(dirfd), + &dirfd, &path, AccessFlags::R_OK | AccessFlags::W_OK, AtFlags::empty(),