From f544033a5219299765f4ed24b46f3c331022c2ac Mon Sep 17 00:00:00 2001 From: Jonathan Woollett-Light Date: Mon, 28 Aug 2023 15:23:51 +0100 Subject: [PATCH] feat: I/O safety `pipe`, `pipe2` & `write` --- src/pty.rs | 4 ++-- src/sys/epoll.rs | 4 ++-- src/sys/select.rs | 21 +++++--------------- src/sys/socket/mod.rs | 4 ++-- src/unistd.rs | 26 +++++++++++++++---------- test/sys/test_select.rs | 10 +++------- test/sys/test_socket.rs | 16 ++++++---------- test/sys/test_sockopt.rs | 6 +++--- test/sys/test_termios.rs | 2 +- test/sys/test_uio.rs | 24 +++++++---------------- test/test_fcntl.rs | 41 +++++++++++++++------------------------- test/test_poll.rs | 12 ++++-------- test/test_pty.rs | 14 +++++++------- test/test_sendfile.rs | 23 ++++------------------ test/test_unistd.rs | 16 ++++++++++------ 15 files changed, 87 insertions(+), 136 deletions(-) diff --git a/src/pty.rs b/src/pty.rs index 455828b703..28c1f4fc73 100644 --- a/src/pty.rs +++ b/src/pty.rs @@ -71,7 +71,7 @@ impl io::Read for PtyMaster { impl io::Write for PtyMaster { fn write(&mut self, buf: &[u8]) -> io::Result { - unistd::write(self.0.as_raw_fd(), buf).map_err(io::Error::from) + unistd::write(&self.0, buf).map_err(io::Error::from) } fn flush(&mut self) -> io::Result<()> { Ok(()) @@ -86,7 +86,7 @@ impl io::Read for &PtyMaster { impl io::Write for &PtyMaster { fn write(&mut self, buf: &[u8]) -> io::Result { - unistd::write(self.0.as_raw_fd(), buf).map_err(io::Error::from) + unistd::write(&self.0, buf).map_err(io::Error::from) } fn flush(&mut self) -> io::Result<()> { Ok(()) diff --git a/src/sys/epoll.rs b/src/sys/epoll.rs index 36f9c17d0e..acb08d0787 100644 --- a/src/sys/epoll.rs +++ b/src/sys/epoll.rs @@ -73,7 +73,7 @@ impl EpollEvent { /// ``` /// # use nix::sys::{epoll::{Epoll, EpollEvent, EpollFlags, EpollCreateFlags}, eventfd::{eventfd, EfdFlags}}; /// # use nix::unistd::write; -/// # use std::os::unix::io::{OwnedFd, FromRawFd, AsRawFd, AsFd}; +/// # use std::os::unix::io::{OwnedFd, FromRawFd, AsFd}; /// # use std::time::{Instant, Duration}; /// # fn main() -> nix::Result<()> { /// const DATA: u64 = 17; @@ -87,7 +87,7 @@ impl EpollEvent { /// epoll.add(&eventfd, EpollEvent::new(EpollFlags::EPOLLIN,DATA))?; /// /// // Arm eventfd & Time wait -/// write(eventfd.as_raw_fd(), &1u64.to_ne_bytes())?; +/// write(&eventfd, &1u64.to_ne_bytes())?; /// let now = Instant::now(); /// /// // Wait on event diff --git a/src/sys/select.rs b/src/sys/select.rs index 0e2193b130..4c5521be90 100644 --- a/src/sys/select.rs +++ b/src/sys/select.rs @@ -322,8 +322,8 @@ where mod tests { use super::*; use crate::sys::time::{TimeVal, TimeValLike}; - use crate::unistd::{close, pipe, write}; - use std::os::unix::io::{FromRawFd, OwnedFd, RawFd}; + use crate::unistd::{pipe, write}; + use std::os::unix::io::RawFd; #[test] fn fdset_insert() { @@ -466,12 +466,9 @@ mod tests { #[test] fn test_select() { let (r1, w1) = pipe().unwrap(); - let r1 = unsafe { OwnedFd::from_raw_fd(r1) }; - let w1 = unsafe { OwnedFd::from_raw_fd(w1) }; let (r2, _w2) = pipe().unwrap(); - let r2 = unsafe { OwnedFd::from_raw_fd(r2) }; - write(w1.as_raw_fd(), b"hi!").unwrap(); + write(&w1, b"hi!").unwrap(); let mut fd_set = FdSet::new(); fd_set.insert(&r1); fd_set.insert(&r2); @@ -483,18 +480,14 @@ mod tests { ); assert!(fd_set.contains(&r1)); assert!(!fd_set.contains(&r2)); - close(_w2).unwrap(); } #[test] fn test_select_nfds() { let (r1, w1) = pipe().unwrap(); let (r2, _w2) = pipe().unwrap(); - let r1 = unsafe { OwnedFd::from_raw_fd(r1) }; - let w1 = unsafe { OwnedFd::from_raw_fd(w1) }; - let r2 = unsafe { OwnedFd::from_raw_fd(r2) }; - write(w1.as_raw_fd(), b"hi!").unwrap(); + write(&w1, b"hi!").unwrap(); let mut fd_set = FdSet::new(); fd_set.insert(&r1); fd_set.insert(&r2); @@ -521,16 +514,13 @@ mod tests { } assert!(fd_set.contains(&r1)); assert!(!fd_set.contains(&r2)); - close(_w2).unwrap(); } #[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 r1 = unsafe { OwnedFd::from_raw_fd(r1) }; - let r2 = unsafe { OwnedFd::from_raw_fd(r2) }; let mut fd_set = FdSet::new(); fd_set.insert(&r1); fd_set.insert(&r2); @@ -549,6 +539,5 @@ mod tests { ); assert!(fd_set.contains(&r1)); assert!(!fd_set.contains(&r2)); - close(_w2).unwrap(); } } diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 78dd617c55..b56d694ab5 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -1479,7 +1479,7 @@ impl<'a> ControlMessage<'a> { /// 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.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), None).unwrap(); /// ``` @@ -1496,7 +1496,7 @@ impl<'a> ControlMessage<'a> { /// 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.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), Some(&localhost)).unwrap(); /// ``` diff --git a/src/unistd.rs b/src/unistd.rs index bb9f1c1f67..b0cbf1c4fa 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -35,7 +35,7 @@ use std::ffi::{CString, OsStr}; use std::os::unix::ffi::OsStrExt; use std::os::unix::ffi::OsStringExt; use std::os::unix::io::RawFd; -use std::os::unix::io::{AsFd, AsRawFd}; +use std::os::unix::io::{AsFd, AsRawFd, OwnedFd}; use std::path::PathBuf; use std::{fmt, mem, ptr}; @@ -260,7 +260,7 @@ impl ForkResult { /// } /// 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(); +/// write(std::io::stdout(), "I'm a new child process\n".as_bytes()).ok(); /// unsafe { libc::_exit(0) }; /// } /// Err(_) => println!("Fork failed"), @@ -1115,9 +1115,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) @@ -1189,14 +1193,15 @@ pub fn lseek64( /// Create an interprocess channel. /// /// See also [pipe(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html) -pub fn pipe() -> std::result::Result<(RawFd, RawFd), Error> { - let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); +pub fn pipe() -> std::result::Result<(OwnedFd, OwnedFd), Error> { + let mut fds = mem::MaybeUninit::<[OwnedFd; 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])) } + let [read, write] = unsafe { fds.assume_init() }; + Ok((read, write)) } feature! { @@ -1230,15 +1235,16 @@ feature! { target_os = "openbsd", target_os = "solaris" ))] -pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> { - let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); +pub fn pipe2(flags: OFlag) -> Result<(OwnedFd, OwnedFd)> { + let mut fds = mem::MaybeUninit::<[OwnedFd; 2]>::uninit(); 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])) } + let [read, write] = unsafe { fds.assume_init() }; + Ok((read, write)) } /// Truncate a file to a specified length diff --git a/test/sys/test_select.rs b/test/sys/test_select.rs index 79f75de3b4..6b4d1c54c1 100644 --- a/test/sys/test_select.rs +++ b/test/sys/test_select.rs @@ -2,17 +2,15 @@ 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, BorrowedFd, FromRawFd, OwnedFd}; +use std::os::unix::io::{AsRawFd, BorrowedFd}; #[test] pub fn test_pselect() { let _mtx = crate::SIGNAL_MTX.lock(); let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); - let r1 = unsafe { OwnedFd::from_raw_fd(r1) }; + write(&w1, b"hi!").unwrap(); let (r2, _w2) = pipe().unwrap(); - let r2 = unsafe { OwnedFd::from_raw_fd(r2) }; let mut fd_set = FdSet::new(); fd_set.insert(&r1); @@ -31,10 +29,8 @@ pub fn test_pselect() { #[test] pub fn test_pselect_nfds2() { let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); - let r1 = unsafe { OwnedFd::from_raw_fd(r1) }; + write(&w1, b"hi!").unwrap(); let (r2, _w2) = pipe().unwrap(); - let r2 = unsafe { OwnedFd::from_raw_fd(r2) }; let mut fd_set = FdSet::new(); fd_set.insert(&r1); diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index ed1686e87d..06efd947e3 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -200,7 +200,7 @@ pub fn test_socketpair() { SockFlag::empty(), ) .unwrap(); - write(fd1.as_raw_fd(), b"hello").unwrap(); + write(&fd1, b"hello").unwrap(); let mut buf = [0; 5]; read(fd2.as_raw_fd(), &mut buf).unwrap(); @@ -757,7 +757,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::<()>( @@ -770,7 +770,6 @@ pub fn test_scm_rights() { .unwrap(), 5 ); - close(r).unwrap(); } { @@ -803,12 +802,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.as_raw_fd(), b"world").unwrap(); + write(&w, b"world").unwrap(); let mut buf = [0u8; 5]; read(received_r.as_raw_fd(), &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 @@ -1451,7 +1449,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), @@ -1467,7 +1465,6 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec) { .unwrap(), 5 ); - close(r).unwrap(); } { @@ -1510,12 +1507,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.as_raw_fd(), b"world").unwrap(); + write(&w, b"world").unwrap(); let mut buf = [0u8; 5]; read(received_r.as_raw_fd(), &mut buf).unwrap(); assert_eq!(&buf[..], b"world"); close(received_r).unwrap(); - close(w).unwrap(); } // Test creating and using named unix domain sockets @@ -1548,7 +1544,7 @@ pub fn test_named_unixdomain() { ) .expect("socket failed"); connect(s2.as_raw_fd(), &sockaddr).expect("connect failed"); - write(s2.as_raw_fd(), b"hello").expect("write failed"); + write(&s2, b"hello").expect("write failed"); }); let s3 = accept(s1.as_raw_fd()).expect("accept failed"); diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs index 0e34917325..90432f9ab9 100644 --- a/test/sys/test_sockopt.rs +++ b/test/sys/test_sockopt.rs @@ -5,7 +5,7 @@ use nix::sys::socket::{ SockProtocol, SockType, }; use rand::{thread_rng, Rng}; -use std::os::unix::io::AsRawFd; +use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd}; // NB: FreeBSD supports LOCAL_PEERCRED for SOCK_SEQPACKET, but OSX does not. #[cfg(any(target_os = "dragonfly", target_os = "freebsd",))] @@ -151,7 +151,8 @@ fn test_so_tcp_maxseg() { .unwrap(); connect(ssock.as_raw_fd(), &sock_addr).unwrap(); let rsess = accept(rsock.as_raw_fd()).unwrap(); - write(rsess, b"hello").unwrap(); + let rsess = unsafe { OwnedFd::from_raw_fd(rsess) }; + write(&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. @@ -185,7 +186,6 @@ fn test_so_type() { #[test] fn test_so_type_unknown() { use nix::errno::Errno; - use std::os::unix::io::{FromRawFd, OwnedFd}; require_capability!("test_so_type", CAP_NET_RAW); let raw_fd = unsafe { libc::socket(libc::AF_PACKET, libc::SOCK_PACKET, 0) }; diff --git a/test/sys/test_termios.rs b/test/sys/test_termios.rs index 83919378a7..21bb8c61ef 100644 --- a/test/sys/test_termios.rs +++ b/test/sys/test_termios.rs @@ -11,7 +11,7 @@ use nix::unistd::{read, write}; fn write_all(f: Fd, buf: &[u8]) { let mut len = 0; while len < buf.len() { - len += write(f.as_fd().as_raw_fd(), &buf[len..]).unwrap(); + len += write(f.as_fd(), &buf[len..]).unwrap(); } } diff --git a/test/sys/test_uio.rs b/test/sys/test_uio.rs index fc09465f19..fe0a3bde07 100644 --- a/test/sys/test_uio.rs +++ b/test/sys/test_uio.rs @@ -4,7 +4,7 @@ use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; use std::fs::OpenOptions; use std::io::IoSlice; -use std::os::unix::io::{FromRawFd, OwnedFd}; +use std::os::unix::io::AsRawFd; use std::{cmp, iter}; #[cfg(not(target_os = "redox"))] @@ -44,22 +44,17 @@ fn test_writev() { // FileDesc will close its filedesc (reader). let mut read_buf: Vec = iter::repeat(0u8).take(128 * 16).collect(); - // Temporary workaround to cope with the existing RawFd pipe(2), should be - // removed when pipe(2) becomes I/O-safe. - let writer = unsafe { OwnedFd::from_raw_fd(writer) }; - // Blocking io, should write all data. let write_res = writev(&writer, &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.as_raw_fd(), &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(reader).expect("closed reader"); } #[test] @@ -92,10 +87,6 @@ fn test_readv() { // Blocking io, should write all data. write(writer, &to_write).expect("write failed"); - // Temporary workaround to cope with the existing RawFd pipe(2), should be - // removed when pipe(2) becomes I/O-safe. - let reader = unsafe { OwnedFd::from_raw_fd(reader) }; - let read = readv(&reader, &mut iovecs[..]).expect("read failed"); // Check whether we've read all data assert_eq!(to_write.len(), read); @@ -108,7 +99,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(writer).expect("couldn't close writer"); } #[test] @@ -230,6 +220,7 @@ fn test_process_vm_readv() { use nix::sys::signal::*; use nix::sys::wait::*; use nix::unistd::ForkResult::*; + use std::os::unix::io::AsRawFd; require_capability!("test_process_vm_readv", CAP_SYS_PTRACE); let _m = crate::FORK_MTX.lock(); @@ -241,10 +232,10 @@ fn test_process_vm_readv() { let (r, w) = pipe().unwrap(); match unsafe { fork() }.expect("Error: Fork Failed") { Parent { child } => { - close(w).unwrap(); + drop(w); // wait for child - read(r, &mut [0u8]).unwrap(); - close(r).unwrap(); + read(r.as_raw_fd(), &mut [0u8]).unwrap(); + drop(r); let ptr = vector.as_ptr() as usize; let remote_iov = RemoteIoVec { base: ptr, len: 5 }; @@ -263,12 +254,11 @@ fn test_process_vm_readv() { assert_eq!(20u8, buf.iter().sum()); } Child => { - let _ = close(r); + drop(r); for i in &mut vector { *i += 1; } let _ = write(w, b"\0"); - let _ = close(w); loop { pause(); } diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs index 5fef04ba9b..f216458e8a 100644 --- a/test/test_fcntl.rs +++ b/test/test_fcntl.rs @@ -280,7 +280,7 @@ mod linux_android { 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(target_os = "linux")] @@ -299,7 +299,7 @@ mod linux_android { let res = splice( tmp.as_raw_fd(), Some(&mut offset), - wr, + wr.as_raw_fd(), None, 2, SpliceFFlags::empty(), @@ -309,12 +309,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.as_raw_fd(), &mut buf).unwrap()); assert_eq!(b"f1", &buf[0..2]); assert_eq!(7, offset); - - close(rd).unwrap(); - close(wr).unwrap(); } #[test] @@ -323,24 +320,21 @@ mod linux_android { let (rd2, wr2) = pipe().unwrap(); write(wr1, b"abc").unwrap(); - let res = tee(rd1, wr2, 2, SpliceFFlags::empty()).unwrap(); + let res = + tee(rd1.as_raw_fd(), wr2.as_raw_fd(), 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.as_raw_fd(), &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.as_raw_fd(), &mut buf).unwrap()); assert_eq!(b"abc", &buf[0..3]); - - close(rd1).unwrap(); - close(wr1).unwrap(); - close(rd2).unwrap(); - close(wr2).unwrap(); } #[test] @@ -351,17 +345,15 @@ mod linux_android { let buf2 = b"defghi"; let iovecs = [IoSlice::new(&buf1[0..3]), IoSlice::new(&buf2[0..3])]; - let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap(); + let res = vmsplice(wr.as_raw_fd(), &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.as_raw_fd(), &mut buf).unwrap()); assert_eq!(b"abcdef", &buf[0..6]); - - close(rd).unwrap(); - close(wr).unwrap(); } #[cfg(target_os = "linux")] @@ -494,7 +486,7 @@ mod test_posix_fadvise { use nix::errno::Errno; use nix::fcntl::*; use nix::unistd::pipe; - use std::os::unix::io::{AsRawFd, RawFd}; + use std::os::unix::io::AsRawFd; use tempfile::NamedTempFile; #[test] @@ -509,7 +501,7 @@ mod test_posix_fadvise { fn test_errno() { let (rd, _wr) = pipe().unwrap(); let res = posix_fadvise( - rd as RawFd, + rd.as_raw_fd(), 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED, @@ -532,10 +524,7 @@ 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, os::unix::io::AsRawFd}; use tempfile::NamedTempFile; #[test] @@ -565,7 +554,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.as_raw_fd(), 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 045ccd3df1..30207c95ea 100644 --- a/test/test_poll.rs +++ b/test/test_poll.rs @@ -1,9 +1,9 @@ use nix::{ errno::Errno, poll::{poll, PollFd, PollFlags}, - unistd::{close, pipe, write}, + unistd::{pipe, write}, }; -use std::os::unix::io::{BorrowedFd, FromRawFd, OwnedFd}; +use std::os::unix::io::BorrowedFd; macro_rules! loop_while_eintr { ($poll_expr: expr) => { @@ -20,7 +20,6 @@ macro_rules! loop_while_eintr { #[test] fn test_poll() { let (r, w) = pipe().unwrap(); - let r = unsafe { OwnedFd::from_raw_fd(r) }; let mut fds = [PollFd::new(&r, PollFlags::POLLIN)]; // Poll an idle pipe. Should timeout @@ -28,13 +27,12 @@ fn test_poll() { 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(); assert_eq!(nfds, 1); assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN)); - close(w).unwrap(); } // ppoll(2) is the same as poll except for how it handles timeouts and signals. @@ -54,7 +52,6 @@ fn test_ppoll() { let timeout = TimeSpec::milliseconds(1); let (r, w) = pipe().unwrap(); - let r = unsafe { OwnedFd::from_raw_fd(r) }; let mut fds = [PollFd::new(&r, PollFlags::POLLIN)]; // Poll an idle pipe. Should timeout @@ -63,13 +60,12 @@ 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(); assert_eq!(nfds, 1); assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN)); - close(w).unwrap(); } #[test] diff --git a/test/test_pty.rs b/test/test_pty.rs index 4cc6620c3c..9b5c500e45 100644 --- a/test/test_pty.rs +++ b/test/test_pty.rs @@ -1,9 +1,9 @@ use std::fs::File; -use std::io::{Read, Write}; +use std::io::{stdout, Read, Write}; use std::os::unix::prelude::*; use std::path::Path; -use libc::{_exit, STDOUT_FILENO}; +use libc::_exit; use nix::fcntl::{open, OFlag}; use nix::pty::*; use nix::sys::stat; @@ -185,7 +185,7 @@ 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.as_raw_fd(), string.as_bytes()).unwrap(); + write(&pty.master, string.as_bytes()).unwrap(); crate::read_exact(&pty.slave, &mut buf); assert_eq!(&buf, string.as_bytes()); @@ -199,7 +199,7 @@ fn test_openpty() { let string2 = "barbarbarbar\n"; let echoed_string2 = "barbarbarbar\r\n"; let mut buf = [0u8; 14]; - write(pty.slave.as_raw_fd(), string2.as_bytes()).unwrap(); + write(&pty.slave, string2.as_bytes()).unwrap(); crate::read_exact(&pty.master, &mut buf); assert_eq!(&buf, echoed_string2.as_bytes()); @@ -224,7 +224,7 @@ 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.as_raw_fd(), string.as_bytes()).unwrap(); + write(&pty.master, string.as_bytes()).unwrap(); crate::read_exact(&pty.slave, &mut buf); assert_eq!(&buf, string.as_bytes()); @@ -237,7 +237,7 @@ fn test_openpty_with_termios() { let string2 = "barbarbarbar\n"; let echoed_string2 = "barbarbarbar\n"; let mut buf = [0u8; 13]; - write(pty.slave.as_raw_fd(), string2.as_bytes()).unwrap(); + write(&pty.slave, string2.as_bytes()).unwrap(); crate::read_exact(&pty.master, &mut buf); assert_eq!(&buf, echoed_string2.as_bytes()); @@ -258,7 +258,7 @@ fn test_forkpty() { let pty = unsafe { forkpty(None, None).unwrap() }; match pty.fork_result { Child => { - write(STDOUT_FILENO, string.as_bytes()).unwrap(); + write(stdout(), 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 b85e030fd3..a594f18e39 100644 --- a/test/test_sendfile.rs +++ b/test/test_sendfile.rs @@ -1,6 +1,4 @@ use std::io::prelude::*; -#[cfg(any(target_os = "android", target_os = "linux"))] -use std::os::unix::io::{FromRawFd, OwnedFd}; use libc::off_t; use nix::sys::sendfile::*; @@ -8,7 +6,8 @@ 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}; + use std::os::unix::io::AsRawFd; } 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; @@ -24,21 +23,14 @@ fn test_sendfile_linux() { let (rd, wr) = pipe().unwrap(); let mut offset: off_t = 5; - // The construct of this `OwnedFd` is a temporary workaround, when `pipe(2)` - // becomes I/O-safe: - // pub fn pipe() -> std::result::Result<(OwnedFd, OwnedFd), Error> - // then it is no longer needed. - let wr = unsafe { OwnedFd::from_raw_fd(wr) }; let res = sendfile(&wr, &tmp, 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.as_raw_fd(), &mut buf).unwrap()); assert_eq!(b"f1", &buf[0..2]); assert_eq!(7, offset); - - close(rd).unwrap(); } #[cfg(target_os = "linux")] @@ -50,21 +42,14 @@ fn test_sendfile64_linux() { let (rd, wr) = pipe().unwrap(); let mut offset: libc::off64_t = 5; - // The construct of this `OwnedFd` is a temporary workaround, when `pipe(2)` - // becomes I/O-safe: - // pub fn pipe() -> std::result::Result<(OwnedFd, OwnedFd), Error> - // then it is no longer needed. - let wr = unsafe { OwnedFd::from_raw_fd(wr) }; let res = sendfile64(&wr, &tmp, 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.as_raw_fd(), &mut buf).unwrap()); assert_eq!(b"f1", &buf[0..2]); assert_eq!(7, offset); - - close(rd).unwrap(); } #[cfg(target_os = "freebsd")] diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 10284e4127..a6fe8f9ef9 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -356,7 +356,7 @@ macro_rules! execve_test_factory ( match unsafe{fork()}.unwrap() { Child => { // Make `writer` be the stdout of the new process. - dup2(writer, 1).unwrap(); + dup2(writer.as_raw_fd(), 1).unwrap(); let r = syscall(); let _ = std::io::stderr() .write_all(format!("{:?}", r).as_bytes()); @@ -370,7 +370,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.as_raw_fd(), &mut buf).unwrap(); // It should contain the things we printed using `/bin/sh`. let string = String::from_utf8_lossy(&buf); assert!(string.contains("nix!!!")); @@ -714,12 +714,12 @@ fn test_getresgid() { fn test_pipe() { let (fd0, fd1) = pipe().unwrap(); let m0 = stat::SFlag::from_bits_truncate( - stat::fstat(fd0).unwrap().st_mode as mode_t, + stat::fstat(fd0.as_raw_fd()).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, + stat::fstat(fd1.as_raw_fd()).unwrap().st_mode as mode_t, ); assert_eq!(m1, SFlag::S_IFIFO); } @@ -743,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)); }