blob: 8ccfbeb0b250c3b83b8b2f5f63f3fd420636ee16 [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
George Liu858fbb22021-07-01 12:25:44 +08005#include <fmt/core.h>
6
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -05007#include <phosphor-logging/elog-errors.hpp>
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -05008
9namespace phosphor
10{
11namespace dump
12{
13namespace inotify
14{
15
16using namespace std::string_literals;
17using namespace phosphor::logging;
18using namespace sdbusplus::xyz::openbmc_project::Common::Error;
19
20Watch::~Watch()
21{
22 if ((fd() >= 0) && (wd >= 0))
23 {
24 inotify_rm_watch(fd(), wd);
25 }
26}
27
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050028Watch::Watch(const EventPtr& eventObj, const int flags, const uint32_t mask,
Jayanth Othayoth3fc6df42021-04-08 03:45:24 -050029 const uint32_t events, const std::filesystem::path& path,
30 UserType userFunc) :
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050031 flags(flags),
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050032 mask(mask), events(events), path(path), fd(inotifyInit()),
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050033 userFunc(userFunc)
34{
35 // Check if watch DIR exists.
Jayanth Othayoth3fc6df42021-04-08 03:45:24 -050036 if (!std::filesystem::is_directory(path))
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050037 {
George Liu858fbb22021-07-01 12:25:44 +080038 log<level::ERR>(
39 fmt::format("Watch directory doesn't exist, DIR({})", path.c_str())
40 .c_str());
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;
George Liu858fbb22021-07-01 12:25:44 +080048 log<level::ERR>(
49 fmt::format(
50 "Error occurred during the inotify_add_watch call, errno({})",
51 error)
52 .c_str());
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050053 elog<InternalFailure>();
54 }
55
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050056 auto rc =
57 sd_event_add_io(eventObj.get(), nullptr, fd(), events, callback, this);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050058 if (0 > rc)
59 {
60 // Failed to add to event loop
George Liu858fbb22021-07-01 12:25:44 +080061 log<level::ERR>(
62 fmt::format(
63 "Error occurred during the sd_event_add_io call, rc({})", rc)
64 .c_str());
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050065 elog<InternalFailure>();
66 }
67}
68
69int Watch::inotifyInit()
70{
71 auto fd = inotify_init1(flags);
72
73 if (-1 == fd)
74 {
75 auto error = errno;
George Liu858fbb22021-07-01 12:25:44 +080076 log<level::ERR>(
77 fmt::format("Error occurred during the inotify_init1, errno({})",
78 error)
79 .c_str());
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050080 elog<InternalFailure>();
81 }
82
83 return fd;
84}
85
Ramesh Iyyarbb410df2020-08-03 03:13:04 -050086int Watch::callback(sd_event_source*, int fd, uint32_t revents, void* userdata)
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050087{
Jayanth Othayoth764d1b22017-07-12 19:14:02 -050088 auto userData = static_cast<Watch*>(userdata);
89
90 if (!(revents & userData->events))
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050091 {
92 return 0;
93 }
94
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -050095 // Maximum inotify events supported in the buffer
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050096 constexpr auto maxBytes = sizeof(struct inotify_event) + NAME_MAX + 1;
97 uint8_t buffer[maxBytes];
98
99 auto bytes = read(fd, buffer, maxBytes);
100 if (0 > bytes)
101 {
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -0500102 // Failed to read inotify event
103 // Report error and return
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500104 auto error = errno;
George Liu858fbb22021-07-01 12:25:44 +0800105 log<level::ERR>(
106 fmt::format("Error occurred during the read, errno({})", error)
107 .c_str());
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500108 report<InternalFailure>();
109 return 0;
110 }
111
112 auto offset = 0;
113
114 UserMap userMap;
115
116 while (offset < bytes)
117 {
118 auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500119 auto mask = event->mask & userData->mask;
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500120
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500121 if (mask)
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500122 {
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -0500123 userMap.emplace((userData->path / event->name), mask);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500124 }
125
126 offset += offsetof(inotify_event, name) + event->len;
127 }
128
Jayanth Othayothcb65ffc2018-10-16 08:29:32 -0500129 // Call user call back function in case valid data in the map
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500130 if (!userMap.empty())
131 {
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500132 userData->userFunc(userMap);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500133 }
134
135 return 0;
136}
137
138} // namespace inotify
139} // namespace dump
140} // namespace phosphor