1 #include <sys/inotify.h>
2 #include <linux/limits.h>
3 #include <msp/core/systemerror.h>
4 #include <msp/io/handle_private.h>
5 #include "filemonitor.h"
6 #include "filemonitor_platform.h"
17 set_events(IO::P_INPUT);
25 int INotify::add_watch(const FS::Path &path, int ev)
27 int ret = inotify_add_watch(*fd, path.c_str(), ev);
29 throw system_error("inotify_add_watch");
33 void INotify::remove_watch(int wd)
35 int ret = inotify_rm_watch(*fd, wd);
37 throw system_error("inotify_rm_watch");
40 size_t INotify::do_write(const char *, size_t)
42 check_access(IO::M_WRITE);
46 size_t INotify::do_read(char *buf, size_t size)
48 return IO::sys_read(fd, buf, size);
52 void FileMonitor::platform_use_event_dispatcher()
54 event_disp->add(priv->inotify);
57 void FileMonitor::prepare_file(MonitoredFile &file)
59 file.tag = priv->inotify.add_watch(file.path, IN_MODIFY|IN_CLOSE_WRITE|IN_DELETE_SELF);
62 void FileMonitor::cleanup_file(MonitoredFile &file)
65 priv->inotify.remove_watch(file.tag);
68 void FileMonitor::tick()
73 if(!first && !IO::poll(priv->inotify, IO::P_INPUT, Time::zero))
77 priv->events_available();
81 void FileMonitor::tick(const Time::TimeDelta &timeout)
83 if(IO::poll(priv->inotify, IO::P_INPUT, timeout))
88 FileMonitor::Private::Private(FileMonitor &m):
91 inotify.signal_data_available.connect(sigc::mem_fun(this, &Private::events_available));
94 void FileMonitor::Private::events_available()
96 vector<FS::Path> changed_files;
97 char event_buf[sizeof(struct inotify_event)+NAME_MAX+1];
98 unsigned len = inotify.read(event_buf, sizeof(event_buf));
99 for(unsigned i=0; i<len; )
101 struct inotify_event *event = reinterpret_cast<struct inotify_event *>(event_buf+i);
102 for(vector<MonitoredFile>::iterator j=monitor.files.begin(); j!=monitor.files.end(); ++j)
103 if(j->tag==event->wd)
105 if(event->mask&IN_MODIFY)
107 if(((event->mask&IN_CLOSE_WRITE) && j->modified) || (event->mask&IN_DELETE_SELF))
110 changed_files.push_back(j->path);
112 if(event->mask&IN_IGNORED)
116 i += sizeof(struct inotify_event)+event->len;
119 for(vector<FS::Path>::const_iterator i=changed_files.begin(); i!=changed_files.end(); ++i)
120 monitor.signal_file_modified.emit(*i);
122 for(vector<MonitoredFile>::iterator j=monitor.files.begin(); j!=monitor.files.end(); )
125 monitor.files.erase(j++);