starry_api/imp/fs/
io.rs

1use core::ffi::c_int;
2
3use axerrno::{LinuxError, LinuxResult};
4use axio::SeekFrom;
5use linux_raw_sys::general::{__kernel_off_t, iovec};
6
7use crate::{
8    file::{File, FileLike, get_file_like},
9    ptr::{UserConstPtr, UserPtr},
10};
11
12/// Read data from the file indicated by `fd`.
13///
14/// Return the read size if success.
15pub fn sys_read(fd: i32, buf: UserPtr<u8>, len: usize) -> LinuxResult<isize> {
16    let buf = buf.get_as_mut_slice(len)?;
17    debug!(
18        "sys_read <= fd: {}, buf: {:p}, len: {}",
19        fd,
20        buf.as_ptr(),
21        buf.len()
22    );
23    Ok(get_file_like(fd)?.read(buf)? as _)
24}
25
26pub fn sys_readv(fd: i32, iov: UserPtr<iovec>, iocnt: usize) -> LinuxResult<isize> {
27    if !(0..=1024).contains(&iocnt) {
28        return Err(LinuxError::EINVAL);
29    }
30
31    let iovs = iov.get_as_mut_slice(iocnt)?;
32    let mut ret = 0;
33    for iov in iovs {
34        if iov.iov_len == 0 {
35            continue;
36        }
37        let buf = UserPtr::<u8>::from(iov.iov_base as usize);
38        let buf = buf.get_as_mut_slice(iov.iov_len as _)?;
39        debug!(
40            "sys_readv <= fd: {}, buf: {:p}, len: {}",
41            fd,
42            buf.as_ptr(),
43            buf.len()
44        );
45
46        let read = get_file_like(fd)?.read(buf)?;
47        ret += read as isize;
48
49        if read < buf.len() {
50            break;
51        }
52    }
53
54    Ok(ret)
55}
56
57/// Write data to the file indicated by `fd`.
58///
59/// Return the written size if success.
60pub fn sys_write(fd: i32, buf: UserConstPtr<u8>, len: usize) -> LinuxResult<isize> {
61    let buf = buf.get_as_slice(len)?;
62    debug!(
63        "sys_write <= fd: {}, buf: {:p}, len: {}",
64        fd,
65        buf.as_ptr(),
66        buf.len()
67    );
68    Ok(get_file_like(fd)?.write(buf)? as _)
69}
70
71pub fn sys_writev(fd: i32, iov: UserConstPtr<iovec>, iocnt: usize) -> LinuxResult<isize> {
72    if !(0..=1024).contains(&iocnt) {
73        return Err(LinuxError::EINVAL);
74    }
75
76    let iovs = iov.get_as_slice(iocnt)?;
77    let mut ret = 0;
78    for iov in iovs {
79        if iov.iov_len == 0 {
80            continue;
81        }
82        let buf = UserConstPtr::<u8>::from(iov.iov_base as usize);
83        let buf = buf.get_as_slice(iov.iov_len as _)?;
84        debug!(
85            "sys_writev <= fd: {}, buf: {:p}, len: {}",
86            fd,
87            buf.as_ptr(),
88            buf.len()
89        );
90
91        let written = get_file_like(fd)?.write(buf)?;
92        ret += written as isize;
93
94        if written < buf.len() {
95            break;
96        }
97    }
98
99    Ok(ret)
100}
101
102pub fn sys_lseek(fd: c_int, offset: __kernel_off_t, whence: c_int) -> LinuxResult<isize> {
103    debug!("sys_lseek <= {} {} {}", fd, offset, whence);
104    let pos = match whence {
105        0 => SeekFrom::Start(offset as _),
106        1 => SeekFrom::Current(offset as _),
107        2 => SeekFrom::End(offset as _),
108        _ => return Err(LinuxError::EINVAL),
109    };
110    let off = File::from_fd(fd)?.inner().seek(pos)?;
111    Ok(off as _)
112}