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 {
20     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      */
44     explicit CustomFd(int fd) : fd(fd)
45     {}
46 
47     ~CustomFd()
48     {
49         if (fd >= 0)
50         {
51             close(fd);
52         }
53     }
54 
55     int operator()() const
56     {
57         return fd;
58     }
59 
60   private:
61     /** @brief File descriptor */
62     int fd = -1;
63 };
64 
65 /** @class Watch
66  *
67  *  @brief Adds inotify watch on PNOR symlinks file to monitor for changes in
68  *         "running" PNOR version
69  *
70  *  The inotify watch is hooked up with sd-event, so that on call back,
71  *  appropriate actions related to a change in the "running" PNOR version
72  *  can be taken.
73  */
74 class Watch
75 {
76   public:
77     /** @brief ctor - hook inotify watch with sd-event
78      *
79      *  @param[in] loop - sd-event object
80      *  @param[in] functionalCallback - The callback function for updating
81      *                                  the functional associations.
82      */
83     Watch(sd_event* loop,
84           std::function<void(const std::string&)> functionalCallback);
85 
86     Watch(const Watch&) = delete;
87     Watch& operator=(const Watch&) = delete;
88     Watch(Watch&&) = delete;
89     Watch& operator=(Watch&&) = delete;
90 
91     /** @brief dtor - remove inotify watch
92      */
93     ~Watch();
94 
95   private:
96     /** @brief sd-event callback
97      *
98      *  @param[in] s - event source, floating (unused) in our case
99      *  @param[in] fd - inotify fd
100      *  @param[in] revents - events that matched for fd
101      *  @param[in] userdata - pointer to Watch object
102      *  @returns 0 on success, -1 on fail
103      */
104     static int callback(sd_event_source* s, int fd, uint32_t revents,
105                         void* userdata);
106 
107     /**  initialize an inotify instance and returns file descriptor */
108     int inotifyInit();
109 
110     /** @brief PNOR symlink file watch descriptor */
111     int wd = -1;
112 
113     /** @brief event source */
114     EventSourcePtr eventSource;
115 
116     /** @brief The callback function for updating the
117                functional associations. */
118     std::function<void(std::string&)> functionalCallback;
119 
120     /** @brief inotify file descriptor */
121     CustomFd fd;
122 };
123 
124 } // namespace updater
125 } // namespace software
126 } // namespace openpower
127