diff options
Diffstat (limited to 'smdirwatcher.cpp')
-rw-r--r-- | smdirwatcher.cpp | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/smdirwatcher.cpp b/smdirwatcher.cpp new file mode 100644 index 0000000..a216af5 --- /dev/null +++ b/smdirwatcher.cpp @@ -0,0 +1,84 @@ +/* + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version + 2 of the License, or (at your option) any later version. +*/ + +#include <QVarLengthArray> +#include <QMutexLocker> + +#include <sys/inotify.h> +#include <stropts.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <errno.h> + +#include "smdirwatcher.h" + +extern int errno; + +SmDirWatcher::SmDirWatcher(QObject *parent) : QThread(parent), mFd(0), mDescr(0) { + mFd = inotify_init1(IN_NONBLOCK); +} + +SmDirWatcher::~SmDirWatcher(){ + if(mFd && mDescr){ + inotify_rm_watch(mFd, mDescr); + } +} + +void SmDirWatcher::setDir(const QString &dir){ + QMutexLocker lock(&mWatchMx); + if(mDescr){ + inotify_rm_watch(mFd, mDescr); //generates IN_IGNORE ??? + } + /* mask rationale: + * IN_DELETE_SELF, IN_MOVE_TO and IN_MOVE_FROM cannot happen, + * since we're only watching one directory at all times + * don't care about the other events + */ + mDescr = inotify_add_watch(mFd, qPrintable(dir), IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_MODIFY); + mCurrent = dir; +} + +#include <QDebug> + +void SmDirWatcher::run(){ + QMutexLocker lock(&mWatchMx); + QVarLengthArray<char, 4096> data(ioctl(mFd, FIONREAD) + 1); + int r = read(mFd, data.data(), data.size()); + while(r < 0){ + int err = errno; + // buffer too small + if(err == EINVAL){ + data.resize(data.size() * 2); + r = read(mFd, data.data(), data.size()); + continue; + // dunno + }else{ + return; + } + } + // inspect data + char *at = data.data(); + char *end = at + data.size(); + while(at < end){ + inotify_event *e = reinterpret_cast<inotify_event*>(at); + qDebug() << "inotify:" << e->name; + if(e->mask & IN_IGNORED){ + at += sizeof(inotify_event) + e->len; + continue; + } + if(e->mask & IN_CREATE){ + emit dwEvent(e->name, Added); + } + if(e->mask & IN_DELETE){ + emit dwEvent(e->name, Deleted); + } + if((e->mask & IN_CLOSE_WRITE) || (e->mask & IN_MODIFY)){ + emit dwEvent(e->name, Modified); + } + at += sizeof(inotify_event) + e->len; + } +} |