blob: e4942fdb4bdbf2bbdbff5c407549edc321d18b73 [file] [log] [blame]
Gunnar Millsb0ce9962018-09-07 13:39:10 -05001#include "config.h"
2
3#include "sync_watch.hpp"
4
5#include <sys/inotify.h>
6#include <unistd.h>
7
Adriana Kobylakc98d9122020-05-05 10:36:01 -05008#include <filesystem>
Adriana Kobylakb072d1b2018-04-24 11:37:21 -05009#include <fstream>
10#include <phosphor-logging/log.hpp>
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050011
12namespace phosphor
13{
14namespace software
15{
16namespace manager
17{
18
19using namespace phosphor::logging;
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050020
Adriana Kobylak3a19e622018-11-09 11:39:46 -060021void SyncWatch::addInotifyWatch(const fs::path& path)
22{
Brad Bishop02516d32018-11-19 15:29:26 -050023 auto wd =
24 inotify_add_watch(inotifyFd, path.c_str(), IN_CLOSE_WRITE | IN_DELETE);
Adriana Kobylak3a19e622018-11-09 11:39:46 -060025 if (-1 == wd)
26 {
27 log<level::ERR>("inotify_add_watch failed", entry("ERRNO=%d", errno),
28 entry("FILENAME=%s", path.c_str()));
Adriana Kobylak3a19e622018-11-09 11:39:46 -060029 return;
30 }
31
Brad Bishop02516d32018-11-19 15:29:26 -050032 fileMap[wd] = fs::path(path);
Adriana Kobylak3a19e622018-11-09 11:39:46 -060033}
34
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050035SyncWatch::SyncWatch(sd_event& loop,
Adriana Kobylaka9074342018-05-08 11:52:44 -050036 std::function<int(int, fs::path&)> syncCallback) :
Brad Bishop02516d32018-11-19 15:29:26 -050037 inotifyFd(-1),
38 syncCallback(syncCallback), loop(loop)
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050039{
Brad Bishop02516d32018-11-19 15:29:26 -050040 auto fd = inotify_init1(IN_NONBLOCK);
41 if (-1 == fd)
42 {
43 log<level::ERR>("inotify_init1 failed", entry("ERRNO=%d", errno));
44 return;
45 }
46 inotifyFd = fd;
47
48 auto rc = sd_event_add_io(&loop, nullptr, fd, EPOLLIN, callback, this);
49 if (0 > rc)
50 {
51 log<level::ERR>("failed to add to event loop", entry("RC=%d", rc));
52 return;
53 }
54
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050055 auto syncfile = fs::path(SYNC_LIST_DIR_PATH) / SYNC_LIST_FILE_NAME;
56 if (fs::exists(syncfile))
57 {
58 std::string line;
59 std::ifstream file(syncfile.c_str());
60 while (std::getline(file, line))
61 {
Adriana Kobylak3a19e622018-11-09 11:39:46 -060062 addInotifyWatch(line);
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050063 }
64 }
65}
66
67SyncWatch::~SyncWatch()
68{
Brad Bishop02516d32018-11-19 15:29:26 -050069 if (inotifyFd != -1)
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050070 {
Brad Bishop02516d32018-11-19 15:29:26 -050071 close(inotifyFd);
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050072 }
73}
74
Adriana Kobylak292159f2020-05-05 09:25:55 -050075int SyncWatch::callback(sd_event_source* /* s */, int fd, uint32_t revents,
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050076 void* userdata)
77{
Adriana Kobylaka9074342018-05-08 11:52:44 -050078 if (!(revents & EPOLLIN))
79 {
80 return 0;
81 }
82
83 constexpr auto maxBytes = 1024;
84 uint8_t buffer[maxBytes];
85 auto bytes = read(fd, buffer, maxBytes);
86 if (0 > bytes)
87 {
88 return 0;
89 }
90
91 auto syncWatch = static_cast<SyncWatch*>(userdata);
92 auto offset = 0;
93 while (offset < bytes)
94 {
95 auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
96
Brad Bishop02516d32018-11-19 15:29:26 -050097 // Watch was removed, re-add it if file still exists.
98 if (event->mask & IN_IGNORED)
Adriana Kobylaka9074342018-05-08 11:52:44 -050099 {
Brad Bishop02516d32018-11-19 15:29:26 -0500100 if (fs::exists(syncWatch->fileMap[event->wd]))
Adriana Kobylak3a19e622018-11-09 11:39:46 -0600101 {
Brad Bishop02516d32018-11-19 15:29:26 -0500102 syncWatch->addInotifyWatch(syncWatch->fileMap[event->wd]);
Adriana Kobylak3a19e622018-11-09 11:39:46 -0600103 }
Brad Bishop02516d32018-11-19 15:29:26 -0500104 else
Adriana Kobylaka9074342018-05-08 11:52:44 -0500105 {
Brad Bishop02516d32018-11-19 15:29:26 -0500106 log<level::INFO>(
107 "The inotify watch was removed",
108 entry("FILENAME=%s",
109 (syncWatch->fileMap[event->wd]).c_str()));
Adriana Kobylaka9074342018-05-08 11:52:44 -0500110 }
Brad Bishop02516d32018-11-19 15:29:26 -0500111 return 0;
112 }
113
114 // fileMap<wd, path>
115 auto rc =
116 syncWatch->syncCallback(event->mask, syncWatch->fileMap[event->wd]);
117 if (rc)
118 {
119 return rc;
Adriana Kobylaka9074342018-05-08 11:52:44 -0500120 }
121
122 offset += offsetof(inotify_event, name) + event->len;
123 }
124
Adriana Kobylakb072d1b2018-04-24 11:37:21 -0500125 return 0;
126}
127
128} // namespace manager
129} // namespace software
130} // namespace phosphor