diff options
author | Dan Gohman <dev@sunfishcode.online> | 2021-11-20 07:19:14 -0800 |
---|---|---|
committer | Dan Gohman <dev@sunfishcode.online> | 2021-12-02 13:03:32 -0800 |
commit | 81f8d8cbdc369acd2f981e5a089369ccbd200e10 (patch) | |
tree | 9abc1206296c7cbca5b203374793263877d0a37f | |
parent | c0f446e2e9bcb8469e64623284a8a0a0b87e6ce8 (diff) | |
download | rust-81f8d8cbdc369acd2f981e5a089369ccbd200e10.tar.gz |
Port library/std/src/sys/unix/fd.rs to rustix.
-rw-r--r-- | library/std/src/sys/unix/fd.rs | 173 | ||||
-rw-r--r-- | library/std/src/sys/unix/io.rs | 77 |
2 files changed, 39 insertions, 211 deletions
diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index ea688571a98..47f77e30373 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -3,89 +3,34 @@ #[cfg(test)] mod tests; -use crate::cmp; use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; -use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; -use libc::{c_int, c_void}; +use rustix::fs::FdFlags; +#[cfg(not(target_os = "linux"))] +use rustix::fs::OFlags; #[derive(Debug)] pub struct FileDesc(OwnedFd); -// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`, -// with the man page quoting that if the count of bytes to read is -// greater than `SSIZE_MAX` the result is "unspecified". -// -// On macOS, however, apparently the 64-bit libc is either buggy or -// intentionally showing odd behavior by rejecting any read with a size -// larger than or equal to INT_MAX. To handle both of these the read -// size is capped on both platforms. -#[cfg(target_os = "macos")] -const READ_LIMIT: usize = c_int::MAX as usize - 1; -#[cfg(not(target_os = "macos"))] -const READ_LIMIT: usize = libc::ssize_t::MAX as usize; - -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -const fn max_iov() -> usize { - libc::IOV_MAX as usize -} - -#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))] -const fn max_iov() -> usize { - libc::UIO_MAXIOV as usize -} - -#[cfg(not(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -)))] -const fn max_iov() -> usize { - 16 // The minimum value required by POSIX. -} - impl FileDesc { pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - let ret = cvt(unsafe { - libc::read( - self.as_raw_fd(), - buf.as_mut_ptr() as *mut c_void, - cmp::min(buf.len(), READ_LIMIT), - ) - })?; - Ok(ret as usize) + let ret = rustix::io::read(self, buf)?; + Ok(ret) } #[cfg(not(target_os = "espidf"))] pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - let ret = cvt(unsafe { - libc::readv( - self.as_raw_fd(), - bufs.as_ptr() as *const libc::iovec, - cmp::min(bufs.len(), max_iov()) as c_int, - ) - })?; - Ok(ret as usize) + let ret = rustix::io::readv(self, unsafe { crate::mem::transmute(bufs) })?; + Ok(ret) } #[cfg(target_os = "espidf")] pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - return crate::io::default_read_vectored(|b| self.read(b), bufs); + return crate::io::default_read_vectored(|b| self.read(b), unsafe { + crate::mem::transmute(bufs) + }); } #[inline] @@ -99,48 +44,26 @@ impl FileDesc { } pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> { - #[cfg(not(any(target_os = "linux", target_os = "android")))] - use libc::pread as pread64; - #[cfg(any(target_os = "linux", target_os = "android"))] - use libc::pread64; - - unsafe { - cvt(pread64( - self.as_raw_fd(), - buf.as_mut_ptr() as *mut c_void, - cmp::min(buf.len(), READ_LIMIT), - offset as i64, - )) - .map(|n| n as usize) - } + let ret = rustix::io::pread(self, buf, offset)?; + Ok(ret) } pub fn write(&self, buf: &[u8]) -> io::Result<usize> { - let ret = cvt(unsafe { - libc::write( - self.as_raw_fd(), - buf.as_ptr() as *const c_void, - cmp::min(buf.len(), READ_LIMIT), - ) - })?; - Ok(ret as usize) + let ret = rustix::io::write(self, buf)?; + Ok(ret) } #[cfg(not(target_os = "espidf"))] pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { - let ret = cvt(unsafe { - libc::writev( - self.as_raw_fd(), - bufs.as_ptr() as *const libc::iovec, - cmp::min(bufs.len(), max_iov()) as c_int, - ) - })?; - Ok(ret as usize) + let ret = rustix::io::writev(self, unsafe { crate::mem::transmute(bufs) })?; + Ok(ret) } #[cfg(target_os = "espidf")] pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { - return crate::io::default_write_vectored(|b| self.write(b), bufs); + return crate::io::default_write_vectored(|b| self.write(b), unsafe { + crate::mem::transmute(bufs) + }); } #[inline] @@ -149,25 +72,13 @@ impl FileDesc { } pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> { - #[cfg(not(any(target_os = "linux", target_os = "android")))] - use libc::pwrite as pwrite64; - #[cfg(any(target_os = "linux", target_os = "android"))] - use libc::pwrite64; - - unsafe { - cvt(pwrite64( - self.as_raw_fd(), - buf.as_ptr() as *const c_void, - cmp::min(buf.len(), READ_LIMIT), - offset as i64, - )) - .map(|n| n as usize) - } + let ret = rustix::io::pwrite(self, buf, offset)?; + Ok(ret) } #[cfg(target_os = "linux")] pub fn get_cloexec(&self) -> io::Result<bool> { - unsafe { Ok((cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) } + Ok(rustix::fs::fcntl_getfd(self)?.contains(FdFlags::CLOEXEC)) } #[cfg(not(any( @@ -183,10 +94,8 @@ impl FileDesc { target_os = "vxworks" )))] pub fn set_cloexec(&self) -> io::Result<()> { - unsafe { - cvt(libc::ioctl(self.as_raw_fd(), libc::FIOCLEX))?; - Ok(()) - } + rustix::io::ioctl_fioclex(self)?; + Ok(()) } #[cfg(any( all(target_env = "newlib", not(target_os = "espidf")), @@ -201,14 +110,12 @@ impl FileDesc { target_os = "vxworks" ))] pub fn set_cloexec(&self) -> io::Result<()> { - unsafe { - let previous = cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFD))?; - let new = previous | libc::FD_CLOEXEC; - if new != previous { - cvt(libc::fcntl(self.as_raw_fd(), libc::F_SETFD, new))?; - } - Ok(()) + let previous = rustix::fs::fcntl_getfd(self)?; + let new = previous | FdFlags::CLOEXEC; + if new != previous { + rustix::fs::fcntl_setfd(self, new)?; } + Ok(()) } #[cfg(target_os = "espidf")] pub fn set_cloexec(&self) -> io::Result<()> { @@ -219,24 +126,21 @@ impl FileDesc { #[cfg(target_os = "linux")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - unsafe { - let v = nonblocking as c_int; - cvt(libc::ioctl(self.as_raw_fd(), libc::FIONBIO, &v))?; - Ok(()) - } + rustix::io::ioctl_fionbio(self, nonblocking)?; + Ok(()) } #[cfg(not(target_os = "linux"))] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { unsafe { - let previous = cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFL))?; + let previous = rustix::fs::fcntl_getfl(self)?; let new = if nonblocking { - previous | libc::O_NONBLOCK + previous | OFlags::NONBLOCK; } else { - previous & !libc::O_NONBLOCK + previous & !OFlags::NONBLOCK; }; if new != previous { - cvt(libc::fcntl(self.as_raw_fd(), libc::F_SETFL, new))?; + rustix::fcntl_setfl(self, new)?; } Ok(()) } @@ -247,17 +151,16 @@ impl FileDesc { // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This // is a POSIX flag that was added to Linux in 2.6.24. #[cfg(not(target_os = "espidf"))] - let cmd = libc::F_DUPFD_CLOEXEC; + let fd = rustix::fs::fcntl_dupfd_cloexec(self, 0)?; // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics // will never be supported, as this is a bare metal framework with // no capabilities for multi-process execution. While F_DUPFD is also // not supported yet, it might be (currently it returns ENOSYS). #[cfg(target_os = "espidf")] - let cmd = libc::F_DUPFD; + let fd = rustix::fs::fcntl_dupfd(self, 0)?; - let fd = cvt(unsafe { libc::fcntl(self.as_raw_fd(), cmd, 0) })?; - Ok(unsafe { FileDesc::from_raw_fd(fd) }) + Ok(FileDesc::from_inner(fd)) } } diff --git a/library/std/src/sys/unix/io.rs b/library/std/src/sys/unix/io.rs index deb5ee76bd0..c31cafcf4f4 100644 --- a/library/std/src/sys/unix/io.rs +++ b/library/std/src/sys/unix/io.rs @@ -1,76 +1 @@ -use crate::marker::PhantomData; -use crate::slice; - -use libc::{c_void, iovec}; - -#[derive(Copy, Clone)] -#[repr(transparent)] -pub struct IoSlice<'a> { - vec: iovec, - _p: PhantomData<&'a [u8]>, -} - -impl<'a> IoSlice<'a> { - #[inline] - pub fn new(buf: &'a [u8]) -> IoSlice<'a> { - IoSlice { - vec: iovec { iov_base: buf.as_ptr() as *mut u8 as *mut c_void, iov_len: buf.len() }, - _p: PhantomData, - } - } - - #[inline] - pub fn advance(&mut self, n: usize) { - if self.vec.iov_len < n { - panic!("advancing IoSlice beyond its length"); - } - - unsafe { - self.vec.iov_len -= n; - self.vec.iov_base = self.vec.iov_base.add(n); - } - } - - #[inline] - pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) } - } -} - -#[repr(transparent)] -pub struct IoSliceMut<'a> { - vec: iovec, - _p: PhantomData<&'a mut [u8]>, -} - -impl<'a> IoSliceMut<'a> { - #[inline] - pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { - IoSliceMut { - vec: iovec { iov_base: buf.as_mut_ptr() as *mut c_void, iov_len: buf.len() }, - _p: PhantomData, - } - } - - #[inline] - pub fn advance(&mut self, n: usize) { - if self.vec.iov_len < n { - panic!("advancing IoSliceMut beyond its length"); - } - - unsafe { - self.vec.iov_len -= n; - self.vec.iov_base = self.vec.iov_base.add(n); - } - } - - #[inline] - pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) } - } - - #[inline] - pub fn as_mut_slice(&mut self) -> &mut [u8] { - unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) } - } -} +pub use rustix::io::{IoSlice, IoSliceMut}; |