blob: caf8ce584347045b994fe369dd595931f29cddb0 [file] [log] [blame]
Marri Devender Raoffad1ef2019-06-03 04:54:12 -05001#include "watch.hpp"
2
3#include <sys/inotify.h>
4#include <unistd.h>
5
6#include <cstring>
7#include <filesystem>
8#include <phosphor-logging/elog-errors.hpp>
9#include <phosphor-logging/elog.hpp>
10#include <xyz/openbmc_project/Common/error.hpp>
Nan Zhoue1289ad2021-12-28 11:02:56 -080011
12namespace phosphor::certs
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050013{
Nan Zhoucf06ccd2021-12-28 16:25:45 -080014
15using ::phosphor::logging::elog;
16using ::phosphor::logging::entry;
17using ::phosphor::logging::level;
18using ::phosphor::logging::log;
19using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050020namespace fs = std::filesystem;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050021
22Watch::Watch(sdeventplus::Event& event, std::string& certFile, Callback cb) :
23 event(event), callback(cb)
24{
25 // get parent directory of certificate file to watch
Nan Zhoucf06ccd2021-12-28 16:25:45 -080026 fs::path path = fs::path(certFile).parent_path();
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050027 try
28 {
29 if (!fs::exists(path))
30 {
31 fs::create_directories(path);
32 }
33 }
Patrick Williams71957992021-10-06 14:42:52 -050034 catch (const fs::filesystem_error& e)
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050035 {
36 log<level::ERR>("Failed to create directory", entry("ERR=%s", e.what()),
37 entry("DIRECTORY=%s", path.c_str()));
38 elog<InternalFailure>();
39 }
40 watchDir = path;
41 watchFile = fs::path(certFile).filename();
42 startWatch();
43}
44
45Watch::~Watch()
46{
47 stopWatch();
48}
49
50void Watch::startWatch()
51{
52 // stop any existing watch
53 stopWatch();
54
55 fd = inotify_init1(IN_NONBLOCK);
56 if (-1 == fd)
57 {
58 log<level::ERR>("inotify_init1 failed,",
59 entry("ERR=%s", std::strerror(errno)));
60 elog<InternalFailure>();
61 }
62 wd = inotify_add_watch(fd, watchDir.c_str(), IN_CLOSE_WRITE);
63 if (-1 == wd)
64 {
65 close(fd);
66 log<level::ERR>("inotify_add_watch failed,",
67 entry("ERR=%s", std::strerror(errno)),
68 entry("WATCH=%s", watchDir.c_str()));
69 elog<InternalFailure>();
70 }
71
72 ioPtr = std::make_unique<sdeventplus::source::IO>(
Patrick Williams7e2797e2021-12-03 13:37:07 -060073 event, fd, EPOLLIN, [this](sdeventplus::source::IO&, int fd, uint32_t) {
Patrick Williams13eba412021-12-03 16:03:43 -060074 constexpr int size = sizeof(struct inotify_event) + NAME_MAX + 1;
75 std::array<char, size> buffer{};
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050076 int length = read(fd, buffer.data(), buffer.size());
77 if (length >= static_cast<int>(sizeof(struct inotify_event)))
78 {
79 struct inotify_event* notifyEvent =
80 reinterpret_cast<struct inotify_event*>(&buffer[0]);
81 if (notifyEvent->len)
82 {
83 if (watchFile == notifyEvent->name)
84 {
85 callback();
86 }
87 }
88 }
89 else
90 {
91 log<level::ERR>("Failed to read inotify event");
92 }
93 });
94}
95
96void Watch::stopWatch()
97{
98 if (-1 != fd)
99 {
100 if (-1 != wd)
101 {
102 inotify_rm_watch(fd, wd);
103 }
104 close(fd);
105 }
106 if (ioPtr)
107 {
108 ioPtr.reset();
109 }
110}
111
Nan Zhoue1289ad2021-12-28 11:02:56 -0800112} // namespace phosphor::certs