?? qfilesystemwatcher_inotify.cpp
字號:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtCore module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qfilesystemwatcher.h"#include "qfilesystemwatcher_inotify_p.h"#ifndef QT_NO_FILESYSTEMWATCHER#include <qdebug.h>#include <qfile.h>#include <qfileinfo.h>#include <qsocketnotifier.h>#include <qvarlengtharray.h>#include <sys/syscall.h>#include <sys/ioctl.h>#include <unistd.h>#include <fcntl.h>#if defined(QT_NO_INOTIFY)#include <linux/types.h>#if defined(__i386__)# define __NR_inotify_init 291# define __NR_inotify_add_watch 292# define __NR_inotify_rm_watch 293#elif defined(__x86_64__)# define __NR_inotify_init 253# define __NR_inotify_add_watch 254# define __NR_inotify_rm_watch 255#elif defined(__powerpc__) || defined(__powerpc64__)# define __NR_inotify_init 275# define __NR_inotify_add_watch 276# define __NR_inotify_rm_watch 277#elif defined (__ia64__)# define __NR_inotify_init 1277# define __NR_inotify_add_watch 1278# define __NR_inotify_rm_watch 1279#elif defined (__s390__) || defined (__s390x__)# define __NR_inotify_init 284# define __NR_inotify_add_watch 285# define __NR_inotify_rm_watch 286#elif defined (__alpha__)# define __NR_inotify_init 444# define __NR_inotify_add_watch 445# define __NR_inotify_rm_watch 446#elif defined (__sparc__) || defined (__sparc64__)# define __NR_inotify_init 151# define __NR_inotify_add_watch 152# define __NR_inotify_rm_watch 156#elif defined (__arm__)# define __NR_inotify_init 316# define __NR_inotify_add_watch 317# define __NR_inotify_rm_watch 318#elif defined (__SH4__)# define __NR_inotify_init 290# define __NR_inotify_add_watch 291# define __NR_inotify_rm_watch 292#elif defined (__SH5__)# define __NR_inotify_init 318# define __NR_inotify_add_watch 319# define __NR_inotify_rm_watch 320#elif defined (__mips__)# define __NR_inotify_init 284# define __NR_inotify_add_watch 285# define __NR_inotify_rm_watch 286#elif defined (__hppa__)# define __NR_inotify_init 269# define __NR_inotify_add_watch 270# define __NR_inotify_rm_watch 271#else# error "This architecture is not supported. Please talk to qt-bugs@trolltech.com"#endif#ifdef QT_LSB// ### the LSB doesn't standardize syscall, need to wait until glib2.4 is standardizedstatic inline int syscall(...) { return -1; }#endifstatic inline int inotify_init(){ return syscall(__NR_inotify_init);}static inline int inotify_add_watch(int fd, const char *name, __u32 mask){ return syscall(__NR_inotify_add_watch, fd, name, mask);}static inline int inotify_rm_watch(int fd, __u32 wd){ return syscall(__NR_inotify_rm_watch, fd, wd);}// from linux/inotify.h// ---------- inotify.h begin -------// Copyright (C) 2005 John McCutchanextern "C" {/* * struct inotify_event - structure read from the inotify device for each event * * When you are watching a directory, you will receive the filename for events * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd. */struct inotify_event { __s32 wd; /* watch descriptor */ __u32 mask; /* watch mask */ __u32 cookie; /* cookie to synchronize two events */ __u32 len; /* length (including nulls) of name */ char name[0]; /* stub for possible name */};/* the following are legal, implemented events that user-space can watch for */#define IN_ACCESS 0x00000001 /* File was accessed */#define IN_MODIFY 0x00000002 /* File was modified */#define IN_ATTRIB 0x00000004 /* Metadata changed */#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed */#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */#define IN_OPEN 0x00000020 /* File was opened */#define IN_MOVED_FROM 0x00000040 /* File was moved from X */#define IN_MOVED_TO 0x00000080 /* File was moved to Y */#define IN_CREATE 0x00000100 /* Subfile was created */#define IN_DELETE 0x00000200 /* Subfile was deleted */#define IN_DELETE_SELF 0x00000400 /* Self was deleted */#define IN_MOVE_SELF 0x00000800 /* Self was moved *//* the following are legal events. they are sent as needed to any watch */#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted */#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */#define IN_IGNORED 0x00008000 /* File was ignored *//* helper events */#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* close */#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves *//* special flags */#define IN_MASK_ADD 0x20000000#define IN_ISDIR 0x40000000 /* event occurred against dir */#define IN_ONESHOT 0x80000000 /* only send event once *//* * All of the events - we build the list by hand so that we can add flags in * the future and not break backward compatibility. Apps will get only the * events that they originally wanted. Be sure to add new events here! */#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \ IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \ IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \ IN_MOVE_SELF)}// --------- inotify.h end ----------#else /* QT_NO_INOTIFY */#include <sys/inotify.h>#endifQInotifyFileSystemWatcherEngine *QInotifyFileSystemWatcherEngine::create(){ int fd = inotify_init(); if (fd <= 0) return 0; return new QInotifyFileSystemWatcherEngine(fd);}QInotifyFileSystemWatcherEngine::QInotifyFileSystemWatcherEngine(int fd) : inotifyFd(fd){ fcntl(inotifyFd, F_SETFD, FD_CLOEXEC); moveToThread(this);}QInotifyFileSystemWatcherEngine::~QInotifyFileSystemWatcherEngine(){ foreach (int id, pathToID.values()) inotify_rm_watch(inotifyFd, id < 0 ? -id : id); ::close(inotifyFd);}void QInotifyFileSystemWatcherEngine::run(){ QSocketNotifier sn(inotifyFd, QSocketNotifier::Read, this); connect(&sn, SIGNAL(activated(int)), SLOT(readFromInotify())); (void) exec();}QStringList QInotifyFileSystemWatcherEngine::addPaths(const QStringList &paths, QStringList *files, QStringList *directories){ QMutexLocker locker(&mutex); QStringList p = paths; QMutableListIterator<QString> it(p); while (it.hasNext()) { QString path = it.next(); QFileInfo fi(path); bool isDir = fi.isDir(); if (isDir) { if (directories->contains(path)) continue; } else { if (files->contains(path)) continue; } int wd = inotify_add_watch(inotifyFd, QFile::encodeName(path), (isDir ? (0 | IN_ATTRIB | IN_MOVE | IN_CREATE | IN_DELETE | IN_DELETE_SELF ) : (0 | IN_ATTRIB | IN_MODIFY | IN_MOVE | IN_DELETE_SELF ))); if (wd <= 0) { perror("QInotifyFileSystemWatcherEngine::addPaths: inotify_add_watch failed"); continue; } it.remove(); int id = isDir ? -wd : wd; if (id < 0) { directories->append(path); } else { files->append(path); } pathToID.insert(path, id); idToPath.insert(id, path); } start(); return p;}QStringList QInotifyFileSystemWatcherEngine::removePaths(const QStringList &paths, QStringList *files, QStringList *directories){ QMutexLocker locker(&mutex); QStringList p = paths; QMutableListIterator<QString> it(p); while (it.hasNext()) { QString path = it.next(); int id = pathToID.take(path); QString x = idToPath.take(id); if (x.isEmpty() || x != path) continue; int wd = id < 0 ? -id : id; // qDebug() << "removing watch for path" << path << "wd" << wd; inotify_rm_watch(inotifyFd, wd); it.remove(); if (id < 0) { directories->removeAll(path); } else { files->removeAll(path); } } return p;}void QInotifyFileSystemWatcherEngine::stop(){ QMetaObject::invokeMethod(this, "quit");}void QInotifyFileSystemWatcherEngine::readFromInotify(){ QMutexLocker locker(&mutex); // qDebug() << "QInotifyFileSystemWatcherEngine::readFromInotify"; int buffSize = 0; ioctl(inotifyFd, FIONREAD, &buffSize); QVarLengthArray<char, 4096> buffer(buffSize); buffSize = read(inotifyFd, buffer.data(), buffSize); inotify_event *ev = reinterpret_cast<inotify_event *>(buffer.data()); inotify_event *end = reinterpret_cast<inotify_event *>(buffer.data() + buffSize); while (ev < end) { // qDebug() << "inotify event, wd" << ev->wd << "mask" << hex << ev->mask; int id = ev->wd; QString path = idToPath.value(id); if (path.isEmpty()) { // perhaps a directory? id = -id; path = idToPath.value(id); if (path.isEmpty()) { ev += sizeof(inotify_event) + ev->len; continue; } } // qDebug() << "event for path" << path; if ((ev->mask & (IN_DELETE_SELF | IN_UNMOUNT)) != 0) { pathToID.remove(path); idToPath.remove(id); inotify_rm_watch(inotifyFd, ev->wd); if (id < 0) emit directoryChanged(path, true); else emit fileChanged(path, true); } else { if (id < 0) emit directoryChanged(path, false); else emit fileChanged(path, false); } ev += sizeof(inotify_event) + ev->len; }}#endif // QT_NO_FILESYSTEMWATCHER
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -