blob: 137ff760f4d7acbc80e88f7ce058df0eed80b5c6 [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>
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -05006
7namespace phosphor
8{
9namespace dump
10{
11namespace inotify
12{
13
14using namespace std::string_literals;
15using namespace phosphor::logging;
16using namespace sdbusplus::xyz::openbmc_project::Common::Error;
17
18Watch::~Watch()
19{
20 if ((fd() >= 0) && (wd >= 0))
21 {
22 inotify_rm_watch(fd(), wd);
23 }
24}
25
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050026Watch::Watch(const EventPtr& eventObj, const int flags, const uint32_t mask,
Jayanth Othayoth3fc6df42021-04-08 03:45:24 -050027 const uint32_t events, const std::filesystem::path& path,
28 UserType userFunc) :
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050029 flags(flags),
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050030 mask(mask), events(events), path(path), fd(inotifyInit()),
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050031 userFunc(userFunc)
32{
33 // Check if watch DIR exists.
Jayanth Othayoth3fc6df42021-04-08 03:45:24 -050034 if (!std::filesystem::is_directory(path))
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050035 {
36 log<level::ERR>("Watch directory doesn't exist",
Gunnar Mills11eaab72017-10-19 16:07:31 -050037 entry("DIR=%s", path.c_str()));
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050038 elog<InternalFailure>();
39 }
40
41 wd = inotify_add_watch(fd(), path.c_str(), mask);
42 if (-1 == wd)
43 {
44 auto error = errno;
45 log<level::ERR>("Error occurred during the inotify_add_watch call",
46 entry("ERRNO=%d", error));
47 elog<InternalFailure>();
48 }
49
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050050 auto rc =
51 sd_event_add_io(eventObj.get(), nullptr, fd(), events, callback, this);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050052 if (0 > rc)
53 {
54 // Failed to add to event loop
55 log<level::ERR>("Error occurred during the sd_event_add_io call",
Gunnar Mills11eaab72017-10-19 16:07:31 -050056 entry("RC=%d", rc));
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050057 elog<InternalFailure>();
58 }
59}
60
61int Watch::inotifyInit()
62{
63 auto fd = inotify_init1(flags);
64
65 if (-1 == fd)
66 {
67 auto error = errno;
68 log<level::ERR>("Error occurred during the inotify_init1",
69 entry("ERRNO=%d", error));
70 elog<InternalFailure>();
71 }
72
73 return fd;
74}
75
Ramesh Iyyarbb410df2020-08-03 03:13:04 -050076int Watch::callback(sd_event_source*, int fd, uint32_t revents, void* userdata)
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050077{
Jayanth Othayoth764d1b22017-07-12 19:14:02 -050078 auto userData = static_cast<Watch*>(userdata);
79
80 if (!(revents & userData->events))
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050081 {
82 return 0;
83 }
84
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050085 // Maximum inotify events supported in the buffer
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050086 constexpr auto maxBytes = sizeof(struct inotify_event) + NAME_MAX + 1;
87 uint8_t buffer[maxBytes];
88
89 auto bytes = read(fd, buffer, maxBytes);
90 if (0 > bytes)
91 {
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050092 // Failed to read inotify event
93 // Report error and return
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050094 auto error = errno;
95 log<level::ERR>("Error occurred during the read",
96 entry("ERRNO=%d", error));
97 report<InternalFailure>();
98 return 0;
99 }
100
101 auto offset = 0;
102
103 UserMap userMap;
104
105 while (offset < bytes)
106 {
107 auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500108 auto mask = event->mask & userData->mask;
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500109
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500110 if (mask)
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500111 {
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -0500112 userMap.emplace((userData->path / event->name), mask);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500113 }
114
115 offset += offsetof(inotify_event, name) + event->len;
116 }
117
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -0500118 // Call user call back function in case valid data in the map
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500119 if (!userMap.empty())
120 {
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500121 userData->userFunc(userMap);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500122 }
123
124 return 0;
125}
126
127} // namespace inotify
128} // namespace dump
129} // namespace phosphor