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