blob: a84c5ef6b1107f786a42e4cd4736340e38328ba1 [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>
Gunnar Mills4e48fd52017-04-28 09:53:02 -05007#include <experimental/filesystem>
Deepak Kodihalli059e2332017-04-12 06:40:53 -05008#include <phosphor-logging/log.hpp>
9#include "config.h"
10#include "watch.hpp"
Gunnar Millse91d3212017-04-19 15:42:47 -050011#include "image_manager.hpp"
Deepak Kodihalli059e2332017-04-12 06:40:53 -050012
13namespace phosphor
14{
15namespace software
16{
17namespace manager
18{
19
Gunnar Millse91d3212017-04-19 15:42:47 -050020using namespace phosphor::logging;
Deepak Kodihalli059e2332017-04-12 06:40:53 -050021using namespace std::string_literals;
Gunnar Mills4e48fd52017-04-28 09:53:02 -050022namespace fs = std::experimental::filesystem;
Deepak Kodihalli059e2332017-04-12 06:40:53 -050023
Adriana Kobylak2285fe02018-02-27 15:36:59 -060024Watch::Watch(sd_event* loop, std::function<int(std::string&)> imageCallback) :
25 imageCallback(imageCallback)
Deepak Kodihalli059e2332017-04-12 06:40:53 -050026{
Gunnar Mills4e48fd52017-04-28 09:53:02 -050027 // Check if IMAGE DIR exists.
28 fs::path imgDirPath(IMG_UPLOAD_DIR);
29 if (!fs::is_directory(imgDirPath))
30 {
Gunnar Mills7e1abfc2017-11-09 15:43:50 -060031 fs::create_directories(imgDirPath);
Gunnar Mills4e48fd52017-04-28 09:53:02 -050032 }
33
Deepak Kodihalli059e2332017-04-12 06:40:53 -050034 fd = inotify_init1(IN_NONBLOCK);
35 if (-1 == fd)
36 {
37 // Store a copy of errno, because the string creation below will
38 // invalidate errno due to one more system calls.
39 auto error = errno;
Adriana Kobylak2285fe02018-02-27 15:36:59 -060040 throw std::runtime_error("inotify_init1 failed, errno="s +
41 std::strerror(error));
Deepak Kodihalli059e2332017-04-12 06:40:53 -050042 }
43
Gunnar Mills368cfcb2017-04-27 16:13:17 -050044 wd = inotify_add_watch(fd, IMG_UPLOAD_DIR, IN_CLOSE_WRITE);
Deepak Kodihalli059e2332017-04-12 06:40:53 -050045 if (-1 == wd)
46 {
47 auto error = errno;
48 close(fd);
Adriana Kobylak2285fe02018-02-27 15:36:59 -060049 throw std::runtime_error("inotify_add_watch failed, errno="s +
50 std::strerror(error));
Deepak Kodihalli059e2332017-04-12 06:40:53 -050051 }
52
Adriana Kobylak2285fe02018-02-27 15:36:59 -060053 auto rc = sd_event_add_io(loop, nullptr, fd, EPOLLIN, callback, this);
Deepak Kodihalli059e2332017-04-12 06:40:53 -050054 if (0 > rc)
55 {
Adriana Kobylak2285fe02018-02-27 15:36:59 -060056 throw std::runtime_error("failed to add to event loop, rc="s +
57 std::strerror(-rc));
Deepak Kodihalli059e2332017-04-12 06:40:53 -050058 }
59}
60
61Watch::~Watch()
62{
63 if ((-1 != fd) && (-1 != wd))
64 {
65 inotify_rm_watch(fd, wd);
66 close(fd);
67 }
68}
69
Adriana Kobylak2285fe02018-02-27 15:36:59 -060070int Watch::callback(sd_event_source* s, int fd, uint32_t revents,
Deepak Kodihalli059e2332017-04-12 06:40:53 -050071 void* userdata)
72{
73 if (!(revents & EPOLLIN))
74 {
75 return 0;
76 }
77
78 constexpr auto maxBytes = 1024;
79 uint8_t buffer[maxBytes];
80 auto bytes = read(fd, buffer, maxBytes);
81 if (0 > bytes)
82 {
83 auto error = errno;
Adriana Kobylak2285fe02018-02-27 15:36:59 -060084 throw std::runtime_error("failed to read inotify event, errno="s +
85 std::strerror(error));
Deepak Kodihalli059e2332017-04-12 06:40:53 -050086 }
87
88 auto offset = 0;
89 while (offset < bytes)
90 {
91 auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
Gunnar Mills368cfcb2017-04-27 16:13:17 -050092 if ((event->mask & IN_CLOSE_WRITE) && !(event->mask & IN_ISDIR))
Deepak Kodihalli059e2332017-04-12 06:40:53 -050093 {
Gunnar Mills3027bba2017-04-27 15:49:03 -050094 auto tarballPath = std::string{IMG_UPLOAD_DIR} + '/' + event->name;
95 auto rc = static_cast<Watch*>(userdata)->imageCallback(tarballPath);
Gunnar Millse91d3212017-04-19 15:42:47 -050096 if (rc < 0)
97 {
98 log<level::ERR>("Error processing image",
Adriana Kobylak596466b2018-02-13 14:48:53 -060099 entry("IMAGE=%s", tarballPath.c_str()));
Gunnar Millse91d3212017-04-19 15:42:47 -0500100 }
Deepak Kodihalli059e2332017-04-12 06:40:53 -0500101 }
102
103 offset += offsetof(inotify_event, name) + event->len;
104 }
105
106 return 0;
107}
108
109} // namespace manager
110} // namespace software
111} // namespace phosphor