Add read_at and write_at for FileLike and InodeHandle

This commit is contained in:
Jianfeng Jiang
2024-05-15 11:03:59 +00:00
committed by Tate, Hongliang Tian
parent 6e9516daa4
commit 14ada9000a
3 changed files with 67 additions and 14 deletions

View File

@ -23,6 +23,23 @@ pub trait FileLike: Send + Sync + Any {
return_errno_with_message!(Errno::EINVAL, "write is not supported");
}
/// Read at the given file offset.
///
/// The file must be seekable to support `read_at`.
/// Unlike [`read`], `read_at` will not change the file offset.
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
return_errno_with_message!(Errno::EINVAL, "read_at is not supported");
}
/// Write at the given file offset.
///
/// The file must be seekable to support `write_at`.
/// Unlike [`write`], `write_at` will not change the file offset.
/// If the file is append-only, the `offset` will be ignored.
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
return_errno_with_message!(Errno::EINVAL, "write_at is not supported");
}
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
return_errno_with_message!(Errno::EINVAL, "ioctl is not supported");
}

View File

@ -98,6 +98,20 @@ impl FileLike for InodeHandle<Rights> {
self.0.write(buf)
}
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
if !self.1.contains(Rights::READ) {
return_errno_with_message!(Errno::EBADF, "file is not readable");
}
self.0.read_at(offset, buf)
}
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
if !self.1.contains(Rights::WRITE) {
return_errno_with_message!(Errno::EBADF, "file is not writable");
}
self.0.write_at(offset, buf)
}
fn resize(&self, new_size: usize) -> Result<()> {
if !self.1.contains(Rights::WRITE) {
return_errno_with_message!(Errno::EINVAL, "File is not writable");

View File

@ -41,42 +41,64 @@ struct InodeHandle_ {
impl InodeHandle_ {
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
let mut offset = self.offset.lock();
if let Some(ref file_io) = self.file_io {
return file_io.read(buf);
}
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
self.dentry.inode().read_direct_at(*offset, buf)?
} else {
self.dentry.inode().read_at(*offset, buf)?
};
let mut offset = self.offset.lock();
let len = self.read_at(*offset, buf)?;
*offset += len;
Ok(len)
}
pub fn write(&self, buf: &[u8]) -> Result<usize> {
let mut offset = self.offset.lock();
if let Some(ref file_io) = self.file_io {
return file_io.write(buf);
}
let mut offset = self.offset.lock();
if self.status_flags().contains(StatusFlags::O_APPEND) {
*offset = self.dentry.size();
}
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
self.dentry.inode().write_direct_at(*offset, buf)?
} else {
self.dentry.inode().write_at(*offset, buf)?
};
let len = self.write_at(*offset, buf)?;
*offset += len;
Ok(len)
}
pub fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
if let Some(ref file_io) = self.file_io {
todo!("support read_at for FileIo");
}
if self.status_flags().contains(StatusFlags::O_DIRECT) {
self.dentry.inode().read_direct_at(offset, buf)
} else {
self.dentry.inode().read_at(offset, buf)
}
}
pub fn write_at(&self, mut offset: usize, buf: &[u8]) -> Result<usize> {
if let Some(ref file_io) = self.file_io {
todo!("support write_at for FileIo");
}
if self.status_flags().contains(StatusFlags::O_APPEND) {
// If the file has the O_APPEND flag, the offset is ignored
offset = self.dentry.size();
}
if self.status_flags().contains(StatusFlags::O_DIRECT) {
self.dentry.inode().write_direct_at(offset, buf)
} else {
self.dentry.inode().write_at(offset, buf)
}
}
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> Result<usize> {
if self.file_io.is_some() {
return_errno_with_message!(Errno::EINVAL, "file io does not support read to end");