mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 00:43:24 +00:00
Add support for truncate syscall
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
31998d1cd4
commit
195c6a0739
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
TESTS ?= chmod_test fsync_test getdents_test link_test lseek_test mkdir_test \
|
TESTS ?= chmod_test fsync_test getdents_test link_test lseek_test mkdir_test \
|
||||||
open_create_test open_test pty_test read_test rename_test stat_test \
|
open_create_test open_test pty_test read_test rename_test stat_test \
|
||||||
statfs_test symlink_test sync_test uidgid_test unlink_test \
|
statfs_test symlink_test sync_test truncate_test uidgid_test unlink_test \
|
||||||
vdso_clock_gettime_test write_test
|
vdso_clock_gettime_test write_test
|
||||||
|
|
||||||
MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
|
MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||||
|
5
regression/syscall_test/blocklists/truncate_test
Normal file
5
regression/syscall_test/blocklists/truncate_test
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
FixtureTruncateTest.Truncate
|
||||||
|
FixtureTruncateTest.Ftruncate
|
||||||
|
FixtureTruncateTest.FtruncateShrinkGrow
|
||||||
|
TruncateTest.TruncateNonWriteable
|
||||||
|
TruncateTest.FtruncateVirtualTmp_NoRandomSave
|
@ -137,7 +137,7 @@ impl RootInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Inode for RootInode {
|
impl Inode for RootInode {
|
||||||
fn len(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.metadata.size
|
self.metadata.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ impl Ptmx {
|
|||||||
// Many methods are left to do nothing because every time the ptmx is being opened,
|
// Many methods are left to do nothing because every time the ptmx is being opened,
|
||||||
// it returns the pty master. So the ptmx can not be used at upper layer.
|
// it returns the pty master. So the ptmx can not be used at upper layer.
|
||||||
impl Inode for Ptmx {
|
impl Inode for Ptmx {
|
||||||
fn len(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.metadata.size
|
self.metadata.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ impl Inode for PtySlaveInode {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.metadata.size
|
self.metadata.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use aster_rights::Full;
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
impl Inode for Ext2Inode {
|
impl Inode for Ext2Inode {
|
||||||
fn len(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.file_size() as _
|
self.file_size() as _
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,8 +630,8 @@ impl Inner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(&mut self, new_size: usize) -> Result<()> {
|
pub fn resize(&mut self, new_size: usize) -> Result<()> {
|
||||||
self.page_cache.pages().resize(new_size)?;
|
|
||||||
self.inode_impl.resize(new_size)?;
|
self.inode_impl.resize(new_size)?;
|
||||||
|
self.page_cache.pages().resize(new_size)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,10 @@ pub trait FileLike: Send + Sync + Any {
|
|||||||
IoEvents::empty()
|
IoEvents::empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resize(&self, new_size: usize) -> Result<()> {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "resize is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
fn flush(&self) -> Result<()> {
|
fn flush(&self) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,13 @@ impl FileLike for InodeHandle<Rights> {
|
|||||||
self.0.ioctl(cmd, arg)
|
self.0.ioctl(cmd, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resize(&self, new_size: usize) -> Result<()> {
|
||||||
|
if !self.1.contains(Rights::WRITE) {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "File is not writable");
|
||||||
|
}
|
||||||
|
self.0.resize(new_size)
|
||||||
|
}
|
||||||
|
|
||||||
fn metadata(&self) -> Metadata {
|
fn metadata(&self) -> Metadata {
|
||||||
self.dentry().inode_metadata()
|
self.dentry().inode_metadata()
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ impl InodeHandle_ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.status_flags().contains(StatusFlags::O_APPEND) {
|
if self.status_flags().contains(StatusFlags::O_APPEND) {
|
||||||
*offset = self.dentry.inode_len();
|
*offset = self.dentry.inode_size();
|
||||||
}
|
}
|
||||||
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
|
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
|
||||||
self.dentry.inode().write_direct_at(*offset, buf)?
|
self.dentry.inode().write_direct_at(*offset, buf)?
|
||||||
@ -92,7 +92,7 @@ impl InodeHandle_ {
|
|||||||
off as isize
|
off as isize
|
||||||
}
|
}
|
||||||
SeekFrom::End(off /* as isize */) => {
|
SeekFrom::End(off /* as isize */) => {
|
||||||
let file_size = self.dentry.inode_len() as isize;
|
let file_size = self.dentry.inode_size() as isize;
|
||||||
assert!(file_size >= 0);
|
assert!(file_size >= 0);
|
||||||
file_size
|
file_size
|
||||||
.checked_add(off)
|
.checked_add(off)
|
||||||
@ -116,8 +116,15 @@ impl InodeHandle_ {
|
|||||||
*offset
|
*offset
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn size(&self) -> usize {
|
||||||
self.dentry.inode_len()
|
self.dentry.inode_size()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resize(&self, new_size: usize) -> Result<()> {
|
||||||
|
if self.status_flags().contains(StatusFlags::O_APPEND) {
|
||||||
|
return_errno_with_message!(Errno::EPERM, "can not resize append-only file");
|
||||||
|
}
|
||||||
|
self.dentry.set_inode_size(new_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn access_mode(&self) -> AccessMode {
|
pub fn access_mode(&self) -> AccessMode {
|
||||||
|
@ -56,7 +56,7 @@ impl<D: DirOps> ProcDir<D> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<D: DirOps + 'static> Inode for ProcDir<D> {
|
impl<D: DirOps + 'static> Inode for ProcDir<D> {
|
||||||
fn len(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.info.size()
|
self.info.size()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ impl<F: FileOps> ProcFile<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<F: FileOps + 'static> Inode for ProcFile<F> {
|
impl<F: FileOps + 'static> Inode for ProcFile<F> {
|
||||||
fn len(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.info.size()
|
self.info.size()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ impl<S: SymOps> ProcSym<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<S: SymOps + 'static> Inode for ProcSym<S> {
|
impl<S: SymOps + 'static> Inode for ProcSym<S> {
|
||||||
fn len(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.info.size()
|
self.info.size()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,8 +412,9 @@ impl RamInode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PageCacheBackend for RamInode {
|
impl PageCacheBackend for RamInode {
|
||||||
fn read_page(&self, _idx: usize, _frame: &VmFrame) -> Result<()> {
|
fn read_page(&self, _idx: usize, frame: &VmFrame) -> Result<()> {
|
||||||
// do nothing
|
// Initially, any block/page in a RamFs inode contains all zeros
|
||||||
|
frame.zero();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,9 +447,9 @@ impl Inode for RamInode {
|
|||||||
return_errno_with_message!(Errno::EISDIR, "read is not supported");
|
return_errno_with_message!(Errno::EISDIR, "read is not supported");
|
||||||
};
|
};
|
||||||
let (offset, read_len) = {
|
let (offset, read_len) = {
|
||||||
let file_len = self_inode.metadata.size;
|
let file_size = self_inode.metadata.size;
|
||||||
let start = file_len.min(offset);
|
let start = file_size.min(offset);
|
||||||
let end = file_len.min(offset + buf.len());
|
let end = file_size.min(offset + buf.len());
|
||||||
(start, end - start)
|
(start, end - start)
|
||||||
};
|
};
|
||||||
page_cache
|
page_cache
|
||||||
@ -470,17 +471,17 @@ impl Inode for RamInode {
|
|||||||
let Some(page_cache) = self_inode.inner.as_file() else {
|
let Some(page_cache) = self_inode.inner.as_file() else {
|
||||||
return_errno_with_message!(Errno::EISDIR, "write is not supported");
|
return_errno_with_message!(Errno::EISDIR, "write is not supported");
|
||||||
};
|
};
|
||||||
let file_len = self_inode.metadata.size;
|
let file_size = self_inode.metadata.size;
|
||||||
let new_len = offset + buf.len();
|
let new_size = offset + buf.len();
|
||||||
let should_expand_len = new_len > file_len;
|
let should_expand_size = new_size > file_size;
|
||||||
if should_expand_len {
|
if should_expand_size {
|
||||||
page_cache.pages().resize(new_len)?;
|
page_cache.pages().resize(new_size)?;
|
||||||
}
|
}
|
||||||
page_cache.pages().write_bytes(offset, buf)?;
|
page_cache.pages().write_bytes(offset, buf)?;
|
||||||
if should_expand_len {
|
if should_expand_size {
|
||||||
// Turn the read guard into a write guard without releasing the lock.
|
// Turn the read guard into a write guard without releasing the lock.
|
||||||
let mut self_inode = self_inode.upgrade();
|
let mut self_inode = self_inode.upgrade();
|
||||||
self_inode.resize(new_len);
|
self_inode.resize(new_size);
|
||||||
}
|
}
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
@ -489,12 +490,26 @@ impl Inode for RamInode {
|
|||||||
self.write_at(offset, buf)
|
self.write_at(offset, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.0.read().metadata.size
|
self.0.read().metadata.size
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&self, new_size: usize) -> Result<()> {
|
fn resize(&self, new_size: usize) -> Result<()> {
|
||||||
self.0.write().resize(new_size);
|
let self_inode = self.0.upread();
|
||||||
|
if self_inode.inner.as_file().is_none() {
|
||||||
|
return_errno!(Errno::EISDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_size = self_inode.metadata.size;
|
||||||
|
if file_size == new_size {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut self_inode = self_inode.upgrade();
|
||||||
|
self_inode.resize(new_size);
|
||||||
|
let page_cache = self_inode.inner.as_file().unwrap();
|
||||||
|
page_cache.pages().resize(new_size)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,9 +410,14 @@ impl Dentry {
|
|||||||
self.inode.set_mode(mode)
|
self.inode.set_mode(mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the inode length
|
/// Gets the size of the inode
|
||||||
pub fn inode_len(&self) -> usize {
|
pub fn inode_size(&self) -> usize {
|
||||||
self.inode.len()
|
self.inode.size()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the size of the inode
|
||||||
|
pub fn set_inode_size(&self, new_size: usize) -> Result<()> {
|
||||||
|
self.inode.resize(new_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the access timestamp
|
/// Get the access timestamp
|
||||||
|
@ -227,11 +227,7 @@ impl Metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Inode: Any + Sync + Send {
|
pub trait Inode: Any + Sync + Send {
|
||||||
fn len(&self) -> usize;
|
fn size(&self) -> usize;
|
||||||
|
|
||||||
fn is_empty(&self) -> bool {
|
|
||||||
self.len() == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resize(&self, new_size: usize) -> Result<()>;
|
fn resize(&self, new_size: usize) -> Result<()>;
|
||||||
|
|
||||||
@ -364,11 +360,11 @@ impl dyn Inode {
|
|||||||
return_errno!(Errno::EISDIR);
|
return_errno!(Errno::EISDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
let file_len = self.len();
|
let file_size = self.size();
|
||||||
if buf.len() < file_len {
|
if buf.len() < file_size {
|
||||||
buf.resize(file_len, 0);
|
buf.resize(file_size, 0);
|
||||||
}
|
}
|
||||||
self.read_at(0, &mut buf[..file_len])
|
self.read_at(0, &mut buf[..file_size])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_direct_to_end(&self, buf: &mut Vec<u8>) -> Result<usize> {
|
pub fn read_direct_to_end(&self, buf: &mut Vec<u8>) -> Result<usize> {
|
||||||
@ -376,11 +372,11 @@ impl dyn Inode {
|
|||||||
return_errno!(Errno::EISDIR);
|
return_errno!(Errno::EISDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
let file_len = self.len();
|
let file_size = self.size();
|
||||||
if buf.len() < file_len {
|
if buf.len() < file_size {
|
||||||
buf.resize(file_len, 0);
|
buf.resize(file_size, 0);
|
||||||
}
|
}
|
||||||
self.read_direct_at(0, &mut buf[..file_len])
|
self.read_direct_at(0, &mut buf[..file_size])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writer(&self, from_offset: usize) -> InodeWriter {
|
pub fn writer(&self, from_offset: usize) -> InodeWriter {
|
||||||
|
@ -56,6 +56,16 @@ impl PageCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for PageCache {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// TODO:
|
||||||
|
// The default destruction procedure exhibits slow performance.
|
||||||
|
// In contrast, resizing the `VMO` to zero greatly accelerates the process.
|
||||||
|
// We need to find out the underlying cause of this discrepancy.
|
||||||
|
let _ = self.pages.resize(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Debug for PageCache {
|
impl Debug for PageCache {
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
f.debug_struct("PageCache")
|
f.debug_struct("PageCache")
|
||||||
@ -147,7 +157,9 @@ impl Pager for PageCacheManager {
|
|||||||
let mut pages = self.pages.lock();
|
let mut pages = self.pages.lock();
|
||||||
if let Some(page) = pages.pop(&idx) {
|
if let Some(page) = pages.pop(&idx) {
|
||||||
if let PageState::Dirty = page.state() {
|
if let PageState::Dirty = page.state() {
|
||||||
let backend = self.backend();
|
let Some(backend) = self.backend.upgrade() else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
if idx < backend.npages() {
|
if idx < backend.npages() {
|
||||||
backend.write_page(idx, page.frame())?;
|
backend.write_page(idx, page.frame())?;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,7 @@ use crate::syscall::symlink::{sys_symlink, sys_symlinkat};
|
|||||||
use crate::syscall::sync::sys_sync;
|
use crate::syscall::sync::sys_sync;
|
||||||
use crate::syscall::tgkill::sys_tgkill;
|
use crate::syscall::tgkill::sys_tgkill;
|
||||||
use crate::syscall::time::sys_time;
|
use crate::syscall::time::sys_time;
|
||||||
|
use crate::syscall::truncate::{sys_ftruncate, sys_truncate};
|
||||||
use crate::syscall::umask::sys_umask;
|
use crate::syscall::umask::sys_umask;
|
||||||
use crate::syscall::uname::sys_uname;
|
use crate::syscall::uname::sys_uname;
|
||||||
use crate::syscall::unlink::{sys_unlink, sys_unlinkat};
|
use crate::syscall::unlink::{sys_unlink, sys_unlinkat};
|
||||||
@ -200,6 +201,7 @@ mod symlink;
|
|||||||
mod sync;
|
mod sync;
|
||||||
mod tgkill;
|
mod tgkill;
|
||||||
mod time;
|
mod time;
|
||||||
|
mod truncate;
|
||||||
mod umask;
|
mod umask;
|
||||||
mod uname;
|
mod uname;
|
||||||
mod unlink;
|
mod unlink;
|
||||||
@ -290,6 +292,8 @@ define_syscall_nums!(
|
|||||||
SYS_UNAME = 63,
|
SYS_UNAME = 63,
|
||||||
SYS_FCNTL = 72,
|
SYS_FCNTL = 72,
|
||||||
SYS_FSYNC = 74,
|
SYS_FSYNC = 74,
|
||||||
|
SYS_TRUNCATE = 76,
|
||||||
|
SYS_FTRUNCATE = 77,
|
||||||
SYS_GETCWD = 79,
|
SYS_GETCWD = 79,
|
||||||
SYS_CHDIR = 80,
|
SYS_CHDIR = 80,
|
||||||
SYS_FCHDIR = 81,
|
SYS_FCHDIR = 81,
|
||||||
@ -468,6 +472,8 @@ pub fn syscall_dispatch(
|
|||||||
SYS_UNAME => syscall_handler!(1, sys_uname, args),
|
SYS_UNAME => syscall_handler!(1, sys_uname, args),
|
||||||
SYS_FCNTL => syscall_handler!(3, sys_fcntl, args),
|
SYS_FCNTL => syscall_handler!(3, sys_fcntl, args),
|
||||||
SYS_FSYNC => syscall_handler!(1, sys_fsync, args),
|
SYS_FSYNC => syscall_handler!(1, sys_fsync, args),
|
||||||
|
SYS_TRUNCATE => syscall_handler!(2, sys_truncate, args),
|
||||||
|
SYS_FTRUNCATE => syscall_handler!(2, sys_ftruncate, args),
|
||||||
SYS_GETCWD => syscall_handler!(2, sys_getcwd, args),
|
SYS_GETCWD => syscall_handler!(2, sys_getcwd, args),
|
||||||
SYS_CHDIR => syscall_handler!(1, sys_chdir, args),
|
SYS_CHDIR => syscall_handler!(1, sys_chdir, args),
|
||||||
SYS_FCHDIR => syscall_handler!(1, sys_fchdir, args),
|
SYS_FCHDIR => syscall_handler!(1, sys_fchdir, args),
|
||||||
|
66
services/libs/aster-std/src/syscall/truncate.rs
Normal file
66
services/libs/aster-std/src/syscall/truncate.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use crate::fs::{
|
||||||
|
file_table::FileDescripter,
|
||||||
|
fs_resolver::{FsPath, AT_FDCWD},
|
||||||
|
utils::PATH_MAX,
|
||||||
|
};
|
||||||
|
use crate::log_syscall_entry;
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::process::ResourceType;
|
||||||
|
use crate::util::read_cstring_from_user;
|
||||||
|
|
||||||
|
use super::SyscallReturn;
|
||||||
|
use super::{SYS_FTRUNCATE, SYS_TRUNCATE};
|
||||||
|
|
||||||
|
pub fn sys_ftruncate(fd: FileDescripter, len: isize) -> Result<SyscallReturn> {
|
||||||
|
log_syscall_entry!(SYS_FTRUNCATE);
|
||||||
|
debug!("fd = {}, lentgh = {}", fd, len);
|
||||||
|
|
||||||
|
check_length(len)?;
|
||||||
|
|
||||||
|
let current = current!();
|
||||||
|
let file_table = current.file_table().lock();
|
||||||
|
let file = file_table.get_file(fd)?;
|
||||||
|
file.resize(len as usize)?;
|
||||||
|
Ok(SyscallReturn::Return(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sys_truncate(path_ptr: Vaddr, len: isize) -> Result<SyscallReturn> {
|
||||||
|
log_syscall_entry!(SYS_TRUNCATE);
|
||||||
|
let path = read_cstring_from_user(path_ptr, PATH_MAX)?;
|
||||||
|
debug!("path = {:?}, length = {}", path, len);
|
||||||
|
|
||||||
|
check_length(len)?;
|
||||||
|
|
||||||
|
let current = current!();
|
||||||
|
let dentry = {
|
||||||
|
let path = path.to_string_lossy();
|
||||||
|
if path.is_empty() {
|
||||||
|
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
||||||
|
}
|
||||||
|
let fs_path = FsPath::new(AT_FDCWD, path.as_ref())?;
|
||||||
|
current.fs().read().lookup(&fs_path)?
|
||||||
|
};
|
||||||
|
dentry.set_inode_size(len as usize)?;
|
||||||
|
Ok(SyscallReturn::Return(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn check_length(len: isize) -> Result<()> {
|
||||||
|
if len < 0 {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "length is negative");
|
||||||
|
}
|
||||||
|
|
||||||
|
let max_file_size = {
|
||||||
|
let current = current!();
|
||||||
|
let resource_limits = current.resource_limits().lock();
|
||||||
|
resource_limits
|
||||||
|
.get_rlimit(ResourceType::RLIMIT_FSIZE)
|
||||||
|
.get_cur() as usize
|
||||||
|
};
|
||||||
|
if len as usize > max_file_size {
|
||||||
|
return_errno_with_message!(Errno::EFBIG, "length is larger than the maximum file size");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
Reference in New Issue
Block a user