diff --git a/Kernel/FileSystem/FileDescriptor.cpp b/Kernel/FileSystem/FileDescriptor.cpp index c546d5545d..4327155acd 100644 --- a/Kernel/FileSystem/FileDescriptor.cpp +++ b/Kernel/FileSystem/FileDescriptor.cpp @@ -11,6 +11,7 @@ #include #include #include +#include Retained FileDescriptor::create(RetainPtr&& inode) { @@ -357,6 +358,11 @@ const char* to_string(SocketRole role) } } +bool FileDescriptor::is_file() const +{ + return !is_tty() && !is_fifo() && !is_device() && !is_socket() && !is_shared_memory(); +} + KResultOr FileDescriptor::absolute_path() { Stopwatch sw("absolute_path"); @@ -439,3 +445,12 @@ const CharacterDevice* FileDescriptor::character_device() const { return is_character_device() ? static_cast(device()) : nullptr; } + +KResult FileDescriptor::truncate(off_t length) +{ + if (is_file()) { + return m_inode->truncate(length); + } + ASSERT(is_shared_memory()); + return shared_memory()->truncate(length); +} diff --git a/Kernel/FileSystem/FileDescriptor.h b/Kernel/FileSystem/FileDescriptor.h index fb0a4b6f31..65361712bc 100644 --- a/Kernel/FileSystem/FileDescriptor.h +++ b/Kernel/FileSystem/FileDescriptor.h @@ -15,6 +15,7 @@ class MasterPTY; class Process; class Region; class CharacterDevice; +class SharedMemory; class FileDescriptor : public Retainable { public: @@ -85,6 +86,11 @@ public: bool is_fifo() const { return m_fifo; } FIFO::Direction fifo_direction() { return m_fifo_direction; } + bool is_file() const; + bool is_shared_memory() const { return m_shared_memory; } + SharedMemory* shared_memory() { return m_shared_memory.ptr(); } + const SharedMemory* shared_memory() const { return m_shared_memory.ptr(); } + ByteBuffer& generator_cache() { return m_generator_cache; } void set_original_inode(Badge, Retained&& inode) { m_inode = move(inode); } @@ -92,6 +98,8 @@ public: SocketRole socket_role() const { return m_socket_role; } void set_socket_role(SocketRole); + KResult truncate(off_t); + private: friend class VFS; FileDescriptor(RetainPtr&&, SocketRole); @@ -115,6 +123,8 @@ private: RetainPtr m_fifo; FIFO::Direction m_fifo_direction { FIFO::Neither }; + RetainPtr m_shared_memory; + bool m_closed { false }; }; diff --git a/Kernel/Makefile b/Kernel/Makefile index be5c9fe6bf..e738a35582 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -31,6 +31,7 @@ KERNEL_OBJS = \ ELF/ELFImage.o \ ELF/ELFLoader.o \ KSyms.o \ + SharedMemory.o \ FileSystem/DevPtsFS.o \ Devices/BXVGADevice.o \ PCI.o \ diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 9c7612ed4d..fbd1f9ce6b 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2468,3 +2468,14 @@ int Process::sys$shm_unlink(const char* name) return -EFAULT; return -ENOTIMPL; } + +int Process::sys$ftruncate(int fd, off_t length) +{ + auto* descriptor = file_descriptor(fd); + if (!descriptor) + return -EBADF; + // FIXME: Check that fd is writable, otherwise EINVAL. + if (!descriptor->is_file() && !descriptor->is_shared_memory()) + return -EINVAL; + return descriptor->truncate(length); +} diff --git a/Kernel/Process.h b/Kernel/Process.h index 135fa7edcb..9cfe73b36f 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -101,6 +101,7 @@ public: int sys$donate(int tid); int sys$shm_open(const char* name, int flags, mode_t); int sys$shm_unlink(const char* name); + int sys$ftruncate(int fd, off_t); pid_t sys$setsid(); pid_t sys$getsid(pid_t); int sys$setpgid(pid_t pid, pid_t pgid); diff --git a/Kernel/SharedMemory.cpp b/Kernel/SharedMemory.cpp new file mode 100644 index 0000000000..1af385de17 --- /dev/null +++ b/Kernel/SharedMemory.cpp @@ -0,0 +1,27 @@ +#include +#include + +SharedMemory::SharedMemory() +{ +} + +SharedMemory::~SharedMemory() +{ +} + +KResult SharedMemory::truncate(int length) +{ + if (!length) { + m_vmo = nullptr; + return KSuccess; + } + + if (!m_vmo) { + m_vmo = VMObject::create_anonymous(length); + return KSuccess; + } + + // FIXME: Support truncation. + ASSERT_NOT_REACHED(); + return KResult(-ENOTIMPL); +} diff --git a/Kernel/SharedMemory.h b/Kernel/SharedMemory.h new file mode 100644 index 0000000000..7b693bbd4b --- /dev/null +++ b/Kernel/SharedMemory.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include + +class VMObject; + +class SharedMemory : public Retainable { +public: + static Retained create(); + ~SharedMemory(); + + KResult truncate(int); + +private: + SharedMemory(); + + int m_uid { 0 }; + int m_gid { 0 }; + RetainPtr m_vmo; +}; diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 812cc7d828..bafad9bddd 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -247,6 +247,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2, return current->process().sys$shm_open((const char*)arg1, (int)arg2, (mode_t)arg3); case Syscall::SC_shm_close: return current->process().sys$shm_unlink((const char*)arg1); + case Syscall::SC_ftruncate: + return current->process().sys$ftruncate((int)arg1, (off_t)arg2); default: kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3); break; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index b11a079d1e..dfaddc070d 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -98,6 +98,7 @@ __ENUMERATE_SYSCALL(rename) \ __ENUMERATE_SYSCALL(shm_open) \ __ENUMERATE_SYSCALL(shm_close) \ + __ENUMERATE_SYSCALL(ftruncate) \ namespace Syscall { diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index 92ad156e59..a0bd5be157 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -442,7 +442,8 @@ int create_thread(int(*entry)(void*), void* argument) int ftruncate(int fd, off_t length) { - ASSERT_NOT_REACHED(); + int rc = syscall(SC_ftruncate, fd, length); + __RETURN_WITH_ERRNO(rc, rc, -1); } int gettid()