1 #pragma once
2 
3 #include <systemd/sd-event.h>
4 #include <unistd.h>
5 
6 #include <functional>
7 #include <memory>
8 #include <string>
9 
10 namespace openpower
11 {
12 namespace software
13 {
14 namespace updater
15 {
16 
17 /* Need a custom deleter for freeing up sd_event_source */
18 struct EventSourceDeleter
19 {
operator ()openpower::software::updater::EventSourceDeleter20     void operator()(sd_event_source* eventSource) const
21     {
22         sd_event_source_unref(eventSource);
23     }
24 };
25 using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>;
26 
27 /** @struct CustomFd
28  *
29  *  RAII wrapper for file descriptor.
30  */
31 struct CustomFd
32 {
33   public:
34     CustomFd() = delete;
35     CustomFd(const CustomFd&) = delete;
36     CustomFd& operator=(const CustomFd&) = delete;
37     CustomFd(CustomFd&&) = delete;
38     CustomFd& operator=(CustomFd&&) = delete;
39 
40     /** @brief Saves File descriptor and uses it to do file operation
41      *
42      *  @param[in] fd - File descriptor
43      */
CustomFdopenpower::software::updater::CustomFd44     explicit CustomFd(int fd) : fd(fd) {}
45 
~CustomFdopenpower::software::updater::CustomFd46     ~CustomFd()
47     {
48         if (fd >= 0)
49         {
50             close(fd);
51         }
52     }
53 
operator ()openpower::software::updater::CustomFd54     int operator()() const
55     {
56         return fd;
57     }
58 
59   private:
60     /** @brief File descriptor */
61     int fd = -1;
62 };
63 
64 /** @class Watch
65  *
66  *  @brief Adds inotify watch on PNOR symlinks file to monitor for changes in
67  *         "running" PNOR version
68  *
69  *  The inotify watch is hooked up with sd-event, so that on call back,
70  *  appropriate actions related to a change in the "running" PNOR version
71  *  can be taken.
72  */
73 class Watch
74 {
75   public:
76     /** @brief ctor - hook inotify watch with sd-event
77      *
78      *  @param[in] loop - sd-event object
79      *  @param[in] functionalCallback - The callback function for updating
80      *                                  the functional associations.
81      */
82     Watch(sd_event* loop,
83           std::function<void(const std::string&)> functionalCallback);
84 
85     Watch(const Watch&) = delete;
86     Watch& operator=(const Watch&) = delete;
87     Watch(Watch&&) = delete;
88     Watch& operator=(Watch&&) = delete;
89 
90     /** @brief dtor - remove inotify watch
91      */
92     ~Watch();
93 
94   private:
95     /** @brief sd-event callback
96      *
97      *  @param[in] s - event source, floating (unused) in our case
98      *  @param[in] fd - inotify fd
99      *  @param[in] revents - events that matched for fd
100      *  @param[in] userdata - pointer to Watch object
101      *  @returns 0 on success, -1 on fail
102      */
103     static int callback(sd_event_source* s, int fd, uint32_t revents,
104                         void* userdata);
105 
106     /**  initialize an inotify instance and returns file descriptor */
107     int inotifyInit();
108 
109     /** @brief PNOR symlink file watch descriptor */
110     int wd = -1;
111 
112     /** @brief event source */
113     EventSourcePtr eventSource;
114 
115     /** @brief The callback function for updating the
116                functional associations. */
117     std::function<void(std::string&)> functionalCallback;
118 
119     /** @brief inotify file descriptor */
120     CustomFd fd;
121 };
122 
123 } // namespace updater
124 } // namespace software
125 } // namespace openpower
126