1use alloc::sync::Arc;
4
5use crate::{
6 arch::trap::SumGuard,
7 kernel::{current_cpu, current_task},
8 vfs::{FdFlags, File, FsError, OpenFlags, PipeFile},
9};
10
11pub fn dup(oldfd: usize) -> isize {
12 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
13 match task.lock().fd_table.dup(oldfd) {
14 Ok(newfd) => newfd as isize,
15 Err(e) => e.to_errno(),
16 }
17}
18
19pub fn dup3(oldfd: usize, newfd: usize, flags: u32) -> isize {
20 let task = current_cpu().lock().current_task.as_ref().unwrap().clone();
21
22 let open_flags = match OpenFlags::from_bits(flags) {
23 Some(f) => f,
24 None => return FsError::InvalidArgument.to_errno(),
25 };
26
27 if open_flags.bits() & !OpenFlags::O_CLOEXEC.bits() != 0 {
28 return FsError::InvalidArgument.to_errno();
29 }
30
31 match task.lock().fd_table.dup3(oldfd, newfd, open_flags) {
32 Ok(newfd) => newfd as isize,
33 Err(e) => e.to_errno(),
34 }
35}
36
37pub fn pipe2(pipefd: *mut i32, flags: u32) -> isize {
38 if pipefd.is_null() {
39 return FsError::InvalidArgument.to_errno();
40 }
41
42 let valid_flags = OpenFlags::O_CLOEXEC | OpenFlags::O_NONBLOCK;
43 if flags & !valid_flags.bits() != 0 {
44 return FsError::InvalidArgument.to_errno();
45 }
46
47 let fd_flags =
48 FdFlags::from_open_flags(OpenFlags::from_bits(flags).unwrap_or(OpenFlags::empty()));
49
50 let (pipe_read, pipe_write) = PipeFile::create_pair();
51
52 let fd_table = current_task().lock().fd_table.clone();
54
55 let read_fd =
57 match fd_table.alloc_with_flags(Arc::new(pipe_read) as Arc<dyn File>, fd_flags.clone()) {
58 Ok(fd) => fd,
59 Err(e) => return e.to_errno(),
60 };
61
62 let write_fd = match fd_table.alloc_with_flags(Arc::new(pipe_write) as Arc<dyn File>, fd_flags)
63 {
64 Ok(fd) => fd,
65 Err(e) => {
66 let _ = fd_table.close(read_fd);
68 return e.to_errno();
69 }
70 };
71
72 {
74 let _guard = SumGuard::new();
75 unsafe {
76 core::ptr::write(pipefd.offset(0), read_fd as i32);
77 core::ptr::write(pipefd.offset(1), write_fd as i32);
78 }
79 }
80
81 0
82}