1*cab87e9cSJagpal Singh Gill #include "config.h"
2*cab87e9cSJagpal Singh Gill
3*cab87e9cSJagpal Singh Gill #include "watch.hpp"
4*cab87e9cSJagpal Singh Gill
5*cab87e9cSJagpal Singh Gill #include "image_manager.hpp"
6*cab87e9cSJagpal Singh Gill
7*cab87e9cSJagpal Singh Gill #include <sys/inotify.h>
8*cab87e9cSJagpal Singh Gill #include <unistd.h>
9*cab87e9cSJagpal Singh Gill
10*cab87e9cSJagpal Singh Gill #include <phosphor-logging/lg2.hpp>
11*cab87e9cSJagpal Singh Gill
12*cab87e9cSJagpal Singh Gill #include <cstddef>
13*cab87e9cSJagpal Singh Gill #include <cstring>
14*cab87e9cSJagpal Singh Gill #include <filesystem>
15*cab87e9cSJagpal Singh Gill #include <stdexcept>
16*cab87e9cSJagpal Singh Gill #include <string>
17*cab87e9cSJagpal Singh Gill #include <system_error>
18*cab87e9cSJagpal Singh Gill
19*cab87e9cSJagpal Singh Gill namespace phosphor
20*cab87e9cSJagpal Singh Gill {
21*cab87e9cSJagpal Singh Gill namespace software
22*cab87e9cSJagpal Singh Gill {
23*cab87e9cSJagpal Singh Gill namespace manager
24*cab87e9cSJagpal Singh Gill {
25*cab87e9cSJagpal Singh Gill
26*cab87e9cSJagpal Singh Gill PHOSPHOR_LOG2_USING;
27*cab87e9cSJagpal Singh Gill using namespace std::string_literals;
28*cab87e9cSJagpal Singh Gill namespace fs = std::filesystem;
29*cab87e9cSJagpal Singh Gill
Watch(sd_event * loop,std::function<int (std::string &)> imageCallback)30*cab87e9cSJagpal Singh Gill Watch::Watch(sd_event* loop, std::function<int(std::string&)> imageCallback) :
31*cab87e9cSJagpal Singh Gill imageCallback(std::move(imageCallback))
32*cab87e9cSJagpal Singh Gill {
33*cab87e9cSJagpal Singh Gill // Check if IMAGE DIR exists.
34*cab87e9cSJagpal Singh Gill std::error_code ec;
35*cab87e9cSJagpal Singh Gill fs::path imgDirPath(IMG_UPLOAD_DIR);
36*cab87e9cSJagpal Singh Gill if (!fs::is_directory(imgDirPath, ec))
37*cab87e9cSJagpal Singh Gill {
38*cab87e9cSJagpal Singh Gill fs::create_directories(imgDirPath, ec);
39*cab87e9cSJagpal Singh Gill }
40*cab87e9cSJagpal Singh Gill
41*cab87e9cSJagpal Singh Gill fd = inotify_init1(IN_NONBLOCK);
42*cab87e9cSJagpal Singh Gill if (-1 == fd)
43*cab87e9cSJagpal Singh Gill {
44*cab87e9cSJagpal Singh Gill // Store a copy of errno, because the string creation below will
45*cab87e9cSJagpal Singh Gill // invalidate errno due to one more system calls.
46*cab87e9cSJagpal Singh Gill auto error = errno;
47*cab87e9cSJagpal Singh Gill throw std::runtime_error(
48*cab87e9cSJagpal Singh Gill "inotify_init1 failed, errno="s + std::strerror(error));
49*cab87e9cSJagpal Singh Gill }
50*cab87e9cSJagpal Singh Gill
51*cab87e9cSJagpal Singh Gill wd = inotify_add_watch(fd, IMG_UPLOAD_DIR, IN_CLOSE_WRITE);
52*cab87e9cSJagpal Singh Gill if (-1 == wd)
53*cab87e9cSJagpal Singh Gill {
54*cab87e9cSJagpal Singh Gill auto error = errno;
55*cab87e9cSJagpal Singh Gill close(fd);
56*cab87e9cSJagpal Singh Gill throw std::runtime_error(
57*cab87e9cSJagpal Singh Gill "inotify_add_watch failed, errno="s + std::strerror(error));
58*cab87e9cSJagpal Singh Gill }
59*cab87e9cSJagpal Singh Gill
60*cab87e9cSJagpal Singh Gill auto rc = sd_event_add_io(loop, nullptr, fd, EPOLLIN, callback, this);
61*cab87e9cSJagpal Singh Gill if (0 > rc)
62*cab87e9cSJagpal Singh Gill {
63*cab87e9cSJagpal Singh Gill throw std::runtime_error(
64*cab87e9cSJagpal Singh Gill "failed to add to event loop, rc="s + std::strerror(-rc));
65*cab87e9cSJagpal Singh Gill }
66*cab87e9cSJagpal Singh Gill }
67*cab87e9cSJagpal Singh Gill
~Watch()68*cab87e9cSJagpal Singh Gill Watch::~Watch()
69*cab87e9cSJagpal Singh Gill {
70*cab87e9cSJagpal Singh Gill if (-1 != fd)
71*cab87e9cSJagpal Singh Gill {
72*cab87e9cSJagpal Singh Gill if (-1 != wd)
73*cab87e9cSJagpal Singh Gill {
74*cab87e9cSJagpal Singh Gill inotify_rm_watch(fd, wd);
75*cab87e9cSJagpal Singh Gill }
76*cab87e9cSJagpal Singh Gill close(fd);
77*cab87e9cSJagpal Singh Gill }
78*cab87e9cSJagpal Singh Gill }
79*cab87e9cSJagpal Singh Gill
callback(sd_event_source *,int fd,uint32_t revents,void * userdata)80*cab87e9cSJagpal Singh Gill int Watch::callback(sd_event_source* /* s */, int fd, uint32_t revents,
81*cab87e9cSJagpal Singh Gill void* userdata)
82*cab87e9cSJagpal Singh Gill {
83*cab87e9cSJagpal Singh Gill if (!(revents & EPOLLIN))
84*cab87e9cSJagpal Singh Gill {
85*cab87e9cSJagpal Singh Gill return 0;
86*cab87e9cSJagpal Singh Gill }
87*cab87e9cSJagpal Singh Gill
88*cab87e9cSJagpal Singh Gill constexpr auto maxBytes = 1024;
89*cab87e9cSJagpal Singh Gill uint8_t buffer[maxBytes];
90*cab87e9cSJagpal Singh Gill auto bytes = read(fd, buffer, maxBytes);
91*cab87e9cSJagpal Singh Gill if (0 > bytes)
92*cab87e9cSJagpal Singh Gill {
93*cab87e9cSJagpal Singh Gill auto error = errno;
94*cab87e9cSJagpal Singh Gill throw std::runtime_error(
95*cab87e9cSJagpal Singh Gill "failed to read inotify event, errno="s + std::strerror(error));
96*cab87e9cSJagpal Singh Gill }
97*cab87e9cSJagpal Singh Gill
98*cab87e9cSJagpal Singh Gill auto offset = 0;
99*cab87e9cSJagpal Singh Gill while (offset < bytes)
100*cab87e9cSJagpal Singh Gill {
101*cab87e9cSJagpal Singh Gill auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
102*cab87e9cSJagpal Singh Gill if ((event->mask & IN_CLOSE_WRITE) && !(event->mask & IN_ISDIR))
103*cab87e9cSJagpal Singh Gill {
104*cab87e9cSJagpal Singh Gill auto tarballPath = std::string{IMG_UPLOAD_DIR} + '/' + event->name;
105*cab87e9cSJagpal Singh Gill auto rc = static_cast<Watch*>(userdata)->imageCallback(tarballPath);
106*cab87e9cSJagpal Singh Gill if (rc < 0)
107*cab87e9cSJagpal Singh Gill {
108*cab87e9cSJagpal Singh Gill error("Error ({RC}) processing image {IMAGE}", "RC", rc,
109*cab87e9cSJagpal Singh Gill "IMAGE", tarballPath);
110*cab87e9cSJagpal Singh Gill }
111*cab87e9cSJagpal Singh Gill }
112*cab87e9cSJagpal Singh Gill
113*cab87e9cSJagpal Singh Gill offset += offsetof(inotify_event, name) + event->len;
114*cab87e9cSJagpal Singh Gill }
115*cab87e9cSJagpal Singh Gill
116*cab87e9cSJagpal Singh Gill return 0;
117*cab87e9cSJagpal Singh Gill }
118*cab87e9cSJagpal Singh Gill
119*cab87e9cSJagpal Singh Gill } // namespace manager
120*cab87e9cSJagpal Singh Gill } // namespace software
121*cab87e9cSJagpal Singh Gill } // namespace phosphor
122