Subversion Repositories public

Rev

Rev 3 | Rev 13 | Go to most recent revision | Details | Compare with Previous | 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
 
11 luk 43
 
44
// forward declaration
45
class InotifyWatch;
46
class Inotify;
47
 
48
 
3 luk 49
/// inotify event class
50
/**
51
 * It holds all information about inotify event and provides
52
 * access to its particular values.
53
 */
54
class InotifyEvent
55
{
56
public:
57
  /// Constructor.
58
  /**
59
   * Creates a plain event.
60
   */
61
  InotifyEvent()
62
  {
63
    memset(&m_evt, 0, sizeof(m_evt));
64
    m_evt.wd = (int32_t) -1;
11 luk 65
    m_pWatch = NULL;
3 luk 66
  }
67
 
68
  /// Constructor.
69
  /**
70
   * Creates an event based on inotify event data.
11 luk 71
   * For NULL pointers it works the same way as InotifyEvent().
3 luk 72
   *
73
   * \param[in] pEvt event data
11 luk 74
   * \param[in] pWatch inotify watch
3 luk 75
   */
11 luk 76
  InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch)
3 luk 77
  {
78
    if (pEvt != NULL) {
79
      memcpy(&m_evt, pEvt, sizeof(m_evt));
80
      if (pEvt->name != NULL)
81
        m_name = pEvt->name;
11 luk 82
      m_pWatch = pWatch;
3 luk 83
    }
84
    else {
85
      memset(&m_evt, 0, sizeof(m_evt));
86
      m_evt.wd = (int32_t) -1;
11 luk 87
      m_pWatch = NULL;
3 luk 88
    }
89
  }
90
 
91
  /// Destructor.
92
  ~InotifyEvent() {}
93
 
94
  /// Returns the event watch descriptor.
95
  /**
96
   * \return watch descriptor
97
   *
98
   * \sa InotifyWatch::GetDescriptor()
99
   */
100
  inline int32_t GetDescriptor() const
101
  {
102
    return (int32_t) m_evt.wd;
103
  }
104
 
105
  /// Returns the event mask.
106
  /**
107
   * \return event mask
108
   *
109
   * \sa InotifyWatch::GetMask()
110
   */
111
  inline uint32_t GetMask() const
112
  {
113
    return (uint32_t) m_evt.mask;
114
  }
115
 
11 luk 116
  /// Checks a value for the event type.
117
  /**
118
   * \param[in] uValue checked value
119
   * \param[in] uType type which is checked for
120
   * \return true = the value contains the given type, false = otherwise
121
   */
122
  inline static bool IsType(uint32_t uValue, uint32_t uType)
123
  {
124
    return ((uValue & uType) != 0) && ((~uValue & uType) == 0);
125
  }
126
 
3 luk 127
  /// Checks for the event type.
128
  /**
129
   * \param[in] uType type which is checked for
130
   * \return true = event mask contains the given type, false = otherwise
131
   */
132
  inline bool IsType(uint32_t uType) const
133
  {
11 luk 134
    return IsType((uint32_t) m_evt.mask, uType);
3 luk 135
  }
136
 
137
  /// Returns the event cookie.
138
  /**
139
   * \return event cookie
140
   */
141
  inline uint32_t GetCookie() const
142
  {
143
    return (uint32_t) m_evt.cookie;
144
  }
145
 
146
  /// Returns the event name length.
147
  /**
148
   * \return event name length
149
   */
150
  inline uint32_t GetLength() const
151
  {
152
    return (uint32_t) m_evt.len;
153
  }
154
 
155
  /// Returns the event name.
156
  /**
157
   * \return event name
158
   */
159
  inline const std::string& GetName() const
160
  {
161
    return m_name;
162
  }
163
 
164
  /// Extracts the event name.
165
  /**
166
   * \param[out] rName event name
167
   */
168
  inline void GetName(std::string& rName) const
169
  {
170
    rName = GetName();
171
  }
172
 
11 luk 173
  /// Returns the source watch.
174
  /**
175
   * \return source watch
176
   */
177
  inline InotifyWatch* GetWatch()
178
  {
179
    return m_pWatch;
180
  }
181
 
3 luk 182
  /// Returns the event raw data.
183
  /**
184
   * For NULL pointer it does nothing.
185
   *
186
   * \param[in,out] pEvt event data
187
   */
188
  inline void GetData(struct inotify_event* pEvt)
189
  {
190
    if (pEvt != NULL)
191
      memcpy(pEvt, &m_evt, sizeof(m_evt));
192
  }
193
 
194
  /// Returns the event raw data.
195
  /**
196
   * \param[in,out] rEvt event data
197
   */
198
  inline void GetData(struct inotify_event& rEvt)
199
  {
200
    memcpy(&rEvt, &m_evt, sizeof(m_evt));
201
  }
202
 
11 luk 203
  /// Finds the appropriate mask for a name.
204
  /**
205
   * \param[in] rName mask name
206
   * \return mask for name; 0 on failure
207
   */
208
  static uint32_t GetMaskByName(const std::string& rName);
209
 
210
  /// Fills the string with all types contained in an event mask value.
211
  /**
212
   * \param[in] uValue event mask value
213
   * \param[out] rStr dumped event types
214
   */
215
  static void DumpTypes(uint32_t uValue, std::string& rStr);
216
 
3 luk 217
  /// Fills the string with all types contained in the event mask.
218
  /**
219
   * \param[out] rStr dumped event types
220
   */
221
  void DumpTypes(std::string& rStr) const;
222
 
223
private:
224
  struct inotify_event m_evt; ///< event structure
225
  std::string m_name;         ///< event name
11 luk 226
  InotifyWatch* m_pWatch;     ///< source watch
3 luk 227
};
228
 
229
 
230
 
231
/// inotify watch class
232
class InotifyWatch
233
{
234
public:
235
  /// Constructor.
236
  /**
237
   * Creates an inotify watch. Because this watch is
238
   * inactive it has an invalid descriptor (-1).
239
   *
240
   * \param[in] rPath watched file path
241
   * \param[in] uMask mask for events
242
   */
243
  InotifyWatch(const std::string& rPath, int32_t uMask)
244
  {
245
    m_path = rPath;
246
    m_uMask = uMask;
247
    m_wd = (int32_t) -1;
248
  }
249
 
250
  /// Destructor.
251
  ~InotifyWatch() {}
252
 
253
  /// Returns the watch descriptor.
254
  /**
255
   * \return watch descriptor; -1 for inactive watch
256
   */
257
  inline int32_t GetDescriptor() const
258
  {
259
    return m_wd;
260
  }
261
 
262
  /// Returns the watched file path.
263
  /**
264
   * \return file path
265
   */
266
  inline const std::string& GetPath() const
267
  {
268
    return m_path;
269
  }
270
 
271
  /// Returns the watch event mask.
272
  /**
273
   * \return event mask
274
   */
275
  inline uint32_t GetMask() const
276
  {
277
    return (uint32_t) m_uMask;
278
  }
279
 
11 luk 280
  /// Returns the appropriate inotify class instance.
281
  /**
282
   * \return inotify instance
283
   */
284
  inline Inotify* GetInotify()
285
  {
286
    return m_pInotify;
287
  }
288
 
3 luk 289
private:
290
  friend class Inotify;
291
 
292
  std::string m_path;   ///< watched file path
293
  uint32_t m_uMask;     ///< event mask
294
  int32_t m_wd;         ///< watch descriptor
11 luk 295
  Inotify* m_pInotify;  ///< inotify object
3 luk 296
};
297
 
298
 
299
/// Mapping from watch descriptors to watch objects.
300
typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
301
 
302
 
303
/// inotify class
304
class Inotify
305
{
306
public:
307
  /// Constructor.
308
  /**
309
   * Creates and initializes an instance of inotify communication
310
   * object (opens the inotify device).
311
   */
312
  Inotify();
313
 
314
  /// Destructor.
315
  /**
316
   * Calls Close() due for clean-up.
317
   */
318
  ~Inotify();
319
 
320
  /// Removes all watches and closes the inotify device.
321
  void Close();
322
 
323
  /// Checks whether the inotify is ready.
324
  /**
325
   * \return true = initialized properly, false = something failed
326
   */
327
  inline bool IsReady() const
328
  {
329
    return m_fd != -1;
330
  }
331
 
332
  /// Adds a new watch.
333
  /**
334
   * \param[in] pWatch inotify watch
335
   * \return true = success, false = failure
336
   */
337
  bool Add(InotifyWatch* pWatch);
338
 
339
  /// Adds a new watch.
340
  /**
341
   * \param[in] rWatch inotify watch
342
   * \return true = success, false = failure
343
   */
344
  inline bool Add(InotifyWatch& rWatch)
345
  {
346
    return Add(&rWatch);
347
  }
348
 
349
  /// Removes a watch.
350
  /**
351
   * If the given watch is not present it does nothing.
352
   *
353
   * \param[in] pWatch inotify watch
354
   */
355
  void Remove(InotifyWatch* pWatch);
356
 
357
  /// Removes a watch.
358
  /**
359
   * If the given watch is not present it does nothing.
360
   *
361
   * \param[in] rWatch inotify watch
362
   */
363
  inline void Remove(InotifyWatch& rWatch)
364
  {
365
    Remove(&rWatch);
366
  }
367
 
368
  /// Removes all watches.
369
  void RemoveAll();
370
 
371
  /// Returns the count of watches.
372
  /**
373
   * \return count of watches
374
   */
375
  inline size_t GetWatchCount() const
376
  {
377
    return (size_t) m_watches.size();
378
  }
379
 
380
  /// Waits for inotify events.
381
  /**
382
   * It waits until one or more events occur.
383
   *
384
   * \param[in] fNoIntr if true it re-calls the system call after a handled signal
385
   * \return true = event(s) occurred, false = failure
386
   */
387
  bool WaitForEvents(bool fNoIntr = false);
388
 
389
  /// Returns the count of received and queued events.
390
  /**
391
   * This number is related to the events in the queue inside
392
   * this object, not to the events pending in the kernel.
393
   *
394
   * \return count of events
395
   */
396
  int GetEventCount();
397
 
398
  /// Extracts a queued inotify event.
399
  /**
400
   * The extracted event is removed from the queue.
401
   * If the pointer is NULL it does nothing.
402
   *
403
   * \param[in,out] pEvt event object
404
   * \return true = success, false = failure
405
   */
406
  bool GetEvent(InotifyEvent* pEvt);
407
 
408
  /// Extracts a queued inotify event.
409
  /**
410
   * The extracted event is removed from the queue.
411
   *
412
   * \param[in,out] rEvt event object
413
   * \return true = success, false = failure
414
   */
415
  bool GetEvent(InotifyEvent& rEvt)
416
  {
417
    return GetEvent(&rEvt);
418
  }
419
 
420
  /// Extracts a queued inotify event (without removing).
421
  /**
422
   * The extracted event stays in the queue.
423
   * If the pointer is NULL it does nothing.
424
   *
425
   * \param[in,out] pEvt event object
426
   * \return true = success, false = failure
427
   */
428
  bool PeekEvent(InotifyEvent* pEvt);
429
 
430
  /// Extracts a queued inotify event (without removing).
431
  /**
432
   * The extracted event stays in the queue.
433
   *
434
   * \param[in,out] rEvt event object
435
   * \return true = success, false = failure
436
   */
437
  bool PeekEvent(InotifyEvent& rEvt)
438
  {
439
    return PeekEvent(&rEvt);
440
  }
441
 
442
  /// Searches for a watch.
443
  /**
444
   * It tries to find a watch by the given descriptor.
445
   *
446
   * \param[in] iDescriptor watch descriptor
447
   * \return found descriptor; NULL if no such watch exists
448
   */
449
  InotifyWatch* FindWatch(int iDescriptor);  
450
 
451
private:
452
  int m_fd;                             ///< file descriptor
453
  IN_WATCH_MAP m_watches;               ///< watches
454
  unsigned char m_buf[INOTIFY_BUFLEN];  ///< buffer for events
455
  std::deque<InotifyEvent> m_events;    ///< event queue
456
};
457
 
458
 
459
#endif //_INOTIFYCXX_H_