Kernel: Move open file descriptors to their own class
This simplifies code a lot :)
This commit is contained in:
parent
274ecbba78
commit
78c091f7f8
|
@ -33,6 +33,7 @@ set(KERNEL_SOURCES
|
||||||
kernel/Memory/kmalloc.cpp
|
kernel/Memory/kmalloc.cpp
|
||||||
kernel/Memory/PhysicalRange.cpp
|
kernel/Memory/PhysicalRange.cpp
|
||||||
kernel/Memory/VirtualRange.cpp
|
kernel/Memory/VirtualRange.cpp
|
||||||
|
kernel/OpenFileDescriptorSet.cpp
|
||||||
kernel/Panic.cpp
|
kernel/Panic.cpp
|
||||||
kernel/PCI.cpp
|
kernel/PCI.cpp
|
||||||
kernel/PIC.cpp
|
kernel/PIC.cpp
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/Array.h>
|
||||||
|
#include <kernel/FS/Inode.h>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
class OpenFileDescriptorSet
|
||||||
|
{
|
||||||
|
BAN_NON_COPYABLE(OpenFileDescriptorSet);
|
||||||
|
|
||||||
|
public:
|
||||||
|
OpenFileDescriptorSet(const Credentials&);
|
||||||
|
~OpenFileDescriptorSet();
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> clone_from(const OpenFileDescriptorSet&);
|
||||||
|
|
||||||
|
BAN::ErrorOr<int> open(BAN::StringView absolute_path, int flags);
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> pipe(int fds[2]);
|
||||||
|
|
||||||
|
BAN::ErrorOr<int> dup2(int, int);
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> seek(int fd, off_t offset, int whence);
|
||||||
|
BAN::ErrorOr<off_t> tell(int) const;
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> fstat(int fd, struct stat*) const;
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> close(int);
|
||||||
|
void close_all();
|
||||||
|
void close_cloexec();
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> read(int fd, void* buffer, size_t count);
|
||||||
|
BAN::ErrorOr<size_t> write(int fd, const void* buffer, size_t count);
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size);
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::StringView> path_of(int) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct OpenFileDescription : public BAN::RefCounted<OpenFileDescription>
|
||||||
|
{
|
||||||
|
OpenFileDescription(BAN::RefPtr<Inode> inode, BAN::String path, off_t offset, uint8_t flags)
|
||||||
|
: inode(inode)
|
||||||
|
, path(BAN::move(path))
|
||||||
|
, offset(offset)
|
||||||
|
, flags(flags)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
BAN::RefPtr<Inode> inode;
|
||||||
|
BAN::String path;
|
||||||
|
off_t offset { 0 };
|
||||||
|
uint8_t flags { 0 };
|
||||||
|
|
||||||
|
friend class BAN::RefPtr<OpenFileDescription>;
|
||||||
|
};
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> validate_fd(int) const;
|
||||||
|
BAN::ErrorOr<int> get_free_fd() const;
|
||||||
|
BAN::ErrorOr<void> get_free_fd_pair(int fds[2]) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Credentials& m_credentials;
|
||||||
|
|
||||||
|
BAN::Array<BAN::RefPtr<OpenFileDescription>, OPEN_MAX> m_open_files;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -9,11 +9,11 @@
|
||||||
#include <kernel/Memory/GeneralAllocator.h>
|
#include <kernel/Memory/GeneralAllocator.h>
|
||||||
#include <kernel/Memory/Heap.h>
|
#include <kernel/Memory/Heap.h>
|
||||||
#include <kernel/Memory/VirtualRange.h>
|
#include <kernel/Memory/VirtualRange.h>
|
||||||
|
#include <kernel/OpenFileDescriptorSet.h>
|
||||||
#include <kernel/SpinLock.h>
|
#include <kernel/SpinLock.h>
|
||||||
#include <kernel/Terminal/TTY.h>
|
#include <kernel/Terminal/TTY.h>
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
namespace LibELF { class ELF; }
|
namespace LibELF { class ELF; }
|
||||||
|
@ -128,20 +128,6 @@ namespace Kernel
|
||||||
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct OpenFileDescription
|
|
||||||
{
|
|
||||||
BAN::RefPtr<Inode> inode;
|
|
||||||
BAN::String path;
|
|
||||||
off_t offset { 0 };
|
|
||||||
uint8_t flags { 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> validate_fd(int);
|
|
||||||
OpenFileDescription& open_file_description(int);
|
|
||||||
BAN::ErrorOr<int> get_free_fd();
|
|
||||||
BAN::ErrorOr<void> get_free_fd_pair(int fds[2]);
|
|
||||||
|
|
||||||
|
|
||||||
struct ExitStatus
|
struct ExitStatus
|
||||||
{
|
{
|
||||||
Semaphore semaphore;
|
Semaphore semaphore;
|
||||||
|
@ -152,7 +138,8 @@ namespace Kernel
|
||||||
|
|
||||||
Credentials m_credentials;
|
Credentials m_credentials;
|
||||||
|
|
||||||
BAN::Vector<OpenFileDescription> m_open_files;
|
OpenFileDescriptorSet m_open_file_descriptors;
|
||||||
|
|
||||||
BAN::Vector<VirtualRange*> m_mapped_ranges;
|
BAN::Vector<VirtualRange*> m_mapped_ranges;
|
||||||
|
|
||||||
mutable RecursiveSpinLock m_lock;
|
mutable RecursiveSpinLock m_lock;
|
||||||
|
|
|
@ -0,0 +1,245 @@
|
||||||
|
#include <kernel/FS/Pipe.h>
|
||||||
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
|
#include <kernel/OpenFileDescriptorSet.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
OpenFileDescriptorSet::OpenFileDescriptorSet(const Credentials& credentials)
|
||||||
|
: m_credentials(credentials)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenFileDescriptorSet::~OpenFileDescriptorSet()
|
||||||
|
{
|
||||||
|
close_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> OpenFileDescriptorSet::clone_from(const OpenFileDescriptorSet& other)
|
||||||
|
{
|
||||||
|
close_all();
|
||||||
|
|
||||||
|
for (int fd = 0; fd < (int)other.m_open_files.size(); fd++)
|
||||||
|
{
|
||||||
|
if (other.validate_fd(fd).is_error())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto& open_file = other.m_open_files[fd];
|
||||||
|
|
||||||
|
auto result = BAN::RefPtr<OpenFileDescription>::create(open_file->inode, open_file->path, open_file->offset, open_file->flags);
|
||||||
|
|
||||||
|
if (result.is_error())
|
||||||
|
{
|
||||||
|
close_all();
|
||||||
|
return result.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_open_files[fd] = result.release_value();
|
||||||
|
|
||||||
|
if (m_open_files[fd]->flags & O_WRONLY && m_open_files[fd]->inode->is_pipe())
|
||||||
|
((Pipe*)m_open_files[fd]->inode.ptr())->clone_writing();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<int> OpenFileDescriptorSet::open(BAN::StringView absolute_path, int flags)
|
||||||
|
{
|
||||||
|
if (flags & ~(O_RDONLY | O_WRONLY | O_NOFOLLOW | O_SEARCH | O_CLOEXEC))
|
||||||
|
return BAN::Error::from_errno(ENOTSUP);
|
||||||
|
|
||||||
|
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flags));
|
||||||
|
|
||||||
|
int fd = TRY(get_free_fd());
|
||||||
|
m_open_files[fd] = TRY(BAN::RefPtr<OpenFileDescription>::create(file.inode, BAN::move(file.canonical_path), 0, flags));
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> OpenFileDescriptorSet::pipe(int fds[2])
|
||||||
|
{
|
||||||
|
TRY(get_free_fd_pair(fds));
|
||||||
|
|
||||||
|
auto pipe = TRY(Pipe::create(m_credentials));
|
||||||
|
m_open_files[fds[0]] = TRY(BAN::RefPtr<OpenFileDescription>::create(pipe, ""sv, 0, O_RDONLY));
|
||||||
|
m_open_files[fds[1]] = TRY(BAN::RefPtr<OpenFileDescription>::create(pipe, ""sv, 0, O_WRONLY));
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<int> OpenFileDescriptorSet::dup2(int fildes, int fildes2)
|
||||||
|
{
|
||||||
|
if (fildes2 < 0 || fildes2 >= (int)m_open_files.size())
|
||||||
|
return BAN::Error::from_errno(EBADF);
|
||||||
|
|
||||||
|
TRY(validate_fd(fildes));
|
||||||
|
if (fildes == fildes2)
|
||||||
|
return fildes;
|
||||||
|
|
||||||
|
(void)close(fildes2);
|
||||||
|
|
||||||
|
m_open_files[fildes2] = m_open_files[fildes];
|
||||||
|
m_open_files[fildes2]->flags &= ~O_CLOEXEC;
|
||||||
|
|
||||||
|
if (m_open_files[fildes]->flags & O_WRONLY && m_open_files[fildes]->inode->is_pipe())
|
||||||
|
((Pipe*)m_open_files[fildes]->inode.ptr())->clone_writing();
|
||||||
|
|
||||||
|
return fildes;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> OpenFileDescriptorSet::seek(int fd, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
TRY(validate_fd(fd));
|
||||||
|
|
||||||
|
off_t new_offset = 0;
|
||||||
|
|
||||||
|
switch (whence)
|
||||||
|
{
|
||||||
|
case SEEK_CUR:
|
||||||
|
new_offset = m_open_files[fd]->offset + offset;
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
new_offset = m_open_files[fd]->inode->size() - offset;
|
||||||
|
break;
|
||||||
|
case SEEK_SET:
|
||||||
|
new_offset = offset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_offset < 0)
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
|
m_open_files[fd]->offset = new_offset;
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<off_t> OpenFileDescriptorSet::tell(int fd) const
|
||||||
|
{
|
||||||
|
TRY(validate_fd(fd));
|
||||||
|
return m_open_files[fd]->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> OpenFileDescriptorSet::fstat(int fd, struct stat* out) const
|
||||||
|
{
|
||||||
|
TRY(validate_fd(fd));
|
||||||
|
|
||||||
|
auto inode = m_open_files[fd]->inode;
|
||||||
|
out->st_dev = inode->dev();
|
||||||
|
out->st_ino = inode->ino();
|
||||||
|
out->st_mode = inode->mode().mode;
|
||||||
|
out->st_nlink = inode->nlink();
|
||||||
|
out->st_uid = inode->uid();
|
||||||
|
out->st_gid = inode->gid();
|
||||||
|
out->st_rdev = inode->rdev();
|
||||||
|
out->st_size = inode->size();
|
||||||
|
out->st_atim = inode->atime();
|
||||||
|
out->st_mtim = inode->mtime();
|
||||||
|
out->st_ctim = inode->ctime();
|
||||||
|
out->st_blksize = inode->blksize();
|
||||||
|
out->st_blocks = inode->blocks();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> OpenFileDescriptorSet::close(int fd)
|
||||||
|
{
|
||||||
|
TRY(validate_fd(fd));
|
||||||
|
|
||||||
|
if (m_open_files[fd]->flags & O_WRONLY && m_open_files[fd]->inode->is_pipe())
|
||||||
|
((Pipe*)m_open_files[fd]->inode.ptr())->close_writing();
|
||||||
|
|
||||||
|
m_open_files[fd].clear();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenFileDescriptorSet::close_all()
|
||||||
|
{
|
||||||
|
for (int fd = 0; fd < (int)m_open_files.size(); fd++)
|
||||||
|
(void)close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenFileDescriptorSet::close_cloexec()
|
||||||
|
{
|
||||||
|
for (int fd = 0; fd < (int)m_open_files.size(); fd++)
|
||||||
|
{
|
||||||
|
if (validate_fd(fd).is_error())
|
||||||
|
continue;
|
||||||
|
if (m_open_files[fd]->flags & O_CLOEXEC)
|
||||||
|
(void)close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> OpenFileDescriptorSet::read(int fd, void* buffer, size_t count)
|
||||||
|
{
|
||||||
|
TRY(validate_fd(fd));
|
||||||
|
auto& open_file = m_open_files[fd];
|
||||||
|
size_t nread = TRY(open_file->inode->read(open_file->offset, buffer, count));
|
||||||
|
open_file->offset += nread;
|
||||||
|
return nread;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> OpenFileDescriptorSet::write(int fd, const void* buffer, size_t count)
|
||||||
|
{
|
||||||
|
TRY(validate_fd(fd));
|
||||||
|
auto& open_file = m_open_files[fd];
|
||||||
|
size_t nwrite = TRY(open_file->inode->write(open_file->offset, buffer, count));
|
||||||
|
open_file->offset += nwrite;
|
||||||
|
return nwrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> OpenFileDescriptorSet::read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size)
|
||||||
|
{
|
||||||
|
TRY(validate_fd(fd));
|
||||||
|
auto& open_file = m_open_files[fd];
|
||||||
|
TRY(open_file->inode->read_next_directory_entries(open_file->offset, list, list_size));
|
||||||
|
open_file->offset++;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::StringView> OpenFileDescriptorSet::path_of(int fd) const
|
||||||
|
{
|
||||||
|
TRY(validate_fd(fd));
|
||||||
|
return m_open_files[fd]->path.sv();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> OpenFileDescriptorSet::validate_fd(int fd) const
|
||||||
|
{
|
||||||
|
if (fd < 0 || fd >= (int)m_open_files.size())
|
||||||
|
return BAN::Error::from_errno(EBADF);
|
||||||
|
if (!m_open_files[fd])
|
||||||
|
return BAN::Error::from_errno(EBADF);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<int> OpenFileDescriptorSet::get_free_fd() const
|
||||||
|
{
|
||||||
|
for (int fd = 0; fd < (int)m_open_files.size(); fd++)
|
||||||
|
if (!m_open_files[fd])
|
||||||
|
return fd;
|
||||||
|
return BAN::Error::from_errno(EMFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> OpenFileDescriptorSet::get_free_fd_pair(int fds[2]) const
|
||||||
|
{
|
||||||
|
size_t found = 0;
|
||||||
|
for (int fd = 0; fd < (int)m_open_files.size(); fd++)
|
||||||
|
{
|
||||||
|
if (!m_open_files[fd])
|
||||||
|
fds[found++] = fd;
|
||||||
|
if (found == 2)
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return BAN::Error::from_errno(EMFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
#include <BAN/StringView.h>
|
#include <BAN/StringView.h>
|
||||||
#include <kernel/CriticalScope.h>
|
#include <kernel/CriticalScope.h>
|
||||||
#include <kernel/FS/Pipe.h>
|
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/LockGuard.h>
|
#include <kernel/LockGuard.h>
|
||||||
#include <kernel/Memory/Heap.h>
|
#include <kernel/Memory/Heap.h>
|
||||||
|
@ -92,6 +91,7 @@ namespace Kernel
|
||||||
|
|
||||||
Process::Process(const Credentials& credentials, pid_t pid)
|
Process::Process(const Credentials& credentials, pid_t pid)
|
||||||
: m_credentials(credentials)
|
: m_credentials(credentials)
|
||||||
|
, m_open_file_descriptors(m_credentials)
|
||||||
, m_pid(pid)
|
, m_pid(pid)
|
||||||
, m_tty(TTY::current())
|
, m_tty(TTY::current())
|
||||||
{ }
|
{ }
|
||||||
|
@ -135,13 +135,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
m_threads.clear();
|
m_threads.clear();
|
||||||
|
m_open_file_descriptors.close_all();
|
||||||
for (int fd = 0; fd < (int)m_open_files.size(); fd++)
|
|
||||||
{
|
|
||||||
if (validate_fd(fd).is_error())
|
|
||||||
continue;
|
|
||||||
(void)sys_close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: We must unmap ranges while the page table is still alive
|
// NOTE: We must unmap ranges while the page table is still alive
|
||||||
for (auto* range : m_mapped_ranges)
|
for (auto* range : m_mapped_ranges)
|
||||||
|
@ -282,15 +276,7 @@ namespace Kernel
|
||||||
forked->m_tty = m_tty;
|
forked->m_tty = m_tty;
|
||||||
forked->m_working_directory = m_working_directory;
|
forked->m_working_directory = m_working_directory;
|
||||||
|
|
||||||
forked->m_open_files = m_open_files;
|
MUST(forked->m_open_file_descriptors.clone_from(m_open_file_descriptors));
|
||||||
for (int fd = 0; fd < (int)m_open_files.size(); fd++)
|
|
||||||
{
|
|
||||||
if (validate_fd(fd).is_error())
|
|
||||||
continue;
|
|
||||||
auto& openfd = open_file_description(fd);
|
|
||||||
if (openfd.flags & O_WRONLY && openfd.inode->is_pipe())
|
|
||||||
((Pipe*)openfd.inode.ptr())->clone_writing();
|
|
||||||
}
|
|
||||||
|
|
||||||
forked->m_userspace_info = m_userspace_info;
|
forked->m_userspace_info = m_userspace_info;
|
||||||
|
|
||||||
|
@ -339,14 +325,7 @@ namespace Kernel
|
||||||
|
|
||||||
LockGuard lock_guard(m_lock);
|
LockGuard lock_guard(m_lock);
|
||||||
|
|
||||||
for (int fd = 0; fd < (int)m_open_files.size(); fd++)
|
m_open_file_descriptors.close_cloexec();
|
||||||
{
|
|
||||||
if (validate_fd(fd).is_error())
|
|
||||||
continue;
|
|
||||||
auto& file = open_file_description(fd);
|
|
||||||
if (file.flags & O_CLOEXEC)
|
|
||||||
MUST(sys_close(fd));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_fixed_width_allocators.clear();
|
m_fixed_width_allocators.clear();
|
||||||
m_general_allocator.clear();
|
m_general_allocator.clear();
|
||||||
|
@ -513,34 +492,17 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_open(BAN::StringView path, int flags)
|
BAN::ErrorOr<long> Process::sys_open(BAN::StringView path, int flags)
|
||||||
{
|
{
|
||||||
if (flags & ~(O_RDONLY | O_WRONLY | O_NOFOLLOW | O_SEARCH | O_CLOEXEC))
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
|
|
||||||
BAN::String absolute_path = TRY(absolute_path_of(path));
|
|
||||||
|
|
||||||
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, flags));
|
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
int fd = TRY(get_free_fd());
|
BAN::String absolute_path = TRY(absolute_path_of(path));
|
||||||
auto& open_file_description = m_open_files[fd];
|
return TRY(m_open_file_descriptors.open(absolute_path, flags));
|
||||||
open_file_description.inode = file.inode;
|
|
||||||
open_file_description.path = BAN::move(file.canonical_path);
|
|
||||||
open_file_description.offset = 0;
|
|
||||||
open_file_description.flags = flags;
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_openat(int fd, BAN::StringView path, int flags)
|
BAN::ErrorOr<long> Process::sys_openat(int fd, BAN::StringView path, int flags)
|
||||||
{
|
|
||||||
BAN::String absolute_path;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
TRY(validate_fd(fd));
|
|
||||||
TRY(absolute_path.append(open_file_description(fd).path));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
BAN::String absolute_path;
|
||||||
|
TRY(absolute_path.append(TRY(m_open_file_descriptors.path_of(fd))));
|
||||||
TRY(absolute_path.push_back('/'));
|
TRY(absolute_path.push_back('/'));
|
||||||
TRY(absolute_path.append(path));
|
TRY(absolute_path.append(path));
|
||||||
|
|
||||||
|
@ -550,149 +512,46 @@ namespace Kernel
|
||||||
BAN::ErrorOr<long> Process::sys_close(int fd)
|
BAN::ErrorOr<long> Process::sys_close(int fd)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
TRY(validate_fd(fd));
|
TRY(m_open_file_descriptors.close(fd));
|
||||||
auto& open_file_description = this->open_file_description(fd);
|
|
||||||
if (open_file_description.flags & O_WRONLY && open_file_description.inode->is_pipe())
|
|
||||||
((Pipe*)open_file_description.inode.ptr())->close_writing();
|
|
||||||
open_file_description.inode = nullptr;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_read(int fd, void* buffer, size_t count)
|
BAN::ErrorOr<long> Process::sys_read(int fd, void* buffer, size_t count)
|
||||||
{
|
|
||||||
OpenFileDescription open_fd_copy;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
TRY(validate_fd(fd));
|
return TRY(m_open_file_descriptors.read(fd, buffer, count));
|
||||||
open_fd_copy = open_file_description(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(open_fd_copy.flags & O_RDONLY))
|
|
||||||
return BAN::Error::from_errno(EBADF);
|
|
||||||
|
|
||||||
size_t nread = TRY(open_fd_copy.inode->read(open_fd_copy.offset, buffer, count));
|
|
||||||
|
|
||||||
{
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
MUST(validate_fd(fd));
|
|
||||||
open_file_description(fd).offset += nread;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_write(int fd, const void* buffer, size_t count)
|
BAN::ErrorOr<long> Process::sys_write(int fd, const void* buffer, size_t count)
|
||||||
{
|
|
||||||
OpenFileDescription open_fd_copy;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
TRY(validate_fd(fd));
|
return TRY(m_open_file_descriptors.write(fd, buffer, count));
|
||||||
open_fd_copy = open_file_description(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(open_fd_copy.flags & O_WRONLY))
|
|
||||||
return BAN::Error::from_errno(EBADF);
|
|
||||||
|
|
||||||
size_t nwrite = TRY(open_fd_copy.inode->write(open_fd_copy.offset, buffer, count));
|
|
||||||
|
|
||||||
{
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
MUST(validate_fd(fd));
|
|
||||||
open_file_description(fd).offset += nwrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nwrite;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_pipe(int fildes[2])
|
BAN::ErrorOr<long> Process::sys_pipe(int fildes[2])
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
TRY(m_open_file_descriptors.pipe(fildes));
|
||||||
auto pipe = TRY(Pipe::create(m_credentials));
|
|
||||||
|
|
||||||
TRY(get_free_fd_pair(fildes));
|
|
||||||
|
|
||||||
auto& openfd_read = m_open_files[fildes[0]];
|
|
||||||
openfd_read.inode = pipe;
|
|
||||||
openfd_read.flags = O_RDONLY;
|
|
||||||
openfd_read.offset = 0;
|
|
||||||
openfd_read.path.clear();
|
|
||||||
|
|
||||||
auto& openfd_write = m_open_files[fildes[1]];
|
|
||||||
openfd_write.inode = pipe;
|
|
||||||
openfd_write.flags = O_WRONLY;
|
|
||||||
openfd_write.offset = 0;
|
|
||||||
openfd_write.path.clear();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_dup2(int fildes, int fildes2)
|
BAN::ErrorOr<long> Process::sys_dup2(int fildes, int fildes2)
|
||||||
{
|
{
|
||||||
// FIXME: m_open_files should be BAN::Array<BAN::RefPtr<OpenFileDescription>, OPEN_MAX> for accurate dup2
|
|
||||||
|
|
||||||
if (fildes2 < 0 || fildes2 >= 100)
|
|
||||||
return BAN::Error::from_errno(EBADF);
|
|
||||||
|
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
return TRY(m_open_file_descriptors.dup2(fildes, fildes2));
|
||||||
TRY(validate_fd(fildes));
|
|
||||||
if (fildes == fildes2)
|
|
||||||
return fildes;
|
|
||||||
|
|
||||||
if (m_open_files.size() <= (size_t)fildes2)
|
|
||||||
TRY(m_open_files.resize(fildes2 + 1));
|
|
||||||
|
|
||||||
if (!validate_fd(fildes2).is_error())
|
|
||||||
TRY(sys_close(fildes2));
|
|
||||||
|
|
||||||
m_open_files[fildes2] = m_open_files[fildes];
|
|
||||||
m_open_files[fildes2].flags &= ~O_CLOEXEC;
|
|
||||||
|
|
||||||
if (m_open_files[fildes].flags & O_WRONLY && m_open_files[fildes].inode->is_pipe())
|
|
||||||
((Pipe*)m_open_files[fildes].inode.ptr())->clone_writing();
|
|
||||||
|
|
||||||
return fildes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_seek(int fd, off_t offset, int whence)
|
BAN::ErrorOr<long> Process::sys_seek(int fd, off_t offset, int whence)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
TRY(validate_fd(fd));
|
TRY(m_open_file_descriptors.seek(fd, offset, whence));
|
||||||
|
|
||||||
auto& open_fd = open_file_description(fd);
|
|
||||||
|
|
||||||
off_t new_offset = 0;
|
|
||||||
|
|
||||||
switch (whence)
|
|
||||||
{
|
|
||||||
case SEEK_CUR:
|
|
||||||
new_offset = open_fd.offset + offset;
|
|
||||||
break;
|
|
||||||
case SEEK_END:
|
|
||||||
new_offset = open_fd.inode->size() - offset;
|
|
||||||
break;
|
|
||||||
case SEEK_SET:
|
|
||||||
new_offset = offset;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_offset < 0)
|
|
||||||
return BAN::Error::from_errno(EINVAL);
|
|
||||||
open_fd.offset = new_offset;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_tell(int fd)
|
BAN::ErrorOr<long> Process::sys_tell(int fd)
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
TRY(validate_fd(fd));
|
return TRY(m_open_file_descriptors.tell(fd));
|
||||||
return open_file_description(fd).offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_creat(BAN::StringView path, mode_t mode)
|
BAN::ErrorOr<long> Process::sys_creat(BAN::StringView path, mode_t mode)
|
||||||
|
@ -726,29 +585,9 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_fstat(int fd, struct stat* out)
|
BAN::ErrorOr<long> Process::sys_fstat(int fd, struct stat* out)
|
||||||
{
|
|
||||||
OpenFileDescription open_fd_copy;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
TRY(validate_fd(fd));
|
TRY(m_open_file_descriptors.fstat(fd, out));
|
||||||
open_fd_copy = open_file_description(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
out->st_dev = open_fd_copy.inode->dev();
|
|
||||||
out->st_ino = open_fd_copy.inode->ino();
|
|
||||||
out->st_mode = open_fd_copy.inode->mode().mode;
|
|
||||||
out->st_nlink = open_fd_copy.inode->nlink();
|
|
||||||
out->st_uid = open_fd_copy.inode->uid();
|
|
||||||
out->st_gid = open_fd_copy.inode->gid();
|
|
||||||
out->st_rdev = open_fd_copy.inode->rdev();
|
|
||||||
out->st_size = open_fd_copy.inode->size();
|
|
||||||
out->st_atim = open_fd_copy.inode->atime();
|
|
||||||
out->st_mtim = open_fd_copy.inode->mtime();
|
|
||||||
out->st_ctim = open_fd_copy.inode->ctime();
|
|
||||||
out->st_blksize = open_fd_copy.inode->blksize();
|
|
||||||
out->st_blocks = open_fd_copy.inode->blocks();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,23 +600,9 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size)
|
BAN::ErrorOr<long> Process::sys_read_dir_entries(int fd, DirectoryEntryList* list, size_t list_size)
|
||||||
{
|
|
||||||
OpenFileDescription open_fd_copy;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
TRY(validate_fd(fd));
|
TRY(m_open_file_descriptors.read_dir_entries(fd, list, list_size));
|
||||||
open_fd_copy = open_file_description(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
TRY(open_fd_copy.inode->read_next_directory_entries(open_fd_copy.offset, list, list_size));
|
|
||||||
|
|
||||||
{
|
|
||||||
LockGuard _(m_lock);
|
|
||||||
MUST(validate_fd(fd));
|
|
||||||
open_file_description(fd).offset = open_fd_copy.offset + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1131,52 +956,4 @@ namespace Kernel
|
||||||
return absolute_path;
|
return absolute_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Process::validate_fd(int fd)
|
|
||||||
{
|
|
||||||
ASSERT(m_lock.is_locked());
|
|
||||||
if (fd < 0 || m_open_files.size() <= (size_t)fd || !m_open_files[fd].inode)
|
|
||||||
return BAN::Error::from_errno(EBADF);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Process::OpenFileDescription& Process::open_file_description(int fd)
|
|
||||||
{
|
|
||||||
ASSERT(m_lock.is_locked());
|
|
||||||
MUST(validate_fd(fd));
|
|
||||||
return m_open_files[fd];
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<int> Process::get_free_fd()
|
|
||||||
{
|
|
||||||
ASSERT(m_lock.is_locked());
|
|
||||||
for (size_t fd = 0; fd < m_open_files.size(); fd++)
|
|
||||||
if (!m_open_files[fd].inode)
|
|
||||||
return fd;
|
|
||||||
TRY(m_open_files.push_back({}));
|
|
||||||
return m_open_files.size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<void> Process::get_free_fd_pair(int fds[2])
|
|
||||||
{
|
|
||||||
ASSERT(m_lock.is_locked());
|
|
||||||
int found = 0;
|
|
||||||
for (size_t fd = 0; fd < m_open_files.size(); fd++)
|
|
||||||
{
|
|
||||||
if (!m_open_files[fd].inode)
|
|
||||||
{
|
|
||||||
fds[found++] = fd;
|
|
||||||
if (found >= 2)
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (found < 2)
|
|
||||||
{
|
|
||||||
TRY(m_open_files.push_back({}));
|
|
||||||
fds[found++] = m_open_files.size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue