summaryrefslogtreecommitdiff
path: root/libopie2/opiecore/linux
Unidiff
Diffstat (limited to 'libopie2/opiecore/linux') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiecore/linux/ofilenotify.cpp40
-rw-r--r--libopie2/opiecore/linux/ofilenotify.h3
2 files changed, 25 insertions, 18 deletions
diff --git a/libopie2/opiecore/linux/ofilenotify.cpp b/libopie2/opiecore/linux/ofilenotify.cpp
index a7820ee..68c5a96 100644
--- a/libopie2/opiecore/linux/ofilenotify.cpp
+++ b/libopie2/opiecore/linux/ofilenotify.cpp
@@ -215,74 +215,80 @@ void OFileNotification::stop()
215 215
216 216
217OFileNotificationType OFileNotification::type() const 217OFileNotificationType OFileNotification::type() const
218{ 218{
219 return _type; 219 return _type;
220} 220}
221 221
222 222
223QString OFileNotification::path() const 223QString OFileNotification::path() const
224{ 224{
225 return _path; 225 return _path;
226} 226}
227 227
228 228
229bool OFileNotification::isSingleShot() const 229bool OFileNotification::isSingleShot() const
230{ 230{
231 return !_multi; 231 return !_multi;
232} 232}
233 233
234 234
235bool OFileNotification::activate( const OFileNotificationEvent* e ) 235bool OFileNotification::activate( const OFileNotificationEvent* e )
236{ 236{
237 qDebug( "OFileNotification::activate(): e = ( %s, %d, 0x%08x, %d, %s )", (const char*) _path, e->descriptor(), e->mask(), e->cookie(), (const char*) e->name() ); 237 qDebug( "OFileNotification::activate(): e = ( %s, %d, 0x%08x, %d, %s )", (const char*) _path, e->descriptor(), e->mask(), e->cookie(), (const char*) e->name() );
238 238
239 //FIXME: Should we really deliver QueueOverflow and/or Ignore to user level code?
240
239 // dumb signal 241 // dumb signal
240 _signal.activate(); 242 _signal.activate();
241 243
242 // generic signal 244 // generic signal
243 emit triggered( _path, e->mask(), e->name() ); 245 emit triggered( _path, e->mask(), e->name() );
244 246
245 // specialized signals 247 // specialized signals
246 switch ( e->mask() ) 248 switch ( e->mask() )
247 { 249 {
248 case Access: emit accessed( _path ); break; 250 case Access: emit accessed( _path ); break;
249 case Modify: emit modified( _path ); break; 251 case Modify: emit modified( _path ); break;
250 case Attrib: emit attributed( _path); break; 252 case Attrib: emit attributed( _path); break;
251 case CloseWrite: emit closed( _path, true ); break; 253 case CloseWrite: emit closed( _path, true ); break;
252 case CloseNoWrite: emit closed( _path, false ); break; 254 case CloseNoWrite: emit closed( _path, false ); break;
253 case Open: emit opened( _path ); break; 255 case Open: emit opened( _path ); break;
254 case MovedFrom: emit movedFrom( _path, e->name() ); break; 256 case MovedFrom: emit movedFrom( _path, e->name() ); break;
255 case MovedTo: emit movedTo( _path, e->name() ); break; 257 case MovedTo: emit movedTo( _path, e->name() ); break;
256 case DeleteSubdir: emit deletedSubdir( _path, e->name() ); break; 258 case DeleteSubdir: emit deletedSubdir( _path, e->name() ); break;
257 case DeleteFile: emit deletedFile( _path, e->name() ); break; 259 case DeleteFile: emit deletedFile( _path, e->name() ); break;
258 case CreateSubdir: emit createdSubdir( _path, e->name() ); break; 260 case CreateSubdir: emit createdSubdir( _path, e->name() ); break;
259 case CreateFile: emit createdFile( _path, e->name() ); break; 261 case CreateFile: emit createdFile( _path, e->name() ); break;
260 case DeleteSelf: emit deleted( _path ); break; 262 case DeleteSelf: emit deleted( _path ); break;
261 case Unmount: emit unmounted( _path ); break; 263 case Unmount: emit unmounted( _path ); break;
264 case _QueueOverflow: qFatal( "OFileNotification::activate() - Inotify Event Queue Overload!" ); break;
265 case _Ignored: qWarning( "OFileNotification::activate() - Further Events for '%s' will be ignored", (const char*) _path ); break;
262 default: assert( 0 ); 266 default: assert( 0 );
263 } 267 }
264 268
269 delete e;
270
265 if ( !_multi ) stop(); 271 if ( !_multi ) stop();
266 272
267 return true; 273 return true;
268} 274}
269 275
270 276
271bool OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) 277bool OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type )
272{ 278{
273 OFileNotification* ofn = new OFileNotification(); 279 OFileNotification* ofn = new OFileNotification();
274 ofn->_signal.connect( receiver, member ); 280 ofn->_signal.connect( receiver, member );
275 return ofn->watch( path, true, type ) != -1; 281 return ofn->watch( path, true, type ) != -1;
276} 282}
277 283
278 284
279void OFileNotification::inotifyEventHandler() 285void OFileNotification::inotifyEventHandler()
280{ 286{
281 qDebug( "OFileNotification::inotifyEventHandler(): reached." ); 287 qDebug( "OFileNotification::inotifyEventHandler(): reached." );
282 288
283 char buffer[16384]; 289 char buffer[16384];
284 ssize_t buffer_i; 290 ssize_t buffer_i;
285 struct inotify_event *pevent, *event; 291 struct inotify_event *pevent, *event;
286 ssize_t r; 292 ssize_t r;
287 size_t event_size; 293 size_t event_size;
288 int count = 0; 294 int count = 0;
@@ -296,97 +302,97 @@ void OFileNotification::inotifyEventHandler()
296 while ( buffer_i < r ) 302 while ( buffer_i < r )
297 { 303 {
298 pevent = (struct inotify_event *)&buffer[buffer_i]; 304 pevent = (struct inotify_event *)&buffer[buffer_i];
299 event_size = sizeof(struct inotify_event) + pevent->len; 305 event_size = sizeof(struct inotify_event) + pevent->len;
300 OFileNotificationEvent* e = new OFileNotificationEvent( notification_list[ pevent->wd ], pevent->wd, pevent->mask, 306 OFileNotificationEvent* e = new OFileNotificationEvent( notification_list[ pevent->wd ], pevent->wd, pevent->mask,
301 pevent->cookie, pevent->len ? pevent->name : 0 ); 307 pevent->cookie, pevent->len ? pevent->name : 0 );
302 e->activate(); 308 e->activate();
303 buffer_i += event_size; 309 buffer_i += event_size;
304 count++; 310 count++;
305 } 311 }
306 312
307 qDebug( "OFileNotification::inotifyEventHandler(): processed %d events", count ); 313 qDebug( "OFileNotification::inotifyEventHandler(): processed %d events", count );
308} 314}
309 315
310 316
311bool OFileNotification::registerEventHandler() 317bool OFileNotification::registerEventHandler()
312{ 318{
313 OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY ); 319 OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY );
314 if ( OFileNotification::_fd < 0 ) 320 if ( OFileNotification::_fd < 0 )
315 { 321 {
316 qWarning( "OFileNotification::registerEventHandler(): couldn't register event handler: %s", strerror( errno ) ); 322 qWarning( "OFileNotification::registerEventHandler(): couldn't register event handler: %s", strerror( errno ) );
317 return false; 323 return false;
318 } 324 }
319 325
320 OFileNotification::_sn = new QSocketNotifier( _fd, QSocketNotifier::Read, this, "inotify event" ); 326 OFileNotification::_sn = new QSocketNotifier( _fd, QSocketNotifier::Read );
321 connect( OFileNotification::_sn, SIGNAL( activated(int) ), this, SLOT( inotifyEventHandler() ) ); 327 connect( OFileNotification::_sn, SIGNAL( activated(int) ), this, SLOT( inotifyEventHandler() ) );
322 328
323 qDebug( "OFileNotification::registerEventHandler(): done" ); 329 qDebug( "OFileNotification::registerEventHandler(): done" );
324 return true; 330 return true;
325} 331}
326 332
327 333
328void OFileNotification::unregisterEventHandler() 334void OFileNotification::unregisterEventHandler()
329{ 335{
330 if ( _sn ) delete _sn; 336 if ( _sn ) delete _sn;
331 if ( OFileNotification::_fd ) 337 if ( OFileNotification::_fd )
332 ::close( OFileNotification::_fd ); 338 ::close( OFileNotification::_fd );
333 qDebug( "OFileNotification::unregisterEventHandler(): done" ); 339 qDebug( "OFileNotification::unregisterEventHandler(): done" );
334} 340}
335 341
336//================================================================================================= 342//=================================================================================================
337// ODirNotification 343// ODirNotification
338//================================================================================================= 344//=================================================================================================
339ODirNotification::ODirNotification( QObject* parent, const char* name ) 345ODirNotification::ODirNotification( QObject* parent, const char* name )
340 :QObject( parent, name ), _topfilenotification( 0 ), _type( Nothing ), _depth( -123 ) 346 :QObject( parent, name ), _topfilenotification( 0 ), _type( Nothing ), _depth( -123 )
341{ 347{
342 qDebug( "ODirNotification::ODirNotification()" ); 348 qDebug( "ODirNotification::ODirNotification()" );
343} 349}
344 350
345 351
346ODirNotification::~ODirNotification() 352ODirNotification::~ODirNotification()
347{ 353{
348 qDebug( "ODirNotification::~ODirNotification()" ); 354 qDebug( "ODirNotification::~ODirNotification()" );
349} 355}
350 356
351/* 357/**
352 Love-Trowbridge recursive directory scanning algorithm: 358 Love-Trowbridge recursive directory scanning algorithm:
353 359
354 Step 1. Start at initial directory foo. Add watch. 360 Step 1. Start at initial directory foo. Add watch.
355 361
356 Step 2. Setup handlers for watch created in Step 1. 362 Step 2. Setup handlers for watch created in Step 1.
357 Specifically, ensure that a directory created 363 Specifically, ensure that a directory created
358 in foo will result in a handled CREATE_SUBDIR 364 in foo will result in a handled CREATE_SUBDIR
359 event. 365 event.
360 366
361 Step 3. Read the contents of foo. 367 Step 3. Read the contents of foo.
362 368
363 Step 4. For each subdirectory of foo read in step 3, repeat 369 Step 4. For each subdirectory of foo read in step 3, repeat
364 step 1. 370 step 1.
365 371
366 Step 5. For any CREATE_SUBDIR event on bar, if a watch is 372 Step 5. For any CREATE_SUBDIR event on bar, if a watch is
367 not yet created on bar, repeat step 1 on bar. 373 not yet created on bar, repeat step 1 on bar.
368*/ 374**/
369 375
370int ODirNotification::watch( const QString& path, bool sshot, OFileNotificationType type, int recurse ) 376int ODirNotification::watch( const QString& path, bool sshot, OFileNotificationType type, int recurse )
371{ 377{
372 if ( _type == Nothing ) _type = type; // only set it once - for the top level call 378 if ( _type == Nothing ) _type = type; // only set it once - for the top level call
373 OFileNotificationType subtype = ( recurse != 0 ) ? (OFileNotificationType) int( _type | CreateSubdir ) : _type; 379 OFileNotificationType subtype = ( recurse != 0 ) ? (OFileNotificationType) int( _type | CreateSubdir ) : _type;
374 qDebug( "ODirNotification::watch( %s, %d, 0x%08x, %d )", (const char*) path, sshot, subtype, recurse ); 380 qDebug( "ODirNotification::watch( %s, %d, 0x%08x, %d )", (const char*) path, sshot, subtype, recurse );
375 OFileNotification* fn = new OFileNotification( this, "ODirNotification delegate" ); 381 OFileNotification* fn = new OFileNotification( this, "ODirNotification delegate" );
376 382
377 int result = fn->startWatching( path, sshot, subtype ); 383 int result = fn->startWatching( path, sshot, subtype );
378 if ( result != -1 ) 384 if ( result != -1 )
379 { 385 {
380 386
381 if ( !_topfilenotification ) _topfilenotification = fn; // only set it once - for the top level call 387 if ( !_topfilenotification ) _topfilenotification = fn; // only set it once - for the top level call
382 if ( _depth == -123 ) _depth = recurse; // only set it once - for the top level call 388 if ( _depth == -123 ) _depth = recurse; // only set it once - for the top level call
383 389
384 connect( fn, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ), this, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ) ); 390 connect( fn, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ), this, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ) );
385 connect( fn, SIGNAL( accessed( const QString& ) ), this, SIGNAL( accessed( const QString& ) ) ); 391 connect( fn, SIGNAL( accessed( const QString& ) ), this, SIGNAL( accessed( const QString& ) ) );
386 connect( fn, SIGNAL( modified( const QString& ) ), this, SIGNAL( modified( const QString& ) ) ); 392 connect( fn, SIGNAL( modified( const QString& ) ), this, SIGNAL( modified( const QString& ) ) );
387 connect( fn, SIGNAL( attributed( const QString& ) ), this, SIGNAL( attributed( const QString& ) ) ); 393 connect( fn, SIGNAL( attributed( const QString& ) ), this, SIGNAL( attributed( const QString& ) ) );
388 connect( fn, SIGNAL( closed( const QString&, bool ) ), this, SIGNAL( closed( const QString&, bool ) ) ); 394 connect( fn, SIGNAL( closed( const QString&, bool ) ), this, SIGNAL( closed( const QString&, bool ) ) );
389 connect( fn, SIGNAL( opened( const QString& ) ), this, SIGNAL( opened( const QString& ) ) ); 395 connect( fn, SIGNAL( opened( const QString& ) ), this, SIGNAL( opened( const QString& ) ) );
390 connect( fn, SIGNAL( movedTo( const QString&, const QString& ) ), this, SIGNAL( movedTo( const QString&, const QString& ) ) ); 396 connect( fn, SIGNAL( movedTo( const QString&, const QString& ) ), this, SIGNAL( movedTo( const QString&, const QString& ) ) );
391 connect( fn, SIGNAL( movedFrom( const QString&, const QString& ) ), this, SIGNAL( movedFrom( const QString&, const QString& ) ) ); 397 connect( fn, SIGNAL( movedFrom( const QString&, const QString& ) ), this, SIGNAL( movedFrom( const QString&, const QString& ) ) );
392 connect( fn, SIGNAL( deletedSubdir( const QString&, const QString& ) ), this, SIGNAL( deletedSubdir( const QString&, const QString& ) ) ); 398 connect( fn, SIGNAL( deletedSubdir( const QString&, const QString& ) ), this, SIGNAL( deletedSubdir( const QString&, const QString& ) ) );
diff --git a/libopie2/opiecore/linux/ofilenotify.h b/libopie2/opiecore/linux/ofilenotify.h
index 17e6b5d..c713b30 100644
--- a/libopie2/opiecore/linux/ofilenotify.h
+++ b/libopie2/opiecore/linux/ofilenotify.h
@@ -236,49 +236,50 @@ class OFileNotification : public QObject
236 private: 236 private:
237 bool registerEventHandler(); 237 bool registerEventHandler();
238 void unregisterEventHandler(); 238 void unregisterEventHandler();
239 239
240 QString _path; 240 QString _path;
241 OFileNotificationType _type; 241 OFileNotificationType _type;
242 QSignal _signal; 242 QSignal _signal;
243 bool _active; 243 bool _active;
244 bool _multi; 244 bool _multi;
245 static QSocketNotifier* _sn; 245 static QSocketNotifier* _sn;
246 int _wd; // inotify watch descriptor 246 int _wd; // inotify watch descriptor
247 static int _fd; // inotify device descriptor 247 static int _fd; // inotify device descriptor
248 248
249 friend class OFileNotificationEvent; 249 friend class OFileNotificationEvent;
250}; 250};
251 251
252/*====================================================================================== 252/*======================================================================================
253 * ODirNotification 253 * ODirNotification
254 *======================================================================================*/ 254 *======================================================================================*/
255 255
256/** 256/**
257 * @brief Represents a directory notification 257 * @brief Represents a directory notification
258 * 258 *
259 * This class allows to watch for events happening to directories 259 * This class allows to watch for events happening to directories
260 * It uses the OFileNotification class 260 * It uses the OFileNotification class and (for recursive watches)
261 * implements the Love-Trowbridge recursive directory scanning algorithm.
261 * 262 *
262 * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ 263 * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/
263 * 264 *
264 * @author Michael 'Mickey' Lauer <mickey@vanille.de> 265 * @author Michael 'Mickey' Lauer <mickey@vanille.de>
265 * 266 *
266 **/ 267 **/
267 268
268class ODirNotification : public QObject 269class ODirNotification : public QObject
269{ 270{
270 Q_OBJECT 271 Q_OBJECT
271 272
272 public: 273 public:
273 ODirNotification( QObject* parent = 0, const char* name = 0 ); 274 ODirNotification( QObject* parent = 0, const char* name = 0 );
274 ~ODirNotification(); 275 ~ODirNotification();
275 /** 276 /**
276 * Starts to watch for @a type changes to @a path. Recurse @a recurse levels down the filesystem tree, 277 * Starts to watch for @a type changes to @a path. Recurse @a recurse levels down the filesystem tree,
277 * use 0 for no recursion and -1 for unlimited recursion. 278 * use 0 for no recursion and -1 for unlimited recursion.
278 * Set @a sshot to True if you want to be notified only once. 279 * Set @a sshot to True if you want to be notified only once.
279 **/ 280 **/
280 int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify, int recurse = 0 ); 281 int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify, int recurse = 0 );
281 282
282 signals: 283 signals:
283 /** 284 /**
284 * This signal is emitted if an event happens of the specified type happens to the directory being watched. 285 * This signal is emitted if an event happens of the specified type happens to the directory being watched.