111 lines
No EOL
3 KiB
Rust
111 lines
No EOL
3 KiB
Rust
use crate::mm::{
|
|
UserBuffer,
|
|
translated_byte_buffer,
|
|
translated_refmut,
|
|
translated_str,
|
|
};
|
|
use crate::task::{current_user_token, current_task};
|
|
use crate::fs::{make_pipe, OpenFlags, open_file};
|
|
use alloc::sync::Arc;
|
|
|
|
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
|
|
let token = current_user_token();
|
|
let task = current_task().unwrap();
|
|
let inner = task.acquire_inner_lock();
|
|
if fd >= inner.fd_table.len() {
|
|
return -1;
|
|
}
|
|
if let Some(file) = &inner.fd_table[fd] {
|
|
if !file.writable() {
|
|
return -1;
|
|
}
|
|
let file = file.clone();
|
|
// release Task lock manually to avoid deadlock
|
|
drop(inner);
|
|
file.write(
|
|
UserBuffer::new(translated_byte_buffer(token, buf, len))
|
|
) as isize
|
|
} else {
|
|
-1
|
|
}
|
|
}
|
|
|
|
pub fn sys_read(fd: usize, buf: *const u8, len: usize) -> isize {
|
|
let token = current_user_token();
|
|
let task = current_task().unwrap();
|
|
let inner = task.acquire_inner_lock();
|
|
if fd >= inner.fd_table.len() {
|
|
return -1;
|
|
}
|
|
if let Some(file) = &inner.fd_table[fd] {
|
|
let file = file.clone();
|
|
if !file.readable() {
|
|
return -1;
|
|
}
|
|
// release Task lock manually to avoid deadlock
|
|
drop(inner);
|
|
file.read(
|
|
UserBuffer::new(translated_byte_buffer(token, buf, len))
|
|
) as isize
|
|
} else {
|
|
-1
|
|
}
|
|
}
|
|
|
|
pub fn sys_open(path: *const u8, flags: u32) -> isize {
|
|
let task = current_task().unwrap();
|
|
let token = current_user_token();
|
|
let path = translated_str(token, path);
|
|
if let Some(inode) = open_file(
|
|
path.as_str(),
|
|
OpenFlags::from_bits(flags).unwrap()
|
|
) {
|
|
let mut inner = task.acquire_inner_lock();
|
|
let fd = inner.alloc_fd();
|
|
inner.fd_table[fd] = Some(inode);
|
|
fd as isize
|
|
} else {
|
|
-1
|
|
}
|
|
}
|
|
|
|
pub fn sys_close(fd: usize) -> isize {
|
|
let task = current_task().unwrap();
|
|
let mut inner = task.acquire_inner_lock();
|
|
if fd >= inner.fd_table.len() {
|
|
return -1;
|
|
}
|
|
if inner.fd_table[fd].is_none() {
|
|
return -1;
|
|
}
|
|
inner.fd_table[fd].take();
|
|
0
|
|
}
|
|
|
|
pub fn sys_pipe(pipe: *mut usize) -> isize {
|
|
let task = current_task().unwrap();
|
|
let token = current_user_token();
|
|
let mut inner = task.acquire_inner_lock();
|
|
let (pipe_read, pipe_write) = make_pipe();
|
|
let read_fd = inner.alloc_fd();
|
|
inner.fd_table[read_fd] = Some(pipe_read);
|
|
let write_fd = inner.alloc_fd();
|
|
inner.fd_table[write_fd] = Some(pipe_write);
|
|
*translated_refmut(token, pipe) = read_fd;
|
|
*translated_refmut(token, unsafe { pipe.add(1) }) = write_fd;
|
|
0
|
|
}
|
|
|
|
pub fn sys_dup(fd: usize) -> isize {
|
|
let task = current_task().unwrap();
|
|
let mut inner = task.acquire_inner_lock();
|
|
if fd >= inner.fd_table.len() {
|
|
return -1;
|
|
}
|
|
if inner.fd_table[fd].is_none() {
|
|
return -1;
|
|
}
|
|
let new_fd = inner.alloc_fd();
|
|
inner.fd_table[new_fd] = Some(Arc::clone(inner.fd_table[fd].as_ref().unwrap()));
|
|
new_fd as isize
|
|
} |