mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-10 13:56:48 +00:00
Add support for lseek syscall
This commit is contained in:
parent
116b687cae
commit
4e3dfe93da
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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) => {
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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 _))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user