void NotifyWorker::startWatching() { QLOG_TRACE() << "inotify starting"; try { Inotify notify; int32_t watch_mask = (IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO); QByteArray dir_str = watch_dir.toLocal8Bit(); InotifyWatch iw(dir_str.data(), watch_mask); notify.Add(iw); for(;;) { notify.WaitForEvents(); QLOG_TRACE() << "iNotify event received"; size_t count = notify.GetEventCount(); while(count > 0) { InotifyEvent event; bool got_event = notify.GetEvent(&event); if(got_event) { FileEvent e; std::string s; event.DumpTypes(s); e.type = QString::fromUtf8(s.c_str()); e.cookie = event.GetCookie(); e.name = QString(event.GetName().c_str()); if(!e.type.contains("IN_ISDIR")) { emit fEvent(e); } } count--; } } } catch(InotifyException e) { QLOG_WARN() << "Inotify failed to start: " + QString::fromStdString(e.GetMessage()); } }
// Set some watchers so we can monitorize dirs, files etc. void On::setWatchers() { // Set JSON watcher Inotify notify; InotifyWatch watch("/var/local/asturix/launcherjsonview.json", IN_CLOSE_WRITE); notify.Add(watch); for (;;) { notify.WaitForEvents(); size_t count = notify.GetEventCount(); while (count > 0) { InotifyEvent event; bool got_event = notify.GetEvent(&event); if (got_event) { QMetaObject::invokeMethod(this,"appsChanged",Qt::QueuedConnection); } count--; } } DConfClient *dConfWallpaper = dconf_client_new(NULL, iconThemeChanged, NULL, NULL); dconf_client_watch(dConfWallpaper, "/org/gnome/desktop/interface/icon-theme", NULL, NULL); }
bool EventDispatcher::ProcessEvents() { // consume pipe events if any (and report back) bool pipe = (m_pPoll[0].revents & POLLIN); if (pipe) { char c; while (read(m_pPoll[0].fd, &c, 1) > 0) {} m_pPoll[0].revents = 0; } // process table management events if any if (m_pPoll[1].revents & POLLIN) { ProcessMgmtEvents(); m_pPoll[1].revents = 0; } InotifyEvent evt; for (size_t i=2; i<m_size; i++) { // process events if occurred if (m_pPoll[i].revents & POLLIN) { FDUT_MAP::iterator it = m_maps.find(m_pPoll[i].fd); if (it != m_maps.end()) { Inotify* pIn = ((*it).second)->GetInotify(); pIn->WaitForEvents(true); // process events for this object while (pIn->GetEvent(evt)) { ((*it).second)->OnEvent(evt); } } m_pPoll[i].revents = 0; } } return pipe; }
/** * Tell the observer to watch the given folder. * Then, the observer will process all the rules * * @param string path the path to be watched * @param vector<Rule> the list of rules to be checked */ void Observer::observe(string path, vector<Rule*> rules){ this->_observing[path] = true; try { Inotify notify; InotifyWatch watch(path, IN_CREATE); notify.Add(watch); cout << "Start observing for changes in " << path << endl; while (this->_observing[path]) { notify.WaitForEvents(); size_t count = notify.GetEventCount(); while (count > 0) { InotifyEvent event; bool got_event = notify.GetEvent(&event); if (got_event) { string mask_str; event.DumpTypes(mask_str); string filename = event.GetName(); this->run_rules(rules, path + '/' + filename, mask_str); } count--; } } } catch (InotifyException &e) { cerr << "Inotify exception occured: " << e.GetMessage() << endl; } catch (exception &e) { cerr << "STL exception occured: " << e.what() << endl; } catch (...) { cerr << "unknown exception occured" << endl; } }
/** * \param[in] argc argument count * \param[in] argv argument array * \return 0 on success, 1 on error * * \attention In daemon mode, it finishes immediately. */ int main(int argc, char** argv) { openlog(INCRON_DAEMON_NAME, INCRON_LOG_OPTS, INCRON_LOG_FACIL); syslog(LOG_NOTICE, "starting service (version %s, built on %s %s)", INCRON_VERSION, __DATE__, __TIME__); try { Inotify in; in.SetNonBlock(true); EventDispatcher ed(&in); try { load_tables(&in, &ed); } catch (InotifyException e) { int err = e.GetErrorNumber(); syslog(LOG_CRIT, "%s: (%i) %s", e.GetMessage().c_str(), err, strerror(err)); syslog(LOG_NOTICE, "stopping service"); closelog(); return 1; } signal(SIGTERM, on_signal); signal(SIGINT, on_signal); signal(SIGCHLD, on_signal); if (DAEMON) daemon(0, 0); uint32_t wm = IN_CLOSE_WRITE | IN_DELETE | IN_MOVE | IN_DELETE_SELF | IN_UNMOUNT; InotifyWatch watch(INCRON_TABLE_BASE, wm); in.Add(watch); syslog(LOG_NOTICE, "ready to process filesystem events"); InotifyEvent e; struct pollfd pfd; pfd.fd = in.GetDescriptor(); pfd.events = (short) POLLIN; pfd.revents = (short) 0; while (!g_fFinish) { int res = poll(&pfd, 1, -1); if (res > 0) { in.WaitForEvents(true); } else if (res < 0) { if (errno != EINTR) throw InotifyException("polling failed", errno, NULL); } UserTable::FinishDone(); while (in.GetEvent(e)) { if (e.GetWatch() == &watch) { if (e.IsType(IN_DELETE_SELF) || e.IsType(IN_UNMOUNT)) { syslog(LOG_CRIT, "base directory destroyed, exitting"); g_fFinish = true; } else if (!e.GetName().empty()) { SUT_MAP::iterator it = g_ut.find(e.GetName()); if (it != g_ut.end()) { UserTable* pUt = (*it).second; if (e.IsType(IN_CLOSE_WRITE) || e.IsType(IN_MOVED_TO)) { syslog(LOG_INFO, "table for user %s changed, reloading", e.GetName().c_str()); pUt->Dispose(); pUt->Load(); } else if (e.IsType(IN_MOVED_FROM) || e.IsType(IN_DELETE)) { syslog(LOG_INFO, "table for user %s destroyed, removing", e.GetName().c_str()); delete pUt; g_ut.erase(it); } } else if (e.IsType(IN_CLOSE_WRITE) || e.IsType(IN_MOVED_TO)) { if (check_user(e.GetName().c_str())) { syslog(LOG_INFO, "table for user %s created, loading", e.GetName().c_str()); UserTable* pUt = new UserTable(&in, &ed, e.GetName()); g_ut.insert(SUT_MAP::value_type(e.GetName(), pUt)); pUt->Load(); } } } } else { ed.DispatchEvent(e); } } } } catch (InotifyException e) { int err = e.GetErrorNumber(); syslog(LOG_CRIT, "*** unhandled exception occurred ***"); syslog(LOG_CRIT, " %s", e.GetMessage().c_str()); syslog(LOG_CRIT, " error: (%i) %s", err, strerror(err)); } syslog(LOG_NOTICE, "stopping service"); closelog(); return 0; }