diff options
Diffstat (limited to 'Kernel/Syscalls')
-rw-r--r-- | Kernel/Syscalls/inode_watcher.cpp | 88 | ||||
-rw-r--r-- | Kernel/Syscalls/watch_file.cpp | 44 |
2 files changed, 88 insertions, 44 deletions
diff --git a/Kernel/Syscalls/inode_watcher.cpp b/Kernel/Syscalls/inode_watcher.cpp new file mode 100644 index 0000000000..fc9e878acb --- /dev/null +++ b/Kernel/Syscalls/inode_watcher.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <Kernel/API/InodeWatcherFlags.h> +#include <Kernel/FileSystem/Custody.h> +#include <Kernel/FileSystem/FileDescription.h> +#include <Kernel/FileSystem/InodeWatcher.h> +#include <Kernel/Process.h> + +namespace Kernel { + +KResultOr<int> Process::sys$create_inode_watcher(u32 flags) +{ + REQUIRE_PROMISE(rpath); + + int fd = alloc_fd(); + if (fd < 0) + return fd; + + auto description_or_error = FileDescription::create(*InodeWatcher::create()); + if (description_or_error.is_error()) + return description_or_error.error(); + + m_fds[fd].set(description_or_error.release_value()); + m_fds[fd].description()->set_readable(true); + + if (flags & static_cast<unsigned>(InodeWatcherFlags::Nonblock)) + m_fds[fd].description()->set_blocking(false); + if (flags & static_cast<unsigned>(InodeWatcherFlags::CloseOnExec)) + m_fds[fd].set_flags(m_fds[fd].flags() | FD_CLOEXEC); + + return fd; +} + +KResultOr<int> Process::sys$inode_watcher_add_watch(Userspace<const Syscall::SC_inode_watcher_add_watch_params*> user_params) +{ + REQUIRE_PROMISE(rpath); + + Syscall::SC_inode_watcher_add_watch_params params; + if (!copy_from_user(¶ms, user_params)) + return EFAULT; + + auto description = file_description(params.fd); + if (!description) + return EBADF; + if (!description->is_inode_watcher()) + return EBADF; + auto inode_watcher = description->inode_watcher(); + + auto path = get_syscall_path_argument(params.user_path.characters, params.user_path.length); + if (path.is_error()) + return path.error(); + + auto custody_or_error = VFS::the().resolve_path(path.value(), current_directory()); + if (custody_or_error.is_error()) + return custody_or_error.error(); + + auto& custody = custody_or_error.value(); + if (!custody->inode().fs().supports_watchers()) + return ENOTSUP; + + auto wd_or_error = inode_watcher->register_inode(custody->inode(), params.event_mask); + if (wd_or_error.is_error()) + return wd_or_error.error(); + return wd_or_error.value(); +} + +KResultOr<int> Process::sys$inode_watcher_remove_watch(int fd, int wd) +{ + auto description = file_description(fd); + if (!description) + return EBADF; + if (!description->is_inode_watcher()) + return EBADF; + auto inode_watcher = description->inode_watcher(); + + auto result = inode_watcher->unregister_by_wd(wd); + if (result.is_error()) + return result; + + return 0; +} + +} diff --git a/Kernel/Syscalls/watch_file.cpp b/Kernel/Syscalls/watch_file.cpp deleted file mode 100644 index 9ccce9ef54..0000000000 --- a/Kernel/Syscalls/watch_file.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include <Kernel/FileSystem/Custody.h> -#include <Kernel/FileSystem/FileDescription.h> -#include <Kernel/FileSystem/InodeWatcher.h> -#include <Kernel/Process.h> - -namespace Kernel { - -KResultOr<int> Process::sys$watch_file(Userspace<const char*> user_path, size_t path_length) -{ - REQUIRE_PROMISE(rpath); - auto path = get_syscall_path_argument(user_path, path_length); - if (path.is_error()) - return path.error(); - - auto custody_or_error = VFS::the().resolve_path(path.value(), current_directory()); - if (custody_or_error.is_error()) - return custody_or_error.error(); - - auto& custody = custody_or_error.value(); - auto& inode = custody->inode(); - - if (!inode.fs().supports_watchers()) - return ENOTSUP; - - int fd = alloc_fd(); - if (fd < 0) - return fd; - - auto description = FileDescription::create(*InodeWatcher::create(inode)); - if (description.is_error()) - return description.error(); - - m_fds[fd].set(description.release_value()); - m_fds[fd].description()->set_readable(true); - return fd; -} - -} |