// SPDX-License-Identifier: MPL-2.0 use device_id::{DeviceId, MajorId, MinorId}; use super::*; use crate::fs::{ inode_handle::FileIo, utils::{AccessMode, StatusFlags}, }; /// Same major number with Linux. const PTMX_MAJOR_NUM: u16 = 5; /// Same minor number with Linux. const PTMX_MINOR_NUM: u32 = 2; /// Ptmx is the multiplexing master of devpts. /// /// Every time the multiplexing master is opened, a new instance of pty master inode is returned /// and an corresponding pty slave inode is also created. pub struct Ptmx { inner: Inner, metadata: RwLock, } #[derive(Clone)] struct Inner(Weak); impl Ptmx { pub fn new(fs: Weak) -> Arc { let inner = Inner(fs); Arc::new(Self { metadata: RwLock::new(Metadata::new_device( PTMX_INO, mkmod!(a+rw), super::BLOCK_SIZE, &inner, )), inner, }) } pub fn devpts(&self) -> Option> { self.inner.0.upgrade() } } // Many methods are left to do nothing because every time the ptmx is being opened, // it returns the pty master. So the ptmx can not be used at upper layer. impl InodeIo for Ptmx { fn read_at( &self, _offset: usize, _writer: &mut VmWriter, _status_flags: StatusFlags, ) -> Result { Ok(0) } fn write_at( &self, _offset: usize, _reader: &mut VmReader, _status_flags: StatusFlags, ) -> Result { Ok(0) } } impl Inode for Ptmx { fn size(&self) -> usize { self.metadata.read().size } fn resize(&self, new_size: usize) -> Result<()> { Ok(()) } fn metadata(&self) -> Metadata { *self.metadata.read() } fn ino(&self) -> u64 { self.metadata.read().ino as _ } fn type_(&self) -> InodeType { self.metadata.read().type_ } fn mode(&self) -> Result { Ok(self.metadata.read().mode) } fn set_mode(&self, mode: InodeMode) -> Result<()> { self.metadata.write().mode = mode; Ok(()) } fn owner(&self) -> Result { Ok(self.metadata.read().uid) } fn set_owner(&self, uid: Uid) -> Result<()> { self.metadata.write().uid = uid; Ok(()) } fn group(&self) -> Result { Ok(self.metadata.read().gid) } fn set_group(&self, gid: Gid) -> Result<()> { self.metadata.write().gid = gid; Ok(()) } fn atime(&self) -> Duration { self.metadata.read().atime } fn set_atime(&self, time: Duration) { self.metadata.write().atime = time; } fn mtime(&self) -> Duration { self.metadata.read().mtime } fn set_mtime(&self, time: Duration) { self.metadata.write().mtime = time; } fn ctime(&self) -> Duration { self.metadata.read().ctime } fn set_ctime(&self, time: Duration) { self.metadata.write().ctime = time; } fn fs(&self) -> Arc { // FIXME: The below code may panic if the devpts is dropped. self.devpts().unwrap() } fn open( &self, access_mode: AccessMode, status_flags: StatusFlags, ) -> Option>> { Some(self.inner.open()) } fn is_dentry_cacheable(&self) -> bool { false } } impl Device for Inner { fn type_(&self) -> DeviceType { DeviceType::Char } fn id(&self) -> DeviceId { DeviceId::new(MajorId::new(PTMX_MAJOR_NUM), MinorId::new(PTMX_MINOR_NUM)) } fn open(&self) -> Result> { let devpts = self.0.upgrade().unwrap(); Ok(devpts.create_master_slave_pair()?.0) } }