implement F_DUPFD for sys_fcntl

This commit is contained in:
Ashwin Naren
2026-01-11 22:05:47 -08:00
parent 56f3bcd654
commit 96fe0378b7
3 changed files with 40 additions and 8 deletions

View File

@@ -88,8 +88,8 @@ impl FileDescriptorTable {
Ok(fd)
}
// Insert the given etnry at the specified index. If there was an entry at
// that index `Some(entry)` is returned. Otherwise, `None` is returned.
/// Insert the given entry at the specified index. If there was an entry at
/// that index `Some(entry)` is returned. Otherwise, `None` is returned.
fn insert_at(&mut self, fd: Fd, entry: FileDescriptorEntry) -> Option<FileDescriptorEntry> {
let fd_idx = fd.0 as usize;
@@ -101,6 +101,29 @@ impl FileDescriptorTable {
self.entries[fd_idx].replace(entry)
}
/// Insert the given entry at or above the specified index, returning the
/// file descriptor used.
fn insert_above(&mut self, min_fd: Fd, file: Arc<OpenFile>) -> Result<Fd> {
let start_idx = min_fd.0 as usize;
let entry = FileDescriptorEntry {
file,
flags: FdFlags::default(),
};
for i in start_idx..self.entries.len() {
if self.entries[i].is_none() {
let fd = Fd(i as i32);
self.insert_at(fd, entry);
return Ok(fd);
}
}
// No free slot found, so we need to expand the table.
let fd = Fd(self.entries.len() as i32);
self.entries.push(Some(entry));
Ok(fd)
}
/// Removes a file descriptor from the table, returning the file if it
/// existed.
pub fn remove(&mut self, fd: Fd) -> Option<Arc<OpenFile>> {

View File

@@ -6,13 +6,22 @@ use libkernel::{
use super::{Fd, FdFlags, FileDescriptorEntry};
pub fn sys_dup(fd: Fd) -> Result<usize> {
pub fn dup_fd(fd: Fd, min_fd: Option<Fd>) -> Result<Fd> {
let task = current_task();
let mut files = task.fd_table.lock_save_irq();
let fd = files.get(fd).ok_or(KernelError::BadFd)?;
let file = files.get(fd).ok_or(KernelError::BadFd)?;
let new_fd = files.insert(fd.clone())?;
let new_fd = match min_fd {
Some(min_fd) => files.insert_above(min_fd, file.clone())?,
None => files.insert(file.clone())?,
};
Ok(new_fd)
}
pub fn sys_dup(fd: Fd) -> Result<usize> {
let new_fd = dup_fd(fd, None)?;
Ok(new_fd.as_raw() as _)
}

View File

@@ -1,9 +1,9 @@
use bitflags::Flags;
use libkernel::error::{KernelError, Result};
use crate::{process::fd_table::FdFlags, sched::current::current_task_shared};
use super::Fd;
use crate::process::fd_table::dup::dup_fd;
use crate::{process::fd_table::FdFlags, sched::current::current_task_shared};
const F_DUPFD: u32 = 0; // Duplicate file descriptor.
const F_GETFD: u32 = 1; // Get file descriptor flags.
@@ -15,7 +15,7 @@ pub async fn sys_fcntl(fd: Fd, op: u32, arg: usize) -> Result<usize> {
let task = current_task_shared();
match op {
F_DUPFD => todo!(),
F_DUPFD => dup_fd(fd, Some(Fd(arg as i32))).map(|new_fd| new_fd.as_raw() as _),
F_GETFD => {
let fds = task.fd_table.lock_save_irq();
let fd = fds