Subversion Repositories public

Rev

Rev 43 | 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
 *
103 luk 8
 * Copyright (C) 2006, 2007, 2009 Lukas Jelinek, <lukas@aiken.cz>
3 luk 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.
103 luk 19
 *
20
 * Credits:
21
 *     Mike Frysinger (cleanup of includes)
22
 *
3 luk 23
 */
24
 
25
 
26
 
27
 
28
 
29
#ifndef _INOTIFYCXX_H_
30
#define _INOTIFYCXX_H_
31
 
43 luk 32
#include <stdint.h>
3 luk 33
#include <string>
34
#include <deque>
35
#include <map>
36
 
103 luk 37
// Please ensure that the following header file takes the right place
3 luk 38
#include <sys/inotify.h>
17 luk 39
 
3 luk 40
 
41
/// Event struct size
42
#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))
43
 
44
/// Event buffer length
45
#define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16))
46
 
13 luk 47
/// Helper macro for creating exception messages.
48
/**
49
 * It prepends the message by the function name.
50
 */
51
#define IN_EXC_MSG(msg) (std::string(__PRETTY_FUNCTION__) + ": " + msg)
11 luk 52
 
29 luk 53
/// inotify capability/limit identifiers 
54
typedef enum
55
{
56
  IN_MAX_EVENTS     = 0,  ///< max. events in the kernel queue
57
  IN_MAX_INSTANCES  = 1,  ///< max. inotify file descriptors per process
58
  IN_MAX_WATCHES    = 2   ///< max. watches per file descriptor
59
} InotifyCapability_t;
60
 
21 luk 61
/// inotify-cxx thread safety
62
/**
63
 * If this symbol is defined you can use this interface safely
64
 * threaded applications. Remember that it slightly degrades
65
 * performance.
66
 *
67
 * Even if INOTIFY_THREAD_SAFE is defined some classes stay
68
 * unsafe. If you must use them (must you?) in more than one
69
 * thread concurrently you need to implement explicite locking.
70
 *
71
 * You need not to define INOTIFY_THREAD_SAFE in that cases
72
 * where the application is multithreaded but all the inotify
73
 * infrastructure will be managed only in one thread. This is
74
 * the recommended way.
75
 *
76
 * Locking may fail (it is very rare but not impossible). In this
77
 * case an exception is thrown. But if unlocking fails in case
78
 * of an error it does nothing (this failure is ignored).
79
 */
80
#ifdef INOTIFY_THREAD_SAFE
13 luk 81
 
21 luk 82
#include <pthread.h>
13 luk 83
 
21 luk 84
#define IN_LOCK_DECL mutable pthread_rwlock_t __m_lock;
85
 
86
#define IN_LOCK_INIT \
87
  { \
88
    pthread_rwlockattr_t attr; \
89
    int res = 0; \
90
    if ((res = pthread_rwlockattr_init(&attr)) != 0) \
91
      throw InotifyException(IN_EXC_MSG("cannot initialize lock attributes"), res, this); \
92
    if ((res = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP)) != 0) \
93
      throw InotifyException(IN_EXC_MSG("cannot set lock kind"), res, this); \
94
    if ((res = pthread_rwlock_init(&__m_lock, &attr)) != 0) \
95
      throw InotifyException(IN_EXC_MSG("cannot initialize lock"), res, this); \
96
    pthread_rwlockattr_destroy(&attr); \
97
  }
98
 
99
#define IN_LOCK_DONE pthread_rwlock_destroy(&__m_lock);
100
 
101
#define IN_READ_BEGIN \
102
  { \
103
    int res = pthread_rwlock_rdlock(&__m_lock); \
104
    if (res != 0) \
105
      throw InotifyException(IN_EXC_MSG("locking for reading failed"), res, (void*) this); \
106
  }
107
 
108
#define IN_READ_END \
109
  { \
110
    int res = pthread_rwlock_unlock(&__m_lock); \
111
    if (res != 0) \
112
      throw InotifyException(IN_EXC_MSG("unlocking failed"), res, (void*) this); \
113
  }
114
 
115
#define IN_READ_END_NOTHROW pthread_rwlock_unlock(&__m_lock);
116
 
117
#define IN_WRITE_BEGIN \
118
  { \
119
    int res = pthread_rwlock_wrlock(&__m_lock); \
120
    if (res != 0) \
121
      throw InotifyException(IN_EXC_MSG("locking for writing failed"), res, (void*) this); \
122
  }
123
 
124
#define IN_WRITE_END IN_READ_END
125
#define IN_WRITE_END_NOTHROW IN_READ_END_NOTHROW
126
 
127
#else // INOTIFY_THREAD_SAFE
128
 
129
#define IN_LOCK_DECL
130
#define IN_LOCK_INIT
131
#define IN_LOCK_DONE
132
#define IN_READ_BEGIN
133
#define IN_READ_END
134
#define IN_READ_END_NOTHROW
135
#define IN_WRITE_BEGIN
136
#define IN_WRITE_END
137
#define IN_WRITE_END_NOTHROW
138
 
139
#endif // INOTIFY_THREAD_SAFE
140
 
141
 
142
 
143
 
11 luk 144
// forward declaration
145
class InotifyWatch;
146
class Inotify;
147
 
148
 
13 luk 149
/// Class for inotify exceptions
21 luk 150
/**
151
 * This class allows to acquire information about exceptional
152
 * events. It makes easier to log or display error messages
153
 * and to identify problematic code locations.
154
 *
155
 * Although this class is basically thread-safe it is not intended
156
 * to be shared between threads.
157
 */
13 luk 158
class InotifyException
159
{
160
public:
161
  /// Constructor
162
  /**
163
   * \param[in] rMsg message
164
   * \param[in] iErr error number (see errno.h)
165
   * \param[in] pSrc source
166
   */
167
  InotifyException(const std::string& rMsg = "", int iErr = 0, void* pSrc = NULL)
168
  : m_msg(rMsg),
169
    m_err(iErr)
170
  {
171
    m_pSrc = pSrc;
172
  }
173
 
174
  /// Returns the exception message.
175
  /**
176
   * \return message
177
   */
178
  inline const std::string& GetMessage() const
179
  {
180
    return m_msg;
181
  }
182
 
183
  /// Returns the exception error number.
184
  /**
185
   * If not applicable this value is 0 (zero).
186
   *
187
   * \return error number (standardized; see errno.h)
188
   */
189
  inline int GetErrorNumber() const
190
  {
191
    return m_err;
192
  }
193
 
194
  /// Returns the exception source.
195
  /**
196
   * \return source
197
   */
198
  inline void* GetSource() const
199
  {
200
    return m_pSrc;
201
  }
202
 
203
protected:
204
  std::string m_msg;      ///< message
205
  int m_err;              ///< error number
206
  mutable void* m_pSrc;   ///< source
207
};
208
 
209
 
3 luk 210
/// inotify event class
211
/**
212
 * It holds all information about inotify event and provides
213
 * access to its particular values.
21 luk 214
 *
215
 * This class is not (and is not intended to be) thread-safe
216
 * and therefore it must not be used concurrently in multiple
217
 * threads.
3 luk 218
 */
219
class InotifyEvent
220
{
221
public:
222
  /// Constructor.
223
  /**
224
   * Creates a plain event.
225
   */
226
  InotifyEvent()
13 luk 227
  : m_uMask(0),
228
    m_uCookie(0)
3 luk 229
  {
11 luk 230
    m_pWatch = NULL;
3 luk 231
  }
232
 
233
  /// Constructor.
234
  /**
235
   * Creates an event based on inotify event data.
11 luk 236
   * For NULL pointers it works the same way as InotifyEvent().
3 luk 237
   *
238
   * \param[in] pEvt event data
11 luk 239
   * \param[in] pWatch inotify watch
3 luk 240
   */
11 luk 241
  InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch)
13 luk 242
  : m_uMask(0),
243
    m_uCookie(0)
3 luk 244
  {
245
    if (pEvt != NULL) {
13 luk 246
      m_uMask = (uint32_t) pEvt->mask;
247
      m_uCookie = (uint32_t) pEvt->cookie;
41 luk 248
      if (pEvt->name != NULL) {
249
        m_name = pEvt->len > 0
250
            ? pEvt->name
251
            : "";
252
      }
11 luk 253
      m_pWatch = pWatch;
3 luk 254
    }
255
    else {
11 luk 256
      m_pWatch = NULL;
3 luk 257
    }
258
  }
259
 
260
  /// Destructor.
261
  ~InotifyEvent() {}
262
 
263
  /// Returns the event watch descriptor.
264
  /**
265
   * \return watch descriptor
266
   *
267
   * \sa InotifyWatch::GetDescriptor()
268
   */
13 luk 269
  int32_t GetDescriptor() const;
3 luk 270
 
271
  /// Returns the event mask.
272
  /**
273
   * \return event mask
274
   *
275
   * \sa InotifyWatch::GetMask()
276
   */
277
  inline uint32_t GetMask() const
278
  {
13 luk 279
    return m_uMask;
3 luk 280
  }
281
 
11 luk 282
  /// Checks a value for the event type.
283
  /**
284
   * \param[in] uValue checked value
285
   * \param[in] uType type which is checked for
286
   * \return true = the value contains the given type, false = otherwise
287
   */
288
  inline static bool IsType(uint32_t uValue, uint32_t uType)
289
  {
290
    return ((uValue & uType) != 0) && ((~uValue & uType) == 0);
291
  }
292
 
3 luk 293
  /// Checks for the event type.
294
  /**
295
   * \param[in] uType type which is checked for
296
   * \return true = event mask contains the given type, false = otherwise
297
   */
298
  inline bool IsType(uint32_t uType) const
299
  {
13 luk 300
    return IsType(m_uMask, uType);
3 luk 301
  }
302
 
303
  /// Returns the event cookie.
304
  /**
305
   * \return event cookie
306
   */
307
  inline uint32_t GetCookie() const
308
  {
13 luk 309
    return m_uCookie;
3 luk 310
  }
311
 
312
  /// Returns the event name length.
313
  /**
314
   * \return event name length
315
   */
316
  inline uint32_t GetLength() const
317
  {
13 luk 318
    return (uint32_t) m_name.length();
3 luk 319
  }
320
 
321
  /// Returns the event name.
322
  /**
323
   * \return event name
324
   */
325
  inline const std::string& GetName() const
326
  {
327
    return m_name;
328
  }
329
 
330
  /// Extracts the event name.
331
  /**
332
   * \param[out] rName event name
333
   */
334
  inline void GetName(std::string& rName) const
335
  {
336
    rName = GetName();
337
  }
338
 
11 luk 339
  /// Returns the source watch.
340
  /**
341
   * \return source watch
342
   */
343
  inline InotifyWatch* GetWatch()
344
  {
345
    return m_pWatch;
346
  }
347
 
348
  /// Finds the appropriate mask for a name.
349
  /**
350
   * \param[in] rName mask name
351
   * \return mask for name; 0 on failure
352
   */
353
  static uint32_t GetMaskByName(const std::string& rName);
354
 
355
  /// Fills the string with all types contained in an event mask value.
356
  /**
357
   * \param[in] uValue event mask value
358
   * \param[out] rStr dumped event types
359
   */
360
  static void DumpTypes(uint32_t uValue, std::string& rStr);
361
 
3 luk 362
  /// Fills the string with all types contained in the event mask.
363
  /**
364
   * \param[out] rStr dumped event types
365
   */
366
  void DumpTypes(std::string& rStr) const;
367
 
368
private:
13 luk 369
  uint32_t m_uMask;           ///< mask
370
  uint32_t m_uCookie;         ///< cookie
371
  std::string m_name;         ///< name
11 luk 372
  InotifyWatch* m_pWatch;     ///< source watch
3 luk 373
};
374
 
375
 
376
 
377
/// inotify watch class
21 luk 378
/**
379
 * It holds information about the inotify watch on a particular
380
 * inode.
381
 *
382
 * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
383
 */
3 luk 384
class InotifyWatch
385
{
386
public:
387
  /// Constructor.
388
  /**
389
   * Creates an inotify watch. Because this watch is
390
   * inactive it has an invalid descriptor (-1).
391
   *
392
   * \param[in] rPath watched file path
393
   * \param[in] uMask mask for events
13 luk 394
   * \param[in] fEnabled events enabled yes/no
3 luk 395
   */
13 luk 396
  InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true)
397
  : m_path(rPath),
398
    m_uMask(uMask),
399
    m_wd((int32_t) -1),
400
    m_fEnabled(fEnabled)
3 luk 401
  {
21 luk 402
    IN_LOCK_INIT
3 luk 403
  }
404
 
405
  /// Destructor.
21 luk 406
  ~InotifyWatch()
407
  {
408
    IN_LOCK_DONE
409
  }
3 luk 410
 
411
  /// Returns the watch descriptor.
412
  /**
413
   * \return watch descriptor; -1 for inactive watch
414
   */
415
  inline int32_t GetDescriptor() const
416
  {
417
    return m_wd;
418
  }
419
 
420
  /// Returns the watched file path.
421
  /**
422
   * \return file path
423
   */
424
  inline const std::string& GetPath() const
425
  {
426
    return m_path;
427
  }
428
 
429
  /// Returns the watch event mask.
430
  /**
431
   * \return event mask
432
   */
433
  inline uint32_t GetMask() const
434
  {
435
    return (uint32_t) m_uMask;
436
  }
437
 
17 luk 438
  /// Sets the watch event mask.
439
  /**
21 luk 440
   * If the watch is active (added to an instance of Inotify)
17 luk 441
   * this method may fail due to unsuccessful re-setting
442
   * the watch in the kernel.
443
   *
444
   * \param[in] uMask event mask
445
   *
446
   * \throw InotifyException thrown if changing fails
447
   */
448
  void SetMask(uint32_t uMask) throw (InotifyException);  
449
 
11 luk 450
  /// Returns the appropriate inotify class instance.
451
  /**
452
   * \return inotify instance
453
   */
454
  inline Inotify* GetInotify()
455
  {
456
    return m_pInotify;
457
  }
458
 
17 luk 459
  /// Enables/disables the watch.
460
  /**
21 luk 461
   * If the watch is active (added to an instance of Inotify)
17 luk 462
   * this method may fail due to unsuccessful re-setting
463
   * the watch in the kernel.
464
   *
465
   * Re-setting the current state has no effect.
466
   *
467
   * \param[in] fEnabled set enabled yes/no
468
   *
469
   * \throw InotifyException thrown if enabling/disabling fails
470
   */
471
  void SetEnabled(bool fEnabled) throw (InotifyException);
13 luk 472
 
17 luk 473
  /// Checks whether the watch is enabled.
474
  /**
475
   * \return true = enables, false = disabled
476
   */
13 luk 477
  inline bool IsEnabled() const
478
  {
479
    return m_fEnabled;
480
  }
481
 
29 luk 482
  /// Checks whether the watch is recursive.
483
  /**
484
   * A recursive watch monitors a directory itself and all
485
   * its subdirectories. This watch is a logical object
486
   * which may have many underlying kernel watches.
487
   *
488
   * \return currently always false (recursive watches not yet supported)
489
   * \attention Recursive watches are currently NOT supported.
490
   *            They are planned for future versions.
491
   */
492
  inline bool IsRecursive() const
493
  {
494
    return false;    
495
  }
496
 
3 luk 497
private:
498
  friend class Inotify;
499
 
500
  std::string m_path;   ///< watched file path
501
  uint32_t m_uMask;     ///< event mask
502
  int32_t m_wd;         ///< watch descriptor
11 luk 503
  Inotify* m_pInotify;  ///< inotify object
13 luk 504
  bool m_fEnabled;      ///< events enabled yes/no
21 luk 505
 
506
  IN_LOCK_DECL
33 luk 507
 
37 luk 508
  /// Disables the watch (due to removing by the kernel).
33 luk 509
  /**
510
   * This method must be called after receiving an event.
511
   * It ensures the watch object is consistent with the kernel
512
   * data.
513
   */
37 luk 514
  void __Disable();
3 luk 515
};
516
 
517
 
518
/// Mapping from watch descriptors to watch objects.
519
typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
520
 
17 luk 521
/// Mapping from paths to watch objects.
522
typedef std::map<std::string, InotifyWatch*> IN_WP_MAP;
3 luk 523
 
17 luk 524
 
3 luk 525
/// inotify class
21 luk 526
/**
527
 * It holds information about the inotify device descriptor
528
 * and manages the event queue.
529
 *
530
 * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
531
 */
3 luk 532
class Inotify
533
{
534
public:
535
  /// Constructor.
536
  /**
537
   * Creates and initializes an instance of inotify communication
538
   * object (opens the inotify device).
13 luk 539
   *
540
   * \throw InotifyException thrown if inotify isn't available
3 luk 541
   */
13 luk 542
  Inotify() throw (InotifyException);
3 luk 543
 
544
  /// Destructor.
545
  /**
13 luk 546
   * Calls Close() due to clean-up.
3 luk 547
   */
548
  ~Inotify();
549
 
550
  /// Removes all watches and closes the inotify device.
551
  void Close();
13 luk 552
 
3 luk 553
  /// Adds a new watch.
554
  /**
555
   * \param[in] pWatch inotify watch
13 luk 556
   *
557
   * \throw InotifyException thrown if adding failed
3 luk 558
   */
13 luk 559
  void Add(InotifyWatch* pWatch) throw (InotifyException);
3 luk 560
 
561
  /// Adds a new watch.
562
  /**
563
   * \param[in] rWatch inotify watch
13 luk 564
   *
565
   * \throw InotifyException thrown if adding failed
3 luk 566
   */
13 luk 567
  inline void Add(InotifyWatch& rWatch) throw (InotifyException)
3 luk 568
  {
13 luk 569
    Add(&rWatch);
3 luk 570
  }
571
 
572
  /// Removes a watch.
573
  /**
574
   * If the given watch is not present it does nothing.
575
   *
576
   * \param[in] pWatch inotify watch
13 luk 577
   *
578
   * \throw InotifyException thrown if removing failed
3 luk 579
   */
13 luk 580
  void Remove(InotifyWatch* pWatch) throw (InotifyException);
3 luk 581
 
582
  /// Removes a watch.
583
  /**
584
   * If the given watch is not present it does nothing.
585
   *
586
   * \param[in] rWatch inotify watch
13 luk 587
   *
588
   * \throw InotifyException thrown if removing failed
3 luk 589
   */
13 luk 590
  inline void Remove(InotifyWatch& rWatch) throw (InotifyException)
3 luk 591
  {
592
    Remove(&rWatch);
593
  }
594
 
595
  /// Removes all watches.
596
  void RemoveAll();
597
 
598
  /// Returns the count of watches.
599
  /**
19 luk 600
   * This is the total count of all watches (regardless whether
601
   * enabled or not).
602
   *
3 luk 603
   * \return count of watches
21 luk 604
   *
605
   * \sa GetEnabledCount()
3 luk 606
   */
607
  inline size_t GetWatchCount() const
608
  {
21 luk 609
    IN_READ_BEGIN
610
    size_t n = (size_t) m_paths.size();
611
    IN_READ_END
612
    return n;
3 luk 613
  }
614
 
21 luk 615
  /// Returns the count of enabled watches.
616
  /**
617
   * \return count of enabled watches
618
   *
619
   * \sa GetWatchCount()
620
   */  
621
  inline size_t GetEnabledCount() const
622
  {
623
    IN_READ_BEGIN
624
    size_t n = (size_t) m_watches.size();
625
    IN_READ_END
626
    return n;
627
  }
628
 
3 luk 629
  /// Waits for inotify events.
630
  /**
13 luk 631
   * It waits until one or more events occur. When called
632
   * in nonblocking mode it only retrieves occurred events
633
   * to the internal queue and exits.
3 luk 634
   *
635
   * \param[in] fNoIntr if true it re-calls the system call after a handled signal
13 luk 636
   *
637
   * \throw InotifyException thrown if reading events failed
638
   *
639
   * \sa SetNonBlock()
3 luk 640
   */
13 luk 641
  void WaitForEvents(bool fNoIntr = false) throw (InotifyException);
3 luk 642
 
643
  /// Returns the count of received and queued events.
644
  /**
645
   * This number is related to the events in the queue inside
646
   * this object, not to the events pending in the kernel.
647
   *
648
   * \return count of events
649
   */
21 luk 650
  inline size_t GetEventCount()
651
  {
652
    IN_READ_BEGIN
653
    size_t n = (size_t) m_events.size();
654
    IN_READ_END
655
    return n;
656
  }
3 luk 657
 
658
  /// Extracts a queued inotify event.
659
  /**
660
   * The extracted event is removed from the queue.
661
   * If the pointer is NULL it does nothing.
662
   *
663
   * \param[in,out] pEvt event object
13 luk 664
   *
665
   * \throw InotifyException thrown if the provided pointer is NULL
3 luk 666
   */
13 luk 667
  bool GetEvent(InotifyEvent* pEvt) throw (InotifyException);
3 luk 668
 
669
  /// Extracts a queued inotify event.
670
  /**
671
   * The extracted event is removed from the queue.
672
   *
673
   * \param[in,out] rEvt event object
13 luk 674
   *
675
   * \throw InotifyException thrown only in very anomalous cases
3 luk 676
   */
13 luk 677
  bool GetEvent(InotifyEvent& rEvt) throw (InotifyException)
3 luk 678
  {
679
    return GetEvent(&rEvt);
680
  }
681
 
682
  /// Extracts a queued inotify event (without removing).
683
  /**
684
   * The extracted event stays in the queue.
685
   * If the pointer is NULL it does nothing.
686
   *
687
   * \param[in,out] pEvt event object
13 luk 688
   *
689
   * \throw InotifyException thrown if the provided pointer is NULL
3 luk 690
   */
13 luk 691
  bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException);
3 luk 692
 
693
  /// Extracts a queued inotify event (without removing).
694
  /**
695
   * The extracted event stays in the queue.
696
   *
697
   * \param[in,out] rEvt event object
13 luk 698
   *
699
   * \throw InotifyException thrown only in very anomalous cases
3 luk 700
   */
13 luk 701
  bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException)
3 luk 702
  {
703
    return PeekEvent(&rEvt);
704
  }
705
 
17 luk 706
  /// Searches for a watch by a watch descriptor.
3 luk 707
  /**
708
   * It tries to find a watch by the given descriptor.
709
   *
710
   * \param[in] iDescriptor watch descriptor
17 luk 711
   * \return pointer to a watch; NULL if no such watch exists
3 luk 712
   */
13 luk 713
  InotifyWatch* FindWatch(int iDescriptor);
714
 
17 luk 715
  /// Searches for a watch by a filesystem path.
716
  /**
717
   * It tries to find a watch by the given filesystem path.
718
   *
719
   * \param[in] rPath filesystem path
720
   * \return pointer to a watch; NULL if no such watch exists
721
   *
722
   * \attention The path must be exactly identical to the one
723
   *            used for the searched watch. Be careful about
724
   *            absolute/relative and case-insensitive paths.
725
   */
726
   InotifyWatch* FindWatch(const std::string& rPath);
727
 
13 luk 728
  /// Returns the file descriptor.
729
  /**
730
   * The descriptor can be used in standard low-level file
731
   * functions (poll(), select(), fcntl() etc.).
732
   *
733
   * \return valid file descriptor or -1 for inactive object
734
   *
735
   * \sa SetNonBlock()
736
   */
737
  inline int GetDescriptor() const
738
  {
739
    return m_fd;
740
  }
741
 
742
  /// Enables/disables non-blocking mode.
743
  /**
744
   * Use this mode if you want to monitor the descriptor
745
   * (acquired thru GetDescriptor()) in functions such as
746
   * poll(), select() etc.
747
   *
39 luk 748
   * Non-blocking mode is disabled by default.
749
   *
13 luk 750
   * \param[in] fNonBlock enable/disable non-blocking mode
751
   *
752
   * \throw InotifyException thrown if setting mode failed
753
   *
39 luk 754
   * \sa GetDescriptor(), SetCloseOnExec()
13 luk 755
   */
756
  void SetNonBlock(bool fNonBlock) throw (InotifyException);
29 luk 757
 
39 luk 758
  /// Enables/disables closing on exec.
759
  /**
760
   * Enable this if you want to close the descriptor when
761
   * executing another program. Otherwise, the descriptor
762
   * will be inherited.
763
   *
764
   * Closing on exec is disabled by default.
765
   *
766
   * \param[in] fClOnEx enable/disable closing on exec
767
   *
768
   * \throw InotifyException thrown if setting failed
769
   *
770
   * \sa GetDescriptor(), SetNonBlock()
771
   */
772
  void SetCloseOnExec(bool fClOnEx) throw (InotifyException);
773
 
29 luk 774
  /// Acquires a particular inotify capability/limit.
775
  /**
776
   * \param[in] cap capability/limit identifier
777
   * \return capability/limit value
778
   * \throw InotifyException thrown if the given value cannot be acquired
779
   */
780
  static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException);
781
 
782
  /// Modifies a particular inotify capability/limit.
783
  /**
784
   * \param[in] cap capability/limit identifier
785
   * \param[in] val new capability/limit value
786
   * \throw InotifyException thrown if the given value cannot be set
787
   * \attention Using this function requires root privileges.
788
   *            Beware of setting extensive values - it may seriously
789
   *            affect system performance and/or stability.
790
   */
791
  static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException);
792
 
793
  /// Returns the maximum number of events in the kernel queue.
794
  /**
795
   * \return maximum number of events in the kernel queue
796
   * \throw InotifyException thrown if the given value cannot be acquired
797
   */
798
  inline static uint32_t GetMaxEvents() throw (InotifyException)
799
  {
800
    return GetCapability(IN_MAX_EVENTS);
801
  }
802
 
803
  /// Sets the maximum number of events in the kernel queue.
804
  /**
805
   * \param[in] val new value
806
   * \throw InotifyException thrown if the given value cannot be set
807
   * \attention Using this function requires root privileges.
808
   *            Beware of setting extensive values - the greater value
809
   *            is set here the more physical memory may be used for the inotify
810
   *            infrastructure.
811
   */
812
  inline static void SetMaxEvents(uint32_t val) throw (InotifyException)
813
  {
814
    SetCapability(IN_MAX_EVENTS, val);
815
  }
816
 
817
  /// Returns the maximum number of inotify instances per process.
818
  /**
819
   * It means the maximum number of open inotify file descriptors
820
   * per running process.
821
   *
822
   * \return maximum number of inotify instances
823
   * \throw InotifyException thrown if the given value cannot be acquired
824
   */
825
  inline static uint32_t GetMaxInstances() throw (InotifyException)
826
  {
827
    return GetCapability(IN_MAX_INSTANCES);
828
  }
829
 
830
  /// Sets the maximum number of inotify instances per process.
831
  /**
832
   * \param[in] val new value
833
   * \throw InotifyException thrown if the given value cannot be set
834
   * \attention Using this function requires root privileges.
835
   *            Beware of setting extensive values - the greater value
836
   *            is set here the more physical memory may be used for the inotify
837
   *            infrastructure.
838
   */
839
  inline static void SetMaxInstances(uint32_t val) throw (InotifyException)
840
  {
841
    SetCapability(IN_MAX_INSTANCES, val);
842
  }
843
 
844
  /// Returns the maximum number of inotify watches per instance.
845
  /**
846
   * It means the maximum number of inotify watches per inotify
847
   * file descriptor.
848
   *
849
   * \return maximum number of inotify watches
850
   * \throw InotifyException thrown if the given value cannot be acquired
851
   */
852
  inline static uint32_t GetMaxWatches() throw (InotifyException)
853
  {
854
    return GetCapability(IN_MAX_WATCHES);
855
  }
856
 
857
  /// Sets the maximum number of inotify watches per instance.
858
  /**
859
   * \param[in] val new value
860
   * \throw InotifyException thrown if the given value cannot be set
861
   * \attention Using this function requires root privileges.
862
   *            Beware of setting extensive values - the greater value
863
   *            is set here the more physical memory may be used for the inotify
864
   *            infrastructure.
865
   */
866
  inline static void SetMaxWatches(uint32_t val) throw (InotifyException)
867
  {
868
    SetCapability(IN_MAX_WATCHES, val);
869
  }
3 luk 870
 
871
private:
872
  int m_fd;                             ///< file descriptor
17 luk 873
  IN_WATCH_MAP m_watches;               ///< watches (by descriptors)
874
  IN_WP_MAP m_paths;                    ///< watches (by paths)
3 luk 875
  unsigned char m_buf[INOTIFY_BUFLEN];  ///< buffer for events
876
  std::deque<InotifyEvent> m_events;    ///< event queue
17 luk 877
 
21 luk 878
  IN_LOCK_DECL
879
 
17 luk 880
  friend class InotifyWatch;
29 luk 881
 
882
  static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException);
3 luk 883
};
884
 
885
 
886
#endif //_INOTIFYCXX_H_
21 luk 887