blob: 653a22d06302813a631a3c001f654a71baf81a84 [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>
George Liu44b9fef2023-02-07 14:31:32 +080012#include <system_error>
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050013
14namespace phosphor
15{
16namespace software
17{
18namespace manager
19{
20
Patrick Williamsc9bb6422021-08-27 06:18:35 -050021PHOSPHOR_LOG2_USING;
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050022
Adriana Kobylak3a19e622018-11-09 11:39:46 -060023void SyncWatch::addInotifyWatch(const fs::path& path)
24{
Patrick Williamsd5e8e732023-05-10 07:50:18 -050025 auto wd = inotify_add_watch(inotifyFd, path.c_str(),
26 IN_CLOSE_WRITE | IN_DELETE);
Adriana Kobylak3a19e622018-11-09 11:39:46 -060027 if (-1 == wd)
28 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -050029 error("inotify_add_watch on {PATH} failed: {ERRNO}", "ERRNO", errno,
30 "PATH", path);
Adriana Kobylak3a19e622018-11-09 11:39:46 -060031 return;
32 }
33
Brad Bishop02516d32018-11-19 15:29:26 -050034 fileMap[wd] = fs::path(path);
Adriana Kobylak3a19e622018-11-09 11:39:46 -060035}
36
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050037SyncWatch::SyncWatch(sd_event& loop,
Adriana Kobylaka9074342018-05-08 11:52:44 -050038 std::function<int(int, fs::path&)> syncCallback) :
Brad Bishop02516d32018-11-19 15:29:26 -050039 inotifyFd(-1),
40 syncCallback(syncCallback), loop(loop)
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050041{
Brad Bishop02516d32018-11-19 15:29:26 -050042 auto fd = inotify_init1(IN_NONBLOCK);
43 if (-1 == fd)
44 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -050045 error("inotify_init1 failed: {ERRNO}", "ERRNO", errno);
Brad Bishop02516d32018-11-19 15:29:26 -050046 return;
47 }
48 inotifyFd = fd;
49
50 auto rc = sd_event_add_io(&loop, nullptr, fd, EPOLLIN, callback, this);
51 if (0 > rc)
52 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -050053 error("failed to add to event loop: {RC}", "RC", rc);
Brad Bishop02516d32018-11-19 15:29:26 -050054 return;
55 }
56
George Liu44b9fef2023-02-07 14:31:32 +080057 std::error_code ec;
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050058 auto syncfile = fs::path(SYNC_LIST_DIR_PATH) / SYNC_LIST_FILE_NAME;
George Liu44b9fef2023-02-07 14:31:32 +080059 if (fs::exists(syncfile, ec))
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050060 {
61 std::string line;
62 std::ifstream file(syncfile.c_str());
63 while (std::getline(file, line))
64 {
Adriana Kobylak3a19e622018-11-09 11:39:46 -060065 addInotifyWatch(line);
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050066 }
67 }
68}
69
70SyncWatch::~SyncWatch()
71{
Brad Bishop02516d32018-11-19 15:29:26 -050072 if (inotifyFd != -1)
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050073 {
Brad Bishop02516d32018-11-19 15:29:26 -050074 close(inotifyFd);
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050075 }
76}
77
Adriana Kobylak292159f2020-05-05 09:25:55 -050078int SyncWatch::callback(sd_event_source* /* s */, int fd, uint32_t revents,
Adriana Kobylakb072d1b2018-04-24 11:37:21 -050079 void* userdata)
80{
Adriana Kobylaka9074342018-05-08 11:52:44 -050081 if (!(revents & EPOLLIN))
82 {
83 return 0;
84 }
85
86 constexpr auto maxBytes = 1024;
87 uint8_t buffer[maxBytes];
88 auto bytes = read(fd, buffer, maxBytes);
89 if (0 > bytes)
90 {
91 return 0;
92 }
93
94 auto syncWatch = static_cast<SyncWatch*>(userdata);
95 auto offset = 0;
96 while (offset < bytes)
97 {
98 auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
99
Brad Bishop02516d32018-11-19 15:29:26 -0500100 // Watch was removed, re-add it if file still exists.
101 if (event->mask & IN_IGNORED)
Adriana Kobylaka9074342018-05-08 11:52:44 -0500102 {
George Liu44b9fef2023-02-07 14:31:32 +0800103 std::error_code ec;
104 if (fs::exists(syncWatch->fileMap[event->wd], ec))
Adriana Kobylak3a19e622018-11-09 11:39:46 -0600105 {
Brad Bishop02516d32018-11-19 15:29:26 -0500106 syncWatch->addInotifyWatch(syncWatch->fileMap[event->wd]);
Adriana Kobylak3a19e622018-11-09 11:39:46 -0600107 }
Brad Bishop02516d32018-11-19 15:29:26 -0500108 else
Adriana Kobylaka9074342018-05-08 11:52:44 -0500109 {
Patrick Williamsc9bb6422021-08-27 06:18:35 -0500110 info("The inotify watch on {PATH} was removed", "PATH",
111 syncWatch->fileMap[event->wd]);
Adriana Kobylaka9074342018-05-08 11:52:44 -0500112 }
Brad Bishop02516d32018-11-19 15:29:26 -0500113 return 0;
114 }
115
116 // fileMap<wd, path>
Patrick Williamsd5e8e732023-05-10 07:50:18 -0500117 auto rc = syncWatch->syncCallback(event->mask,
118 syncWatch->fileMap[event->wd]);
Brad Bishop02516d32018-11-19 15:29:26 -0500119 if (rc)
120 {
121 return rc;
Adriana Kobylaka9074342018-05-08 11:52:44 -0500122 }
123
124 offset += offsetof(inotify_event, name) + event->len;
125 }
126
Adriana Kobylakb072d1b2018-04-24 11:37:21 -0500127 return 0;
128}
129
130} // namespace manager
131} // namespace software
132} // namespace phosphor