Diffstat (limited to 'libopie2/opiecore/ofilenotify.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libopie2/opiecore/ofilenotify.cpp | 160 |
1 files changed, 114 insertions, 46 deletions
diff --git a/libopie2/opiecore/ofilenotify.cpp b/libopie2/opiecore/ofilenotify.cpp index 2242570..5e9f97b 100644 --- a/libopie2/opiecore/ofilenotify.cpp +++ b/libopie2/opiecore/ofilenotify.cpp | |||
@@ -31,128 +31,196 @@ using namespace Opie::Core; | |||
31 | 31 | ||
32 | /* OPIE */ | 32 | /* OPIE */ |
33 | 33 | ||
34 | /* QT */ | 34 | /* QT */ |
35 | #include <qobject.h> | ||
35 | #include <qsignal.h> | 36 | #include <qsignal.h> |
36 | #include <qintdict.h> | 37 | #include <qintdict.h> |
37 | #include <qdir.h> | 38 | #include <qdir.h> |
38 | 39 | ||
39 | /* STD */ | 40 | /* STD */ |
40 | #include <sys/types.h> | 41 | #include <sys/types.h> |
41 | #include <sys/stat.h> | 42 | #include <sys/stat.h> |
42 | #include <fcntl.h> | 43 | #ifndef _GNU_SOURCE |
44 | #define _GNU_SOURCE | ||
45 | #include <fcntl.h> | ||
46 | #undef _GNU_SOURCE | ||
47 | #else | ||
48 | #include <fcntl.h> | ||
49 | #endif | ||
43 | #include <string.h> | 50 | #include <string.h> |
44 | #include <errno.h> | 51 | #include <errno.h> |
52 | #include <unistd.h> | ||
53 | |||
54 | static QIntDict<OFileNotification> notification_list; | ||
45 | 55 | ||
46 | namespace Opie { | 56 | namespace Opie { |
47 | namespace Core { | 57 | namespace Core { |
48 | 58 | ||
49 | class OFileNotification | 59 | OFileNotification::OFileNotification( QObject* parent, const char* name ) |
60 | :QObject( parent, name ), _active( false ) | ||
50 | { | 61 | { |
51 | public: | 62 | qDebug( "OFileNotification::OFileNotification()" ); |
52 | OFileNotification( QObject* receiver, const char* member, OFileNotificationType type ) : _type( type ) | 63 | } |
53 | { | ||
54 | _signal.connect( receiver, member ); | ||
55 | } | ||
56 | ~OFileNotification() | ||
57 | { | ||
58 | } | ||
59 | |||
60 | void activate() | ||
61 | { | ||
62 | _signal.activate(); | ||
63 | } | ||
64 | 64 | ||
65 | OFileNotificationType type() | ||
66 | { | ||
67 | return _type; | ||
68 | } | ||
69 | 65 | ||
70 | private: | 66 | OFileNotification::~OFileNotification() |
71 | OFileNotificationType _type; | 67 | { |
72 | QSignal _signal; | 68 | qDebug( "OFileNotification::~OFileNotification()" ); |
73 | }; | 69 | } |
74 | 70 | ||
75 | 71 | ||
76 | static QIntDict<OFileNotification> notification_list; | 72 | bool OFileNotification::isActive() const |
73 | { | ||
74 | return _active; | ||
75 | } | ||
77 | 76 | ||
78 | 77 | ||
79 | void OFileNotifier::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) | 78 | int OFileNotification::start( const QString& path, bool sshot, OFileNotificationType type ) |
80 | { | 79 | { |
80 | _path = QString::null; | ||
81 | _fd = 0; | ||
82 | if ( _active ) stop(); | ||
83 | |||
81 | int fd = ::open( (const char*) path, O_RDONLY ); | 84 | int fd = ::open( (const char*) path, O_RDONLY ); |
82 | if ( fd != -1 ) | 85 | if ( fd != -1 ) |
83 | { | 86 | { |
84 | if ( notification_list.isEmpty() ) | 87 | if ( notification_list.isEmpty() ) |
85 | { | 88 | { |
86 | OFileNotifier::registerSignalHandler(); | 89 | OFileNotification::registerSignalHandler(); |
87 | } | 90 | } |
88 | int result = ::fcntl( fd, F_SETSIG, SIGRTMIN ); | 91 | int result = ::fcntl( fd, F_SETSIG, SIGRTMIN ); |
89 | if ( result == -1 ) | 92 | if ( result == -1 ) |
90 | { | 93 | { |
91 | qWarning( "OFileNotifier::singleShot(): Can't subscribe to '%s': %s.", (const char*) path, strerror( errno ) ); | 94 | qWarning( "OFileNotification::start(): Can't subscribe to '%s': %s.", (const char*) path, strerror( errno ) ); |
92 | return; | 95 | return -1; |
93 | } | 96 | } |
97 | if ( !sshot ) (int) type |= (int) Multi; | ||
94 | result = ::fcntl( fd, F_NOTIFY, type ); | 98 | result = ::fcntl( fd, F_NOTIFY, type ); |
95 | if ( result == -1 ) | 99 | if ( result == -1 ) |
96 | { | 100 | { |
97 | qWarning( "OFileNotifier::singleShot(): Can't subscribe to '%s': %s.", (const char*) path, strerror( errno ) ); | 101 | qWarning( "OFileNotification::start(): Can't subscribe to '%s': %s.", (const char*) path, strerror( errno ) ); |
98 | return; | 102 | return -1; |
99 | } | 103 | } |
100 | qDebug( "OFileNotifier::singleShot(): Subscribed for changes to %s (fd = %d)", (const char*) path, fd ); | 104 | qDebug( "OFileNotification::start(): Subscribed for changes to %s (fd = %d, mask = 0x%0x)", (const char*) path, fd, type ); |
101 | notification_list.insert( fd, new OFileNotification( receiver, member, type ) ); | 105 | notification_list.insert( fd, this ); |
106 | _type = type; | ||
107 | _path = path; | ||
108 | _fd = fd; | ||
109 | return fd; | ||
102 | } | 110 | } |
103 | else | 111 | else |
104 | { | 112 | { |
105 | qWarning( "OFileNotifier::singleShot(): Error with path '%s': %s.", (const char*) path, strerror( errno ) ); | 113 | qWarning( "OFileNotification::start(): Error with path '%s': %s.", (const char*) path, strerror( errno ) ); |
114 | return -1; | ||
106 | } | 115 | } |
107 | } | 116 | } |
108 | 117 | ||
109 | 118 | ||
110 | void OFileNotifier::__signalHandler( int sig, siginfo_t *si, void *data ) | 119 | void OFileNotification::stop() |
111 | { | 120 | { |
112 | qWarning( "OFileNotifier::__signalHandler(): reached." ); | 121 | if ( !_active ) return; |
122 | |||
123 | int result = ::fcntl( _fd, F_NOTIFY, 0 ); | ||
124 | if ( result == -1 ) | ||
125 | { | ||
126 | qWarning( "OFileNotification::stop(): Can't remove subscription to '%s': %s.", (const char*) _path, strerror( errno ) ); | ||
127 | } | ||
128 | else | ||
129 | { | ||
130 | ::close( _fd ); | ||
131 | _type = Single; | ||
132 | _path = QString::null; | ||
133 | _fd = 0; | ||
134 | _active = false; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | |||
139 | OFileNotificationType OFileNotification::type() const | ||
140 | { | ||
141 | return _type; | ||
142 | } | ||
143 | |||
144 | |||
145 | QString OFileNotification::path() const | ||
146 | { | ||
147 | return _path; | ||
148 | } | ||
149 | |||
150 | int OFileNotification::fileno() const | ||
151 | { | ||
152 | return _fd; | ||
153 | } | ||
154 | |||
155 | void OFileNotification::activate() | ||
156 | { | ||
157 | emit triggered(); | ||
158 | _signal.activate(); | ||
159 | } | ||
160 | |||
161 | |||
162 | void OFileNotification::singleShot( const QString& path, QObject* receiver, const char* member, OFileNotificationType type ) | ||
163 | { | ||
164 | OFileNotification* ofn = new OFileNotification(); | ||
165 | ofn->_signal.connect( receiver, member ); | ||
166 | ofn->start( path, true, type ); | ||
167 | } | ||
168 | |||
169 | |||
170 | void OFileNotification::__signalHandler( int sig, siginfo_t *si, void *data ) | ||
171 | { | ||
172 | qWarning( "OFileNotification::__signalHandler(): reached." ); | ||
113 | int fd = si->si_fd; | 173 | int fd = si->si_fd; |
114 | OFileNotification* fn = notification_list[fd]; | 174 | OFileNotification* fn = notification_list[fd]; |
115 | if ( fn ) | 175 | if ( fn ) |
116 | { | 176 | { |
117 | fn->activate(); | 177 | fn->activate(); |
118 | #if 1 | 178 | #if 1 |
119 | if ( !(fn->type() & Multi) ) | 179 | if ( !(fn->type() & Multi) ) |
120 | { | 180 | { |
121 | qDebug( "OFileNotifier::__signalHandler(): '%d' was singleShot. Removing from list.", fd ); | 181 | qDebug( "OFileNotification::__signalHandler(): '%d' was singleShot. Removing from list.", fd ); |
122 | notification_list.remove( fd ); | 182 | notification_list.remove( fd ); |
123 | if ( notification_list.isEmpty() ) | 183 | if ( notification_list.isEmpty() ) |
124 | { | 184 | { |
125 | OFileNotifier::unregisterSignalHandler(); | 185 | OFileNotification::unregisterSignalHandler(); |
126 | } | 186 | } |
127 | } | 187 | } |
128 | #endif | 188 | #endif |
129 | } | 189 | } |
130 | else | 190 | else |
131 | { | 191 | { |
132 | qWarning( "OFileNotifier::__signalHandler(): D'oh! Called without fd in notification_list. Race condition?" ); | 192 | qWarning( "OFileNotification::__signalHandler(): D'oh! Called without fd in notification_list. Race condition?" ); |
133 | } | 193 | } |
134 | } | 194 | } |
135 | 195 | ||
136 | 196 | ||
137 | void OFileNotifier::registerSignalHandler() | 197 | bool OFileNotification::registerSignalHandler() |
138 | { | 198 | { |
139 | struct sigaction act; | 199 | struct sigaction act; |
140 | act.sa_sigaction = OFileNotifier::__signalHandler; | 200 | act.sa_sigaction = OFileNotification::__signalHandler; |
141 | ::sigemptyset( &act.sa_mask ); | 201 | ::sigemptyset( &act.sa_mask ); |
142 | act.sa_flags = SA_SIGINFO; | 202 | act.sa_flags = SA_SIGINFO; |
143 | ::sigaction( SIGRTMIN, &act, NULL ); | 203 | if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 ) |
144 | qDebug( "OFileNotifier::registerSignalHandler(): done" ); | 204 | { |
205 | qWarning( "OFileNotification::registerSignalHandler(): couldn't register signal handler: %s", strerror( errno ) ); | ||
206 | return false; | ||
207 | } | ||
208 | qDebug( "OFileNotification::registerSignalHandler(): done" ); | ||
145 | } | 209 | } |
146 | 210 | ||
147 | 211 | ||
148 | void OFileNotifier::unregisterSignalHandler() | 212 | void OFileNotification::unregisterSignalHandler() |
149 | { | 213 | { |
150 | struct sigaction act; | 214 | struct sigaction act; |
151 | act.sa_sigaction = ( void (*)(int, siginfo_t*, void*) ) SIG_DFL; | 215 | act.sa_sigaction = ( void (*)(int, siginfo_t*, void*) ) SIG_DFL; |
152 | sigemptyset( &act.sa_mask ); | 216 | ::sigemptyset( &act.sa_mask ); |
153 | ::sigaction( SIGRTMIN, &act, NULL ); | 217 | if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 ) |
154 | qDebug( "OFileNotifier::unregisterSignalHandler(): done" ); | 218 | if ( ::sigaction( SIGRTMIN, &act, NULL ) == -1 ) |
219 | { | ||
220 | qWarning( "OFileNotification::unregisterSignalHandler(): couldn't deregister signal handler: %s", strerror( errno ) ); | ||
221 | } | ||
222 | qDebug( "OFileNotification::unregisterSignalHandler(): done" ); | ||
155 | } | 223 | } |
156 | 224 | ||
157 | 225 | ||
158 | } | 226 | } |