summaryrefslogtreecommitdiff
path: root/libopie2
Unidiff
Diffstat (limited to 'libopie2') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiecore/ofilenotify.cpp122
-rw-r--r--libopie2/opiecore/ofilenotify.h63
2 files changed, 154 insertions, 31 deletions
diff --git a/libopie2/opiecore/ofilenotify.cpp b/libopie2/opiecore/ofilenotify.cpp
index 11d4f87..4264327 100644
--- a/libopie2/opiecore/ofilenotify.cpp
+++ b/libopie2/opiecore/ofilenotify.cpp
@@ -45,32 +45,50 @@ using namespace Opie::Core;
45#include <fcntl.h> 45#include <fcntl.h>
46#include <assert.h> 46#include <assert.h>
47#include <string.h> 47#include <string.h>
48#include <errno.h> 48#include <errno.h>
49#include <unistd.h> 49#include <unistd.h>
50 50
51static QIntDict<OFileNotification> notification_list; 51static QIntDict<OFileNotification> notification_list;
52 52
53QSocketNotifier* OFileNotification::_sn; 53QSocketNotifier* OFileNotification::_sn;
54int OFileNotification::_fd = -1; 54int OFileNotification::_fd = -1;
55 55
56#define INOTIFY_DEVICE "/dev/inotify" 56#define INOTIFY_DEVICE "/dev/inotify"
57 57
58namespace Opie { 58namespace Opie {
59namespace Core { 59namespace Core {
60 60
61//=================================================================================================
62// OFileNotificationEvent
63//=================================================================================================
64OFileNotificationEvent::OFileNotificationEvent( OFileNotification* parent, int wd, unsigned int mask, unsigned int cookie, const QString& name )
65 :_parent( parent ), _wd( wd ), _mask( mask ), _cookie( cookie ), _name( name )
66{
67 qDebug( "OFileNotificationEvent()" );
68}
69
70
71OFileNotificationEvent::~OFileNotificationEvent()
72{
73 qDebug( "~OFileNotificationEvent()" );
74}
75
76//=================================================================================================
77// OFileNotification
78//=================================================================================================
61OFileNotification::OFileNotification( QObject* parent, const char* name ) 79OFileNotification::OFileNotification( QObject* parent, const char* name )
62 :QObject( parent, name ), _active( false ), _multi( true ) 80 :QObject( parent, name ), _active( false ), _multi( true )
63{ 81{
64 qDebug( "OFileNotification::OFileNotification()" ); 82 qDebug( "OFileNotification::OFileNotification()" );
65} 83}
66 84
67 85
68OFileNotification::~OFileNotification() 86OFileNotification::~OFileNotification()
69{ 87{
70 stop(); 88 stop();
71 qDebug( "OFileNotification::~OFileNotification()" ); 89 qDebug( "OFileNotification::~OFileNotification()" );
72} 90}
73 91
74 92
75bool OFileNotification::isActive() const 93bool OFileNotification::isActive() const
76{ 94{
@@ -139,88 +157,105 @@ void OFileNotification::stop()
139 } 157 }
140} 158}
141 159
142 160
143OFileNotificationType OFileNotification::type() const 161OFileNotificationType OFileNotification::type() const
144{ 162{
145 return _type; 163 return _type;
146} 164}
147 165
148 166
149QString OFileNotification::path() const 167QString OFileNotification::path() const
150{ 168{
151 return _path; 169 return _path;
152} 170}
153 171
154 172
155bool OFileNotification::activate() 173bool OFileNotification::activate( const OFileNotificationEvent* e )
156{ 174{
157 emit triggered( _path ); 175 qDebug( "OFileNotification::activate(): e = ( %s, %d, 0x%08x, %d, %s )", (const char*) _path, e->descriptor(), e->mask(), e->cookie(), (const char*) e->name() );
176
177 // dumb signal
158 _signal.activate(); 178 _signal.activate();
179
180 // generic signal
181 emit triggered( _path, e->mask(), e->name() );
182
183 // specialized signals
184 switch ( e->mask() )
185 {
186 case Access: emit accessed( _path ); break;
187 case Modify: emit modified( _path ); break;
188 case Attrib: emit attributed( _path); break;
189 case CloseWrite: emit closed( _path, true ); break;
190 case CloseNoWrite: emit closed( _path, false ); break;
191 case Open: emit opened( _path ); break;
192 case MovedFrom: emit movedFrom( _path, e->name() ); break;
193 case MovedTo: emit movedTo( _path, e->name() ); break;
194 case DeleteSubdir: emit deletedSubdir( _path, e->name() ); break;
195 case DeleteFile: emit deletedFile( _path, e->name() ); break;
196 case CreateSubdir: emit createdSubdir( _path, e->name() ); break;
197 case CreateFile: emit createdFile( _path, e->name() ); break;
198 case DeleteSelf: emit deleted( _path ); break;
199 case Unmount: emit unmounted( _path ); break;
200 default: assert( 0 );
201 }
202
159 if ( !_multi ) stop(); 203 if ( !_multi ) stop();
204
160 return true; 205 return true;
161} 206}
162 207
163 208
164bool OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) 209bool OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type )
165{ 210{
166 OFileNotification* ofn = new OFileNotification(); 211 OFileNotification* ofn = new OFileNotification();
167 ofn->_signal.connect( receiver, member ); 212 ofn->_signal.connect( receiver, member );
168 return ofn->watch( path, true, type ) != -1; 213 return ofn->watch( path, true, type ) != -1;
169} 214}
170 215
171 216
172void OFileNotification::inotifyEventHandler() 217void OFileNotification::inotifyEventHandler()
173{ 218{
174 qWarning( "OFileNotification::__eventHandler(): reached." ); 219 qDebug( "OFileNotification::inotifyEventHandler(): reached." );
175 220
176 char buffer[16384]; 221 char buffer[16384];
177 size_t buffer_i; 222 size_t buffer_i;
178 struct inotify_event *pevent, *event; 223 struct inotify_event *pevent, *event;
179 ssize_t r; 224 ssize_t r;
180 size_t event_size; 225 size_t event_size;
181 int count = 0; 226 int count = 0;
182 227
183 r = ::read(_fd, buffer, 16384); 228 r = ::read(_fd, buffer, 16384);
184 229
185 if ( r <= 0 ) 230 if ( r <= 0 )
186 return; 231 return;
187 232
188 buffer_i = 0; 233 buffer_i = 0;
189 while ( buffer_i < r ) 234 while ( buffer_i < r )
190 { 235 {
191 /* Parse events and queue them ! */ 236 pevent = (struct inotify_event *)&buffer[buffer_i];
192 pevent = (struct inotify_event *)&buffer[buffer_i]; 237 event_size = sizeof(struct inotify_event) + pevent->len;
193 event_size = sizeof(struct inotify_event) + pevent->len; 238 OFileNotificationEvent* e = new OFileNotificationEvent( notification_list[ pevent->wd ], pevent->wd, pevent->mask,
194 qDebug( "pevent->len = %d\n", pevent->len); 239 pevent->cookie, pevent->len ? pevent->name : 0 );
195 240 e->activate();
196 OFileNotification* fn = notification_list[ pevent->wd ]; 241 buffer_i += event_size;
197 if ( fn ) 242 count++;
198 fn->activate();
199 else
200 assert( false );
201
202 //event = malloc(event_size);
203 //memmove(event, pevent, event_size);
204 //queue_enqueue(event, q);
205 buffer_i += event_size;
206 count++;
207 } 243 }
208 244
209 qDebug( "received %d events...", count ); 245 qDebug( "OFileNotification::inotifyEventHandler(): processed %d events", count );
210 return;
211} 246}
212 247
213 248
214bool OFileNotification::registerEventHandler() 249bool OFileNotification::registerEventHandler()
215{ 250{
216 OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY ); 251 OFileNotification::_fd = ::open( INOTIFY_DEVICE, O_RDONLY );
217 if ( OFileNotification::_fd < 0 ) 252 if ( OFileNotification::_fd < 0 )
218 { 253 {
219 qWarning( "OFileNotification::registerEventHandler(): couldn't register event handler: %s", strerror( errno ) ); 254 qWarning( "OFileNotification::registerEventHandler(): couldn't register event handler: %s", strerror( errno ) );
220 return false; 255 return false;
221 } 256 }
222 257
223 OFileNotification::_sn = new QSocketNotifier( _fd, QSocketNotifier::Read, this, "inotify event" ); 258 OFileNotification::_sn = new QSocketNotifier( _fd, QSocketNotifier::Read, this, "inotify event" );
224 connect( OFileNotification::_sn, SIGNAL( activated(int) ), this, SLOT( inotifyEventHandler() ) ); 259 connect( OFileNotification::_sn, SIGNAL( activated(int) ), this, SLOT( inotifyEventHandler() ) );
225 260
226 qDebug( "OFileNotification::registerEventHandler(): done" ); 261 qDebug( "OFileNotification::registerEventHandler(): done" );
@@ -249,30 +284,67 @@ ODirNotification::ODirNotification( QObject* parent, const char* name )
249ODirNotification::~ODirNotification() 284ODirNotification::~ODirNotification()
250{ 285{
251 qDebug( "ODirNotification::~ODirNotification()" ); 286 qDebug( "ODirNotification::~ODirNotification()" );
252} 287}
253 288
254 289
255int ODirNotification::watch( const QString& path, bool sshot, OFileNotificationType type, int recurse ) 290int ODirNotification::watch( const QString& path, bool sshot, OFileNotificationType type, int recurse )
256{ 291{
257 qDebug( "ODirNotification::watch( %s, %d, 0x%08x, %d )", (const char*) path, sshot, type, recurse ); 292 qDebug( "ODirNotification::watch( %s, %d, 0x%08x, %d )", (const char*) path, sshot, type, recurse );
258 293
259 if ( recurse == 0 ) 294 if ( recurse == 0 )
260 { 295 {
261 OFileNotification* fn = new OFileNotification( this, "ODirNotification delegate" ); 296 OFileNotification* fn = new OFileNotification( this, "ODirNotification delegate" );
262 int result = fn->startWatching( path, sshot, type ); 297 int result = fn->startWatching( path, sshot, type );
263 if ( result != -1 ) 298 if ( result != -1 )
264 { 299 {
265 connect( fn, SIGNAL( triggered( const QString& ) ), this, SIGNAL( triggered( const QString& ) ) ); 300 connect( fn, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ), this, SIGNAL( triggered( const QString&, unsigned int, const QString& ) ) );
266 return result; 301 connect( fn, SIGNAL( accessed( const QString& ) ), this, SIGNAL( accessed( const QString& ) ) );
302 connect( fn, SIGNAL( modified( const QString& ) ), this, SIGNAL( modified( const QString& ) ) );
303 connect( fn, SIGNAL( attributed( const QString& ) ), this, SIGNAL( attributed( const QString& ) ) );
304 connect( fn, SIGNAL( closed( const QString&, bool ) ), this, SIGNAL( closed( const QString&, bool ) ) );
305 connect( fn, SIGNAL( opened( const QString& ) ), this, SIGNAL( opened( const QString& ) ) );
306 connect( fn, SIGNAL( movedTo( const QString&, const QString& ) ), this, SIGNAL( movedTo( const QString&, const QString& ) ) );
307 connect( fn, SIGNAL( movedFrom( const QString&, const QString& ) ), this, SIGNAL( movedFrom( const QString&, const QString& ) ) );
308 connect( fn, SIGNAL( deletedSubdir( const QString&, const QString& ) ), this, SIGNAL( deletedSubdir( const QString&, const QString& ) ) );
309 connect( fn, SIGNAL( deletedFile( const QString&, const QString& ) ), this, SIGNAL( deletedFile( const QString&, const QString& ) ) );;
310 connect( fn, SIGNAL( createdSubdir( const QString&, const QString& ) ), this, SIGNAL( createdSubdir( const QString&, const QString& ) ) );
311 connect( fn, SIGNAL( createdFile( const QString&, const QString& ) ), this, SIGNAL( createdFile( const QString&, const QString& ) ) );
312 connect( fn, SIGNAL( deleted( const QString& ) ), this, SIGNAL( deleted( const QString& ) ) );
313 connect( fn, SIGNAL( unmounted( const QString& ) ), this, SIGNAL( unmounted( const QString& ) ) );
267 } 314 }
315 return result;
268 } 316 }
269 else 317 else
270 { 318 {
271 qDebug( "ODirNotification::watch(), recursion not yet implemented... :)" ); 319
272 return -1; 320 return 1;
273 } 321 }
274} 322}
275 323
324
325// void ODirNotification::subdirCreated( const QString& name )
326
327
328/*
329 Love-Trowbridge recursive directory scanning algorithm:
330
331 Step 1. Start at initial directory foo. Add watch.
332
333 Step 2. Setup handlers for watch created in Step 1.
334 Specifically, ensure that a directory created
335 in foo will result in a handled CREATE_SUBDIR
336 event.
337
338 Step 3. Read the contents of foo.
339
340 Step 4. For each subdirectory of foo read in step 3, repeat
341 step 1.
342
343 Step 5. For any CREATE_SUBDIR event on bar, if a watch is
344 not yet created on bar, repeat step 1 on bar.
345*/
346
347
276} // namespace Ui 348} // namespace Ui
277 349
278} // namespace Opie 350} // namespace Opie
diff --git a/libopie2/opiecore/ofilenotify.h b/libopie2/opiecore/ofilenotify.h
index 3eb917e..5bbf421 100644
--- a/libopie2/opiecore/ofilenotify.h
+++ b/libopie2/opiecore/ofilenotify.h
@@ -29,32 +29,34 @@ _;:,     .>    :=|. This program is free software; you can
29#ifndef OFILENOTIFY_H 29#ifndef OFILENOTIFY_H
30#define OFILENOTIFY_H 30#define OFILENOTIFY_H
31#if defined (__GNUC__) && (__GNUC__ < 3) 31#if defined (__GNUC__) && (__GNUC__ < 3)
32#define _GNU_SOURCE 32#define _GNU_SOURCE
33#endif 33#endif
34 34
35#include "linux_inotify.h" 35#include "linux_inotify.h"
36 36
37/* QT */ 37/* QT */
38#include <qsocketnotifier.h> 38#include <qsocketnotifier.h>
39#include <qsignal.h> 39#include <qsignal.h>
40#include <qstring.h> 40#include <qstring.h>
41 41
42namespace Opie { 42namespace Opie {
43namespace Core { 43namespace Core {
44 44
45class OFileNotificationEvent;
46
45/*====================================================================================== 47/*======================================================================================
46 * OFileNotificationType 48 * OFileNotificationType
47 *======================================================================================*/ 49 *======================================================================================*/
48 50
49/** 51/**
50 * @brief An enumerate for the different types of file notifications 52 * @brief An enumerate for the different types of file notifications
51 * 53 *
52 * This enumerate provides a means to specify the type of events that you are interest in. 54 * This enumerate provides a means to specify the type of events that you are interest in.
53 * Valid values are: 55 * Valid values are:
54 * <ul> 56 * <ul>
55 * <li>Access: The file was accessed (read) 57 * <li>Access: The file was accessed (read)
56 * <li>Modify The file was modified (write,truncate) 58 * <li>Modify The file was modified (write,truncate)
57 * <li>Attrib = The file had its attributes changed (chmod,chown,chgrp) 59 * <li>Attrib = The file had its attributes changed (chmod,chown,chgrp)
58 * <li>CloseWrite = Writable file was closed 60 * <li>CloseWrite = Writable file was closed
59 * <li>CloseNoWrite = Unwritable file was closed 61 * <li>CloseNoWrite = Unwritable file was closed
60 * <li>Open = File was opened 62 * <li>Open = File was opened
@@ -155,55 +157,67 @@ class OFileNotification : public QObject
155 **/ 157 **/
156 OFileNotificationType type() const; 158 OFileNotificationType type() const;
157 /** 159 /**
158 * @returns the path to the file being watched by this instance. 160 * @returns the path to the file being watched by this instance.
159 **/ 161 **/
160 QString path() const; 162 QString path() const;
161 /** 163 /**
162 * @returns if a file is currently being watched. 164 * @returns if a file is currently being watched.
163 **/ 165 **/
164 bool isActive() const; 166 bool isActive() const;
165 /** 167 /**
166 * @internal 168 * @internal
167 */ 169 */
168 int startWatching( const QString& path, bool sshot = false, OFileNotificationType type = Modify ); 170 int startWatching( const QString& path, bool sshot = false, OFileNotificationType type = Modify );
169 171
170 signals: 172 signals:
171 /** 173 void triggered( const QString&, unsigned int, const QString& );
172 * This signal is emitted if an event happens of the specified type happens to the file being watched. 174 void accessed( const QString& );
173 **/ 175 void modified( const QString& );
174 void triggered( const QString& name ); 176 void attributed( const QString& );
177 void closed( const QString&, bool );
178 void opened( const QString& );
179 void movedTo( const QString&, const QString& );
180 void movedFrom( const QString&, const QString& );
181 void deletedSubdir( const QString&, const QString& );
182 void deletedFile( const QString&, const QString& );
183 void createdSubdir( const QString&, const QString& );
184 void createdFile( const QString&, const QString& );
185 void deleted( const QString& );
186 void unmounted( const QString& );
175 187
176 protected: 188 protected:
177 bool activate(); 189 bool activate( const OFileNotificationEvent* e );
178 190
179 private slots: 191 private slots:
180 void inotifyEventHandler(); 192 void inotifyEventHandler();
181 193
182 private: 194 private:
183 bool registerEventHandler(); 195 bool registerEventHandler();
184 void unregisterEventHandler(); 196 void unregisterEventHandler();
185 197
186 QString _path; 198 QString _path;
187 OFileNotificationType _type; 199 OFileNotificationType _type;
188 QSignal _signal; 200 QSignal _signal;
189 bool _active; 201 bool _active;
190 bool _multi; 202 bool _multi;
191 static QSocketNotifier* _sn; 203 static QSocketNotifier* _sn;
192 int _wd; // inotify watch descriptor 204 int _wd; // inotify watch descriptor
193 static int _fd; // inotify device descriptor 205 static int _fd; // inotify device descriptor
206
207 friend class OFileNotificationEvent;
194}; 208};
195 209
196/*====================================================================================== 210/*======================================================================================
197 * ODirNotification 211 * ODirNotification
198 *======================================================================================*/ 212 *======================================================================================*/
199 213
200/** 214/**
201 * @brief Represents a directory notification 215 * @brief Represents a directory notification
202 * 216 *
203 * This class allows to watch for events happening to directories 217 * This class allows to watch for events happening to directories
204 * It uses the OFileNotification class 218 * It uses the OFileNotification class
205 * 219 *
206 * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/ 220 * @see http://www.kernel.org/pub/linux/kernel/people/rml/inotify/
207 * 221 *
208 * @author Michael 'Mickey' Lauer <mickey@vanille.de> 222 * @author Michael 'Mickey' Lauer <mickey@vanille.de>
209 * 223 *
@@ -214,25 +228,62 @@ class ODirNotification : public QObject
214 Q_OBJECT 228 Q_OBJECT
215 229
216 public: 230 public:
217 ODirNotification( QObject* parent = 0, const char* name = 0 ); 231 ODirNotification( QObject* parent = 0, const char* name = 0 );
218 ~ODirNotification(); 232 ~ODirNotification();
219 /** 233 /**
220 * Starts to watch for @a type changes to @a path. Recurse @a recurse levels down the filesystem tree, 234 * Starts to watch for @a type changes to @a path. Recurse @a recurse levels down the filesystem tree,
221 * use 0 for no recursion and -1 for unlimited recursion. 235 * use 0 for no recursion and -1 for unlimited recursion.
222 * Set @a sshot to True if you want to be notified only once. 236 * Set @a sshot to True if you want to be notified only once.
223 **/ 237 **/
224 int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify, int recurse = 0 ); 238 int watch( const QString& path, bool sshot = false, OFileNotificationType type = Modify, int recurse = 0 );
225 239
226 signals: 240 signals:
227 /** 241 /**
228 * This signal is emitted if an event happens of the specified type happens to the directory being watched. 242 * This signal is emitted if an event happens of the specified type happens to the directory being watched.
229 **/ 243 **/
230 void triggered( const QString& name ); 244 void triggered( const QString&, unsigned int, const QString& );
245 void accessed( const QString& );
246 void modified( const QString& );
247 void attributed( const QString& );
248 void closed( const QString&, bool );
249 void opened( const QString& );
250 void movedTo( const QString&, const QString& );
251 void movedFrom( const QString&, const QString& );
252 void deletedSubdir( const QString&, const QString& );
253 void deletedFile( const QString&, const QString& );
254 void createdSubdir( const QString&, const QString& );
255 void createdFile( const QString&, const QString& );
256 void deleted( const QString& );
257 void unmounted( const QString& );
258};
259
260/*======================================================================================
261 * OFileNotificationEvent
262 *======================================================================================*/
263
264class OFileNotificationEvent
265{
266 public:
267 OFileNotificationEvent( OFileNotification* parent, int wd, unsigned int mask, unsigned int cookie, const QString& name );
268 ~OFileNotificationEvent();
269 OFileNotification* parent() const { return _parent; };
270 int descriptor() const { return _wd; };
271 unsigned int mask() const { return _mask; };
272 unsigned int cookie() const { return _cookie; };
273 QString name() const { return _name; };
274 void activate() { _parent->activate( this ); };
275
276 private:
277 OFileNotification* _parent;
278 int _wd;
279 unsigned int _mask;
280 unsigned int _cookie;
281 QString _name;
231}; 282};
232 283
233 284
234} 285}
235} 286}
236 287
237#endif 288#endif
238 289