io/qfilesystemwatcher_inotify.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
5** -
6** This file is part of the QtCore module of the Qt Toolkit. -
7** -
8** $QT_BEGIN_LICENSE:LGPL$ -
9** Commercial License Usage -
10** Licensees holding valid commercial Qt licenses may use this file in -
11** accordance with the commercial license agreement provided with the -
12** Software or, alternatively, in accordance with the terms contained in -
13** a written agreement between you and Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/contact-us. -
16** -
17** GNU Lesser General Public License Usage -
18** Alternatively, this file may be used under the terms of the GNU Lesser -
19** General Public License version 2.1 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qfilesystemwatcher.h" -
43#include "qfilesystemwatcher_inotify_p.h" -
44 -
45#ifndef QT_NO_FILESYSTEMWATCHER -
46 -
47#include "private/qcore_unix_p.h" -
48 -
49#include <qdebug.h> -
50#include <qfile.h> -
51#include <qfileinfo.h> -
52#include <qsocketnotifier.h> -
53#include <qvarlengtharray.h> -
54 -
55#if defined(Q_OS_LINUX) -
56#include <sys/syscall.h> -
57#include <sys/ioctl.h> -
58#include <unistd.h> -
59#include <fcntl.h> -
60#endif -
61 -
62#if defined(QT_NO_INOTIFY) -
63 -
64#if defined(Q_OS_QNX) -
65// These files should only be compiled on QNX if the inotify headers are found -
66#error "Should not get here." -
67#endif -
68 -
69#include <linux/types.h> -
70 -
71#if defined(__i386__) -
72# define __NR_inotify_init 291 -
73# define __NR_inotify_add_watch 292 -
74# define __NR_inotify_rm_watch 293 -
75# define __NR_inotify_init1 332 -
76#elif defined(__x86_64__) -
77# define __NR_inotify_init 253 -
78# define __NR_inotify_add_watch 254 -
79# define __NR_inotify_rm_watch 255 -
80# define __NR_inotify_init1 294 -
81#elif defined(__powerpc__) || defined(__powerpc64__) -
82# define __NR_inotify_init 275 -
83# define __NR_inotify_add_watch 276 -
84# define __NR_inotify_rm_watch 277 -
85# define __NR_inotify_init1 318 -
86#elif defined (__ia64__) -
87# define __NR_inotify_init 1277 -
88# define __NR_inotify_add_watch 1278 -
89# define __NR_inotify_rm_watch 1279 -
90# define __NR_inotify_init1 1318 -
91#elif defined (__s390__) || defined (__s390x__) -
92# define __NR_inotify_init 284 -
93# define __NR_inotify_add_watch 285 -
94# define __NR_inotify_rm_watch 286 -
95# define __NR_inotify_init1 324 -
96#elif defined (__alpha__) -
97# define __NR_inotify_init 444 -
98# define __NR_inotify_add_watch 445 -
99# define __NR_inotify_rm_watch 446 -
100// no inotify_init1 for the Alpha -
101#elif defined (__sparc__) || defined (__sparc64__) -
102# define __NR_inotify_init 151 -
103# define __NR_inotify_add_watch 152 -
104# define __NR_inotify_rm_watch 156 -
105# define __NR_inotify_init1 322 -
106#elif defined (__arm__) -
107# define __NR_inotify_init 316 -
108# define __NR_inotify_add_watch 317 -
109# define __NR_inotify_rm_watch 318 -
110# define __NR_inotify_init1 360 -
111#elif defined (__sh__) -
112# define __NR_inotify_init 290 -
113# define __NR_inotify_add_watch 291 -
114# define __NR_inotify_rm_watch 292 -
115# define __NR_inotify_init1 332 -
116#elif defined (__sh64__) -
117# define __NR_inotify_init 318 -
118# define __NR_inotify_add_watch 319 -
119# define __NR_inotify_rm_watch 320 -
120# define __NR_inotify_init1 360 -
121#elif defined (__mips__) -
122# define __NR_inotify_init 284 -
123# define __NR_inotify_add_watch 285 -
124# define __NR_inotify_rm_watch 286 -
125# define __NR_inotify_init1 329 -
126#elif defined (__hppa__) -
127# define __NR_inotify_init 269 -
128# define __NR_inotify_add_watch 270 -
129# define __NR_inotify_rm_watch 271 -
130# define __NR_inotify_init1 314 -
131#elif defined (__avr32__) -
132# define __NR_inotify_init 240 -
133# define __NR_inotify_add_watch 241 -
134# define __NR_inotify_rm_watch 242 -
135// no inotify_init1 for AVR32 -
136#elif defined (__mc68000__) -
137# define __NR_inotify_init 284 -
138# define __NR_inotify_add_watch 285 -
139# define __NR_inotify_rm_watch 286 -
140# define __NR_inotify_init1 328 -
141#else -
142# error "This architecture is not supported. Please see http://www.qt-project.org/" -
143#endif -
144 -
145#if !defined(IN_CLOEXEC) && defined(O_CLOEXEC) && defined(__NR_inotify_init1) -
146# define IN_CLOEXEC O_CLOEXEC -
147#endif -
148 -
149QT_BEGIN_NAMESPACE -
150 -
151#ifdef QT_LINUXBASE -
152// ### the LSB doesn't standardize syscall, need to wait until glib2.4 is standardized -
153static inline int syscall(...) { return -1; } -
154#endif -
155 -
156static inline int inotify_init() -
157{ -
158 return syscall(__NR_inotify_init); -
159} -
160 -
161static inline int inotify_add_watch(int fd, const char *name, __u32 mask) -
162{ -
163 return syscall(__NR_inotify_add_watch, fd, name, mask); -
164} -
165 -
166static inline int inotify_rm_watch(int fd, __u32 wd) -
167{ -
168 return syscall(__NR_inotify_rm_watch, fd, wd); -
169} -
170 -
171#ifdef IN_CLOEXEC -
172static inline int inotify_init1(int flags) -
173{ -
174 return syscall(__NR_inotify_init1, flags); -
175} -
176#endif -
177 -
178// the following struct and values are documented in linux/inotify.h -
179extern "C" { -
180 -
181struct inotify_event { -
182 __s32 wd; -
183 __u32 mask; -
184 __u32 cookie; -
185 __u32 len; -
186 char name[0]; -
187}; -
188 -
189#define IN_ACCESS 0x00000001 -
190#define IN_MODIFY 0x00000002 -
191#define IN_ATTRIB 0x00000004 -
192#define IN_CLOSE_WRITE 0x00000008 -
193#define IN_CLOSE_NOWRITE 0x00000010 -
194#define IN_OPEN 0x00000020 -
195#define IN_MOVED_FROM 0x00000040 -
196#define IN_MOVED_TO 0x00000080 -
197#define IN_CREATE 0x00000100 -
198#define IN_DELETE 0x00000200 -
199#define IN_DELETE_SELF 0x00000400 -
200#define IN_MOVE_SELF 0x00000800 -
201#define IN_UNMOUNT 0x00002000 -
202#define IN_Q_OVERFLOW 0x00004000 -
203#define IN_IGNORED 0x00008000 -
204 -
205#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) -
206#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) -
207} -
208 -
209QT_END_NAMESPACE -
210 -
211// --------- inotify.h end ---------- -
212 -
213#else /* QT_NO_INOTIFY */ -
214 -
215#include <sys/inotify.h> -
216 -
217#endif -
218 -
219QT_BEGIN_NAMESPACE -
220 -
221QInotifyFileSystemWatcherEngine *QInotifyFileSystemWatcherEngine::create(QObject *parent) -
222{ -
223 register int fd = -1;
executed (the execution status of this line is deduced): register int fd = -1;
-
224#ifdef IN_CLOEXEC -
225 fd = inotify_init1(IN_CLOEXEC);
executed (the execution status of this line is deduced): fd = inotify_init1(IN_CLOEXEC);
-
226#endif -
227 if (fd == -1) {
partially evaluated: fd == -1
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:289
0-289
228 fd = inotify_init();
never executed (the execution status of this line is deduced): fd = inotify_init();
-
229 if (fd == -1)
never evaluated: fd == -1
0
230 return 0;
never executed: return 0;
0
231 }
never executed: }
0
232 return new QInotifyFileSystemWatcherEngine(fd, parent);
executed: return new QInotifyFileSystemWatcherEngine(fd, parent);
Execution Count:289
289
233} -
234 -
235QInotifyFileSystemWatcherEngine::QInotifyFileSystemWatcherEngine(int fd, QObject *parent) -
236 : QFileSystemWatcherEngine(parent), -
237 inotifyFd(fd), -
238 notifier(fd, QSocketNotifier::Read, this) -
239{ -
240 fcntl(inotifyFd, F_SETFD, FD_CLOEXEC);
executed (the execution status of this line is deduced): fcntl(inotifyFd, 2, 1);
-
241 connect(&notifier, SIGNAL(activated(int)), SLOT(readFromInotify()));
executed (the execution status of this line is deduced): connect(&notifier, "2""activated(int)", "1""readFromInotify()");
-
242}
executed: }
Execution Count:289
289
243 -
244QInotifyFileSystemWatcherEngine::~QInotifyFileSystemWatcherEngine() -
245{ -
246 notifier.setEnabled(false);
executed (the execution status of this line is deduced): notifier.setEnabled(false);
-
247 foreach (int id, pathToID)
executed (the execution status of this line is deduced): for (QForeachContainer<__typeof__(pathToID)> _container_(pathToID); !_container_.brk && _container_.i != _container_.e; __extension__ ({ ++_container_.brk; ++_container_.i; })) for (int id = *_container_.i;; __extension__ ({--_container_.brk; break;}))
-
248 inotify_rm_watch(inotifyFd, id < 0 ? -id : id);
executed: inotify_rm_watch(inotifyFd, id < 0 ? -id : id);
Execution Count:268
268
249 -
250 ::close(inotifyFd);
executed (the execution status of this line is deduced): ::close(inotifyFd);
-
251}
executed: }
Execution Count:289
289
252 -
253QStringList QInotifyFileSystemWatcherEngine::addPaths(const QStringList &paths, -
254 QStringList *files, -
255 QStringList *directories) -
256{ -
257 QStringList p = paths;
executed (the execution status of this line is deduced): QStringList p = paths;
-
258 QMutableListIterator<QString> it(p);
executed (the execution status of this line is deduced): QMutableListIterator<QString> it(p);
-
259 while (it.hasNext()) {
evaluated: it.hasNext()
TRUEFALSE
yes
Evaluation Count:320
yes
Evaluation Count:318
318-320
260 QString path = it.next();
executed (the execution status of this line is deduced): QString path = it.next();
-
261 QFileInfo fi(path);
executed (the execution status of this line is deduced): QFileInfo fi(path);
-
262 bool isDir = fi.isDir();
executed (the execution status of this line is deduced): bool isDir = fi.isDir();
-
263 if (isDir) {
evaluated: isDir
TRUEFALSE
yes
Evaluation Count:311
yes
Evaluation Count:9
9-311
264 if (directories->contains(path))
evaluated: directories->contains(path)
TRUEFALSE
yes
Evaluation Count:1
yes
Evaluation Count:310
1-310
265 continue;
executed: continue;
Execution Count:1
1
266 } else {
executed: }
Execution Count:310
310
267 if (files->contains(path))
partially evaluated: files->contains(path)
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:9
0-9
268 continue;
never executed: continue;
0
269 }
executed: }
Execution Count:9
9
270 -
271 int wd = inotify_add_watch(inotifyFd,
executed (the execution status of this line is deduced): int wd = inotify_add_watch(inotifyFd,
-
272 QFile::encodeName(path),
executed (the execution status of this line is deduced): QFile::encodeName(path),
-
273 (isDir
executed (the execution status of this line is deduced): (isDir
-
274 ? (0
executed (the execution status of this line is deduced): ? (0
-
275 | IN_ATTRIB
executed (the execution status of this line is deduced): | 0x00000004
-
276 | IN_MOVE
executed (the execution status of this line is deduced): | (0x00000040 | 0x00000080)
-
277 | IN_CREATE
executed (the execution status of this line is deduced): | 0x00000100
-
278 | IN_DELETE
executed (the execution status of this line is deduced): | 0x00000200
-
279 | IN_DELETE_SELF
executed (the execution status of this line is deduced): | 0x00000400
-
280 )
executed (the execution status of this line is deduced): )
-
281 : (0
executed (the execution status of this line is deduced): : (0
-
282 | IN_ATTRIB
executed (the execution status of this line is deduced): | 0x00000004
-
283 | IN_MODIFY
executed (the execution status of this line is deduced): | 0x00000002
-
284 | IN_MOVE
executed (the execution status of this line is deduced): | (0x00000040 | 0x00000080)
-
285 | IN_MOVE_SELF
executed (the execution status of this line is deduced): | 0x00000800
-
286 | IN_DELETE_SELF
executed (the execution status of this line is deduced): | 0x00000400
-
287 )));
executed (the execution status of this line is deduced): )));
-
288 if (wd < 0) {
evaluated: wd < 0
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:317
2-317
289 perror("QInotifyFileSystemWatcherEngine::addPaths: inotify_add_watch failed");
executed (the execution status of this line is deduced): perror("QInotifyFileSystemWatcherEngine::addPaths: inotify_add_watch failed");
-
290 continue;
executed: continue;
Execution Count:2
2
291 } -
292 -
293 it.remove();
executed (the execution status of this line is deduced): it.remove();
-
294 -
295 int id = isDir ? -wd : wd;
evaluated: isDir
TRUEFALSE
yes
Evaluation Count:310
yes
Evaluation Count:7
7-310
296 if (id < 0) {
evaluated: id < 0
TRUEFALSE
yes
Evaluation Count:310
yes
Evaluation Count:7
7-310
297 directories->append(path);
executed (the execution status of this line is deduced): directories->append(path);
-
298 } else {
executed: }
Execution Count:310
310
299 files->append(path);
executed (the execution status of this line is deduced): files->append(path);
-
300 }
executed: }
Execution Count:7
7
301 -
302 pathToID.insert(path, id);
executed (the execution status of this line is deduced): pathToID.insert(path, id);
-
303 idToPath.insert(id, path);
executed (the execution status of this line is deduced): idToPath.insert(id, path);
-
304 }
executed: }
Execution Count:317
317
305 -
306 return p;
executed: return p;
Execution Count:318
318
307} -
308 -
309QStringList QInotifyFileSystemWatcherEngine::removePaths(const QStringList &paths, -
310 QStringList *files, -
311 QStringList *directories) -
312{ -
313 QStringList p = paths;
executed (the execution status of this line is deduced): QStringList p = paths;
-
314 QMutableListIterator<QString> it(p);
executed (the execution status of this line is deduced): QMutableListIterator<QString> it(p);
-
315 while (it.hasNext()) {
evaluated: it.hasNext()
TRUEFALSE
yes
Evaluation Count:67
yes
Evaluation Count:66
66-67
316 QString path = it.next();
executed (the execution status of this line is deduced): QString path = it.next();
-
317 int id = pathToID.take(path);
executed (the execution status of this line is deduced): int id = pathToID.take(path);
-
318 QString x = idToPath.take(id);
executed (the execution status of this line is deduced): QString x = idToPath.take(id);
-
319 if (x.isEmpty() || x != path)
evaluated: x.isEmpty()
TRUEFALSE
yes
Evaluation Count:22
yes
Evaluation Count:45
partially evaluated: x != path
TRUEFALSE
no
Evaluation Count:0
yes
Evaluation Count:45
0-45
320 continue;
executed: continue;
Execution Count:22
22
321 -
322 int wd = id < 0 ? -id : id;
evaluated: id < 0
TRUEFALSE
yes
Evaluation Count:41
yes
Evaluation Count:4
4-41
323 // qDebug() << "removing watch for path" << path << "wd" << wd; -
324 inotify_rm_watch(inotifyFd, wd);
executed (the execution status of this line is deduced): inotify_rm_watch(inotifyFd, wd);
-
325 -
326 it.remove();
executed (the execution status of this line is deduced): it.remove();
-
327 if (id < 0) {
evaluated: id < 0
TRUEFALSE
yes
Evaluation Count:41
yes
Evaluation Count:4
4-41
328 directories->removeAll(path);
executed (the execution status of this line is deduced): directories->removeAll(path);
-
329 } else {
executed: }
Execution Count:41
41
330 files->removeAll(path);
executed (the execution status of this line is deduced): files->removeAll(path);
-
331 }
executed: }
Execution Count:4
4
332 } -
333 -
334 return p;
executed: return p;
Execution Count:66
66
335} -
336 -
337void QInotifyFileSystemWatcherEngine::readFromInotify() -
338{ -
339 // qDebug() << "QInotifyFileSystemWatcherEngine::readFromInotify"; -
340 -
341 int buffSize = 0;
executed (the execution status of this line is deduced): int buffSize = 0;
-
342 ioctl(inotifyFd, FIONREAD, (char *) &buffSize);
executed (the execution status of this line is deduced): ioctl(inotifyFd, 0x541B, (char *) &buffSize);
-
343 QVarLengthArray<char, 4096> buffer(buffSize);
executed (the execution status of this line is deduced): QVarLengthArray<char, 4096> buffer(buffSize);
-
344 buffSize = read(inotifyFd, buffer.data(), buffSize);
executed (the execution status of this line is deduced): buffSize = read(inotifyFd, buffer.data(), buffSize);
-
345 char *at = buffer.data();
executed (the execution status of this line is deduced): char *at = buffer.data();
-
346 char * const end = at + buffSize;
executed (the execution status of this line is deduced): char * const end = at + buffSize;
-
347 -
348 QHash<int, inotify_event *> eventForId;
executed (the execution status of this line is deduced): QHash<int, inotify_event *> eventForId;
-
349 while (at < end) {
evaluated: at < end
TRUEFALSE
yes
Evaluation Count:165
yes
Evaluation Count:80
80-165
350 inotify_event *event = reinterpret_cast<inotify_event *>(at);
executed (the execution status of this line is deduced): inotify_event *event = reinterpret_cast<inotify_event *>(at);
-
351 -
352 if (eventForId.contains(event->wd))
evaluated: eventForId.contains(event->wd)
TRUEFALSE
yes
Evaluation Count:81
yes
Evaluation Count:84
81-84
353 eventForId[event->wd]->mask |= event->mask;
executed: eventForId[event->wd]->mask |= event->mask;
Execution Count:81
81
354 else -
355 eventForId.insert(event->wd, event);
executed: eventForId.insert(event->wd, event);
Execution Count:84
84
356 -
357 at += sizeof(inotify_event) + event->len;
executed (the execution status of this line is deduced): at += sizeof(inotify_event) + event->len;
-
358 }
executed: }
Execution Count:165
165
359 -
360 QHash<int, inotify_event *>::const_iterator it = eventForId.constBegin();
executed (the execution status of this line is deduced): QHash<int, inotify_event *>::const_iterator it = eventForId.constBegin();
-
361 while (it != eventForId.constEnd()) {
evaluated: it != eventForId.constEnd()
TRUEFALSE
yes
Evaluation Count:84
yes
Evaluation Count:80
80-84
362 const inotify_event &event = **it;
executed (the execution status of this line is deduced): const inotify_event &event = **it;
-
363 ++it;
executed (the execution status of this line is deduced): ++it;
-
364 -
365 // qDebug() << "inotify event, wd" << event.wd << "mask" << hex << event.mask; -
366 -
367 int id = event.wd;
executed (the execution status of this line is deduced): int id = event.wd;
-
368 QString path = idToPath.value(id);
executed (the execution status of this line is deduced): QString path = idToPath.value(id);
-
369 if (path.isEmpty()) {
evaluated: path.isEmpty()
TRUEFALSE
yes
Evaluation Count:78
yes
Evaluation Count:6
6-78
370 // perhaps a directory? -
371 id = -id;
executed (the execution status of this line is deduced): id = -id;
-
372 path = idToPath.value(id);
executed (the execution status of this line is deduced): path = idToPath.value(id);
-
373 if (path.isEmpty())
evaluated: path.isEmpty()
TRUEFALSE
yes
Evaluation Count:29
yes
Evaluation Count:49
29-49
374 continue;
executed: continue;
Execution Count:29
29
375 }
executed: }
Execution Count:49
49
376 -
377 // qDebug() << "event for path" << path; -
378 -
379 if ((event.mask & (IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT)) != 0) {
evaluated: (event.mask & (0x00000400 | 0x00000800 | 0x00002000)) != 0
TRUEFALSE
yes
Evaluation Count:4
yes
Evaluation Count:51
4-51
380 pathToID.remove(path);
executed (the execution status of this line is deduced): pathToID.remove(path);
-
381 idToPath.remove(id);
executed (the execution status of this line is deduced): idToPath.remove(id);
-
382 inotify_rm_watch(inotifyFd, event.wd);
executed (the execution status of this line is deduced): inotify_rm_watch(inotifyFd, event.wd);
-
383 -
384 if (id < 0)
evaluated: id < 0
TRUEFALSE
yes
Evaluation Count:2
yes
Evaluation Count:2
2
385 emit directoryChanged(path, true);
executed: directoryChanged(path, true);
Execution Count:2
2
386 else -
387 emit fileChanged(path, true);
executed: fileChanged(path, true);
Execution Count:2
2
388 } else { -
389 if (id < 0)
evaluated: id < 0
TRUEFALSE
yes
Evaluation Count:47
yes
Evaluation Count:4
4-47
390 emit directoryChanged(path, false);
executed: directoryChanged(path, false);
Execution Count:47
47
391 else -
392 emit fileChanged(path, false);
executed: fileChanged(path, false);
Execution Count:4
4
393 } -
394 } -
395}
executed: }
Execution Count:80
80
396 -
397QT_END_NAMESPACE -
398 -
399#endif // QT_NO_FILESYSTEMWATCHER -
400 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial