inode_watcher.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  16. REQUIRE_PROMISE(rpath);
  17. auto fd_or_error = m_fds.allocate();
  18. if (fd_or_error.is_error())
  19. return fd_or_error.error();
  20. auto inode_watcher_fd = fd_or_error.release_value();
  21. auto watcher_or_error = InodeWatcher::try_create();
  22. if (watcher_or_error.is_error())
  23. return watcher_or_error.error();
  24. auto description_or_error = FileDescription::try_create(*watcher_or_error.value());
  25. if (description_or_error.is_error())
  26. return description_or_error.error();
  27. m_fds[inode_watcher_fd.fd].set(description_or_error.release_value());
  28. m_fds[inode_watcher_fd.fd].description()->set_readable(true);
  29. if (flags & static_cast<unsigned>(InodeWatcherFlags::Nonblock))
  30. m_fds[inode_watcher_fd.fd].description()->set_blocking(false);
  31. if (flags & static_cast<unsigned>(InodeWatcherFlags::CloseOnExec))
  32. m_fds[inode_watcher_fd.fd].set_flags(m_fds[inode_watcher_fd.fd].flags() | FD_CLOEXEC);
  33. return inode_watcher_fd.fd;
  34. }
  35. KResultOr<FlatPtr> Process::sys$inode_watcher_add_watch(Userspace<const Syscall::SC_inode_watcher_add_watch_params*> user_params)
  36. {
  37. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  38. REQUIRE_PROMISE(rpath);
  39. Syscall::SC_inode_watcher_add_watch_params params;
  40. if (!copy_from_user(&params, user_params))
  41. return EFAULT;
  42. auto description = fds().file_description(params.fd);
  43. if (!description)
  44. return EBADF;
  45. if (!description->is_inode_watcher())
  46. return EBADF;
  47. auto inode_watcher = description->inode_watcher();
  48. auto path = get_syscall_path_argument(params.user_path);
  49. if (path.is_error())
  50. return path.error();
  51. auto custody_or_error = VirtualFileSystem::the().resolve_path(path.value()->view(), current_directory());
  52. if (custody_or_error.is_error())
  53. return custody_or_error.error();
  54. auto& custody = custody_or_error.value();
  55. if (!custody->inode().fs().supports_watchers())
  56. return ENOTSUP;
  57. auto wd_or_error = inode_watcher->register_inode(custody->inode(), params.event_mask);
  58. if (wd_or_error.is_error())
  59. return wd_or_error.error();
  60. return wd_or_error.value();
  61. }
  62. KResultOr<FlatPtr> Process::sys$inode_watcher_remove_watch(int fd, int wd)
  63. {
  64. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  65. auto description = fds().file_description(fd);
  66. if (!description)
  67. return EBADF;
  68. if (!description->is_inode_watcher())
  69. return EBADF;
  70. auto inode_watcher = description->inode_watcher();
  71. auto result = inode_watcher->unregister_by_wd(wd);
  72. if (result.is_error())
  73. return result;
  74. return 0;
  75. }
  76. }