1*cab87e9cSJagpal Singh Gill #include "config.h"
2*cab87e9cSJagpal Singh Gill
3*cab87e9cSJagpal Singh Gill #include "sync_watch.hpp"
4*cab87e9cSJagpal Singh Gill
5*cab87e9cSJagpal Singh Gill #include <sys/inotify.h>
6*cab87e9cSJagpal Singh Gill #include <unistd.h>
7*cab87e9cSJagpal Singh Gill
8*cab87e9cSJagpal Singh Gill #include <phosphor-logging/lg2.hpp>
9*cab87e9cSJagpal Singh Gill
10*cab87e9cSJagpal Singh Gill #include <filesystem>
11*cab87e9cSJagpal Singh Gill #include <fstream>
12*cab87e9cSJagpal Singh Gill #include <system_error>
13*cab87e9cSJagpal Singh Gill
14*cab87e9cSJagpal Singh Gill namespace phosphor
15*cab87e9cSJagpal Singh Gill {
16*cab87e9cSJagpal Singh Gill namespace software
17*cab87e9cSJagpal Singh Gill {
18*cab87e9cSJagpal Singh Gill namespace manager
19*cab87e9cSJagpal Singh Gill {
20*cab87e9cSJagpal Singh Gill
21*cab87e9cSJagpal Singh Gill PHOSPHOR_LOG2_USING;
22*cab87e9cSJagpal Singh Gill
addInotifyWatch(const fs::path & path)23*cab87e9cSJagpal Singh Gill void SyncWatch::addInotifyWatch(const fs::path& path)
24*cab87e9cSJagpal Singh Gill {
25*cab87e9cSJagpal Singh Gill auto wd =
26*cab87e9cSJagpal Singh Gill inotify_add_watch(inotifyFd, path.c_str(), IN_CLOSE_WRITE | IN_DELETE);
27*cab87e9cSJagpal Singh Gill if (-1 == wd)
28*cab87e9cSJagpal Singh Gill {
29*cab87e9cSJagpal Singh Gill error("inotify_add_watch on {PATH} failed: {ERRNO}", "ERRNO", errno,
30*cab87e9cSJagpal Singh Gill "PATH", path);
31*cab87e9cSJagpal Singh Gill return;
32*cab87e9cSJagpal Singh Gill }
33*cab87e9cSJagpal Singh Gill
34*cab87e9cSJagpal Singh Gill fileMap[wd] = fs::path(path);
35*cab87e9cSJagpal Singh Gill }
36*cab87e9cSJagpal Singh Gill
SyncWatch(sd_event & loop,std::function<int (int,fs::path &)> syncCallback)37*cab87e9cSJagpal Singh Gill SyncWatch::SyncWatch(sd_event& loop,
38*cab87e9cSJagpal Singh Gill std::function<int(int, fs::path&)> syncCallback) :
39*cab87e9cSJagpal Singh Gill inotifyFd(-1), syncCallback(std::move(syncCallback))
40*cab87e9cSJagpal Singh Gill {
41*cab87e9cSJagpal Singh Gill auto fd = inotify_init1(IN_NONBLOCK);
42*cab87e9cSJagpal Singh Gill if (-1 == fd)
43*cab87e9cSJagpal Singh Gill {
44*cab87e9cSJagpal Singh Gill error("inotify_init1 failed: {ERRNO}", "ERRNO", errno);
45*cab87e9cSJagpal Singh Gill return;
46*cab87e9cSJagpal Singh Gill }
47*cab87e9cSJagpal Singh Gill inotifyFd = fd;
48*cab87e9cSJagpal Singh Gill
49*cab87e9cSJagpal Singh Gill auto rc = sd_event_add_io(&loop, nullptr, fd, EPOLLIN, callback, this);
50*cab87e9cSJagpal Singh Gill if (0 > rc)
51*cab87e9cSJagpal Singh Gill {
52*cab87e9cSJagpal Singh Gill error("failed to add to event loop: {RC}", "RC", rc);
53*cab87e9cSJagpal Singh Gill return;
54*cab87e9cSJagpal Singh Gill }
55*cab87e9cSJagpal Singh Gill
56*cab87e9cSJagpal Singh Gill std::error_code ec;
57*cab87e9cSJagpal Singh Gill auto syncfile = fs::path(SYNC_LIST_DIR_PATH) / SYNC_LIST_FILE_NAME;
58*cab87e9cSJagpal Singh Gill if (fs::exists(syncfile, ec))
59*cab87e9cSJagpal Singh Gill {
60*cab87e9cSJagpal Singh Gill std::string line;
61*cab87e9cSJagpal Singh Gill std::ifstream file(syncfile.c_str());
62*cab87e9cSJagpal Singh Gill while (std::getline(file, line))
63*cab87e9cSJagpal Singh Gill {
64*cab87e9cSJagpal Singh Gill addInotifyWatch(line);
65*cab87e9cSJagpal Singh Gill }
66*cab87e9cSJagpal Singh Gill }
67*cab87e9cSJagpal Singh Gill }
68*cab87e9cSJagpal Singh Gill
~SyncWatch()69*cab87e9cSJagpal Singh Gill SyncWatch::~SyncWatch()
70*cab87e9cSJagpal Singh Gill {
71*cab87e9cSJagpal Singh Gill if (inotifyFd != -1)
72*cab87e9cSJagpal Singh Gill {
73*cab87e9cSJagpal Singh Gill close(inotifyFd);
74*cab87e9cSJagpal Singh Gill }
75*cab87e9cSJagpal Singh Gill }
76*cab87e9cSJagpal Singh Gill
callback(sd_event_source *,int fd,uint32_t revents,void * userdata)77*cab87e9cSJagpal Singh Gill int SyncWatch::callback(sd_event_source* /* s */, int fd, uint32_t revents,
78*cab87e9cSJagpal Singh Gill void* userdata)
79*cab87e9cSJagpal Singh Gill {
80*cab87e9cSJagpal Singh Gill if (!(revents & EPOLLIN))
81*cab87e9cSJagpal Singh Gill {
82*cab87e9cSJagpal Singh Gill return 0;
83*cab87e9cSJagpal Singh Gill }
84*cab87e9cSJagpal Singh Gill
85*cab87e9cSJagpal Singh Gill constexpr auto maxBytes = 1024;
86*cab87e9cSJagpal Singh Gill uint8_t buffer[maxBytes];
87*cab87e9cSJagpal Singh Gill auto bytes = read(fd, buffer, maxBytes);
88*cab87e9cSJagpal Singh Gill if (0 > bytes)
89*cab87e9cSJagpal Singh Gill {
90*cab87e9cSJagpal Singh Gill return 0;
91*cab87e9cSJagpal Singh Gill }
92*cab87e9cSJagpal Singh Gill
93*cab87e9cSJagpal Singh Gill auto syncWatch = static_cast<SyncWatch*>(userdata);
94*cab87e9cSJagpal Singh Gill auto offset = 0;
95*cab87e9cSJagpal Singh Gill while (offset < bytes)
96*cab87e9cSJagpal Singh Gill {
97*cab87e9cSJagpal Singh Gill auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
98*cab87e9cSJagpal Singh Gill
99*cab87e9cSJagpal Singh Gill // Watch was removed, re-add it if file still exists.
100*cab87e9cSJagpal Singh Gill if (event->mask & IN_IGNORED)
101*cab87e9cSJagpal Singh Gill {
102*cab87e9cSJagpal Singh Gill std::error_code ec;
103*cab87e9cSJagpal Singh Gill if (fs::exists(syncWatch->fileMap[event->wd], ec))
104*cab87e9cSJagpal Singh Gill {
105*cab87e9cSJagpal Singh Gill syncWatch->addInotifyWatch(syncWatch->fileMap[event->wd]);
106*cab87e9cSJagpal Singh Gill }
107*cab87e9cSJagpal Singh Gill else
108*cab87e9cSJagpal Singh Gill {
109*cab87e9cSJagpal Singh Gill info("The inotify watch on {PATH} was removed", "PATH",
110*cab87e9cSJagpal Singh Gill syncWatch->fileMap[event->wd]);
111*cab87e9cSJagpal Singh Gill }
112*cab87e9cSJagpal Singh Gill return 0;
113*cab87e9cSJagpal Singh Gill }
114*cab87e9cSJagpal Singh Gill
115*cab87e9cSJagpal Singh Gill // fileMap<wd, path>
116*cab87e9cSJagpal Singh Gill auto rc = syncWatch->syncCallback(static_cast<int>(event->mask),
117*cab87e9cSJagpal Singh Gill syncWatch->fileMap[event->wd]);
118*cab87e9cSJagpal Singh Gill if (rc)
119*cab87e9cSJagpal Singh Gill {
120*cab87e9cSJagpal Singh Gill return rc;
121*cab87e9cSJagpal Singh Gill }
122*cab87e9cSJagpal Singh Gill
123*cab87e9cSJagpal Singh Gill offset += offsetof(inotify_event, name) + event->len;
124*cab87e9cSJagpal Singh Gill }
125*cab87e9cSJagpal Singh Gill
126*cab87e9cSJagpal Singh Gill return 0;
127*cab87e9cSJagpal Singh Gill }
128*cab87e9cSJagpal Singh Gill
129*cab87e9cSJagpal Singh Gill } // namespace manager
130*cab87e9cSJagpal Singh Gill } // namespace software
131*cab87e9cSJagpal Singh Gill } // namespace phosphor
132