1 #pragma once
2 
3 #include <systemd/sd-event.h>
4 #include <unistd.h>
5 
6 #include <functional>
7 #include <memory>
8 
9 namespace openpower
10 {
11 namespace software
12 {
13 namespace updater
14 {
15 
16 /* Need a custom deleter for freeing up sd_event_source */
17 struct EventSourceDeleter
18 {
19     void operator()(sd_event_source* eventSource) const
20     {
21         eventSource = sd_event_source_unref(eventSource);
22     }
23 };
24 using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>;
25 
26 /** @struct CustomFd
27  *
28  *  RAII wrapper for file descriptor.
29  */
30 struct CustomFd
31 {
32   public:
33     CustomFd() = delete;
34     CustomFd(const CustomFd&) = delete;
35     CustomFd& operator=(const CustomFd&) = delete;
36     CustomFd(CustomFd&&) = delete;
37     CustomFd& operator=(CustomFd&&) = delete;
38 
39     /** @brief Saves File descriptor and uses it to do file operation
40      *
41      *  @param[in] fd - File descriptor
42      */
43     CustomFd(int fd) : fd(fd)
44     {
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