blob: e84d0619421ef8255f9847c1e756b6243e9558ad [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
Patrick Williamsc9bb6422021-08-27 06:18:35 -05008#include <phosphor-logging/lg2.hpp>
Adriana Kobylak58aa7502020-06-08 11:12:11 -05009
Adriana Kobylakc98d9122020-05-05 10:36:01 -050010#include <filesystem>
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050011#include <fstream>
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050012
13namespace phosphor
14{
15namespace software
16{
17namespace manager
18{
19
Patrick Williamsc9bb6422021-08-27 06:18:35 -050020PHOSPHOR_LOG2_USING;
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050021
Adriana Kobylak3a19e622018-11-09 11:39:46 -060022void SyncWatch::addInotifyWatch(const fs::path& path)
23{
Brad Bishop02516d32018-11-19 15:29:26 -050024 auto wd =
25 inotify_add_watch(inotifyFd, path.c_str(), IN_CLOSE_WRITE | IN_DELETE);
Adriana Kobylak3a19e622018-11-09 11:39:46 -060026 if (-1 == wd)
27 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -050028 error("inotify_add_watch on {PATH} failed: {ERRNO}", "ERRNO", errno,
29 "PATH", path);
Adriana Kobylak3a19e622018-11-09 11:39:46 -060030 return;
31 }
32
Brad Bishop02516d32018-11-19 15:29:26 -050033 fileMap[wd] = fs::path(path);
Adriana Kobylak3a19e622018-11-09 11:39:46 -060034}
35
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050036SyncWatch::SyncWatch(sd_event& loop,
Adriana Kobylaka9074342018-05-08 11:52:44 -050037 std::function<int(int, fs::path&)> syncCallback) :
Brad Bishop02516d32018-11-19 15:29:26 -050038 inotifyFd(-1),
39 syncCallback(syncCallback), loop(loop)
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050040{
Brad Bishop02516d32018-11-19 15:29:26 -050041 auto fd = inotify_init1(IN_NONBLOCK);
42 if (-1 == fd)
43 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -050044 error("inotify_init1 failed: {ERRNO}", "ERRNO", errno);
Brad Bishop02516d32018-11-19 15:29:26 -050045 return;
46 }
47 inotifyFd = fd;
48
49 auto rc = sd_event_add_io(&loop, nullptr, fd, EPOLLIN, callback, this);
50 if (0 > rc)
51 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -050052 error("failed to add to event loop: {RC}", "RC", rc);
Brad Bishop02516d32018-11-19 15:29:26 -050053 return;
54 }
55
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050056 auto syncfile = fs::path(SYNC_LIST_DIR_PATH) / SYNC_LIST_FILE_NAME;
57 if (fs::exists(syncfile))
58 {
59 std::string line;
60 std::ifstream file(syncfile.c_str());
61 while (std::getline(file, line))
62 {
Adriana Kobylak3a19e622018-11-09 11:39:46 -060063 addInotifyWatch(line);
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050064 }
65 }
66}
67
68SyncWatch::~SyncWatch()
69{
Brad Bishop02516d32018-11-19 15:29:26 -050070 if (inotifyFd != -1)
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050071 {
Brad Bishop02516d32018-11-19 15:29:26 -050072 close(inotifyFd);
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050073 }
74}
75
Adriana Kobylak292159f2020-05-05 09:25:55 -050076int SyncWatch::callback(sd_event_source* /* s */, int fd, uint32_t revents,
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050077 void* userdata)
78{
Adriana Kobylaka9074342018-05-08 11:52:44 -050079 if (!(revents & EPOLLIN))
80 {
81 return 0;
82 }
83
84 constexpr auto maxBytes = 1024;
85 uint8_t buffer[maxBytes];
86 auto bytes = read(fd, buffer, maxBytes);
87 if (0 > bytes)
88 {
89 return 0;
90 }
91
92 auto syncWatch = static_cast<SyncWatch*>(userdata);
93 auto offset = 0;
94 while (offset < bytes)
95 {
96 auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
97
Brad Bishop02516d32018-11-19 15:29:26 -050098 // Watch was removed, re-add it if file still exists.
99 if (event->mask & IN_IGNORED)
Adriana Kobylaka9074342018-05-08 11:52:44 -0500100 {
Brad Bishop02516d32018-11-19 15:29:26 -0500101 if (fs::exists(syncWatch->fileMap[event->wd]))
Adriana Kobylak3a19e622018-11-09 11:39:46 -0600102 {
Brad Bishop02516d32018-11-19 15:29:26 -0500103 syncWatch->addInotifyWatch(syncWatch->fileMap[event->wd]);
Adriana Kobylak3a19e622018-11-09 11:39:46 -0600104 }
Brad Bishop02516d32018-11-19 15:29:26 -0500105 else
Adriana Kobylaka9074342018-05-08 11:52:44 -0500106 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500107 info("The inotify watch on {PATH} was removed", "PATH",
108 syncWatch->fileMap[event->wd]);
Adriana Kobylaka9074342018-05-08 11:52:44 -0500109 }
Brad Bishop02516d32018-11-19 15:29:26 -0500110 return 0;
111 }
112
113 // fileMap<wd, path>
114 auto rc =
115 syncWatch->syncCallback(event->mask, syncWatch->fileMap[event->wd]);
116 if (rc)
117 {
118 return rc;
Adriana Kobylaka9074342018-05-08 11:52:44 -0500119 }
120
121 offset += offsetof(inotify_event, name) + event->len;
122 }
123
Adriana Kobylakb072d1b2018-04-24 11:37:21 -0500124 return 0;
125}
126
127} // namespace manager
128} // namespace software
129} // namespace phosphor