2016-11-20 17:04:31 -05:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2016-11-25 07:55:15 -05:00
|
|
|
#include "errors.hpp"
|
2016-11-02 15:22:45 -04:00
|
|
|
#include "utils/inotify.hpp"
|
|
|
|
#include "utils/memory.hpp"
|
|
|
|
|
2016-11-19 00:22:44 -05:00
|
|
|
POLYBAR_NS
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
/**
|
|
|
|
* Construct inotify watch
|
|
|
|
*/
|
|
|
|
inotify_watch::inotify_watch(string path) : m_path(move(path)) {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deconstruct inotify watch
|
|
|
|
*/
|
|
|
|
inotify_watch::~inotify_watch() {
|
|
|
|
if (m_wd != -1) {
|
|
|
|
inotify_rm_watch(m_fd, m_wd);
|
2016-11-02 15:22:45 -04:00
|
|
|
}
|
2016-12-19 23:05:43 -05:00
|
|
|
if (m_fd != -1) {
|
|
|
|
close(m_fd);
|
2016-11-02 15:22:45 -04:00
|
|
|
}
|
2016-12-19 23:05:43 -05:00
|
|
|
}
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
/**
|
|
|
|
* Attach inotify watch
|
|
|
|
*/
|
|
|
|
void inotify_watch::attach(int mask) {
|
|
|
|
if (m_fd == -1 && (m_fd = inotify_init()) == -1) {
|
|
|
|
throw system_error("Failed to allocate inotify fd");
|
|
|
|
}
|
|
|
|
if ((m_wd = inotify_add_watch(m_fd, m_path.c_str(), mask)) == -1) {
|
|
|
|
throw system_error("Failed to attach inotify watch");
|
2016-11-02 15:22:45 -04:00
|
|
|
}
|
2016-12-19 23:05:43 -05:00
|
|
|
m_mask |= mask;
|
|
|
|
}
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
/**
|
|
|
|
* Remove inotify watch
|
|
|
|
*/
|
|
|
|
void inotify_watch::remove(bool force) {
|
|
|
|
if (inotify_rm_watch(m_fd, m_wd) == -1 && !force) {
|
|
|
|
throw system_error("Failed to remove inotify watch");
|
|
|
|
}
|
|
|
|
m_wd = -1;
|
|
|
|
m_mask = 0;
|
|
|
|
}
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
/**
|
|
|
|
* Poll the inotify fd for events
|
|
|
|
*
|
|
|
|
* @brief A wait_ms of -1 blocks until an event is fired
|
|
|
|
*/
|
|
|
|
bool inotify_watch::poll(int wait_ms) {
|
|
|
|
if (m_fd == -1) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
struct pollfd fds[1];
|
|
|
|
fds[0].fd = m_fd;
|
|
|
|
fds[0].events = POLLIN;
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
::poll(fds, 1, wait_ms);
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
return fds[0].revents & POLLIN;
|
|
|
|
}
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
/**
|
|
|
|
* Get the latest inotify event
|
|
|
|
*/
|
|
|
|
unique_ptr<inotify_event> inotify_watch::get_event() {
|
|
|
|
auto event = factory_util::unique<inotify_event>();
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
if (m_fd == -1 || m_wd == -1) {
|
|
|
|
return event;
|
|
|
|
}
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
char buffer[1024];
|
|
|
|
size_t bytes = read(m_fd, buffer, 1024);
|
|
|
|
size_t len = 0;
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
while (len < bytes) {
|
|
|
|
auto* e = reinterpret_cast<::inotify_event*>(&buffer[len]);
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
event->filename = e->len ? e->name : m_path;
|
|
|
|
event->wd = e->wd;
|
|
|
|
event->cookie = e->cookie;
|
|
|
|
event->is_dir = e->mask & IN_ISDIR;
|
|
|
|
event->mask |= e->mask;
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
len += sizeof(*e) + e->len;
|
2016-11-02 15:22:45 -04:00
|
|
|
}
|
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
return event;
|
|
|
|
}
|
2016-11-25 05:40:32 -05:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
/**
|
|
|
|
* Wait for matching event
|
|
|
|
*/
|
|
|
|
bool inotify_watch::await_match() {
|
|
|
|
return (get_event()->mask & m_mask) == m_mask;
|
|
|
|
}
|
2016-11-02 15:22:45 -04:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
/**
|
|
|
|
* Get watch file path
|
|
|
|
*/
|
|
|
|
const string inotify_watch::path() const {
|
|
|
|
return m_path;
|
|
|
|
}
|
2016-12-05 14:41:00 -05:00
|
|
|
|
2016-12-19 23:05:43 -05:00
|
|
|
/**
|
|
|
|
* Get the file descriptor associated with the watch
|
|
|
|
*/
|
|
|
|
int inotify_watch::get_file_descriptor() const {
|
|
|
|
return m_fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool match(const inotify_event* evt, int mask) {
|
|
|
|
return (evt->mask & mask) == mask;
|
2016-11-02 15:22:45 -04:00
|
|
|
}
|
|
|
|
|
2016-11-19 00:22:44 -05:00
|
|
|
POLYBAR_NS_END
|