blob: a520dd2e37c14cc4720fefe780adef72a1984918 [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"
10
11namespace phosphor
12{
13namespace software
14{
15namespace manager
16{
17
18using namespace std::string_literals;
19
20Watch::Watch(sd_event* loop)
21{
22 fd = inotify_init1(IN_NONBLOCK);
23 if (-1 == fd)
24 {
25 // Store a copy of errno, because the string creation below will
26 // invalidate errno due to one more system calls.
27 auto error = errno;
28 throw std::runtime_error(
29 "inotify_init1 failed, errno="s + std::strerror(error));
30 }
31
32 wd = inotify_add_watch(fd, IMG_UPLOAD_DIR, IN_CREATE);
33 if (-1 == wd)
34 {
35 auto error = errno;
36 close(fd);
37 throw std::runtime_error(
38 "inotify_add_watch failed, errno="s + std::strerror(error));
39 }
40
41 auto rc = sd_event_add_io(loop,
42 nullptr,
43 fd,
44 EPOLLIN,
45 callback,
46 this);
47 if (0 > rc)
48 {
49 throw std::runtime_error(
50 "failed to add to event loop, rc="s + std::strerror(-rc));
51 }
52}
53
54Watch::~Watch()
55{
56 if ((-1 != fd) && (-1 != wd))
57 {
58 inotify_rm_watch(fd, wd);
59 close(fd);
60 }
61}
62
63int Watch::callback(sd_event_source* s,
64 int fd,
65 uint32_t revents,
66 void* userdata)
67{
68 if (!(revents & EPOLLIN))
69 {
70 return 0;
71 }
72
73 constexpr auto maxBytes = 1024;
74 uint8_t buffer[maxBytes];
75 auto bytes = read(fd, buffer, maxBytes);
76 if (0 > bytes)
77 {
78 auto error = errno;
79 throw std::runtime_error(
80 "failed to read inotify event, errno="s + std::strerror(error));
81 }
82
83 auto offset = 0;
84 while (offset < bytes)
85 {
86 auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
87 if ((event->mask & IN_CREATE) && !(event->mask & IN_ISDIR))
88 {
89 // TODO: openbmc/openbmc#1352 - invoke method (which takes uploaded
90 // filepath) to construct software version d-bus objects.
91 // For now, log the image filename.
92 using namespace phosphor::logging;
93 log<level::INFO>(event->name);
94 }
95
96 offset += offsetof(inotify_event, name) + event->len;
97 }
98
99 return 0;
100}
101
102} // namespace manager
103} // namespace software
104} // namespace phosphor