blob: cec97affc4c3466ee890745d8e9509c9535ad5e7 [file] [log] [blame]
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -05001#include <phosphor-logging/elog-errors.hpp>
2
3#include "xyz/openbmc_project/Common/error.hpp"
4#include "watch.hpp"
5
6namespace phosphor
7{
8namespace dump
9{
10namespace inotify
11{
12
13using namespace std::string_literals;
14using namespace phosphor::logging;
15using namespace sdbusplus::xyz::openbmc_project::Common::Error;
16
17Watch::~Watch()
18{
19 if ((fd() >= 0) && (wd >= 0))
20 {
21 inotify_rm_watch(fd(), wd);
22 }
23}
24
25Watch::Watch(const EventPtr& eventObj,
26 const int flags,
27 const uint32_t mask,
28 const uint32_t events,
29 const fs::path& path,
30 UserType userFunc):
31 flags(flags),
32 mask(mask),
33 events(events),
34 path(path),
35 fd(inotifyInit()),
36 userFunc(userFunc)
37{
38 // Check if watch DIR exists.
39 if (!fs::is_directory(path))
40 {
41 log<level::ERR>("Watch directory doesn't exist",
42 entry("dir=%s", path.c_str()));
43 elog<InternalFailure>();
44 }
45
46 wd = inotify_add_watch(fd(), path.c_str(), mask);
47 if (-1 == wd)
48 {
49 auto error = errno;
50 log<level::ERR>("Error occurred during the inotify_add_watch call",
51 entry("ERRNO=%d", error));
52 elog<InternalFailure>();
53 }
54
55 auto rc = sd_event_add_io(eventObj.get(),
56 nullptr,
57 fd(),
58 events,
59 callback,
60 this);
61 if (0 > rc)
62 {
63 // Failed to add to event loop
64 log<level::ERR>("Error occurred during the sd_event_add_io call",
65 entry("rc=%d", rc));
66 elog<InternalFailure>();
67 }
68}
69
70int Watch::inotifyInit()
71{
72 auto fd = inotify_init1(flags);
73
74 if (-1 == fd)
75 {
76 auto error = errno;
77 log<level::ERR>("Error occurred during the inotify_init1",
78 entry("ERRNO=%d", error));
79 elog<InternalFailure>();
80 }
81
82 return fd;
83}
84
85int Watch::callback(sd_event_source* s,
86 int fd,
87 uint32_t revents,
88 void* userdata)
89{
Jayanth Othayoth764d1b22017-07-12 19:14:02 -050090 auto userData = static_cast<Watch*>(userdata);
91
92 if (!(revents & userData->events))
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -050093 {
94 return 0;
95 }
96
97 //Maximum inotify events supported in the buffer
98 constexpr auto maxBytes = sizeof(struct inotify_event) + NAME_MAX + 1;
99 uint8_t buffer[maxBytes];
100
101 auto bytes = read(fd, buffer, maxBytes);
102 if (0 > bytes)
103 {
104 //Failed to read inotify event
105 //Report error and return
106 auto error = errno;
107 log<level::ERR>("Error occurred during the read",
108 entry("ERRNO=%d", error));
109 report<InternalFailure>();
110 return 0;
111 }
112
113 auto offset = 0;
114
115 UserMap userMap;
116
117 while (offset < bytes)
118 {
119 auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500120 auto mask = event->mask & userData->mask;
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500121
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500122 if (mask)
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500123 {
124 userMap.emplace(
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500125 (userData->path / event->name), mask);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500126 }
127
128 offset += offsetof(inotify_event, name) + event->len;
129 }
130
131 //Call user call back function incase valid data in the map
132 if (!userMap.empty())
133 {
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500134 userData->userFunc(userMap);
Jayanth Othayoth671fc7f2017-06-14 08:01:41 -0500135 }
136
137 return 0;
138}
139
140} // namespace inotify
141} // namespace dump
142} // namespace phosphor