inode_watcher.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <Kernel/API/InodeWatcherFlags.h>
  8. #include <Kernel/FileSystem/Custody.h>
  9. #include <Kernel/FileSystem/FileDescription.h>
  10. #include <Kernel/FileSystem/InodeWatcher.h>
  11. #include <Kernel/Process.h>
  12. namespace Kernel {
  13. KResultOr<FlatPtr> Process::sys$create_inode_watcher(u32 flags)
  14. {
  15. REQUIRE_PROMISE(rpath);
  16. int fd = alloc_fd();
  17. if (fd < 0)
  18. return fd;
  19. auto watcher_or_error = InodeWatcher::create();
  20. if (watcher_or_error.is_error())
  21. return watcher_or_error.error();
  22. auto description_or_error = FileDescription::create(*watcher_or_error.value());
  23. if (description_or_error.is_error())
  24. return description_or_error.error();
  25. m_fds[fd].set(description_or_error.release_value());
  26. m_fds[fd].description()->set_readable(true);
  27. if (flags & static_cast<unsigned>(InodeWatcherFlags::Nonblock))
  28. m_fds[fd].description()->set_blocking(false);
  29. if (flags & static_cast<unsigned>(InodeWatcherFlags::CloseOnExec))
  30. m_fds[fd].set_flags(m_fds[fd].flags() | FD_CLOEXEC);
  31. return fd;
  32. }
  33. KResultOr<FlatPtr> Process::sys$inode_watcher_add_watch(Userspace<const Syscall::SC_inode_watcher_add_watch_params*> user_params)
  34. {
  35. REQUIRE_PROMISE(rpath);
  36. Syscall::SC_inode_watcher_add_watch_params params;
  37. if (!copy_from_user(&params, user_params))
  38. return EFAULT;
  39. auto description = file_description(params.fd);
  40. if (!description)
  41. return EBADF;
  42. if (!description->is_inode_watcher())
  43. return EBADF;
  44. auto inode_watcher = description->inode_watcher();
  45. auto path = get_syscall_path_argument(params.user_path.characters, params.user_path.length);
  46. if (path.is_error())
  47. return path.error();
  48. auto custody_or_error = VFS::the().resolve_path(path.value()->view(), current_directory());
  49. if (custody_or_error.is_error())
  50. return custody_or_error.error();
  51. auto& custody = custody_or_error.value();
  52. if (!custody->inode().fs().supports_watchers())
  53. return ENOTSUP;
  54. auto wd_or_error = inode_watcher->register_inode(custody->inode(), params.event_mask);
  55. if (wd_or_error.is_error())
  56. return wd_or_error.error();
  57. return wd_or_error.value();
  58. }
  59. KResultOr<FlatPtr> Process::sys$inode_watcher_remove_watch(int fd, int wd)
  60. {
  61. auto description = file_description(fd);
  62. if (!description)
  63. return EBADF;
  64. if (!description->is_inode_watcher())
  65. return EBADF;
  66. auto inode_watcher = description->inode_watcher();
  67. auto result = inode_watcher->unregister_by_wd(wd);
  68. if (result.is_error())
  69. return result;
  70. return 0;
  71. }
  72. }