starry-kernel 0.2.0-preview.1

Core kernel library for Starry OS, providing Linux-compatible syscall implementations
use alloc::{borrow::Cow, boxed::Box, string::ToString, sync::Arc, vec::Vec};
use core::sync::atomic::Ordering;

use axerrno::{AxError, AxResult};
use axfs_ng_vfs::{DeviceId, NodeType, VfsResult};
use flatten_objects::FlattenObjects;
use kspin::SpinNoIrq;

use crate::pseudofs::{Device, NodeOpsMux, SimpleDirOps, SimpleFs, dev::tty::pty::PtyDriver};

static PTS_TABLE: SpinNoIrq<FlattenObjects<Arc<Device>, 16>> =
    SpinNoIrq::new(FlattenObjects::new());

pub fn add_slave(fs: Arc<SimpleFs>, pty: Arc<PtyDriver>) -> AxResult<u32> {
    let terminal = pty.terminal.clone();
    let mut table = PTS_TABLE.lock();
    let pty_number = table
        .add(Device::new(
            fs,
            NodeType::CharacterDevice,
            DeviceId::default(),
            pty,
        ))
        .map_err(|_| AxError::TooManyOpenFiles)? as u32;
    terminal.pty_number.store(pty_number, Ordering::Release);
    table
        .get(pty_number as usize)
        .unwrap()
        .set_device_id(DeviceId::new(136, pty_number));
    Ok(pty_number)
}

/// /dev/pts directory
pub struct PtsDir;

impl SimpleDirOps for PtsDir {
    fn child_names<'a>(&'a self) -> Box<dyn Iterator<Item = Cow<'a, str>> + 'a> {
        let ids = PTS_TABLE
            .lock()
            .ids()
            .map(|it| Cow::Owned(it.to_string()))
            .collect::<Vec<_>>();
        Box::new(ids.into_iter())
    }

    fn lookup_child(&self, name: &str) -> VfsResult<NodeOpsMux> {
        let id = name.parse::<usize>().map_err(|_| AxError::InvalidData)?;
        let pty = PTS_TABLE.lock().get(id).ok_or(AxError::NotFound)?.clone();
        Ok(NodeOpsMux::File(pty))
    }
}