48 #include <io/config-kdirwatch.h> 
   54 #include <QtCore/QDir> 
   55 #include <QtCore/QFile> 
   56 #include <QtCore/QSocketNotifier> 
   57 #include <QtCore/QTimer> 
   58 #include <QtCore/QCoreApplication> 
   71 #include <sys/ioctl.h> 
   74 #include <sys/utsname.h> 
   89   if (method == QLatin1String(
"Fam")) {
 
   91   } 
else if (method == QLatin1String(
"Stat")) {
 
   93   } 
else if (method == QLatin1String(
"QFSWatch")) {
 
  158     delayRemove( false ),
 
  162   timer.setObjectName(QLatin1String(
"KDirWatchPrivate::timer"));
 
  177   availableMethods << 
"Stat";
 
  180   rescan_timer.setObjectName(QString::fromLatin1(
"KDirWatchPrivate::rescan_timer"));
 
  186   if (FAMOpen(&fc) ==0) {
 
  187     availableMethods << 
"FAM";
 
  189     sn = 
new QSocketNotifier( FAMCONNECTION_GETFD(&fc),
 
  190                   QSocketNotifier::Read, 
this);
 
  191     connect( sn, SIGNAL(activated(
int)),
 
  195     kDebug(7001) << 
"Can't use FAM (fam daemon not running?)";
 
  200 #ifdef HAVE_SYS_INOTIFY_H 
  201   supports_inotify = 
true;
 
  203   m_inotify_fd = inotify_init();
 
  205   if ( m_inotify_fd <= 0 ) {
 
  206     kDebug(7001) << 
"Can't use Inotify, kernel doesn't support it";
 
  207     supports_inotify = 
false;
 
  212     int major, minor, patch;
 
  213     if (uname(&uts) < 0) {
 
  214       supports_inotify = 
false;
 
  215       kDebug(7001) << 
"Unable to get uname";
 
  216     } 
else if (sscanf(uts.release, 
"%d.%d", &major, &minor) != 2) {
 
  217       supports_inotify = 
false;
 
  218       kDebug(7001) << 
"The version is malformed: " << uts.release;
 
  219     } 
else if(major == 2 && minor == 6) { 
 
  220       if (sscanf(uts.release, 
"%d.%d.%d", &major, &minor, &patch) != 3) {
 
  221         supports_inotify = 
false;
 
  222         kDebug() << 
"Detected 2.6 kernel but can't know more: " << uts.release;
 
  223       } 
else if (major * 1000000 + minor * 1000 + patch < 2006014 ){
 
  224         supports_inotify = 
false;
 
  225         kDebug(7001) << 
"Can't use INotify, Linux kernel too old " << uts.release;
 
  230   kDebug(7001) << 
"INotify available: " << supports_inotify;
 
  231   if ( supports_inotify ) {
 
  232     availableMethods << 
"INotify";
 
  233     (void)fcntl(m_inotify_fd, F_SETFD, FD_CLOEXEC);
 
  235     mSn = 
new QSocketNotifier( m_inotify_fd, QSocketNotifier::Read, 
this );
 
  236     connect( mSn, SIGNAL(activated(
int)),
 
  240 #ifdef HAVE_QFILESYSTEMWATCHER 
  241   availableMethods << 
"QFileSystemWatcher";
 
  262 #ifdef HAVE_SYS_INOTIFY_H 
  263   if ( supports_inotify )
 
  264     ::close( m_inotify_fd );
 
  266 #ifdef HAVE_QFILESYSTEMWATCHER 
  274 #ifdef HAVE_SYS_INOTIFY_H 
  275   if ( !supports_inotify )
 
  279   int offsetStartRead = 0; 
 
  281   assert( m_inotify_fd > -1 );
 
  282   ioctl( m_inotify_fd, FIONREAD, &pending );
 
  284   while ( pending > 0 ) {
 
  286     const int bytesToRead = qMin( pending, (
int)
sizeof( buf ) - offsetStartRead );
 
  288     int bytesAvailable = read( m_inotify_fd, &buf[offsetStartRead], bytesToRead );
 
  289     pending -= bytesAvailable;
 
  290     bytesAvailable += offsetStartRead;
 
  293     int offsetCurrent = 0;
 
  294     while ( bytesAvailable >= (
int)
sizeof( 
struct inotify_event ) ) {
 
  295       const struct inotify_event * 
const event = (
struct inotify_event *) &buf[offsetCurrent];
 
  296       const int eventSize = 
sizeof( 
struct inotify_event ) + event->len;
 
  297       if ( bytesAvailable < eventSize ) {
 
  301       bytesAvailable -= eventSize;
 
  302       offsetCurrent += eventSize;
 
  305       QByteArray cpath(event->name, event->len);
 
  307         path = QFile::decodeName ( cpath );
 
  313       const bool isDir = (
event->mask & (IN_ISDIR));
 
  323         if ( e->wd == event->wd ) {
 
  324           const bool wasDirty = e->
dirty;
 
  327           const QString tpath = e->
path + QLatin1Char(
'/') + path;
 
  333           if( event->mask & IN_DELETE_SELF) {
 
  334             if (s_verboseDebug) {
 
  335               kDebug(7001) << 
"-->got deleteself signal for" << e->
path;
 
  344                 parentEntry->
dirty = 
true;
 
  348           if ( event->mask & IN_IGNORED ) {
 
  352           if ( event->mask & (IN_CREATE|IN_MOVED_TO) ) {
 
  355             if (s_verboseDebug) {
 
  356               kDebug(7001) << 
"-->got CREATE signal for" << (tpath) << 
"sub_entry=" << sub_entry;
 
  363               sub_entry->
dirty = 
true;
 
  367               Q_FOREACH(
Client *client, clients) {
 
  375               if (!clients.isEmpty()) {
 
  377                 kDebug(7001).nospace() << clients.count() << 
" instance(s) monitoring the new " 
  378                                        << (isDir ? 
"dir " : 
"file ") << tpath;
 
  380               e->m_pendingFileChanges.append(e->
path);
 
  385           if (event->mask & (IN_DELETE|IN_MOVED_FROM)) {
 
  386             if (s_verboseDebug) {
 
  387               kDebug(7001) << 
"-->got DELETE signal for" << tpath;
 
  407           if (event->mask & (IN_MODIFY|IN_ATTRIB)) {
 
  409               if (s_verboseDebug) {
 
  410                 kDebug(7001) << 
"-->got MODIFY signal for" << (tpath);
 
  427               e->m_pendingFileChanges.append(tpath);
 
  429               e->
dirty = (wasDirty || (path.isEmpty() && (
event->mask & IN_ATTRIB)));
 
  440     if (bytesAvailable > 0) {
 
  442         memmove(buf, &buf[offsetCurrent], bytesAvailable);
 
  443         offsetStartRead = bytesAvailable;
 
  457      if (!sub_entry->
dirty)
 
  459         sub_entry->
dirty = 
true;
 
  470                                         KDirWatch::WatchModes watchModes)
 
  475   foreach(
Client* client, m_clients) {
 
  490   m_clients.append(client);
 
  497   for ( ; it != end ; ++it ) {
 
  501       if (client->
count == 0) {
 
  514   foreach(
Client* client, m_clients)
 
  515     clients += client->
count;
 
  522   return QDir::cleanPath(path + QLatin1String(
"/.."));
 
  528   KDE_struct_stat stat_buf;
 
  530     *isDir = S_ISDIR(stat_buf.st_mode);
 
  531     const KDirWatch::WatchModes flag =
 
  533     Q_FOREACH(
Client *client, this->m_clients) {
 
  553   Q_FOREACH(
Client *client, this->m_clients) {
 
  563   debug.nospace() << 
"[ Entry for " << entry.
path << 
", " << (entry.
isDir ? 
"dir" : 
"file");
 
  565     debug << 
", non-existent";
 
  571 #ifdef HAVE_SYS_INOTIFY_H 
  573     debug << 
" inotify_wd=" << entry.wd;
 
  575   debug << 
", has " << entry.
m_clients.count() << 
" clients";
 
  578     debug << 
", nonexistent subentries:";
 
  580       debug << subEntry << subEntry->
path;
 
  589   if (_path.isEmpty() || QDir::isRelativePath(_path)) {
 
  595   if ( path.length() > 1 && path.endsWith( QLatin1Char( 
'/' ) ) )
 
  596     path.truncate( path.length() - 1 );
 
  614     kDebug(7001) << 
"Global Poll Freq is now" << 
freq << 
"msec";
 
  619 #if defined(HAVE_FAM) 
  621 bool KDirWatchPrivate::useFAM(Entry* e)
 
  623   if (!use_fam) 
return false;
 
  635       addEntry(0, e->parentDirectory(), e, 
true);
 
  638       int res =FAMMonitorDirectory(&fc, QFile::encodeName(e->path),
 
  646       kDebug(7001).nospace() << 
" Setup FAM (Req " << FAMREQUEST_GETREQNUM(&(e->fr))
 
  647                    << 
") for " << e->path;
 
  653       addEntry(0, QFileInfo(e->path).absolutePath(), e, 
true);
 
  656       int res = FAMMonitorFile(&fc, QFile::encodeName(e->path),
 
  665       kDebug(7001).nospace() << 
" Setup FAM (Req " << FAMREQUEST_GETREQNUM(&(e->fr))
 
  666                    << 
") for " << e->path;
 
  678 #ifdef HAVE_SYS_INOTIFY_H 
  680 bool KDirWatchPrivate::useINotify( Entry* e )
 
  687   if (!supports_inotify) 
return false;
 
  692     addEntry(0, e->parentDirectory(), e, 
true);
 
  697   int mask = IN_DELETE|IN_DELETE_SELF|IN_CREATE|IN_MOVE|IN_MOVE_SELF|IN_DONT_FOLLOW|IN_MOVED_FROM|IN_MODIFY|IN_ATTRIB;
 
  699   if ( ( e->wd = inotify_add_watch( m_inotify_fd,
 
  700                                     QFile::encodeName( e->path ), mask) ) >= 0)
 
  702     if (s_verboseDebug) {
 
  703       kDebug(7001) << 
"inotify successfully used for monitoring" << e->path << 
"wd=" << e->wd;
 
  708    kDebug(7001) << 
"inotify failed for monitoring" << e->path << 
":" << strerror(errno);
 
  712 #ifdef HAVE_QFILESYSTEMWATCHER 
  723   kDebug(7001) << 
"fsWatcher->addPath" << e->
path;
 
  748       kDebug(7001) << 
" Started Polling Timer, freq " << 
freq;
 
  752   kDebug(7001) << 
" Setup Stat (freq " << e->
freq << 
") for " << e->
path;
 
  764                 Entry* sub_entry, 
bool isDir, KDirWatch::WatchModes watchModes)
 
  769      || path == QLatin1String(
"/dev")
 
  770      || (path.startsWith(QLatin1String(
"/dev/")) && !path.startsWith(QLatin1String(
"/dev/.")))
 
  775   if ( path.length() > 1 && path.endsWith( QLatin1Char( 
'/' ) ) )
 
  776     path.truncate( path.length() - 1 );
 
  782        (*it).m_entries.append(sub_entry);
 
  783        if (s_verboseDebug) {
 
  784          kDebug(7001) << 
"Added already watched Entry" << path
 
  785                       << 
"(for" << sub_entry->
path << 
")";
 
  787 #ifdef HAVE_SYS_INOTIFY_H 
  790          int mask = IN_DELETE|IN_DELETE_SELF|IN_CREATE|IN_MOVE|IN_MOVE_SELF|IN_DONT_FOLLOW;
 
  792            mask |= IN_MODIFY|IN_ATTRIB;
 
  796          inotify_rm_watch (m_inotify_fd, e->wd);
 
  797          e->wd = inotify_add_watch( m_inotify_fd, QFile::encodeName( e->
path ),
 
  804        (*it).addClient(instance, watchModes);
 
  805        if (s_verboseDebug) {
 
  806          kDebug(7001) << 
"Added already watched Entry" << path
 
  807                       << 
"(now" <<  (*it).clientCount() << 
"clients)" 
  808                       << QString::fromLatin1(
"[%1]").arg(instance->objectName());
 
  816   KDE_struct_stat stat_buf;
 
  817   bool exists = (
KDE::stat(path, &stat_buf) == 0);
 
  821   Entry* e = &(*newIt);
 
  824     e->
isDir = S_ISDIR(stat_buf.st_mode);
 
  826     if (e->
isDir && !isDir) {
 
  828         if (S_ISLNK(stat_buf.st_mode))
 
  832           qWarning() << 
"KDirWatch:" << path << 
"is a directory. Use addDir!";
 
  834     } 
else if (!e->
isDir && isDir)
 
  835       qWarning(
"KDirWatch: %s is a file. Use addFile!", qPrintable(path));
 
  838       qWarning() << 
"KDirWatch:" << path << 
"is a file. You can't use recursive or " 
  839                     "watchFiles options";
 
  845     e->
m_ctime = stat_buf.st_mtime;
 
  847     e->
m_ctime = stat_buf.st_ctime;
 
  850     e->
m_nlink = stat_buf.st_nlink;
 
  851     e->
m_ino = stat_buf.st_ino;
 
  867   kDebug(7001).nospace() << 
"Added " << (e->
isDir ? 
"Dir " : 
"File ") << path
 
  869     << 
" for " << (sub_entry ? sub_entry->
path : 
QString())
 
  870     << 
" [" << (instance ? instance->objectName() : 
QString()) << 
"]";
 
  880     QFlags<QDir::Filter> filters = QDir::NoDotAndDotDot;
 
  884       filters |= (QDir::Dirs|QDir::Files);
 
  885     } 
else if (watchModes & KDirWatch::WatchSubDirs) {
 
  886       filters |= QDir::Dirs;
 
  888       filters |= QDir::Files;
 
  891 #if defined(HAVE_SYS_INOTIFY_H) 
  898         filters &= ~QDir::Files;
 
  902     QDir basedir (e->
path);
 
  903     const QFileInfoList contents = basedir.entryInfoList(filters);
 
  904     for (QFileInfoList::const_iterator iter = contents.constBegin();
 
  905          iter != contents.constEnd(); ++iter)
 
  907       const QFileInfo &fileInfo = *iter;
 
  909       bool isDir = fileInfo.isDir() && !fileInfo.isSymLink();
 
  911       addEntry (instance, fileInfo.absoluteFilePath(), 0, isDir,
 
  937   bool entryAdded = 
false;
 
  938   switch (preferredMethod) {
 
  939 #if defined(HAVE_FAM) 
  942 #if defined(HAVE_SYS_INOTIFY_H) 
  945 #if defined(HAVE_QFILESYSTEMWATCHER) 
  954 #if defined(HAVE_SYS_INOTIFY_H) 
  955     if (useINotify(e)) 
return;
 
  957 #if defined(HAVE_FAM) 
  958     if (useFAM(e)) 
return;
 
  960 #if defined(HAVE_QFILESYSTEMWATCHER) 
  971         FAMCancelMonitor(&fc, &(e->fr) );
 
  972         kDebug(7001).nospace()  << 
"Cancelled FAM (Req " << FAMREQUEST_GETREQNUM(&(e->fr))
 
  973                                 << 
") for " << e->
path;
 
  976 #ifdef HAVE_SYS_INOTIFY_H 
  978         (void) inotify_rm_watch( m_inotify_fd, e->wd );
 
  979         if (s_verboseDebug) {
 
  980             kDebug(7001).nospace() << 
"Cancelled INotify (fd " << m_inotify_fd << 
", " 
  981                                    << e->wd << 
") for " << e->
path;
 
  985 #ifdef HAVE_QFILESYSTEMWATCHER 
  988             kDebug(7001) << 
"fsWatcher->removePath" << e->
path;
 
  998   if (s_verboseDebug) {
 
  999     kDebug(7001) << 
"path=" << _path << 
"sub_entry:" << sub_entry;
 
 1044       kDebug(7001) << 
" Stopped Polling Timer";
 
 1048   if (s_verboseDebug) {
 
 1049     kDebug(7001).nospace() << 
"Removed " << (e->
isDir ? 
"Dir ":
"File ") << e->
path 
 1050                            << 
" for " << (sub_entry ? sub_entry->
path : 
QString())
 
 1051                            << 
" [" << (instance ? instance->objectName() : 
QString()) << 
"]";
 
 1062   int minfreq = 3600000;
 
 1069     foreach(
Client* client, (*it).m_clients) {
 
 1070       if (client->
instance == instance) {
 
 1077       pathList.append((*it).path);
 
 1079     else if ( (*it).m_mode == 
StatMode && (*it).freq < minfreq )
 
 1080       minfreq = (*it).freq;
 
 1083   foreach(
const QString &path, pathList)
 
 1086   if (minfreq > 
freq) {
 
 1090     kDebug(7001) << 
"Poll Freq now" << 
freq << 
"msec";
 
 1097   int stillWatching = 0;
 
 1099     if (!instance || instance == client->
instance)
 
 1102       stillWatching += client->
count;
 
 1105   kDebug(7001)  << (instance ? instance->objectName() : QString::fromLatin1(
"all"))
 
 1106                 << 
"stopped scanning" << e->
path << 
"(now" 
 1107                 << stillWatching << 
"watchers)";
 
 1109   if (stillWatching == 0) {
 
 1124   int wasWatching = 0, newWatching = 0;
 
 1127       wasWatching += client->
count;
 
 1128     else if (!instance || instance == client->
instance) {
 
 1130       newWatching += client->
count;
 
 1133   if (newWatching == 0)
 
 1136   kDebug(7001)  << (instance ? instance->objectName() : QString::fromLatin1(
"all"))
 
 1137                 << 
"restarted scanning" << e->
path 
 1138                 << 
"(now" << wasWatching+newWatching << 
"watchers)";
 
 1143   if (wasWatching == 0) {
 
 1145       KDE_struct_stat stat_buf;
 
 1150         e->
m_ctime = stat_buf.st_mtime;
 
 1152         e->
m_ctime = stat_buf.st_ctime;
 
 1155         if (s_verboseDebug) {
 
 1156           kDebug(7001) << 
"Setting status to Normal for" << e << e->
path;
 
 1158         e->
m_nlink = stat_buf.st_nlink;
 
 1159         e->
m_ino = stat_buf.st_ino;
 
 1168         if (s_verboseDebug) {
 
 1169           kDebug(7001) << 
"Setting status to NonExistent for" << e << e->
path;
 
 1191                                  bool notify, 
bool skippedToo )
 
 1210     foreach(
Client* client, (*it).m_clients) {
 
 1240   KDE_struct_stat stat_buf;
 
 1247       e->
m_ctime = qMax(stat_buf.st_ctime, stat_buf.st_mtime);
 
 1249       e->
m_ino = stat_buf.st_ino;
 
 1250       if (s_verboseDebug) {
 
 1251         kDebug(7001) << 
"Setting status to Normal for just created" << e << e->
path;
 
 1259 #if 1 // for debugging the if() below 
 1260     if (s_verboseDebug) {
 
 1261       struct tm* tmp = localtime(&e->
m_ctime);
 
 1263       strftime(outstr, 
sizeof(outstr), 
"%T", tmp);
 
 1265                    << 
"stat_buf.st_ctime=" << stat_buf.st_ctime
 
 1266                    << 
"e->m_nlink=" << e->
m_nlink 
 1267                    << 
"stat_buf.st_nlink=" << stat_buf.st_nlink
 
 1268                    << 
"e->m_ino=" << e->
m_ino 
 1269                    << 
"stat_buf.st_ino=" << stat_buf.st_ino;
 
 1274           (qMax(stat_buf.st_ctime, stat_buf.st_mtime) != e->
m_ctime ||
 
 1275            stat_buf.st_ino != e->
m_ino ||
 
 1276            stat_buf.st_nlink != nlink_t(e->
m_nlink)))
 
 1282       e->
m_ctime = qMax(stat_buf.st_ctime, stat_buf.st_mtime);
 
 1283       e->
m_nlink = stat_buf.st_nlink;
 
 1284       if (e->
m_ino != stat_buf.st_ino) {
 
 1289       e->
m_ino = stat_buf.st_ino;
 
 1317   if (!fileName.isEmpty()) {
 
 1318     if (!QDir::isRelativePath(fileName))
 
 1322       path += QLatin1Char(
'/') + fileName;
 
 1323 #elif defined(Q_WS_WIN) 
 1325       path += QDir::currentPath().left(2) + QLatin1Char(
'/') + fileName;
 
 1330   if (s_verboseDebug) {
 
 1355       QMetaObject::invokeMethod(c->
instance, 
"setDeleted", Qt::QueuedConnection, Q_ARG(
QString, path));
 
 1361       QMetaObject::invokeMethod(c->
instance, 
"setCreated", Qt::QueuedConnection, Q_ARG(
QString, path));
 
 1366       QMetaObject::invokeMethod(c->
instance, 
"setDirty", Qt::QueuedConnection, Q_ARG(
QString, path));
 
 1392   EntryMap::Iterator it;
 
 1398   bool timerRunning = 
timer.isActive();
 
 1421         (*it).propagate_dirty();
 
 1424 #ifdef HAVE_SYS_INOTIFY_H 
 1432     if (!entry->
isValid()) 
continue;
 
 1436       kDebug(7001) << 
"scanEntry for" << entry->
path << 
"says" << ev;
 
 1439 #ifdef HAVE_SYS_INOTIFY_H 
 1443           kDebug(7001) << 
"scanEntry says" << entry->
path << 
"was deleted";
 
 1447           kDebug(7001) << 
"scanEntry says" << entry->
path << 
"was created. wd=" << entry->wd;
 
 1448         if (entry->wd < 0) {
 
 1449           cList.append(entry);
 
 1466 #ifdef HAVE_SYS_INOTIFY_H 
 1472       QStringList pendingFileChanges = entry->m_pendingFileChanges;
 
 1473       pendingFileChanges.removeDuplicates();
 
 1474       Q_FOREACH(
const QString &changedFilename, pendingFileChanges) {
 
 1475         if (s_verboseDebug) {
 
 1476           kDebug(7001) << 
"processing pending file change for" << changedFilename;
 
 1480       entry->m_pendingFileChanges.clear();
 
 1492 #ifdef HAVE_SYS_INOTIFY_H 
 1494   Q_FOREACH(
Entry* e, cList)
 
 1504   if ( *filename == 
'.') {
 
 1505     if (strncmp(filename, 
".X.err", 6) == 0) 
return true;
 
 1506     if (strncmp(filename, 
".xsession-errors", 16) == 0) 
return true;
 
 1509     if (strncmp(filename, 
".fonts.cache", 12) == 0) 
return true;
 
 1524   while(use_fam && FAMPending(&fc)) {
 
 1525     if (FAMNextEvent(&fc, &fe) == -1) {
 
 1526       kWarning(7001) << 
"FAM connection problem, switching to polling.";
 
 1533         if ((*it).m_mode == 
FAMMode && (*it).m_clients.count()>0) {
 
 1545 void KDirWatchPrivate::checkFAMEvent(FAMEvent* fe)
 
 1550   if ((fe->code == FAMExists) ||
 
 1551       (fe->code == FAMEndExist) ||
 
 1552       (fe->code == FAMAcknowledge)) 
return;
 
 1560     if (FAMREQUEST_GETREQNUM(&( (*it).fr )) ==
 
 1561        FAMREQUEST_GETREQNUM(&(fe->fr)) ) {
 
 1568   if (s_verboseDebug) { 
 
 1569     kDebug(7001)  << 
"Processing FAM event (" 
 1570                 << ((fe->code == FAMChanged) ? 
"FAMChanged" :
 
 1571                     (fe->code == FAMDeleted) ? 
"FAMDeleted" :
 
 1572                     (fe->code == FAMStartExecuting) ? 
"FAMStartExecuting" :
 
 1573                     (fe->code == FAMStopExecuting) ? 
"FAMStopExecuting" :
 
 1574                     (fe->code == FAMCreated) ? 
"FAMCreated" :
 
 1575                     (fe->code == FAMMoved) ? 
"FAMMoved" :
 
 1576                     (fe->code == FAMAcknowledge) ? 
"FAMAcknowledge" :
 
 1577                     (fe->code == FAMExists) ? 
"FAMExists" :
 
 1578                     (fe->code == FAMEndExist) ? 
"FAMEndExist" : 
"Unknown Code")
 
 1579                   << 
", " << fe->filename
 
 1580                   << 
", Req " << FAMREQUEST_GETREQNUM(&(fe->fr)) << 
") e=" << e;
 
 1590     kDebug(7001) << 
"FAM event for nonExistent entry " << e->path;
 
 1603         if (!QDir::isRelativePath(QFile::decodeName(fe->filename))) {
 
 1604           FAMCancelMonitor(&fc, &(e->fr) ); 
 
 1605           kDebug(7001)  << 
"Cancelled FAMReq" 
 1606                         << FAMREQUEST_GETREQNUM(&(e->fr))
 
 1607                         << 
"for" << e->path;
 
 1612           Entry* parentEntry = 
entry(e->parentDirectory());
 
 1614               parentEntry->
dirty = 
true;
 
 1616           addEntry(0, e->parentDirectory(), e, 
true );
 
 1627         QString tpath(e->path + QLatin1Char(
'/') + QFile::decodeName(fe->filename));
 
 1630         Entry* sub_entry = e->findSubEntry(tpath);
 
 1634           sub_entry->dirty = 
true;
 
 1636         } 
else if (e->isDir && !e->m_clients.empty()) {
 
 1638           const QList<Client *> clients = e->clientsForFileOrDir(tpath, &isDir);
 
 1639           Q_FOREACH(Client *client, clients) {
 
 1640             addEntry (client->instance, tpath, 0, isDir,
 
 1644           if (!clients.isEmpty()) {
 
 1647             kDebug(7001).nospace() << clients.count() << 
" instance(s) monitoring the new " 
 1648                                    << (isDir ? 
"dir " : 
"file ") << tpath;
 
 1660     kWarning (7001) << 
"Fam event received but FAM is not supported";
 
 1667   EntryMap::Iterator it;
 
 1669   kDebug(7001) << 
"Entries watched:";
 
 1671     kDebug(7001) << 
"  None.";
 
 1677       kDebug(7001) << 
"  " << *e;
 
 1685           if (!pending.isEmpty()) pending = 
" (pending: " + pending + 
')';
 
 1686           pending = 
", stopped" + pending;
 
 1689                       << 
" (" << c->
count << 
" times)" << pending;
 
 1692         kDebug(7001) << 
"    dependent entries:";
 
 1695           if (s_verboseDebug) {
 
 1704 #ifdef HAVE_QFILESYSTEMWATCHER 
 1716       kDebug(7001) << 
"scanEntry for" << e->
path << 
"says" << ev;
 
 1723         addEntry(0, QFileInfo(e->
path).absolutePath(), e, 
true);
 
 1727     } 
else if (e->
isDir) {
 
 1739     kWarning (7001) << 
"QFileSystemWatcher event received but QFileSystemWatcher is not supported";
 
 1741 #endif    // HAVE_QFILESYSTEMWATCHER 
 1750   return s_pKDirWatchSelf;
 
 1756   return s_pKDirWatchSelf.exists();
 
 1761   s_pKDirWatchSelf->deleteQFSWatcher();
 
 1767   static int nameCounter = 0;
 
 1770   setObjectName(QString::fromLatin1(
"KDirWatch-%1").arg(nameCounter) );
 
 1776     static bool cleanupRegistered = 
false;
 
 1777     if (!cleanupRegistered) {
 
 1778         cleanupRegistered = 
true;
 
 1797   if (d) d->
addEntry(
this, _path, 0, 
true, watchModes);
 
 1805   d->
addEntry(
this, _path, 0, 
false);
 
 1822             kWarning() << 
"doesn't know" << _path;
 
 1831             kWarning() << 
"doesn't know" << _path;
 
 1901     kDebug(7001) << 
"KDirWatch not used";
 
 1910   kDebug(7001) << objectName() << 
"emitting created" << _file;
 
 1917   emit 
dirty( _file );
 
 1922   kDebug(7001) << objectName() << 
"emitting deleted" << _file;
 
 1932 #include "kdirwatch.moc" 
 1933 #include "kdirwatch_p.moc" 
QString parentDirectory() const 
 
static const char * methodToString(KDirWatch::Method method)
 
QList< Client * > inotifyClientsForFileOrDir(bool isDir) const 
 
static KDirWatchPrivate * createPrivate()
 
QList< Client * > clientsForFileOrDir(const QString &tpath, bool *isDir) const 
 
void setCreated(const QString &path)
Emits created(). 
 
void addFile(const QString &file)
Adds a file to be watched. 
 
QList< Client * > m_clients
 
void useFreq(Entry *e, int newFreq)
 
bool removeEntry(KDirWatch *, const QString &, Entry *sub_entry)
 
static bool isNoisyFile(const char *filename)
 
KDirWatch(QObject *parent=0)
Constructor. 
 
void stopScan()
Stops scanning of all directories in internal list. 
 
Watch just the specified directory. 
 
void stopScan(KDirWatch *)
 
bool stopEntryScan(KDirWatch *, Entry *)
 
static QDateTime fromTime_t(qint32 seconds)
 
#define K_GLOBAL_STATIC(TYPE, NAME)
This macro makes it easy to use non-POD types as global statics. 
 
void startScan(bool notify=false, bool skippedToo=false)
Starts scanning of all dirs in list. 
 
Method internalMethod()
Returns the preferred internal method to watch for changes. 
 
int stat(const QString &path, KDE_struct_stat *buf)
 
bool restartEntryScan(KDirWatch *, Entry *, bool)
 
QList< Entry * > m_entries
 
void removeEntries(KDirWatch *)
 
KDirWatch::WatchModes m_watchModes
 
void removePath(const QString &file)
 
Type fileSystemType(const QString &path)
 
KSharedConfigPtr config()
Returns the general config object. 
 
bool stopDirScan(const QString &path)
Stops scanning the specified path. 
 
void deleted(const QString &path)
Emitted when a file or directory is deleted. 
 
void resetList(KDirWatch *, bool)
 
bool useQFSWatch(Entry *e)
 
void emitEvent(const Entry *e, int event, const QString &fileName=QString())
 
KDirWatch::Method m_preferredMethod
 
KDirWatch::Method m_nfsPreferredMethod
 
static void statistics()
Dump statistic information about the KDirWatch::self() instance. 
 
KFileSystemWatcher * fsWatcher
 
void fswEventReceived(const QString &path)
 
void setDeleted(const QString &path)
Emits deleted(). 
 
void removeWatch(Entry *entry)
 
static KDirWatchPrivate * dwp_self
 
QDateTime ctime(const QString &path) const 
Returns the time the directory/file was last changed. 
 
void created(const QString &path)
Emitted when a file or directory is created. 
 
void startScan(KDirWatch *, bool, bool)
 
int lstat(const QString &path, KDE_struct_stat *buf)
 
Watch also all files contained by the directory. 
 
bool contains(const QString &path) const 
Check if a directory is being watched by this KDirWatch instance. 
 
A class for one specific group in a KConfig object. 
 
void inotifyEventReceived()
 
static void cleanupQFSWatcher()
 
void removeClient(KDirWatch *)
 
QDebug operator<<(QDebug debug, const KDirWatchPrivate::Entry &entry)
 
QSet< Entry * > removeList
 
void addPath(const QString &file)
 
void removeDir(const QString &path)
Removes a directory from the list of scanned directories. 
 
void addDir(const QString &path, WatchModes watchModes=WatchDirOnly)
Adds a directory to be watched. 
 
Entry * entry(const QString &)
 
static bool exists()
Returns true if there is an instance of KDirWatch. 
 
Class for watching directory and file changes. 
 
void dirty(const QString &path)
Emitted when a watched object is changed. 
 
Watch also all the subdirs contained by the directory. 
 
void setDirty(const QString &path)
Emits dirty(). 
 
bool isStopped()
Is scanning stopped? After creation of a KDirWatch instance, this is false. 
 
void removeFile(const QString &file)
Removes a file from the list of watched files. 
 
Entry * findSubEntry(const QString &path) const 
 
static KDirWatch::Method methodFromString(const QString &method)
 
T readEntry(const QString &key, const T &aDefault) const 
Reads the value of an entry specified by pKey in the current group. 
 
void addClient(KDirWatch *, KDirWatch::WatchModes)
 
void addEntry(KDirWatch *instance, const QString &_path, Entry *sub_entry, bool isDir, KDirWatch::WatchModes watchModes=KDirWatch::WatchDirOnly)
 
bool restartDirScan(const QString &path)
Restarts scanning for specified path. 
 
void addWatch(Entry *entry)
 
static const bool s_verboseDebug