blob: ae1e41914b8fd13d402aa354a85271b0c236012f [file] [log] [blame]
Deepak Kodihalli059e2332017-04-12 06:40:53 -05001#include <stdexcept>
2#include <cstddef>
3#include <cstring>
4#include <string>
5#include <sys/inotify.h>
6#include <unistd.h>
7#include <phosphor-logging/log.hpp>
8#include "config.h"
9#include "watch.hpp"
Gunnar Millse91d3212017-04-19 15:42:47 -050010#include "image_manager.hpp"
Deepak Kodihalli059e2332017-04-12 06:40:53 -050011
12namespace phosphor
13{
14namespace software
15{
16namespace manager
17{
18
Gunnar Millse91d3212017-04-19 15:42:47 -050019using namespace phosphor::logging;
Deepak Kodihalli059e2332017-04-12 06:40:53 -050020using namespace std::string_literals;
21
22Watch::Watch(sd_event* loop)
23{
24 fd = inotify_init1(IN_NONBLOCK);
25 if (-1 == fd)
26 {
27 // Store a copy of errno, because the string creation below will
28 // invalidate errno due to one more system calls.
29 auto error = errno;
30 throw std::runtime_error(
31 "inotify_init1 failed, errno="s + std::strerror(error));
32 }
33
Gunnar Mills368cfcb2017-04-27 16:13:17 -050034 wd = inotify_add_watch(fd, IMG_UPLOAD_DIR, IN_CLOSE_WRITE);
Deepak Kodihalli059e2332017-04-12 06:40:53 -050035 if (-1 == wd)
36 {
37 auto error = errno;
38 close(fd);
39 throw std::runtime_error(
40 "inotify_add_watch failed, errno="s + std::strerror(error));
41 }
42
43 auto rc = sd_event_add_io(loop,
44 nullptr,
45 fd,
46 EPOLLIN,
47 callback,
48 this);
49 if (0 > rc)
50 {
51 throw std::runtime_error(
52 "failed to add to event loop, rc="s + std::strerror(-rc));
53 }
54}
55
56Watch::~Watch()
57{
58 if ((-1 != fd) && (-1 != wd))
59 {
60 inotify_rm_watch(fd, wd);
61 close(fd);
62 }
63}
64
65int Watch::callback(sd_event_source* s,
66 int fd,
67 uint32_t revents,
68 void* userdata)
69{
70 if (!(revents & EPOLLIN))
71 {
72 return 0;
73 }
74
75 constexpr auto maxBytes = 1024;
76 uint8_t buffer[maxBytes];
77 auto bytes = read(fd, buffer, maxBytes);
78 if (0 > bytes)
79 {
80 auto error = errno;
81 throw std::runtime_error(
82 "failed to read inotify event, errno="s + std::strerror(error));
83 }
84
85 auto offset = 0;
86 while (offset < bytes)
87 {
88 auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
Gunnar Mills368cfcb2017-04-27 16:13:17 -050089 if ((event->mask & IN_CLOSE_WRITE) && !(event->mask & IN_ISDIR))
Deepak Kodihalli059e2332017-04-12 06:40:53 -050090 {
Gunnar Millse91d3212017-04-19 15:42:47 -050091 auto rc = processImage(std::string{IMG_UPLOAD_DIR} +
92 '/' + event->name);
93 if (rc < 0)
94 {
95 log<level::ERR>("Error processing image",
96 entry("IMAGE=%s", std::string{event->name}));
97 }
98
Deepak Kodihalli059e2332017-04-12 06:40:53 -050099 }
100
101 offset += offsetof(inotify_event, name) + event->len;
102 }
103
104 return 0;
105}
106
107} // namespace manager
108} // namespace software
109} // namespace phosphor