os/syscall/
fs.rs

1use crate::fs::{OpenFlags, make_pipe, open_file};
2use crate::mm::{UserBuffer, translated_byte_buffer, translated_refmut, translated_str};
3use crate::task::{current_process, current_user_token};
4use alloc::sync::Arc;
5
6pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
7    let token = current_user_token();
8    let process = current_process();
9    let inner = process.inner_exclusive_access();
10    if fd >= inner.fd_table.len() {
11        return -1;
12    }
13    if let Some(file) = &inner.fd_table[fd] {
14        if !file.writable() {
15            return -1;
16        }
17        let file = file.clone();
18        // release current task TCB manually to avoid multi-borrow
19        drop(inner);
20        file.write(UserBuffer::new(translated_byte_buffer(token, buf, len))) as isize
21    } else {
22        -1
23    }
24}
25
26pub fn sys_read(fd: usize, buf: *const u8, len: usize) -> isize {
27    let token = current_user_token();
28    let process = current_process();
29    let inner = process.inner_exclusive_access();
30    if fd >= inner.fd_table.len() {
31        return -1;
32    }
33    if let Some(file) = &inner.fd_table[fd] {
34        let file = file.clone();
35        if !file.readable() {
36            return -1;
37        }
38        // release current task TCB manually to avoid multi-borrow
39        drop(inner);
40        file.read(UserBuffer::new(translated_byte_buffer(token, buf, len))) as isize
41    } else {
42        -1
43    }
44}
45
46pub fn sys_open(path: *const u8, flags: u32) -> isize {
47    let process = current_process();
48    let token = current_user_token();
49    let path = translated_str(token, path);
50    if let Some(inode) = open_file(path.as_str(), OpenFlags::from_bits(flags).unwrap()) {
51        let mut inner = process.inner_exclusive_access();
52        let fd = inner.alloc_fd();
53        inner.fd_table[fd] = Some(inode);
54        fd as isize
55    } else {
56        -1
57    }
58}
59
60pub fn sys_close(fd: usize) -> isize {
61    let process = current_process();
62    let mut inner = process.inner_exclusive_access();
63    if fd >= inner.fd_table.len() {
64        return -1;
65    }
66    if inner.fd_table[fd].is_none() {
67        return -1;
68    }
69    inner.fd_table[fd].take();
70    0
71}
72
73pub fn sys_pipe(pipe: *mut usize) -> isize {
74    let process = current_process();
75    let token = current_user_token();
76    let mut inner = process.inner_exclusive_access();
77    let (pipe_read, pipe_write) = make_pipe();
78    let read_fd = inner.alloc_fd();
79    inner.fd_table[read_fd] = Some(pipe_read);
80    let write_fd = inner.alloc_fd();
81    inner.fd_table[write_fd] = Some(pipe_write);
82    *translated_refmut(token, pipe) = read_fd;
83    *translated_refmut(token, unsafe { pipe.add(1) }) = write_fd;
84    0
85}
86
87pub fn sys_dup(fd: usize) -> isize {
88    let process = current_process();
89    let mut inner = process.inner_exclusive_access();
90    if fd >= inner.fd_table.len() {
91        return -1;
92    }
93    if inner.fd_table[fd].is_none() {
94        return -1;
95    }
96    let new_fd = inner.alloc_fd();
97    inner.fd_table[new_fd] = Some(Arc::clone(inner.fd_table[fd].as_ref().unwrap()));
98    new_fd as isize
99}