blob: 37a0b6aade927841dbcb515fc5bc071a3df85ce3 [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
8namespace phosphor
9{
10namespace dump
11{
12namespace inotify
13{
14
15using namespace std::string_literals;
16using namespace phosphor::logging;
17using namespace sdbusplus::xyz::openbmc_project::Common::Error;
18
19Watch::~Watch()
20{
21 if ((fd() >= 0) && (wd >= 0))
22 {
23 inotify_rm_watch(fd(), wd);
24 }
25}
26
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050027Watch::Watch(const EventPtr& eventObj, const int flags, const uint32_t mask,
Jayanth Othayoth3fc6df42021-04-08 03:45:24 -050028 const uint32_t events, const std::filesystem::path& path,
29 UserType userFunc) :
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050030 flags(flags),
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050031 mask(mask), events(events), path(path), fd(inotifyInit()),
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050032 userFunc(userFunc)
33{
34 // Check if watch DIR exists.
Jayanth Othayoth3fc6df42021-04-08 03:45:24 -050035 if (!std::filesystem::is_directory(path))
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050036 {
Dhruvaraj Subhashchandrand1f670f2023-06-05 22:19:25 -050037 lg2::error("Watch directory doesn't exist, DIR: {DIRECTORY}",
38 "DIRECTORY", path);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050039 elog<InternalFailure>();
40 }
41
42 wd = inotify_add_watch(fd(), path.c_str(), mask);
43 if (-1 == wd)
44 {
45 auto error = errno;
Dhruvaraj Subhashchandrand1f670f2023-06-05 22:19:25 -050046 lg2::error(
47 "Error occurred during the inotify_add_watch call, errno: {ERRNO}",
48 "ERRNO", error);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050049 elog<InternalFailure>();
50 }
51
Patrick Williams78e88402023-05-10 07:50:48 -050052 auto rc = sd_event_add_io(eventObj.get(), nullptr, fd(), events, callback,
53 this);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050054 if (0 > rc)
55 {
56 // Failed to add to event loop
Dhruvaraj Subhashchandrand1f670f2023-06-05 22:19:25 -050057 lg2::error("Error occurred during the sd_event_add_io call, rc: {RC}",
58 "RC", rc);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050059 elog<InternalFailure>();
60 }
61}
62
63int Watch::inotifyInit()
64{
65 auto fd = inotify_init1(flags);
66
67 if (-1 == fd)
68 {
69 auto error = errno;
Dhruvaraj Subhashchandrand1f670f2023-06-05 22:19:25 -050070 lg2::error("Error occurred during the inotify_init1, errno: {ERRNO}",
71 "ERRNO", error);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050072 elog<InternalFailure>();
73 }
74
75 return fd;
76}
77
Ramesh Iyyarbb410df2020-08-03 03:13:04 -050078int Watch::callback(sd_event_source*, int fd, uint32_t revents, void* userdata)
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050079{
Jayanth Othayoth764d1b22017-07-12 19:14:02 -050080 auto userData = static_cast<Watch*>(userdata);
81
82 if (!(revents & userData->events))
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050083 {
84 return 0;
85 }
86
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050087 // Maximum inotify events supported in the buffer
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050088 constexpr auto maxBytes = sizeof(struct inotify_event) + NAME_MAX + 1;
89 uint8_t buffer[maxBytes];
90
91 auto bytes = read(fd, buffer, maxBytes);
92 if (0 > bytes)
93 {
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050094 // Failed to read inotify event
95 // Report error and return
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050096 auto error = errno;
Dhruvaraj Subhashchandrand1f670f2023-06-05 22:19:25 -050097 lg2::error("Error occurred during the read, errno: {ERRNO}", "ERRNO",
98 error);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050099 report<InternalFailure>();
100 return 0;
101 }
102
103 auto offset = 0;
104
105 UserMap userMap;
106
107 while (offset < bytes)
108 {
109 auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500110 auto mask = event->mask & userData->mask;
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500111
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500112 if (mask)
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500113 {
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -0500114 userMap.emplace((userData->path / event->name), mask);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500115 }
116
117 offset += offsetof(inotify_event, name) + event->len;
118 }
119
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -0500120 // Call user call back function in case valid data in the map
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500121 if (!userMap.empty())
122 {
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500123 userData->userFunc(userMap);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500124 }
125
126 return 0;
127}
128
129} // namespace inotify
130} // namespace dump
131} // namespace phosphor