Add support for lseek syscall

This commit is contained in:
LI Qing 2023-02-20 16:40:04 +08:00 committed by Tate, Hongliang Tian
parent 116b687cae
commit 4e3dfe93da
6 changed files with 59 additions and 18 deletions

View File

@ -2,7 +2,7 @@ use crate::prelude::*;
use crate::tty::get_n_tty;
use core::any::Any;
use crate::fs::utils::{IoEvents, IoctlCmd, Metadata};
use crate::fs::utils::{IoEvents, IoctlCmd, Metadata, SeekFrom};
/// The basic operations defined on a file
pub trait File: Send + Sync + Any {
@ -36,4 +36,8 @@ pub trait File: Send + Sync + Any {
fn metadata(&self) -> Metadata {
panic!("metadata unsupported");
}
fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
panic!("seek unsupported");
}
}

View File

@ -70,28 +70,28 @@ impl InodeHandle_ {
pub fn seek(&self, pos: SeekFrom) -> Result<usize> {
let mut offset = self.offset.lock();
let new_offset: i64 = match pos {
SeekFrom::Start(off /* as u64 */) => {
if off > i64::max_value() as u64 {
let new_offset: isize = match pos {
SeekFrom::Start(off /* as usize */) => {
if off > isize::max_value() as usize {
return_errno_with_message!(Errno::EINVAL, "file offset is too large");
}
off as i64
off as isize
}
SeekFrom::End(off /* as i64 */) => {
let file_size = self.dentry.vnode().inode().metadata().size as i64;
SeekFrom::End(off /* as isize */) => {
let file_size = self.dentry.vnode().inode().metadata().size as isize;
assert!(file_size >= 0);
file_size
.checked_add(off)
.ok_or_else(|| Error::with_message(Errno::EOVERFLOW, "file offset overflow"))?
}
SeekFrom::Current(off /* as i64 */) => (*offset as i64)
SeekFrom::Current(off /* as isize */) => (*offset as isize)
.checked_add(off)
.ok_or_else(|| Error::with_message(Errno::EOVERFLOW, "file offset overflow"))?,
};
if new_offset < 0 {
return_errno_with_message!(Errno::EINVAL, "file offset must not be negative");
}
// Invariant: 0 <= new_offset <= i64::max_value()
// Invariant: 0 <= new_offset <= isize::max_value()
let new_offset = new_offset as usize;
*offset = new_offset;
Ok(new_offset)

View File

@ -3,7 +3,7 @@
mod file;
mod inode_handle;
use crate::fs::utils::Metadata;
use crate::fs::utils::{Metadata, SeekFrom};
use crate::prelude::*;
use crate::rights::{ReadOp, WriteOp};
use alloc::sync::Arc;
@ -74,6 +74,13 @@ impl FileHandle {
}
}
pub fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
match &self.inner {
Inner::File(file) => file.seek(seek_from),
Inner::Inode(inode_handle) => inode_handle.seek(seek_from),
}
}
pub fn clean_for_close(&self) -> Result<()> {
match &self.inner {
Inner::Inode(inode_handle) => {

View File

@ -3,7 +3,7 @@ use crate::tty::{get_n_tty, Tty};
use super::file_handle::File;
use super::file_table::FileDescripter;
use super::utils::{InodeMode, InodeType, IoEvents, Metadata};
use super::utils::{InodeMode, InodeType, IoEvents, Metadata, SeekFrom};
pub const FD_STDIN: FileDescripter = 0;
pub const FD_STDOUT: FileDescripter = 1;
@ -46,6 +46,11 @@ impl File for Stdin {
}
}
fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
// TODO: do real seek
Ok(0)
}
fn metadata(&self) -> Metadata {
Metadata {
dev: 0,
@ -82,6 +87,11 @@ impl File for Stdout {
}
}
fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
// TODO: do real seek
Ok(0)
}
fn metadata(&self) -> Metadata {
Metadata {
dev: 0,
@ -119,6 +129,11 @@ impl File for Stderr {
}
}
fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
// TODO: do real seek
Ok(0)
}
fn metadata(&self) -> Metadata {
Metadata {
dev: 0,

View File

@ -32,9 +32,9 @@ mod vnode;
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
pub enum SeekFrom {
Start(u64),
End(i64),
Current(i64),
Start(usize),
End(isize),
Current(isize),
}
/// Maximum bytes in a path

View File

@ -1,12 +1,27 @@
use crate::fs::{file_table::FileDescripter, utils::SeekFrom};
use crate::log_syscall_entry;
use crate::{fs::file_table::FileDescripter, prelude::*};
use crate::prelude::*;
use super::SyscallReturn;
use super::SYS_LSEEK;
pub fn sys_lseek(fd: FileDescripter, offset: usize, whence: u32) -> Result<SyscallReturn> {
pub fn sys_lseek(fd: FileDescripter, offset: isize, whence: u32) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_LSEEK);
debug!("fd = {}, offset = {}, whence = {}", fd, offset, whence);
// TODO: do lseek
Ok(SyscallReturn::Return(0))
let seek_from = match whence {
0 => {
if offset < 0 {
return_errno!(Errno::EINVAL);
}
SeekFrom::Start(offset as usize)
}
1 => SeekFrom::Current(offset),
2 => SeekFrom::End(offset),
_ => return_errno!(Errno::EINVAL),
};
let current = current!();
let file_table = current.file_table().lock();
let file = file_table.get_file(fd)?;
let offset = file.seek(seek_from)?;
Ok(SyscallReturn::Return(offset as _))
}