2022-06-18 16:37:54 +00:00
/*
* Copyright ( c ) 2022 , Leon Albrecht < leon . a @ serenityos . org >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# include <AK/Checked.h>
# include <Kernel/FileSystem/Inode.h>
# include <Kernel/FileSystem/InodeFile.h>
# include <Kernel/FileSystem/OpenFileDescription.h>
2023-02-24 17:45:37 +00:00
# include <Kernel/Tasks/Process.h>
2022-06-18 16:37:54 +00:00
namespace Kernel {
2022-11-27 19:13:15 +00:00
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fallocate.html
2023-08-11 08:47:31 +00:00
ErrorOr < FlatPtr > Process : : sys $ posix_fallocate ( int fd , off_t offset , off_t length )
2022-06-18 16:37:54 +00:00
{
VERIFY_NO_PROCESS_BIG_LOCK ( this ) ;
TRY ( require_promise ( Pledge : : stdio ) ) ;
2022-11-27 19:13:15 +00:00
// [EINVAL] The len argument is less than zero, or the offset argument is less than zero, or the underlying file system does not support this operation.
2022-06-18 16:37:54 +00:00
if ( offset < 0 )
return EINVAL ;
if ( length < = 0 )
return EINVAL ;
Checked < size_t > checked_size { length } ;
checked_size + = offset ;
// FIXME: Return EFBIG if offset+length > FileSizeMax
if ( checked_size . has_overflow ( ) )
return EFBIG ;
auto description = TRY ( open_file_description ( fd ) ) ;
2022-11-27 19:13:15 +00:00
// [EBADF] The fd argument references a file that was opened without write permission.
2022-06-18 16:37:54 +00:00
if ( ! description - > is_writable ( ) )
return EBADF ;
2022-11-27 19:13:15 +00:00
// [ESPIPE] The fd argument is associated with a pipe or FIFO.
2022-06-18 16:37:54 +00:00
if ( description - > is_fifo ( ) )
return ESPIPE ;
2022-11-27 19:09:17 +00:00
// [ENODEV] The fd argument does not refer to a regular file.
if ( ! description - > file ( ) . is_regular_file ( ) )
2022-06-18 16:37:54 +00:00
return ENODEV ;
VERIFY ( description - > file ( ) . is_inode ( ) ) ;
auto & file = static_cast < InodeFile & > ( description - > file ( ) ) ;
if ( file . inode ( ) . size ( ) > = checked_size . value ( ) )
return 0 ;
// Note: truncate essentially calls resize in the inodes implementation
// while resize is not a standard member of an inode, so we just call
// truncate instead
TRY ( file . inode ( ) . truncate ( checked_size . value ( ) ) ) ;
// FIXME: EINTR: A signal was caught during execution.
return 0 ;
}
}