1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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;
}
}
|