author | mickeyl <mickeyl> | 2005-05-02 13:49:14 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2005-05-02 13:49:14 (UTC) |
commit | 8cbb0586482ec650d7ff4fa9b6a7390b8b050793 (patch) (side-by-side diff) | |
tree | 926c2fedf0f62a965362178620625e3ddc5171de | |
parent | 3a86e1464fb00d3d9b9962bcabc1041d8a3d9343 (diff) | |
download | opie-8cbb0586482ec650d7ff4fa9b6a7390b8b050793.zip opie-8cbb0586482ec650d7ff4fa9b6a7390b8b050793.tar.gz opie-8cbb0586482ec650d7ff4fa9b6a7390b8b050793.tar.bz2 |
Rewrite OFileNotification to use the upcoming inotify (kernel 2.6) interface instead of the deprecated dnotify
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | examples/opiecore/onotifydemo/onotifydemo.cpp | 42 | ||||
-rw-r--r-- | libopie2/opiecore/ofilenotify.cpp | 272 | ||||
-rw-r--r-- | libopie2/opiecore/ofilenotify.h | 93 |
4 files changed, 168 insertions, 246 deletions
@@ -1,281 +1,282 @@ 2005-??-?? Opie 1.2.1 New Features ------------ * OpieStumbler: Scans WiFi networks using the wireless extension scanning (skyhusker) Fixed Bugs ---------- + * #1476 - Wrong order of application entries in the O-menu (skyhusker) * #1535 - Missing line break and unnecessary location shown with Today-Calendar plugin (deller) * #1565 - crash-fix in odevice.cpp while scanning the distribution table (deller) * #1614 - Make Opie-console start in $HOME instead of / (skyhusker) * n.a. - always show volume and wireless applet popups inside visible screen (deller) * n.a. - scale O-Menu-Applets appropriately (mickeyl) * n.a. - libopienet: fix bugs in wireless scanning and setting SSID (skyhusker) * n.a. - Wellenreiter: relax WE version matching test a bit (mickeyl) - * n.a. - scale BluezApplet appropriately (mickeyl) + * n.a. - scale BluezApplet appropriately and use larger icons (mickeyl) * n.a. - memoryapplet: fix crash in memoryapplet on kernels without swap support (seneca cunningham) - * #1476 - Wrong order of application entries in the O-menu (skyhusker) Internal -------- - * make BluezApplet use OTaskbarApplet (mickeyl) + * Make BluezApplet use OTaskbarApplet (mickeyl) + * Rewrite OFileNotification to use the upcoming inotify interface instead of the deprecated dnotify (mickeyl) 2005-03-25 Opie 1.2.0 Fixed Bugs ---------- * #1613 - AdvancedFM - scale toolbar icons appropriately (drw) * #1620 - OFileSelector - show the button on press and not on press on hold (alwin) * #1473 - Opie-Eye - Same as #1620 but we lack a common FileSystem Button class (zecke) * n.a. - PackageManager - fix bug where messages show up multiple times in install dialog (drw) * n.a. - make qpeglobal.h include qglobal.h (zecke) 2005-03-20 Opie 1.2.0-rc1 New Features ------------ * Launcher: Support a static background pixmap (mickeyl) * LauncherSettings: Choose whether to have a static background pixmap (mickeyl) * PackageManager supports the 'lists_dir' ipkg configuration option (drw) * Added hi-res inline images for large resolution devices (drw) * Improved launcher icons for consistency (ar) * Datebook: Added plugin system to datebook so holidays and birthdays from contacts may displayed in datebook (alwin) Fixed Bugs ---------- * #1236 - VCards contained empty home and work address entries causing Palms to crash (eilers) * #1412 - Launcher Settings - fixed default settings for background in Edit tab dialog (drw) * #1472 - Opie textedit now check for unsaved changes on ESC key (ljp) * #1474 - Implement GUI for Scrollbars on the Left in Appearance (zecke) * #1482 - Fix double '/' in paths (zecke) * #1536 - Autosave of custom locations in opie backup (ar) * #1539 - Fixed displaying too long path in the delete dialog in opie-eye (zecke) * #1540 - Implemented deletion of DocLnks in opie-eye (zecke) * #1542 - Fixed Todo crash when priority < 1 or > 5 (drw) * #1550 - Browse for alarm sound start in QPEDIR/sounds/ (zecke) * #1554 - Fixed Opie-Console name in .desktop file (mickeyl) * #1556 - Start to look for sound files in /opt/QtPalmtop/sounds (zecke) * #1558 - Fixed opie-login breaking opie startup (mickeyl) * #1560 - Fixed Opie-Console picking up the wrong shell (bluelightning) * #1570 - Confirmation needed befor Restore a backup and overwrite local data (ar) * #1591 - Addressbook sortorder changed by clicking on column 0 (eilers) * #1599 - Security - change recommendation for opie-multiauth to opie-securityplugin (gints) * #1604 - Checkbook crashed on startup (drw) * #1608 - Addressbook crashed after search, which may caused by not initialzed member variable (eilers) * #1608 - QueryByExampe-Datediff on SQL database did not worked properly (eilers) * n.a. - Netsystemtime - fixed UI to prevent error dialog from displaying when it shouldn't, get rid of some compiler warnings (drw) * n.a. - PackageManager - fixed where last package in status file was not shown as installed when it should be (drw) * n.a. - PackageManager - fixed bug where lists_dir was not being honored at startup (drw) * n.a. - PackageManager - provided default value for lists_dir when none is entered in configuration dialog (drw) * n.a. - OTabWidget - fixed scroll buttons, fix display position of tabs (drw) * n.a. - AddressBook - fixed sorting by 'File As' name (drw) * n.a. - AddressBook - fixed category handling for 'All' and 'Unfiled' (eilers) * n.a. - AddressBook - fixed letter picker record selection and sort records afterwards (drw) Internal -------- * Worked around bug in Qt/Embedded 2.3.10: qt_version() returns 231 (mickeyl) * Killed the need for weak symbols in QtE (zecke) * Added optional building libqpe without inline images (mickeyl) * OColorButton - fixed so does not emit a colorSelected signal inside of resizeEvent (drw) 2005-02-03 Opie 1.1.9 New Features ------------ * Number of icon columns in Launcher is customizable through Launcher.conf (hrw,zecke,mickeyl) * Number of icon columns in Launcher is customizable through LauncherSettings (mickeyl) * Usability enhancements in OpieIRC (skyhusker) Fixed Bugs ---------- * #1501 - Fixed bug in todo sql backend (eilers) * #1505 - Added more Swap sizes in memoryapplet (mickeyl) * #1525 - Hopefully fixed double alarms and not removing alarms set with the Clock application (zecke) * #1533 - Security Owner Dialog (shown in case of unsuccessfull authentiacation) wasn't able to display information in non latin1 encoding (zecke) * n.a. - Removed hard coded font sizes in a couple of inputmethods (mickeyl) * n.a. - Removed MediumDlg appearing prior to FirstUsage wizard (i.e. calibration) (mickeyl) * n.a. - Fixed numerous buglets in OpieIRC (skyhusker) Internal -------- * Added the Qtopia 1.7 SDK macros for quick-apps to easa compilation of 3rd party apps against our headers (mickeyl) * You can now use the Opie build system in combination with a OpenEmbedded staging area which makes a nice cross development environment (mickeyl) * Made Opie compilable with Qt/Embedded 2.3.10 (ar) * Changed Launcher to get default orientation from ODevice w/ QWS_DISPLAY overriding (mickeyl) * Build tree cleanups (mickeyl) 2004-11-26 Opie 1.1.8 New Features ------------ * PackageManager supports installation of local ipkg files (drw) * PackageManager supports linking of applications to root (drw) * PackageManager supports src/gz feeds (drw,wimpie) * Added a syslog information tab to sysinfo (mickeyl) * Added new, more consistent, PIM icons + a GIMP teplate (ar) Fixed Bugs ---------- * #1017 - Tetrix doesn't display correctly for high resolution screens (drw) * #1269 - VCards were imported into personal area if it was activated (eilers) * #1464 - Packagemanager dont set active filter after install a package (drw) * #1479 - Improved VCard-Parser to import VCards created by Evolution 2 and Apple Addressbook (eilers) * #1493 - Fixed one column layout bug of the launcher (hrw) * n.a. - PackageManager - (Minor UI tweak) in filter dialog, when option is enabled, set focus to widget that corresponds to that option (drw) * n.a. - PackageManager - (Minor UI tweak) fix double entry in source feed configuration when adding a new feed (drw) * n.a. - Battery Applet - fix sizing of battery info popup (drw,mickeyl) Internal -------- * Moved libopie1 to unsupported (mickeyl) * Implemented generic queryByExample() with incremental searching. A lot of internal changes of the Pim2-library (eilers) * Added fast and full featured and incremental sorted() for SQL addressbook backend (eilers) 2004-11-14 Opie 1.1.7 New Features ------------ * libOpieDB now uses SQLite V3 instead V2. Remember to upgrade your database files! (eilers) * Backup now uses the busy indicator when backing up and restore (ar) * OpiePlayer2 gained adding of Directories to the playlist (zecke) * OpiePlayer2 better error handling (zecke) * OpiePlayer2 progress indication while streaming (zecke) * OpiePlayer2 ported to use libxine 1.0.0-rc6a (brad,zecke) * Ported brightnessapplet from Qtopia 1.7 (mickeyl) * Opie-Eye got a Digital Camera File Backend (alwin,zecke) * Support for Tuxpad1 of Tradesquare.NL (mickeyl,zecke) * Opie-Console use Custom Font and Size in a Profile (harlekin) * Opie-Console transparently log the Output and Input to a file (harlekin) * Added new O-menu icon to lock the PDA immediately: opie-lockapplet (clem) * Opie-Security now hides the plugin-based authentication tabs if no auth. plugin package is installed (clem) * Opie-Security gained a 'test authentication' button (clem) * Opie-Eye got a more unique layout (menubar), a slideshow, user can setup some defaults * Opie-Mail improve the handling of POP mail boxes (alwin) * Both Opie-Eye and Opie-Mail were greatly improved due the hard work of Rajko Albrecht(alwin) * Opie IRC - backports of the 'NeIRC fork' (zecke) Fixed Bugs ---------- * #501 - Pickboard is able to show 'Umlaute' (TT,zecke) * #608 - Make Opie usable for left handed users (zecke) * #957 - Import of VCards/VTodos/VEvents with BASE64 encoding (ljp,zecke) * #1245 - Opie-Go 'paused' (zecke) * #1358 - DocTab didn't show any MimeTypes (was fixed earlier) (zecke) * #1380 - QDateBookAccess::remove() doesn't remove entries (eilers, zecke) * #1395 - Build VNC Backend with gcc3.4 * #1440 - The icon of opie-mobilemsg is missing (CoreDump) * #1426 - Add missing opie-bartender Icon (CoreDump) * #1445 - Opie-Sheet Has No Icon (CoreDump) * #1448 - Brightness Applet added (mickeyl) * #1450 - ZSame didn't clear the bonus item after winning a game (zecke) * #1482 - Fix OFileSelector to be able to sort by size (zecke) * n.a. - Opie-mail: fixed some crasher, some layout-problems * n.a. - Converted applications to not hardcode /opt/QtPalmtop but to use QPEApplication::qpeDir (zecke) * n.a. - Converted usage of qpeDir() not to include a '/' as first charachter of the string (zecke) * n.a. - Build system: Enable distcc and ccache when crosscompiling too, and use them everywhere we can (clem) * n.a. - Build system: Fix deps in several config.in (and fix scripts/deps.pl too) to stop breaking builds, especially with make -j highNumber (clem) * n.a. - Removed hardcoded icon size in a couple of applets (mickeyl) Internal -------- * Opie-Qashmoney has been moved to unsupported (mickeyl) * Opie-Ubrowser has been moved to unsupported (mickeyl) 2004-09-17 Opie 1.1.6 New Features ------------ * Fifteen gained configurable number of items (zecke) * Fifteen can have custom background images (zecke) * Added daemonizing capabilities to QWS Server [via Qt/Embedded] (mickeyl) * Integrated the new security framework into libopie2 (zecke,clem) * Converted the launcher to use the new security framework (zecke) * Backup can now handle custom locations for backup and restore (ar) * Implemented right-on-hold feedback (wimpie,zecke) * Lots of new features in opie-reader (tim,pohly) * Build system cleanups (schurig) Fixed Bugs -------- * #1005 - Fixed backup to CompactFlash (ar) * #1167 - Fixed Opie write crashing on more text than one page (ar) * #1225 - Fixed repeated light flashing on Zaurus with keyz (mickeyl) * #1359 - Fixed bookmarks in Gutenbrowser (ljp) * #1361 - Fixed auto upercase in Opie-Addressbook (eilers) * #1370 - Pimconverter now reacts on cancel key (eilers) * #1376 - Bring back the capslock/numlock display (zecke) * #1383 - Language settings now warns about losing open apps (Markus Litz) * #1393 - Fixed line wrap issues in opie-console for the default profile (mickeyl) * #1394 - Fixed oversized headline in opie-login (coredump) * #1396 - Opie-console captures the escape key and vim is working (zecke) * #1401 - Scrollbar is now only visible if necessary in DocTab (mickeyl) 2004-07-06 Opie 1.1.4 New Features ------------ * Added four themes courtesy Robert Griebl (http://www.softforge.de/zstyle) * Added Conversion tool for pim-data (eilers) * Introduced new OPimAccessFactory and OBackendFactory which simplyfies database access (eilers) * Modified the PIM API for providing generic use of OPimRecords (eilers) * Clicking on the application symbol now iterates over the application's top level widgets if already raised (zecke) Fixed Bugs -------- * #1068 - Country Drop Down Box Off Screen * #1291 - Opie tinykate does not open .desktop files (ar) * #1291 - Opie sheet not saving correctly (ar) * #1294 - Opie does not know about British Summer Time * #1314 - Drawpad initialization (mickeyl) * #1317 - Packagemanager crashes on hold-down or install (chicken) * #1321 - Batteryapplet graphic glitch (harlekin) * #1324 - ZSafe not starting up (mickeyl) * #1328 - Personal Home Address fields is trimmed to 1char (eilers) * #1327 - Opie-mail ipk does not depend on libopiedb2 (chicken) * #1345 - Networksettingsplugin wlan plugin dependency on libpcap0 (mickeyl) * #1348 - Datebook dependency on libopiedb2 (chicken) * #1328 - Switched SQLDatabase and VCards char encoding from latin1 to unicode (eilers) 2004-04-25 Opie 1.1.3 * Introduced first implementation of SQL-Support using SQLite (eilers) * Added a new Gutenberg Project reader app - opie-gutenbrowser (ljp) * Added a real system graffiti character set (brad) * Added Generic Keyconfig Widget (zecke) * Improved Screenshotapplet and Drawpad integration. You can now open a screenshot in drawpad and take notes (zecke) * Added new Bible reader app - opie-dagger (drw) * Added a new Image Viewer. Work is ongoing (zecke,alwin) * Added namespace usage in libopie2 and everywhere (zecke,alwin) * Enabled the possibility to pass command line arguments to applications (mickeyl) * Added an about applet showing some credits and information about Opie (mickeyl) * Added benchmarking functionality to sysinfo (mickeyl) * Added applet and configuration application for switching hardware keyboard layouts (alwin) * Ported applications from libopie1 to libopie2* (drw,ar,alwin) * Imported fullscreen and font improvements from the Qkonsole fork to embeddedkonsole (waspe) * Clean-up of package information in control files (drw) * Repaired mediummount which was broken since integrating the quicklauncher (alwin) * Improved big-screen support (zecke,ar) * Improved multikeyboard support, added keyboard layout switching applet (mouse) * Added a new mail client based on libetpan (harlekin,alwin,jgf) * Added new package manager - opie-packagemanager (drw) * Improved light-n-power for C7x0 (mickeyl) * Added automatic rotation support for C7x0 (treke) * Split libopie1 up into a set of smaller - functionally grouped - libraries (mickeyl) * Added scanning the wireless network neighbourhood to networksettings (mickeyl) 2003-11-29 Opie 1.0.3 * Released as Version 1.0.3 * Improved i18n (various contributors) * Reduced application startup time by integrating the TT quicklauncher (zecke,harlekin) * Made the Documents Tab optional (mickeyl) * Integrated basic support for HP iPAQ 54xx and the Jornada 5xx (chicken) 2003-08-04 Opie 1.0.0 * Released as Version 1.0.0 * Including a PPP module for easy dial up (tille,harlekin,zecke) diff --git a/examples/opiecore/onotifydemo/onotifydemo.cpp b/examples/opiecore/onotifydemo/onotifydemo.cpp index a38ffee..0e84d80 100644 --- a/examples/opiecore/onotifydemo/onotifydemo.cpp +++ b/examples/opiecore/onotifydemo/onotifydemo.cpp @@ -1,132 +1,140 @@ #include "onotifydemo.h" /* OPIE */ #include <opie2/odebug.h> #include <opie2/oapplication.h> #include <opie2/ofiledialog.h> #include <opie2/olistview.h> #include <opie2/ofilenotify.h> using namespace Opie::Core; using namespace Opie::Ui; /* QT */ #include <qcheckbox.h> #include <qvbox.h> #include <qhbox.h> #include <qhbuttongroup.h> #include <qvbuttongroup.h> #include <qmessagebox.h> #include <qpushbutton.h> DemoApp::DemoApp( int argc, char** argv ) : OApplication( argc, argv, "libopie2 notify demo" ) { QVBox* vbox = new QVBox(); setMainWidget( vbox ); l = new OListView( vbox ); l->addColumn( "Notification Path" ); l->addColumn( "Trigger Type" ); l->addColumn( "Trigger Mask" ); l->setColumnAlignment( 1, AlignCenter ); l->setColumnAlignment( 2, AlignCenter ); QHBox* hbox = new QHBox( vbox ); - g2 = new QVButtonGroup( "Specify Trigger Type", hbox ); - //QCheckBox* c1 = new QCheckBox( "Multi", g2 ); - QCheckBox* c2 = new QCheckBox( "Access", g2 ); - QCheckBox* c3 = new QCheckBox( "Modify", g2 ); - QCheckBox* c4 = new QCheckBox( "Create", g2 ); - QCheckBox* c5 = new QCheckBox( "Delete", g2 ); - QCheckBox* c6 = new QCheckBox( "Rename", g2 ); - QCheckBox* c7 = new QCheckBox( "Attrib", g2 ); - g2->insert( c2, Access ); - g2->insert( c3, Modify ); - g2->insert( c4, Create ); - g2->insert( c5, Delete ); - g2->insert( c6, Rename ); - g2->insert( c7, Attrib ); + QCheckBox* c1 = new QCheckBox( "Access", g2 ); + QCheckBox* c2 = new QCheckBox( "Modify", g2 ); + QCheckBox* c3 = new QCheckBox( "Attrib", g2 ); + QCheckBox* c4 = new QCheckBox( "CloseWrite", g2 ); + QCheckBox* c5 = new QCheckBox( "CloseNoWrite", g2 ); + QCheckBox* c6 = new QCheckBox( "MovedFrom", g2 ); + QCheckBox* c7 = new QCheckBox( "MovedTo", g2 ); + QCheckBox* c8 = new QCheckBox( "DeleteSubdir", g2 ); + QCheckBox* c9 = new QCheckBox( "DeleteFile", g2 ); + QCheckBox* c10 = new QCheckBox( "CreateSubdir", g2 ); + QCheckBox* c11 = new QCheckBox( "CreateFile", g2 ); + QCheckBox* c12 = new QCheckBox( "Unmount", g2 ); + g2->insert( c1, Access ); + g2->insert( c2, Modify ); + g2->insert( c3, Attrib ); + g2->insert( c4, CloseWrite ); + g2->insert( c5, CloseNoWrite ); + g2->insert( c6, MovedFrom ); + g2->insert( c7, MovedTo ); + g2->insert( c8, DeleteSubdir ); + g2->insert( c9, DeleteFile ); + g2->insert( c10, CreateSubdir ); + g2->insert( c11, CreateFile ); + g2->insert( c12, Unmount ); connect( g2, SIGNAL( pressed(int) ), this, SLOT( modifierClicked(int) ) ); g1 = new QVButtonGroup( "Add/Remove", hbox ); QPushButton* plus1 = new QPushButton( "Add\n&Single", g1 ); QPushButton* plus2 = new QPushButton( "Add\n&Multi", g1 ); QPushButton* minus = new QPushButton( "&Remove\nIt!", g1 ); g1->insert( plus1, 0 ); g1->insert( plus2, 1 ); g1->insert( minus, 2 ); connect( plus1, SIGNAL( clicked() ), this, SLOT( addSingle() ) ); connect( plus2, SIGNAL( clicked() ), this, SLOT( addMulti() ) ); connect( minus, SIGNAL( clicked() ), this, SLOT( delTrigger() ) ); g1->show(); g2->show(); l->show(); hbox->show(); vbox->show(); showMainWidget( vbox ); } void DemoApp::addTrigger( bool multi ) { if ( !m ) { QMessageBox::warning( 0, "Add Trigger", "<p>Can't add trigger without at least one selected trigger type</p>", "&Sorry", 0 ); return; } QString filename = OFileDialog::getOpenFileName( OFileSelector::ExtendedAll ); if ( !filename.isEmpty() ) { odebug << "Filename = " << filename << oendl; int fntype = m; - if ( multi ) fntype |=(int) Multi; - QString modifier = QString().sprintf( " = 0x%08x", fntype ); new OListViewItem( l, filename, multi ? "MULTI" : "SINGLE", modifier ); if ( !multi ) OFileNotification::singleShot( filename, this, SLOT( trigger() ), (OFileNotificationType) fntype ); else - OFileNotification::singleShot( filename, this, SLOT( trigger() ), (OFileNotificationType) fntype ); + odebug << "not yet implemented..." << oendl; } else { odebug << "cancelled." << oendl; } } void DemoApp::modifierClicked( int modifier ) { m = static_cast<OFileNotificationType>( (int)m ^ int(modifier) ); }; void DemoApp::addSingle() { addTrigger(); }; void DemoApp::addMulti() { addTrigger( true ); }; void DemoApp::delTrigger() { QListViewItem* item = l->selectedItem(); if ( !item ) { QMessageBox::warning( 0, "Del Trigger", "<p>No trigger selected!</p>", "&Sorry", 0 ); return; } else { QString filename( item->text( 0 ) ); odebug << "Filename = " << filename << oendl; } } void DemoApp::trigger() { owarn << "FIRE!" << oendl; } int main( int argc, char** argv ) { DemoApp* app = new DemoApp( argc, argv ); app->exec(); return 0; } diff --git a/libopie2/opiecore/ofilenotify.cpp b/libopie2/opiecore/ofilenotify.cpp index 2a9bb8c..c221e58 100644 --- a/libopie2/opiecore/ofilenotify.cpp +++ b/libopie2/opiecore/ofilenotify.cpp @@ -1,322 +1,228 @@ /* This file is part of the Opie Project - =. Copyright (C) 2004 Michael 'Mickey' Lauer <mickey@Vanille.de> + =. Copyright (C) 2004-2005 Michael 'Mickey' Lauer <mickey@Vanille.de> .=l. Copyright (C) The Opie Team <opie-devel@handhelds.org> .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU Library General Public .="- .-=="i, .._ License as published by the Free Software -- . .-<_> .<> Foundation; either version 2 of the License, - ._= =} : or (at your option) any later version. +- . .-<_> .<> Foundation; version 2 of the License. + ._= =} : .%`+i> _;_. .i_,=:_. -<s. This program is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ofilenotify.h" using namespace Opie::Core; /* OPIE */ /* QT */ #include <qobject.h> +#include <qsocketnotifier.h> #include <qsignal.h> #include <qintdict.h> #include <qdir.h> /* STD */ #include <sys/types.h> #include <sys/stat.h> -#include <assert.h> +#include <sys/ioctl.h> #include <fcntl.h> +#include <assert.h> #include <string.h> #include <errno.h> #include <unistd.h> static QIntDict<OFileNotification> notification_list; +QSocketNotifier* OFileNotification::_sn; +int OFileNotification::_fd = -1; + +#define INOTIFY_DEVICE "/dev/inotify" + namespace Opie { namespace Core { OFileNotification::OFileNotification( QObject* parent, const char* name ) - :QObject( parent, name ), _active( false ) + :QObject( parent, name ), _active( false ), _multi( true ) { qDebug( "OFileNotification::OFileNotification()" ); } OFileNotification::~OFileNotification() { + stop(); qDebug( "OFileNotification::~OFileNotification()" ); } bool OFileNotification::isActive() const { return _active; } -int OFileNotification::start( const QString& path, bool sshot, OFileNotificationType type ) +int OFileNotification::watch( const QString& path, bool sshot, OFileNotificationType type ) { - _path = QString::null; - _fd = 0; - if ( _active ) stop(); - QString dirpath; - - // check if path exists and whether it is a file or a directory, if it exists at all - int result = ::stat( (const char*) path, &_stat ); - if ( !(type & Create) && result == -1 ) - { - qWarning( "OFileNotification::start(): Can't stat '%s': %s.", (const char*) path, strerror( errno ) ); - return -1; - } - - // if it is not a directory, we need to find out in which directory the file is - bool isDirectory = S_ISDIR( _stat.st_mode ); - if ( !isDirectory ) - { - int slashpos; - slashpos = path.findRev( '/' ); - if ( slashpos > 0 ) - { - _path = path; - dirpath = path.left( slashpos ); - } - } - else /* isDirectory */ - { - qWarning( "FIXME FIXME FIXME = Directory Notification Not Yet Implemented!" ); - _path = path; - dirpath = path; - assert( 0 ); - } - - int fd = ::open( (const char*) dirpath, O_RDONLY ); - if ( fd != -1 ) + if ( QFile::exists( path ) ) { if ( notification_list.isEmpty() ) { - OFileNotification::registerSignalHandler(); + OFileNotification::registerEventHandler(); } - result = ::fcntl( fd, F_SETSIG, SIGRTMIN ); - if ( result == -1 ) - { - qWarning( "OFileNotification::start(): Can't subscribe to '%s': %s.", (const char*) dirpath, strerror( errno ) ); - return -1; - } - if ( !sshot ) type = static_cast<OFileNotificationType>( (int) type | (int) Multi ); - result = ::fcntl( fd, F_NOTIFY, type ); - if ( result == -1 ) + struct inotify_watch_request iwr; + ::memset( &iwr, 0, sizeof iwr ); + iwr.name = const_cast<char*>( (const char*) path ); + iwr.mask = type; + + _wd = ::ioctl( OFileNotification::_fd, INOTIFY_WATCH, &iwr ); + + if ( _wd < 0 ) { - qWarning( "OFileNotification::start(): Can't subscribe to '%s': %s.", (const char*) dirpath, strerror( errno ) ); + qWarning( "OFileNotification::watch(): inotify can't watch '%s': %s.", (const char*) path, strerror( errno ) ); return -1; } - qDebug( "OFileNotification::start(): Subscribed for changes to %s (fd = %d, mask = 0x%0x)", (const char*) dirpath, fd, type ); - notification_list.insert( fd, this ); + + notification_list.insert( _wd, this ); + _multi = !sshot; _type = type; - _fd = fd; _active = true; - ::memset( &_stat, 0, sizeof _stat ); - ::stat( _path, &_stat ); - return fd; + qDebug( "OFileNotification::watch(): watching '%s' [wd=%d].", (const char*) path, _wd ); + return _wd; } else { - qWarning( "OFileNotification::start(): Error with path '%s': %s.", (const char*) dirpath, strerror( errno ) ); + qWarning( "OFileNotification::watch(): Can't watch '%s': %s.", (const char*) path, strerror( errno ) ); return -1; } } void OFileNotification::stop() { - if ( !_active ) return; - - int result = ::fcntl( _fd, F_NOTIFY, 0 ); - if ( result == -1 ) - { - qWarning( "OFileNotification::stop(): Can't remove subscription to '%s': %s.", (const char*) _path, strerror( errno ) ); - } - else + notification_list.remove( _wd ); + _path = QString::null; + _wd = 0; + _active = false; + if ( notification_list.isEmpty() ) { - ::close( _fd ); - _type = Single; - _path = QString::null; - _fd = 0; - _active = false; + OFileNotification::unregisterEventHandler(); } } OFileNotificationType OFileNotification::type() const { return _type; } QString OFileNotification::path() const { return _path; } -int OFileNotification::fileno() const +bool OFileNotification::activate() { - return _fd; + emit triggered(); + _signal.activate(); + if ( !_multi ) stop(); + return true; } -bool OFileNotification::activate() +void OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) { - if ( hasChanged() ) - { - emit triggered(); - _signal.activate(); - return true; - } - else - return false; + OFileNotification* ofn = new OFileNotification(); + ofn->_signal.connect( receiver, member ); + ofn->watch( path, true, type ); } -bool OFileNotification::hasChanged() +void OFileNotification::inotifyEventHandler() { - bool c = false; + qWarning( "OFileNotification::__eventHandler(): reached." ); - struct stat newstat; - ::memset( &newstat, 0, sizeof newstat ); - int result = ::stat( _path, &newstat ); // may fail if file has been renamed or deleted. that doesn't matter :) + char buffer[16384]; + size_t buffer_i; + struct inotify_event *pevent, *event; + ssize_t r; + size_t event_size; + int count = 0; - qDebug( "result of newstat call is %d (%s=%d)", result, result == -1 ? strerror( errno ) : "success", errno ); - qDebug( "stat.atime = %0lx, newstat.atime = %0lx", (long)_stat.st_atime, (long)newstat.st_atime ); - qDebug( "stat.mtime = %0lx, newstat.mtime = %0lx", (long)_stat.st_mtime, (long)newstat.st_mtime ); - qDebug( "stat.ctime = %0lx, newstat.ctime = %0lx", (long)_stat.st_ctime, (long)newstat.st_ctime ); + r = ::read(_fd, buffer, 16384); - if ( !c && (_type & Create) && - (long)_stat.st_atime == 0 && (long)_stat.st_mtime == 0 && (long)_stat.st_ctime == 0 && - (long)newstat.st_atime > 0 && (long)newstat.st_mtime > 0 && (long)newstat.st_ctime > 0) - { - qDebug( "OFileNotification::hasChanged(): file has been created" ); - c = true; - } - if ( !c && (_type & (Delete|Rename)) && (long)newstat.st_atime == 0 && (long)newstat.st_mtime == 0 && (long)newstat.st_ctime == 0) - { - qDebug( "OFileNotification::hasChanged(): file has been deleted or renamed" ); - c = true; - } - if ( !c && (_type & Access) && (long)_stat.st_atime < (long)newstat.st_atime ) - { - qDebug( "OFileNotification::hasChanged(): atime changed" ); - c = true; - } - if ( !c && (_type & Modify) && (long)_stat.st_mtime < (long)newstat.st_mtime ) - { - qDebug( "OFileNotification::hasChanged(): mtime changed" ); - c = true; - } - if ( !c && (_type & Attrib) && (long)_stat.st_ctime < (long)newstat.st_ctime ) + if ( r <= 0 ) + return; + + buffer_i = 0; + while ( buffer_i < r ) { - qDebug( "OFileNotification::hasChanged(): ctime changed" ); - c = true; - } + /* Parse events and queue them ! */ + pevent = (struct inotify_event *)&buffer[buffer_i]; + event_size = sizeof(struct inotify_event) + pevent->len; + qDebug( "pevent->len = %d\n", pevent->len); - return c; -} + OFileNotification* fn = notification_list[ pevent->wd ]; + if ( fn ) + fn->activate(); + else + assert( false ); + //event = malloc(event_size); + //memmove(event, pevent, event_size); + //queue_enqueue(event, q); + buffer_i += event_size; + count++; + } -void OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) -{ - OFileNotification* ofn = new OFileNotification(); - ofn->_signal.connect( receiver, member ); - ofn->start( path, true, type ); + qDebug( "received %d events...", count ); + return; } -void OFileNotification::__signalHandler( int sig, siginfo_t *si, void *data ) +bool OFileNotification::registerEventHandler() { - Q_UNUSED( sig ) - Q_UNUSED( data ) - qWarning( "OFileNotification::__signalHandler(): reached." ); - int fd = si->si_fd; - OFileNotification* fn = notification_list[fd]; - if ( fn ) - { - // check if it really was the file (dnotify triggers on directory granularity, not file granularity) - if ( !fn->activate() ) - { - qDebug( "OFileNotification::__signalHandler(): false alarm ;) Restarting the trigger (if it was single)..." ); - if ( !(fn->type() & Multi ) ) - { - int result = ::fcntl( fn->fileno(), F_NOTIFY, fn->type() ); - if ( result == -1 ) - { - qWarning( "OFileNotification::__signalHandler(): Can't restart the trigger: %s.", strerror( errno ) ); - } - } - return; - } - #if 1 - if ( !(fn->type() & Multi) ) - { - qDebug( "OFileNotification::__signalHandler(): '%d' was singleShot. Removing from list.", fd ); - notification_list.remove( fd ); - if ( notification_list.isEmpty() ) - { - OFileNotification::unregisterSignalHandler(); - } - } - #endif - } - else + OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY ); + if ( OFileNotification::_fd < 0 ) { - qWarning( "OFileNotification::__signalHandler(): D'oh! Called without fd in notification_list. Race condition?" ); + qWarning( "OFileNotification::registerEventHandler(): couldn't register event handler: %s", strerror( errno ) ); + return false; } -} + OFileNotification::_sn = new QSocketNotifier( _fd, QSocketNotifier::Read, this, "inotify event" ); + connect( OFileNotification::_sn, SIGNAL( activated(int) ), this, SLOT( inotifyEventHandler() ) ); -bool OFileNotification::registerSignalHandler() -{ - struct sigaction act; - act.sa_sigaction = OFileNotification::__signalHandler; - ::sigemptyset( &act.sa_mask ); - act.sa_flags = SA_SIGINFO; - if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 ) - { - qWarning( "OFileNotification::registerSignalHandler(): couldn't register signal handler: %s", strerror( errno ) ); - return false; - } - qDebug( "OFileNotification::registerSignalHandler(): done" ); + qDebug( "OFileNotification::registerEventHandler(): done" ); return true; } -void OFileNotification::unregisterSignalHandler() +void OFileNotification::unregisterEventHandler() { - struct sigaction act; - act.sa_sigaction = ( void (*)(int, siginfo_t*, void*) ) SIG_DFL; - ::sigemptyset( &act.sa_mask ); - if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 ) - { - qWarning( "OFileNotification::unregisterSignalHandler(): couldn't deregister signal handler: %s", strerror( errno ) ); - } - qDebug( "OFileNotification::unregisterSignalHandler(): done" ); + if ( OFileNotification::_fd ) + ::close( OFileNotification::_fd ); + qDebug( "OFileNotification::unregisterEventHandler(): done" ); } } } diff --git a/libopie2/opiecore/ofilenotify.h b/libopie2/opiecore/ofilenotify.h index d820f7c..e3621cf 100644 --- a/libopie2/opiecore/ofilenotify.h +++ b/libopie2/opiecore/ofilenotify.h @@ -1,190 +1,197 @@ /* This file is part of the Opie Project - =. Copyright (C) 2004 Michael 'Mickey' Lauer <mickey@Vanille.de> + =. Copyright (C) 2004-2005 Michael 'Mickey' Lauer <mickey@Vanille.de> .=l. Copyright (C) The Opie Team <opie-devel@handhelds.org> .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU Library General Public .="- .-=="i, .._ License as published by the Free Software -- . .-<_> .<> Foundation; either version 2 of the License, - ._= =} : or (at your option) any later version. +- . .-<_> .<> Foundation; version 2 of the License. + ._= =} : .%`+i> _;_. .i_,=:_. -<s. This program is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef OFILENOTIFY_H #define OFILENOTIFY_H #if defined (__GNUC__) && (__GNUC__ < 3) #define _GNU_SOURCE #endif /* QT */ -#include <qobject.h> +#include <qsocketnotifier.h> #include <qsignal.h> #include <qstring.h> /* STD */ -#include <signal.h> -#include <fcntl.h> +#include "inotify.h" namespace Opie { namespace Core { /*====================================================================================== * OFileNotificationType *======================================================================================*/ /** * @brief An enumerate for the different types of file notifications * * This enumerate provides a means to specify the type of events that you are interest in. * Valid values are: * <ul> * <li>Access: The file was accessed (read) * <li>Modify The file was modified (write,truncate) - * <li>Create = The file was created in the directory - * <li>Delete = The file was unlinked from directory - * <li>Rename = The file was renamed * <li>Attrib = The file had its attributes changed (chmod,chown,chgrp) + * <li>CloseWrite = Writable file was closed + * <li>CloseNoWrite = Unwritable file was closed + * <li>Open = File was opened + * <li>MovedFrom = File was moved from X + * <li>MovedTo = File was moved to Y + * <li>DeleteSubdir = Subdir was deleted + * <li>DeleteFile = Subfile was deleted + * <li>CreateSubdir = Subdir was created + * <li>CreateFile = Subfile was created + * <li>DeleteSelf = Self was deleted + * <li>Unmount = The backing filesystem was unmounted * </ul> * **/ -enum OFileNotificationType { Single = 0x0000000, - Multi = DN_MULTISHOT, - Access = DN_ACCESS, - Modify = DN_MODIFY, - Create = DN_CREATE, - Delete = DN_DELETE, - Rename = DN_RENAME, - Attrib = DN_ATTRIB }; +enum OFileNotificationType +{ + Access = IN_ACCESS, + Modify = IN_MODIFY, + Attrib = IN_ATTRIB, + CloseWrite = IN_CLOSE_WRITE, + CloseNoWrite = IN_CLOSE_NOWRITE, + Open = IN_OPEN, + MovedFrom = IN_MOVED_FROM, + MovedTo = IN_MOVED_TO, + DeleteSubdir = IN_DELETE_SUBDIR, + DeleteFile = IN_DELETE_FILE, + CreateSubdir = IN_CREATE_SUBDIR, + CreateFile = IN_CREATE_FILE, + DeleteSelf = IN_DELETE_SELF, + Unmount = IN_UNMOUNT, + _QueueOverflow = IN_Q_OVERFLOW, /* Internal, don't use this in client code */ + _Ignored = IN_IGNORED, /* Internal, don't use this in client code */ +}; /*====================================================================================== * OFileNotification *======================================================================================*/ /** * @brief Represents a file notification * * This class allows to watch for events happening to files. - * It uses the dnotify kernel interface which is a very efficient signalling interface. + * It uses the inotify kernel interface * - * @see <file:///usr/src/linux/Documentation/dnotify.txt> + * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ * * @author Michael 'Mickey' Lauer <mickey@vanille.de> * **/ class OFileNotification : public QObject { Q_OBJECT public: OFileNotification( QObject* parent = 0, const char* name = 0 ); ~OFileNotification(); /** * This static function calls a slot when an event with @a type happens to file @a path. * * It is very convenient to use this function because you do not need to * bother with a timerEvent or to create a local QTimer object. * * Example: * <pre> * * #include <opie2/oapplication.h> - * #include <opie2/onitify.h> + * #include <opie2/ofilenotify.h> * using namespace Opie::Core; * * int main( int argc, char **argv ) * { * OApplication a( argc, argv, "File Notification Example" ); * OFileNotification::singleShot( "/tmp/quit", &a, SLOT(quit()), Create ); * ... // create and show your widgets * return a.exec(); * } * </pre> * - * This sample program automatically terminates when the file "/tmp/quite" has been created. + * This sample program automatically terminates when the file "/tmp/quit" has been created. * * * The @a receiver is the receiving object and the @a member is the slot. **/ static void singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type = Modify ); /** * Starts to watch for @a type changes to @a path. Set @a sshot to True if you want to be notified only once. * Note that in that case it may be more convenient to use @ref OFileNotification::singleShot() then. **/ - int start( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); + int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); /** * Stop watching for file events. **/ void stop(); /** * @returns the notification type as set by @ref start(). **/ OFileNotificationType type() const; /** * @returns the path to the file being watched by this instance. **/ QString path() const; /** - * @returns the UNIX file descriptor for the file being watched. - **/ - int fileno() const; - /** * @returns if a file is currently being watched. **/ bool isActive() const; signals: /** * This signal is emitted if an event happens of the specified type happens to the file being watched. **/ void triggered(); protected: bool activate(); - virtual bool hasChanged(); - static bool registerSignalHandler(); - static void unregisterSignalHandler(); - static void __signalHandler( int sig, siginfo_t *si, void *data ); + + private slots: + void inotifyEventHandler(); private: + bool registerEventHandler(); + void unregisterEventHandler(); + QString _path; OFileNotificationType _type; QSignal _signal; - int _fd; bool _active; - struct stat _stat; -}; - -#if 0 - -class ODirectoryNotification : public OFileNotification -{ - - public: - virtual bool hasChanged() { return true; }; + bool _multi; + static QSocketNotifier* _sn; + int _wd; // inotify watch descriptor + static int _fd; // inotify device descriptor }; -#endif - } } #endif |