Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions kernel/src/device/tty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,18 @@

use crate::{
device::serial,
file::{File, fs::FileOps},
file::{
File,
fs::FileOps,
poll::{POLLIN, POLLOUT},
},
memory::user::{UserPtr, UserSlice},
process::{
Process,
pid::Pid,
signal::{Signal, SignalHandler},
},
syscall::{
FromSyscallArg, ioctl,
select::{POLLIN, POLLOUT},
},
syscall::{FromSyscallArg, ioctl},
tty::{TTY, WinSize, termios, termios::Termios},
};
use core::ffi::c_void;
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/file/fs/ext2/dirent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ impl Dirent {
pub fn set_type(&mut self, superblock: &Superblock, file_type: Option<FileType>) {
if superblock.s_feature_incompat & super::REQUIRED_FEATURE_DIRECTORY_TYPE != 0 {
self.file_type = match file_type {
None => TYPE_INDICATOR_UNKNOWN,
None | Some(FileType::None) => TYPE_INDICATOR_UNKNOWN,
Some(FileType::Regular) => TYPE_INDICATOR_REGULAR,
Some(FileType::Directory) => TYPE_INDICATOR_DIRECTORY,
Some(FileType::CharDevice) => TYPE_INDICATOR_CHAR_DEVICE,
Expand Down
5 changes: 5 additions & 0 deletions kernel/src/file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub mod fs;
pub mod lock;
pub mod perm;
pub mod pipe;
pub mod poll;
pub mod socket;
pub mod util;
pub mod vfs;
Expand Down Expand Up @@ -145,6 +146,8 @@ pub const O_TRUNC: i32 = 0b00000000000000000000001000000000;
/// Enumeration representing the different file types.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum FileType {
/// No file type, used by anonymous inodes.
None,
/// A regular file storing data.
Regular,
/// A directory, containing other files.
Expand Down Expand Up @@ -181,6 +184,7 @@ impl FileType {
/// Returns the mode corresponding to the type.
pub const fn to_mode(self) -> Mode {
match self {
Self::None => 0,
Self::Socket => S_IFSOCK,
Self::Link => S_IFLNK,
Self::Regular => S_IFREG,
Expand All @@ -194,6 +198,7 @@ impl FileType {
/// Returns the directory entry type.
pub const fn to_dirent_type(self) -> u8 {
match self {
Self::None => DT_UNKNOWN,
Self::Socket => DT_SOCK,
Self::Link => DT_LNK,
Self::Regular => DT_REG,
Expand Down
141 changes: 141 additions & 0 deletions kernel/src/file/poll.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Copyright 2026 Luc Lenôtre
*
* This file is part of Maestro.
*
* Maestro is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* Maestro is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Maestro. If not, see <https://www.gnu.org/licenses/>.
*/

//! Files polling.

use crate::{
file::{File, fs::FileOps},
sync::mutex::Mutex,
};
use core::ffi::c_long;
use utils::{collections::hashmap::HashMap, errno::EResult, ptr::arc::Arc};

/// The number of file descriptors in FDSet.
pub const FD_SETSIZE: usize = 1024;

/// Structure representing `fd_set`.
#[repr(C)]
#[derive(Clone, Debug, Default)]
pub struct FDSet {
/// The set's bitfield.
fds_bits: [c_long; FD_SETSIZE / c_long::BITS as usize],
}

impl FDSet {
/// Tells whether the given file descriptor `fd` is set in the list.
pub fn is_set(&self, fd: u32) -> bool {
if fd as usize >= FD_SETSIZE {
return false;
}
let i = fd as usize / c_long::BITS as usize;
let bit = fd % c_long::BITS;
self.fds_bits[i] & (1 << bit) != 0
}

/// Sets or clears the bit for file descriptor `fd`.
pub fn set(&mut self, fd: u32, val: bool) {
if fd as usize >= FD_SETSIZE {
return;
}
let i = fd as usize / c_long::BITS as usize;
let bit = fd % c_long::BITS;
if val {
self.fds_bits[i] |= 1 << bit;
} else {
self.fds_bits[i] &= !(1 << bit);
}
}
}

/// Poll event: There is data to read.
pub const POLLIN: u32 = 0x1;
/// Poll event: There is some exceptional condition on the file descriptor.
pub const POLLPRI: u32 = 0x2;
/// Poll event: Writing is now possible.
pub const POLLOUT: u32 = 0x4;
/// Poll event: Error condition.
pub const POLLERR: u32 = 0x8;
/// Poll event: Hang up.
pub const POLLHUP: u32 = 0x10;
/// Poll event: Invalid request.
pub const POLLNVAL: u32 = 0x20;
/// Poll event: Equivalent to POLLIN.
pub const POLLRDNORM: u32 = 0x40;
/// Poll event: Priority band data can be read.
pub const POLLRDBAND: u32 = 0x80;
/// Poll event: Equivalent to POLLOUT.
pub const POLLWRNORM: u32 = 0x100;
/// Poll event: Priority data may be written.
pub const POLLWRBAND: u32 = 0x200;
/// Poll event: Stream socket peer closed connection, or shut down writing half
/// of connection.
pub const POLLRDHUP: u32 = 0x2000;

/// A file descriptor passed to the `poll` system call.
#[repr(C)]
#[derive(Debug)]
pub struct PollFD {
/// The file descriptor.
pub fd: i32,
/// The input mask telling which events to look for.
pub events: i16,
/// The output mask telling which events happened.
pub revents: i16,
}

/// An epoll event, matching the userspace `struct epoll_event`.
///
/// **Note**: on x86 this structure is *packed*, hence the `repr(C, packed)`.
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct EpollEvent {
/// The events bitmask.
pub events: u32,
/// Opaque user data associated with the entry.
pub data: u64,
}

/// An entry of the interest list: a file being watched by an epoll instance.
#[derive(Debug)]
pub struct EpollItem {
/// The watched open file description.
pub file: Arc<File>,
/// The events the user is interested in (poll bits only, without the
/// behaviour flags).
pub events: u32,
/// The behaviour flags ([`EPOLLET`] and [`EPOLLONESHOT`]).
pub flags: u32,
/// Opaque user data associated with the entry.
pub data: u64,
/// For edge-triggered entries, the set of events last reported to userspace.
///
/// An event is only reported again once it has been observed as not ready in
/// between (rising edge).
pub reported: u32,
}

/// The interest list of an epoll instance.
#[derive(Debug, Default)]
pub struct EpollFileOps(pub Mutex<HashMap<*const File, EpollItem>, false>);

impl FileOps for EpollFileOps {
fn poll(&self, _file: &File, _mask: u32) -> EResult<u32> {
// Nested epoll is not implemented
Ok(0)
}
}
2 changes: 1 addition & 1 deletion kernel/src/memory/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ impl<'a, T: Sized + fmt::Debug> UserSlice<'a, T> {
/// Copies the slice to userspace.
///
/// Arguments:
/// - `off` is the byte offset in the slice to which the data is to be copied
/// - `off` is the offset in the slice to which the data is to be copied
/// - `buf` is the source slice to copy from
///
/// The function returns the number of elements written.
Expand Down
Loading
Loading