diff options
Diffstat (limited to 'vendor/rustix/src/backend/libc/pty/syscalls.rs')
-rw-r--r-- | vendor/rustix/src/backend/libc/pty/syscalls.rs | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/vendor/rustix/src/backend/libc/pty/syscalls.rs b/vendor/rustix/src/backend/libc/pty/syscalls.rs new file mode 100644 index 0000000..2395efd --- /dev/null +++ b/vendor/rustix/src/backend/libc/pty/syscalls.rs @@ -0,0 +1,106 @@ +//! libc syscalls supporting `rustix::pty`. + +use crate::backend::c; +use crate::backend::conv::{borrowed_fd, ret}; +use crate::fd::BorrowedFd; +use crate::io; +#[cfg(all( + feature = "alloc", + any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia") +))] +use { + crate::ffi::{CStr, CString}, + crate::path::SMALL_PATH_BUFFER_SIZE, + alloc::borrow::ToOwned, + alloc::vec::Vec, +}; + +#[cfg(not(linux_kernel))] +use crate::{backend::conv::ret_owned_fd, fd::OwnedFd, pty::OpenptFlags}; + +#[cfg(not(linux_kernel))] +#[inline] +pub(crate) fn openpt(flags: OpenptFlags) -> io::Result<OwnedFd> { + unsafe { ret_owned_fd(c::posix_openpt(flags.bits() as _)) } +} + +#[cfg(all( + feature = "alloc", + any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia") +))] +#[inline] +pub(crate) fn ptsname(fd: BorrowedFd<'_>, mut buffer: Vec<u8>) -> io::Result<CString> { + // This code would benefit from having a better way to read into + // uninitialized memory, but that requires `unsafe`. + buffer.clear(); + buffer.reserve(SMALL_PATH_BUFFER_SIZE); + buffer.resize(buffer.capacity(), 0_u8); + + loop { + // On platforms with `ptsname_r`, use it. + #[cfg(any(linux_like, target_os = "fuchsia"))] + let r = unsafe { c::ptsname_r(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len()) }; + + // FreeBSD 12 doesn't have `ptsname_r`. + #[cfg(target_os = "freebsd")] + let r = unsafe { + weak! { + fn ptsname_r( + c::c_int, + *mut c::c_char, + c::size_t + ) -> c::c_int + } + if let Some(func) = ptsname_r.get() { + func(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len()) + } else { + libc::ENOSYS + } + }; + + // macOS 10.13.4 has `ptsname_r`; use it if we have it, otherwise fall + // back to calling the underlying ioctl directly. + #[cfg(apple)] + let r = unsafe { + weak! { fn ptsname_r(c::c_int, *mut c::c_char, c::size_t) -> c::c_int } + + if let Some(libc_ptsname_r) = ptsname_r.get() { + libc_ptsname_r(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len()) + } else { + // The size declared in the `TIOCPTYGNAME` macro in + // sys/ttycom.h is 128. + let mut name: [u8; 128] = [0_u8; 128]; + match c::ioctl(borrowed_fd(fd), c::TIOCPTYGNAME as _, &mut name) { + 0 => { + let len = CStr::from_ptr(name.as_ptr().cast()).to_bytes().len(); + std::ptr::copy_nonoverlapping(name.as_ptr(), buffer.as_mut_ptr(), len + 1); + 0 + } + _ => libc_errno::errno().0, + } + } + }; + + if r == 0 { + return Ok(unsafe { CStr::from_ptr(buffer.as_ptr().cast()).to_owned() }); + } + if r != c::ERANGE { + return Err(io::Errno::from_raw_os_error(r)); + } + + // Use `Vec` reallocation strategy to grow capacity exponentially. + buffer.reserve(1); + buffer.resize(buffer.capacity(), 0_u8); + } +} + +#[inline] +pub(crate) fn unlockpt(fd: BorrowedFd<'_>) -> io::Result<()> { + unsafe { ret(c::unlockpt(borrowed_fd(fd))) } +} + +#[cfg(not(linux_kernel))] +#[inline] +pub(crate) fn grantpt(fd: BorrowedFd<'_>) -> io::Result<()> { + unsafe { ret(c::grantpt(borrowed_fd(fd))) } +} |