Subversion Repositories public

Rev

Rev 11 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 luk 1
 
2
/// inotify C++ interface header
3
/**
4
 * \file inotify-cxx.h
5
 *
6
 * inotify C++ interface
7
 *
8
 * Copyright (C) 2006 Lukas Jelinek, <lukas@aiken.cz>
9
 *
10
 * This program is free software; you can redistribute it and/or
11
 * modify it under the terms of one of the following licenses:
12
 *
13
 * \li 1. X11-style license (see LICENSE-X11)
14
 * \li 2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL)
15
 * \li 3. GNU General Public License, version 2  (see LICENSE-GPL)
16
 *
17
 * If you want to help with choosing the best license for you,
18
 * please visit http://www.gnu.org/licenses/license-list.html.
19
 *
20
 */
21
 
22
 
23
 
24
 
25
 
26
#ifndef _INOTIFYCXX_H_
27
#define _INOTIFYCXX_H_
28
 
29
#include <string>
30
#include <deque>
31
#include <map>
32
 
33
// Please ensure that the following headers take the right place.
34
#include <sys/inotify.h>
35
#include <sys/inotify-syscalls.h>
36
 
37
/// Event struct size
38
#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))
39
 
40
/// Event buffer length
41
#define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16))
42
 
43
/// inotify event class
44
/**
45
 * It holds all information about inotify event and provides
46
 * access to its particular values.
47
 */
48
class InotifyEvent
49
{
50
public:
51
  /// Constructor.
52
  /**
53
   * Creates a plain event.
54
   */
55
  InotifyEvent()
56
  {
57
    memset(&m_evt, 0, sizeof(m_evt));
58
    m_evt.wd = (int32_t) -1;
59
  }
60
 
61
  /// Constructor.
62
  /**
63
   * Creates an event based on inotify event data.
64
   * For NULL pointer it works the same way as InotifyEvent().
65
   *
66
   * \param[in] pEvt event data
67
   */
68
  InotifyEvent(const struct inotify_event* pEvt)
69
  {
70
    if (pEvt != NULL) {
71
      memcpy(&m_evt, pEvt, sizeof(m_evt));
72
      if (pEvt->name != NULL)
73
        m_name = pEvt->name;
74
    }
75
    else {
76
      memset(&m_evt, 0, sizeof(m_evt));
77
      m_evt.wd = (int32_t) -1;
78
    }
79
  }
80
 
81
  /// Destructor.
82
  ~InotifyEvent() {}
83
 
84
  /// Returns the event watch descriptor.
85
  /**
86
   * \return watch descriptor
87
   *
88
   * \sa InotifyWatch::GetDescriptor()
89
   */
90
  inline int32_t GetDescriptor() const
91
  {
92
    return (int32_t) m_evt.wd;
93
  }
94
 
95
  /// Returns the event mask.
96
  /**
97
   * \return event mask
98
   *
99
   * \sa InotifyWatch::GetMask()
100
   */
101
  inline uint32_t GetMask() const
102
  {
103
    return (uint32_t) m_evt.mask;
104
  }
105
 
106
  /// Checks for the event type.
107
  /**
108
   * \param[in] uType type which is checked for
109
   * \return true = event mask contains the given type, false = otherwise
110
   */
111
  inline bool IsType(uint32_t uType) const
112
  {
113
    return (((uint32_t) m_evt.mask) & uType) != 0;
114
  }
115
 
116
  /// Returns the event cookie.
117
  /**
118
   * \return event cookie
119
   */
120
  inline uint32_t GetCookie() const
121
  {
122
    return (uint32_t) m_evt.cookie;
123
  }
124
 
125
  /// Returns the event name length.
126
  /**
127
   * \return event name length
128
   */
129
  inline uint32_t GetLength() const
130
  {
131
    return (uint32_t) m_evt.len;
132
  }
133
 
134
  /// Returns the event name.
135
  /**
136
   * \return event name
137
   */
138
  inline const std::string& GetName() const
139
  {
140
    return m_name;
141
  }
142
 
143
  /// Extracts the event name.
144
  /**
145
   * \param[out] rName event name
146
   */
147
  inline void GetName(std::string& rName) const
148
  {
149
    rName = GetName();
150
  }
151
 
152
  /// Returns the event raw data.
153
  /**
154
   * For NULL pointer it does nothing.
155
   *
156
   * \param[in,out] pEvt event data
157
   */
158
  inline void GetData(struct inotify_event* pEvt)
159
  {
160
    if (pEvt != NULL)
161
      memcpy(pEvt, &m_evt, sizeof(m_evt));
162
  }
163
 
164
  /// Returns the event raw data.
165
  /**
166
   * \param[in,out] rEvt event data
167
   */
168
  inline void GetData(struct inotify_event& rEvt)
169
  {
170
    memcpy(&rEvt, &m_evt, sizeof(m_evt));
171
  }
172
 
173
  /// Fills the string with all types contained in the event mask.
174
  /**
175
   * \param[out] rStr dumped event types
176
   */
177
  void DumpTypes(std::string& rStr) const;
178
 
179
private:
180
  struct inotify_event m_evt; ///< event structure
181
  std::string m_name;         ///< event name
182
};
183
 
184
 
185
class Inotify;  // forward declaration
186
 
187
 
188
/// inotify watch class
189
class InotifyWatch
190
{
191
public:
192
  /// Constructor.
193
  /**
194
   * Creates an inotify watch. Because this watch is
195
   * inactive it has an invalid descriptor (-1).
196
   *
197
   * \param[in] rPath watched file path
198
   * \param[in] uMask mask for events
199
   */
200
  InotifyWatch(const std::string& rPath, int32_t uMask)
201
  {
202
    m_path = rPath;
203
    m_uMask = uMask;
204
    m_wd = (int32_t) -1;
205
  }
206
 
207
  /// Destructor.
208
  ~InotifyWatch() {}
209
 
210
  /// Returns the watch descriptor.
211
  /**
212
   * \return watch descriptor; -1 for inactive watch
213
   */
214
  inline int32_t GetDescriptor() const
215
  {
216
    return m_wd;
217
  }
218
 
219
  /// Returns the watched file path.
220
  /**
221
   * \return file path
222
   */
223
  inline const std::string& GetPath() const
224
  {
225
    return m_path;
226
  }
227
 
228
  /// Returns the watch event mask.
229
  /**
230
   * \return event mask
231
   */
232
  inline uint32_t GetMask() const
233
  {
234
    return (uint32_t) m_uMask;
235
  }
236
 
237
private:
238
  friend class Inotify;
239
 
240
  std::string m_path;   ///< watched file path
241
  uint32_t m_uMask;     ///< event mask
242
  int32_t m_wd;         ///< watch descriptor
243
};
244
 
245
 
246
/// Mapping from watch descriptors to watch objects.
247
typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
248
 
249
 
250
/// inotify class
251
class Inotify
252
{
253
public:
254
  /// Constructor.
255
  /**
256
   * Creates and initializes an instance of inotify communication
257
   * object (opens the inotify device).
258
   */
259
  Inotify();
260
 
261
  /// Destructor.
262
  /**
263
   * Calls Close() due for clean-up.
264
   */
265
  ~Inotify();
266
 
267
  /// Removes all watches and closes the inotify device.
268
  void Close();
269
 
270
  /// Checks whether the inotify is ready.
271
  /**
272
   * \return true = initialized properly, false = something failed
273
   */
274
  inline bool IsReady() const
275
  {
276
    return m_fd != -1;
277
  }
278
 
279
  /// Adds a new watch.
280
  /**
281
   * \param[in] pWatch inotify watch
282
   * \return true = success, false = failure
283
   */
284
  bool Add(InotifyWatch* pWatch);
285
 
286
  /// Adds a new watch.
287
  /**
288
   * \param[in] rWatch inotify watch
289
   * \return true = success, false = failure
290
   */
291
  inline bool Add(InotifyWatch& rWatch)
292
  {
293
    return Add(&rWatch);
294
  }
295
 
296
  /// Removes a watch.
297
  /**
298
   * If the given watch is not present it does nothing.
299
   *
300
   * \param[in] pWatch inotify watch
301
   */
302
  void Remove(InotifyWatch* pWatch);
303
 
304
  /// Removes a watch.
305
  /**
306
   * If the given watch is not present it does nothing.
307
   *
308
   * \param[in] rWatch inotify watch
309
   */
310
  inline void Remove(InotifyWatch& rWatch)
311
  {
312
    Remove(&rWatch);
313
  }
314
 
315
  /// Removes all watches.
316
  void RemoveAll();
317
 
318
  /// Returns the count of watches.
319
  /**
320
   * \return count of watches
321
   */
322
  inline size_t GetWatchCount() const
323
  {
324
    return (size_t) m_watches.size();
325
  }
326
 
327
  /// Waits for inotify events.
328
  /**
329
   * It waits until one or more events occur.
330
   *
331
   * \param[in] fNoIntr if true it re-calls the system call after a handled signal
332
   * \return true = event(s) occurred, false = failure
333
   */
334
  bool WaitForEvents(bool fNoIntr = false);
335
 
336
  /// Returns the count of received and queued events.
337
  /**
338
   * This number is related to the events in the queue inside
339
   * this object, not to the events pending in the kernel.
340
   *
341
   * \return count of events
342
   */
343
  int GetEventCount();
344
 
345
  /// Extracts a queued inotify event.
346
  /**
347
   * The extracted event is removed from the queue.
348
   * If the pointer is NULL it does nothing.
349
   *
350
   * \param[in,out] pEvt event object
351
   * \return true = success, false = failure
352
   */
353
  bool GetEvent(InotifyEvent* pEvt);
354
 
355
  /// Extracts a queued inotify event.
356
  /**
357
   * The extracted event is removed from the queue.
358
   *
359
   * \param[in,out] rEvt event object
360
   * \return true = success, false = failure
361
   */
362
  bool GetEvent(InotifyEvent& rEvt)
363
  {
364
    return GetEvent(&rEvt);
365
  }
366
 
367
  /// Extracts a queued inotify event (without removing).
368
  /**
369
   * The extracted event stays in the queue.
370
   * If the pointer is NULL it does nothing.
371
   *
372
   * \param[in,out] pEvt event object
373
   * \return true = success, false = failure
374
   */
375
  bool PeekEvent(InotifyEvent* pEvt);
376
 
377
  /// Extracts a queued inotify event (without removing).
378
  /**
379
   * The extracted event stays in the queue.
380
   *
381
   * \param[in,out] rEvt event object
382
   * \return true = success, false = failure
383
   */
384
  bool PeekEvent(InotifyEvent& rEvt)
385
  {
386
    return PeekEvent(&rEvt);
387
  }
388
 
389
  /// Searches for a watch.
390
  /**
391
   * It tries to find a watch by the given descriptor.
392
   *
393
   * \param[in] iDescriptor watch descriptor
394
   * \return found descriptor; NULL if no such watch exists
395
   */
396
  InotifyWatch* FindWatch(int iDescriptor);  
397
 
398
private:
399
  int m_fd;                             ///< file descriptor
400
  IN_WATCH_MAP m_watches;               ///< watches
401
  unsigned char m_buf[INOTIFY_BUFLEN];  ///< buffer for events
402
  std::deque<InotifyEvent> m_events;    ///< event queue
403
};
404
 
405
 
406
#endif //_INOTIFYCXX_H_