Files
RedBear-OS/ptyd/src/ptlock.rs
T
Connor-GH ddd6c4f3ac ptyd: implement TIOCGPTN and TIOC{S,G}PTLCK
This functionality is needed according to POSIX. Additionally, some
logic had to be changed in order for the ptsname to be correct for the
manager terminal (ptmx). If you want to obtain a pty, you must go
through the `posix_openpt`-`grantpt`-`unlockpt`-`ptsname`-`open`
process. Alternatively, relibc as a function called `openpty`.

This is part of my ptyd series. This can be safely merged once the MRs
for relibc/ and userutils/ are merged at the same time.
2026-06-03 19:33:09 -05:00

94 lines
2.3 KiB
Rust

use std::cell::RefCell;
use std::rc::Weak;
use syscall::error::{Error, Result, EBADF, EINVAL, EPIPE};
use syscall::flag::{EventFlags, F_GETFL, F_SETFL, O_ACCMODE};
use crate::pty::Pty;
use crate::resource::Resource;
/// Read side of a pipe
pub struct PtyLock {
pty: Weak<RefCell<Pty>>,
flags: usize,
}
impl PtyLock {
pub fn new(pty: Weak<RefCell<Pty>>, flags: usize) -> Self {
PtyLock { pty, flags }
}
}
impl Resource for PtyLock {
fn pty(&self) -> Weak<RefCell<Pty>> {
self.pty.clone()
}
fn flags(&self) -> usize {
self.flags
}
fn path(&mut self, buf: &mut [u8]) -> Result<usize> {
if let Some(pty_lock) = self.pty.upgrade() {
pty_lock.borrow_mut().path(buf)
} else {
Err(Error::new(EPIPE))
}
}
// FIXME assuming c_int has same size as u32
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
if let Some(pty_lock) = self.pty.upgrade() {
let pty = pty_lock.borrow();
let lock_buf = buf
.get_mut(..4)
.and_then(|b| <&mut [u8; 4]>::try_from(b).ok())
.ok_or(Error::new(EBADF))?;
*lock_buf = (pty.locked as u32).to_ne_bytes();
Ok(4)
} else {
Ok(0)
}
}
fn write(&mut self, buf: &[u8]) -> Result<usize> {
if let Some(pty_lock) = self.pty.upgrade() {
let mut pty = pty_lock.borrow_mut();
let lock_val = u32::from_ne_bytes(
buf.get(..4)
.and_then(|b| <[u8; 4]>::try_from(b).ok())
.ok_or(Error::new(EBADF))?,
);
pty.locked = lock_val != 0;
Ok(4)
} else {
Ok(0)
}
}
fn sync(&mut self) -> Result<()> {
Ok(())
}
fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize> {
match cmd {
F_GETFL => Ok(self.flags),
F_SETFL => {
self.flags = (self.flags & O_ACCMODE) | (arg & !O_ACCMODE);
Ok(0)
}
_ => Err(Error::new(EINVAL)),
}
}
fn fevent(&mut self) -> Result<EventFlags> {
Err(Error::new(EBADF))
}
fn events(&mut self) -> EventFlags {
EventFlags::empty()
}
}