mirror of
https://github.com/hexagonal-sun/moss-kernel.git
synced 2026-01-31 09:31:58 -05:00
implement F_DUPFD for sys_fcntl
This commit is contained in:
@@ -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>> {
|
||||
|
||||
@@ -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 _)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user