X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Ffs%2Funix%2Ffilemonitor.cpp;fp=source%2Ffs%2Funix%2Ffilemonitor.cpp;h=70cfc4ec4b524e432a529aba08d6cacd366b5499;hp=0000000000000000000000000000000000000000;hb=ffab0509a65f6f32851e64d66a5f7eeb453ab29f;hpb=c7b4b9d6e07b3e32e5b03f41f0640a8273eed848 diff --git a/source/fs/unix/filemonitor.cpp b/source/fs/unix/filemonitor.cpp new file mode 100644 index 0000000..70cfc4e --- /dev/null +++ b/source/fs/unix/filemonitor.cpp @@ -0,0 +1,131 @@ +#include +#include +#include +#include "filemonitor.h" +#include "filemonitor_platform.h" + +using namespace std; + +namespace Msp { +namespace FS { + +INotify::INotify() +{ + *fd = inotify_init(); + mode = IO::M_READ; + set_events(IO::P_INPUT); +} + +INotify::~INotify() +{ + IO::sys_close(fd); +} + +int INotify::add_watch(const FS::Path &path, int ev) +{ + int ret = inotify_add_watch(*fd, path.c_str(), ev); + if(ret==-1) + throw system_error("inotify_add_watch"); + return ret; +} + +void INotify::remove_watch(int wd) +{ + int ret = inotify_rm_watch(*fd, wd); + if(ret==-1) + throw system_error("inotify_rm_watch"); +} + +unsigned INotify::do_write(const char *, unsigned) +{ + check_access(IO::M_WRITE); + return 0; +} + +unsigned INotify::do_read(char *buf, unsigned size) +{ + return IO::sys_read(fd, buf, size); +} + + +void FileMonitor::platform_use_event_dispatcher() +{ + event_disp->add(priv->inotify); +} + +void FileMonitor::prepare_file(MonitoredFile &file) +{ + file.tag = priv->inotify.add_watch(file.path, IN_MODIFY|IN_CLOSE_WRITE|IN_DELETE_SELF); +} + +void FileMonitor::cleanup_file(MonitoredFile &file) +{ + if(file.tag!=-1) + priv->inotify.remove_watch(file.tag); +} + +void FileMonitor::tick() +{ + bool first = true; + while(1) + { + if(!first && !IO::poll(priv->inotify, IO::P_INPUT, Time::zero)) + break; + + first = false; + priv->events_available(); + } +} + +void FileMonitor::tick(const Time::TimeDelta &timeout) +{ + if(IO::poll(priv->inotify, IO::P_INPUT, timeout)) + tick(); +} + + +FileMonitor::Private::Private(FileMonitor &m): + monitor(m) +{ + inotify.signal_data_available.connect(sigc::mem_fun(this, &Private::events_available)); +} + +void FileMonitor::Private::events_available() +{ + vector changed_files; + char event_buf[sizeof(struct inotify_event)+NAME_MAX+1]; + unsigned len = inotify.read(event_buf, sizeof(event_buf)); + for(unsigned i=0; i(event_buf+i); + for(vector::iterator j=monitor.files.begin(); j!=monitor.files.end(); ++j) + if(j->tag==event->wd) + { + if(event->mask&IN_MODIFY) + j->modified = true; + if(((event->mask&IN_CLOSE_WRITE) && j->modified) || (event->mask&IN_DELETE_SELF)) + { + j->modified = false; + changed_files.push_back(j->path); + } + if(event->mask&IN_IGNORED) + j->tag = -1; + break; + } + i += sizeof(struct inotify_event)+event->len; + } + + for(vector::const_iterator i=changed_files.begin(); i!=changed_files.end(); ++i) + monitor.signal_file_modified.emit(*i); + + for(vector::iterator j=monitor.files.begin(); j!=monitor.files.end(); ) + { + if(j->tag==-1) + monitor.files.erase(j++); + else + ++j; + } +} + +} // namespace FS +} // namespace Msp