23 #include <core/exception.h>
24 #include <logging/liblogger.h>
25 #include <utils/system/fam.h>
28 # include <sys/inotify.h>
29 # include <sys/stat.h>
93 (FAM_ACCESS | FAM_MODIFY | FAM_ATTRIB | FAM_CLOSE_WRITE | FAM_CLOSE_NOWRITE | FAM_OPEN
94 | FAM_MOVED_FROM | FAM_MOVED_TO | FAM_CREATE | FAM_DELETE | FAM_DELETE_SELF | FAM_MOVE_SELF);
112 inotify_bufsize_ = 0;
115 if ((inotify_fd_ = inotify_init()) == -1) {
116 throw Exception(errno,
"Failed to initialize inotify");
120 inotify_bufsize_ = 1024 * (
sizeof(
struct inotify_event) + 16);
121 inotify_buf_ = (
char *)malloc(inotify_bufsize_);
124 interrupted_ =
false;
125 interruptible_ = (pipe(pipe_fds_) == 0);
133 for (rxit_ = regexes_.begin(); rxit_ != regexes_.end(); ++rxit_) {
139 for (inotify_wit_ = inotify_watches_.begin(); inotify_wit_ != inotify_watches_.end();
141 inotify_rm_watch(inotify_fd_, inotify_wit_->first);
159 DIR *d = opendir(dirpath);
161 throw Exception(errno,
"Failed to open dir %s", dirpath);
164 uint32_t mask = IN_MODIFY | IN_MOVE | IN_CREATE | IN_DELETE | IN_DELETE_SELF;
168 if ((iw = inotify_add_watch(inotify_fd_, dirpath, mask)) >= 0) {
169 inotify_watches_[iw] = dirpath;
172 while ((de = readdir(d))) {
173 std::string fp = std::string(dirpath) +
"/" + de->d_name;
175 if (stat(fp.c_str(), &st) == 0) {
176 if ((de->d_name[0] !=
'.') && S_ISDIR(st.st_mode)) {
193 throw Exception(errno,
"FileAlterationMonitor: cannot add watch for %s", dirpath);
208 uint32_t mask = IN_MODIFY | IN_MOVE | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF;
211 if ((iw = inotify_add_watch(inotify_fd_, filepath, mask)) >= 0) {
213 inotify_watches_[iw] = filepath;
215 throw Exception(
"FileAlterationMonitor: cannot add watch for file %s", filepath);
225 std::map<int, std::string>::iterator wit;
226 for (wit = inotify_watches_.begin(); wit != inotify_watches_.end(); ++wit) {
227 inotify_rm_watch(inotify_fd_, wit->first);
229 inotify_watches_.clear();
249 regex_t *rx = (regex_t *)malloc(
sizeof(regex_t));
250 if ((regerr = regcomp(rx, regex, REG_EXTENDED)) != 0) {
252 regerror(regerr, rx, errtmp,
sizeof(errtmp));
254 throw Exception(
"Failed to compile lua file regex: %s", errtmp);
265 listeners_.push_back_locked(listener);
274 listeners_.remove_locked(listener);
287 interrupted_ =
false;
288 std::map<std::string, unsigned int> events;
291 ipfd[0].fd = inotify_fd_;
292 ipfd[0].events = POLLIN;
294 ipfd[1].fd = pipe_fds_[0];
295 ipfd[1].events = POLLIN;
297 int prv = poll(ipfd, 2, timeout);
299 if (errno != EINTR) {
307 while (!interrupted_ && (prv > 0)) {
309 if (ipfd[0].revents & POLLERR) {
311 }
else if (interrupted_) {
316 int bytes = 0, i = 0;
318 if ((bytes = read(inotify_fd_, inotify_buf_, inotify_bufsize_)) != -1) {
319 while (!interrupted_ && (i < bytes)) {
320 struct inotify_event *
event = (
struct inotify_event *)&inotify_buf_[i];
322 if (event->mask & IN_IGNORED) {
323 i +=
sizeof(
struct inotify_event) + event->len;
328 if (!(event->mask & IN_ISDIR)) {
329 for (rxit_ = regexes_.begin(); rxit_ != regexes_.end(); ++rxit_) {
330 if (event->len > 0 && (regexec(*rxit_, event->name, 0, NULL, 0) == REG_NOMATCH)) {
338 if (event->len == 0) {
339 if (inotify_watches_.find(event->wd) != inotify_watches_.end()) {
340 if (events.find(inotify_watches_[event->wd]) != events.end()) {
341 events[inotify_watches_[
event->wd]] |=
event->mask;
343 events[inotify_watches_[
event->wd]] =
event->mask;
347 if (events.find(event->name) != events.end()) {
348 events[
event->name] |=
event->mask;
350 events[
event->name] =
event->mask;
355 if (event->mask & IN_DELETE_SELF) {
357 inotify_watches_.erase(event->wd);
358 inotify_rm_watch(inotify_fd_, event->wd);
361 if (event->mask & IN_CREATE) {
363 std::string fp = inotify_watches_[
event->wd] +
"/" +
event->name;
364 if ((event->mask & IN_ISDIR) && (event->name[0] !=
'.')) {
372 }
catch (Exception &e) {
379 i +=
sizeof(
struct inotify_event) + event->len;
387 prv = poll(ipfd, 2, 0);
390 std::map<std::string, unsigned int>::const_iterator e;
391 for (e = events.begin(); e != events.end(); ++e) {
394 for (lit_ = listeners_.begin(); lit_ != listeners_.end(); ++lit_) {
395 (*lit_)->fam_event(e->first.c_str(), e->second);
403 throw Exception(
"FileAlterationMonitor: inotify support not available, "
404 "but process_events() was called.");
415 if (interruptible_) {
418 if (write(pipe_fds_[1], &tmp, 1) != 1) {
420 "Failed to interrupt file alteration monitor,"
421 " failed to write to pipe");
424 throw Exception(
"Currently not interruptible");