From d783389877435ef937b4306ac689470a5ca576bb Mon Sep 17 00:00:00 2001 From: Hendiadyoin1 Date: Sat, 18 Jun 2022 18:37:54 +0200 Subject: [PATCH] Kernel+LibC: Add posix_fallocate syscall --- Kernel/API/Syscall.h | 1 + Kernel/CMakeLists.txt | 1 + Kernel/Process.h | 1 + Kernel/Syscalls/fallocate.cpp | 59 +++++++++++++++++++++++++++++++ Userland/Libraries/LibC/fcntl.cpp | 7 ++++ Userland/Libraries/LibC/fcntl.h | 1 + 6 files changed, 70 insertions(+) create mode 100644 Kernel/Syscalls/fallocate.cpp diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index 72c89d587e..c973b14883 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -128,6 +128,7 @@ enum class NeedsBigProcessLock { S(pipe, NeedsBigProcessLock::Yes) \ S(pledge, NeedsBigProcessLock::Yes) \ S(poll, NeedsBigProcessLock::Yes) \ + S(posix_fallocate, NeedsBigProcessLock::No) \ S(prctl, NeedsBigProcessLock::Yes) \ S(profiling_disable, NeedsBigProcessLock::Yes) \ S(profiling_enable, NeedsBigProcessLock::Yes) \ diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index b7efb3d917..ecbeb7db77 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -243,6 +243,7 @@ set(KERNEL_SOURCES Syscalls/emuctl.cpp Syscalls/execve.cpp Syscalls/exit.cpp + Syscalls/fallocate.cpp Syscalls/fcntl.cpp Syscalls/fork.cpp Syscalls/fsync.cpp diff --git a/Kernel/Process.h b/Kernel/Process.h index aae7df23e5..5b64a578b3 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -301,6 +301,7 @@ public: ErrorOr sys$stat(Userspace); ErrorOr sys$lseek(int fd, Userspace, int whence); ErrorOr sys$ftruncate(int fd, Userspace); + ErrorOr sys$posix_fallocate(int fd, Userspace, Userspace); ErrorOr sys$kill(pid_t pid_or_pgid, int sig); [[noreturn]] void sys$exit(int status); ErrorOr sys$sigreturn(RegisterState& registers); diff --git a/Kernel/Syscalls/fallocate.cpp b/Kernel/Syscalls/fallocate.cpp new file mode 100644 index 0000000000..1a46b54d25 --- /dev/null +++ b/Kernel/Syscalls/fallocate.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022, Leon Albrecht + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +namespace Kernel { + +ErrorOr Process::sys$posix_fallocate(int fd, Userspace userspace_offset, Userspace userspace_length) +{ + VERIFY_NO_PROCESS_BIG_LOCK(this); + TRY(require_promise(Pledge::stdio)); + + auto offset = TRY(copy_typed_from_user(userspace_offset)); + if (offset < 0) + return EINVAL; + auto length = TRY(copy_typed_from_user(userspace_length)); + if (length <= 0) + return EINVAL; + + Checked 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)); + if (!description->is_writable()) + return EBADF; + + if (description->is_fifo()) + return ESPIPE; + + if (!S_ISREG(TRY(description->file().stat()).st_mode)) + return ENODEV; + + VERIFY(description->file().is_inode()); + + auto& file = static_cast(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: ENOSPC: There is not enough space left on the device containing the file referred to by fd. + // FIXME: EINTR: A signal was caught during execution. + return 0; +} + +} diff --git a/Userland/Libraries/LibC/fcntl.cpp b/Userland/Libraries/LibC/fcntl.cpp index e67a82d357..97fe440606 100644 --- a/Userland/Libraries/LibC/fcntl.cpp +++ b/Userland/Libraries/LibC/fcntl.cpp @@ -104,6 +104,13 @@ int posix_fadvise(int fd, off_t offset, off_t len, int advice) return 0; } +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fallocate.html +int posix_fallocate(int fd, off_t offset, off_t len) +{ + // posix_fallocate does not set errno. + return static_cast(syscall(SC_posix_fallocate, fd, &offset, &len)); +} + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimensat.html int utimensat(int dirfd, char const* path, struct timespec const times[2], int flag) { diff --git a/Userland/Libraries/LibC/fcntl.h b/Userland/Libraries/LibC/fcntl.h index 3704d6a7a7..bf640c79f5 100644 --- a/Userland/Libraries/LibC/fcntl.h +++ b/Userland/Libraries/LibC/fcntl.h @@ -29,6 +29,7 @@ int inode_watcher_add_watch(int fd, char const* path, size_t path_length, unsign int inode_watcher_remove_watch(int fd, int wd); int posix_fadvise(int fd, off_t offset, off_t len, int advice); +int posix_fallocate(int fd, off_t offset, off_t len); int utimensat(int dirfd, char const* path, struct timespec const times[2], int flag);