blob: 4e8743149d503fc2cfa88e4960ee305cdc862d32 [file] [log] [blame]
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -05001#include "watch.hpp"
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -05002
3#include "xyz/openbmc_project/Common/error.hpp"
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -05004
5#include <phosphor-logging/elog-errors.hpp>
Dhruvaraj Subhashchandrand1f670f2023-06-05 22:19:25 -05006#include <phosphor-logging/lg2.hpp>
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -05007
Jayanth Othayothceb3e762024-11-25 23:19:37 -06008#include <span>
9
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050010namespace phosphor
11{
12namespace dump
13{
14namespace inotify
15{
16
17using namespace std::string_literals;
18using namespace phosphor::logging;
19using namespace sdbusplus::xyz::openbmc_project::Common::Error;
20
21Watch::~Watch()
22{
23 if ((fd() >= 0) && (wd >= 0))
24 {
Jian Zhangfa6a47b2024-03-25 13:22:21 +080025 sd_event_source_unref(source);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050026 inotify_rm_watch(fd(), wd);
27 }
28}
29
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050030Watch::Watch(const EventPtr& eventObj, const int flags, const uint32_t mask,
Jayanth Othayoth3fc6df42021-04-08 03:45:24 -050031 const uint32_t events, const std::filesystem::path& path,
32 UserType userFunc) :
Patrick Williams973b2912024-08-16 15:20:50 -040033 flags(flags), mask(mask), events(events), path(path), fd(inotifyInit()),
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050034 userFunc(userFunc)
35{
36 // Check if watch DIR exists.
Jayanth Othayoth3fc6df42021-04-08 03:45:24 -050037 if (!std::filesystem::is_directory(path))
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050038 {
Dhruvaraj Subhashchandrand1f670f2023-06-05 22:19:25 -050039 lg2::error("Watch directory doesn't exist, DIR: {DIRECTORY}",
40 "DIRECTORY", path);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050041 elog<InternalFailure>();
42 }
43
44 wd = inotify_add_watch(fd(), path.c_str(), mask);
45 if (-1 == wd)
46 {
47 auto error = errno;
Dhruvaraj Subhashchandrand1f670f2023-06-05 22:19:25 -050048 lg2::error(
49 "Error occurred during the inotify_add_watch call, errno: {ERRNO}",
50 "ERRNO", error);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050051 elog<InternalFailure>();
52 }
53
Patrick Williams973b2912024-08-16 15:20:50 -040054 auto rc =
Jian Zhangfa6a47b2024-03-25 13:22:21 +080055 sd_event_add_io(eventObj.get(), &source, fd(), events, callback, this);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050056 if (0 > rc)
57 {
58 // Failed to add to event loop
Dhruvaraj Subhashchandrand1f670f2023-06-05 22:19:25 -050059 lg2::error("Error occurred during the sd_event_add_io call, rc: {RC}",
60 "RC", rc);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050061 elog<InternalFailure>();
62 }
63}
64
65int Watch::inotifyInit()
66{
67 auto fd = inotify_init1(flags);
68
69 if (-1 == fd)
70 {
71 auto error = errno;
Dhruvaraj Subhashchandrand1f670f2023-06-05 22:19:25 -050072 lg2::error("Error occurred during the inotify_init1, errno: {ERRNO}",
73 "ERRNO", error);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050074 elog<InternalFailure>();
75 }
76
77 return fd;
78}
79
Ramesh Iyyarbb410df2020-08-03 03:13:04 -050080int Watch::callback(sd_event_source*, int fd, uint32_t revents, void* userdata)
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050081{
Jayanth Othayoth764d1b22017-07-12 19:14:02 -050082 auto userData = static_cast<Watch*>(userdata);
83
Jayanth Othayothb913e072024-11-26 01:23:20 -060084 if ((revents & userData->events) == 0U)
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050085 {
86 return 0;
87 }
88
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050089 // Maximum inotify events supported in the buffer
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050090 constexpr auto maxBytes = sizeof(struct inotify_event) + NAME_MAX + 1;
91 uint8_t buffer[maxBytes];
92
Jayanth Othayothceb3e762024-11-25 23:19:37 -060093 std::span<char> bufferSpan(reinterpret_cast<char*>(buffer), maxBytes);
94 auto bytes = read(fd, bufferSpan.data(), bufferSpan.size());
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050095 if (0 > bytes)
96 {
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050097 // Failed to read inotify event
98 // Report error and return
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050099 auto error = errno;
Dhruvaraj Subhashchandrand1f670f2023-06-05 22:19:25 -0500100 lg2::error("Error occurred during the read, errno: {ERRNO}", "ERRNO",
101 error);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500102 report<InternalFailure>();
103 return 0;
104 }
105
106 auto offset = 0;
107
108 UserMap userMap;
109
110 while (offset < bytes)
111 {
112 auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500113 auto mask = event->mask & userData->mask;
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500114
Jayanth Othayothb913e072024-11-26 01:23:20 -0600115 if (mask != 0U)
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500116 {
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -0500117 userMap.emplace((userData->path / event->name), mask);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500118 }
119
120 offset += offsetof(inotify_event, name) + event->len;
121 }
122
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -0500123 // Call user call back function in case valid data in the map
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500124 if (!userMap.empty())
125 {
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500126 userData->userFunc(userMap);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500127 }
128
129 return 0;
130}
131
132} // namespace inotify
133} // namespace dump
134} // namespace phosphor