incron
0.5.10
|
00001 00003 00026 #ifndef _INOTIFYCXX_H_ 00027 #define _INOTIFYCXX_H_ 00028 00029 #include <stdint.h> 00030 #include <string> 00031 #include <deque> 00032 #include <map> 00033 00034 // Please ensure that the following headers take the right place 00035 #include <sys/syscall.h> 00036 #include <sys/inotify.h> 00037 00038 // Use this if syscalls not defined 00039 #ifndef __NR_inotify_init 00040 #include <sys/inotify-syscalls.h> 00041 #endif // __NR_inotify_init 00042 00044 #define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event)) 00045 00047 #define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16)) 00048 00050 00053 #define IN_EXC_MSG(msg) (std::string(__PRETTY_FUNCTION__) + ": " + msg) 00054 00056 typedef enum 00057 { 00058 IN_MAX_EVENTS = 0, 00059 IN_MAX_INSTANCES = 1, 00060 IN_MAX_WATCHES = 2 00061 } InotifyCapability_t; 00062 00064 00082 #ifdef INOTIFY_THREAD_SAFE 00083 00084 #include <pthread.h> 00085 00086 #define IN_LOCK_DECL mutable pthread_rwlock_t __m_lock; 00087 00088 #define IN_LOCK_INIT \ 00089 { \ 00090 pthread_rwlockattr_t attr; \ 00091 int res = 0; \ 00092 if ((res = pthread_rwlockattr_init(&attr)) != 0) \ 00093 throw InotifyException(IN_EXC_MSG("cannot initialize lock attributes"), res, this); \ 00094 if ((res = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP)) != 0) \ 00095 throw InotifyException(IN_EXC_MSG("cannot set lock kind"), res, this); \ 00096 if ((res = pthread_rwlock_init(&__m_lock, &attr)) != 0) \ 00097 throw InotifyException(IN_EXC_MSG("cannot initialize lock"), res, this); \ 00098 pthread_rwlockattr_destroy(&attr); \ 00099 } 00100 00101 #define IN_LOCK_DONE pthread_rwlock_destroy(&__m_lock); 00102 00103 #define IN_READ_BEGIN \ 00104 { \ 00105 int res = pthread_rwlock_rdlock(&__m_lock); \ 00106 if (res != 0) \ 00107 throw InotifyException(IN_EXC_MSG("locking for reading failed"), res, (void*) this); \ 00108 } 00109 00110 #define IN_READ_END \ 00111 { \ 00112 int res = pthread_rwlock_unlock(&__m_lock); \ 00113 if (res != 0) \ 00114 throw InotifyException(IN_EXC_MSG("unlocking failed"), res, (void*) this); \ 00115 } 00116 00117 #define IN_READ_END_NOTHROW pthread_rwlock_unlock(&__m_lock); 00118 00119 #define IN_WRITE_BEGIN \ 00120 { \ 00121 int res = pthread_rwlock_wrlock(&__m_lock); \ 00122 if (res != 0) \ 00123 throw InotifyException(IN_EXC_MSG("locking for writing failed"), res, (void*) this); \ 00124 } 00125 00126 #define IN_WRITE_END IN_READ_END 00127 #define IN_WRITE_END_NOTHROW IN_READ_END_NOTHROW 00128 00129 #else // INOTIFY_THREAD_SAFE 00130 00131 #define IN_LOCK_DECL 00132 #define IN_LOCK_INIT 00133 #define IN_LOCK_DONE 00134 #define IN_READ_BEGIN 00135 #define IN_READ_END 00136 #define IN_READ_END_NOTHROW 00137 #define IN_WRITE_BEGIN 00138 #define IN_WRITE_END 00139 #define IN_WRITE_END_NOTHROW 00140 00141 #endif // INOTIFY_THREAD_SAFE 00142 00143 00144 00145 00146 // forward declaration 00147 class InotifyWatch; 00148 class Inotify; 00149 00150 00152 00160 class InotifyException 00161 { 00162 public: 00164 00169 InotifyException(const std::string& rMsg = "", int iErr = 0, void* pSrc = NULL) 00170 : m_msg(rMsg), 00171 m_err(iErr) 00172 { 00173 m_pSrc = pSrc; 00174 } 00175 00177 00180 inline const std::string& GetMessage() const 00181 { 00182 return m_msg; 00183 } 00184 00186 00191 inline int GetErrorNumber() const 00192 { 00193 return m_err; 00194 } 00195 00197 00200 inline void* GetSource() const 00201 { 00202 return m_pSrc; 00203 } 00204 00205 protected: 00206 std::string m_msg; 00207 int m_err; 00208 mutable void* m_pSrc; 00209 }; 00210 00211 00213 00221 class InotifyEvent 00222 { 00223 public: 00225 00228 InotifyEvent() 00229 : m_uMask(0), 00230 m_uCookie(0) 00231 { 00232 m_pWatch = NULL; 00233 } 00234 00236 00243 InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch) 00244 : m_uMask(0), 00245 m_uCookie(0) 00246 { 00247 if (pEvt != NULL) { 00248 m_uMask = (uint32_t) pEvt->mask; 00249 m_uCookie = (uint32_t) pEvt->cookie; 00250 if (pEvt->name != NULL) { 00251 m_name = pEvt->len > 0 00252 ? pEvt->name 00253 : ""; 00254 } 00255 m_pWatch = pWatch; 00256 } 00257 else { 00258 m_pWatch = NULL; 00259 } 00260 } 00261 00263 ~InotifyEvent() {} 00264 00266 00271 int32_t GetDescriptor() const; 00272 00274 00279 inline uint32_t GetMask() const 00280 { 00281 return m_uMask; 00282 } 00283 00285 00290 inline static bool IsType(uint32_t uValue, uint32_t uType) 00291 { 00292 return ((uValue & uType) != 0) && ((~uValue & uType) == 0); 00293 } 00294 00296 00300 inline bool IsType(uint32_t uType) const 00301 { 00302 return IsType(m_uMask, uType); 00303 } 00304 00306 00309 inline uint32_t GetCookie() const 00310 { 00311 return m_uCookie; 00312 } 00313 00315 00318 inline uint32_t GetLength() const 00319 { 00320 return (uint32_t) m_name.length(); 00321 } 00322 00324 00327 inline const std::string& GetName() const 00328 { 00329 return m_name; 00330 } 00331 00333 00336 inline void GetName(std::string& rName) const 00337 { 00338 rName = GetName(); 00339 } 00340 00342 00345 inline InotifyWatch* GetWatch() 00346 { 00347 return m_pWatch; 00348 } 00349 00351 00355 static uint32_t GetMaskByName(const std::string& rName); 00356 00358 00362 static void DumpTypes(uint32_t uValue, std::string& rStr); 00363 00365 00368 void DumpTypes(std::string& rStr) const; 00369 00370 private: 00371 uint32_t m_uMask; 00372 uint32_t m_uCookie; 00373 std::string m_name; 00374 InotifyWatch* m_pWatch; 00375 }; 00376 00377 00378 00380 00386 class InotifyWatch 00387 { 00388 public: 00390 00398 InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true) 00399 : m_path(rPath), 00400 m_uMask(uMask), 00401 m_wd((int32_t) -1), 00402 m_fEnabled(fEnabled) 00403 { 00404 IN_LOCK_INIT 00405 } 00406 00408 ~InotifyWatch() 00409 { 00410 IN_LOCK_DONE 00411 } 00412 00414 00417 inline int32_t GetDescriptor() const 00418 { 00419 return m_wd; 00420 } 00421 00423 00426 inline const std::string& GetPath() const 00427 { 00428 return m_path; 00429 } 00430 00432 00435 inline uint32_t GetMask() const 00436 { 00437 return (uint32_t) m_uMask; 00438 } 00439 00441 00450 void SetMask(uint32_t uMask) throw (InotifyException); 00451 00453 00456 inline Inotify* GetInotify() 00457 { 00458 return m_pInotify; 00459 } 00460 00462 00473 void SetEnabled(bool fEnabled) throw (InotifyException); 00474 00476 00479 inline bool IsEnabled() const 00480 { 00481 return m_fEnabled; 00482 } 00483 00485 00494 inline bool IsRecursive() const 00495 { 00496 return false; 00497 } 00498 00499 private: 00500 friend class Inotify; 00501 00502 std::string m_path; 00503 uint32_t m_uMask; 00504 int32_t m_wd; 00505 Inotify* m_pInotify; 00506 bool m_fEnabled; 00507 00508 IN_LOCK_DECL 00509 00511 00516 void __Disable(); 00517 }; 00518 00519 00521 typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP; 00522 00524 typedef std::map<std::string, InotifyWatch*> IN_WP_MAP; 00525 00526 00528 00534 class Inotify 00535 { 00536 public: 00538 00544 Inotify() throw (InotifyException); 00545 00547 00550 ~Inotify(); 00551 00553 void Close(); 00554 00556 00561 void Add(InotifyWatch* pWatch) throw (InotifyException); 00562 00564 00569 inline void Add(InotifyWatch& rWatch) throw (InotifyException) 00570 { 00571 Add(&rWatch); 00572 } 00573 00575 00582 void Remove(InotifyWatch* pWatch) throw (InotifyException); 00583 00585 00592 inline void Remove(InotifyWatch& rWatch) throw (InotifyException) 00593 { 00594 Remove(&rWatch); 00595 } 00596 00598 void RemoveAll(); 00599 00601 00609 inline size_t GetWatchCount() const 00610 { 00611 IN_READ_BEGIN 00612 size_t n = (size_t) m_paths.size(); 00613 IN_READ_END 00614 return n; 00615 } 00616 00618 00623 inline size_t GetEnabledCount() const 00624 { 00625 IN_READ_BEGIN 00626 size_t n = (size_t) m_watches.size(); 00627 IN_READ_END 00628 return n; 00629 } 00630 00632 00643 void WaitForEvents(bool fNoIntr = false) throw (InotifyException); 00644 00646 00652 inline size_t GetEventCount() 00653 { 00654 IN_READ_BEGIN 00655 size_t n = (size_t) m_events.size(); 00656 IN_READ_END 00657 return n; 00658 } 00659 00661 00669 bool GetEvent(InotifyEvent* pEvt) throw (InotifyException); 00670 00672 00679 bool GetEvent(InotifyEvent& rEvt) throw (InotifyException) 00680 { 00681 return GetEvent(&rEvt); 00682 } 00683 00685 00693 bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException); 00694 00696 00703 bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException) 00704 { 00705 return PeekEvent(&rEvt); 00706 } 00707 00709 00715 InotifyWatch* FindWatch(int iDescriptor); 00716 00718 00728 InotifyWatch* FindWatch(const std::string& rPath); 00729 00731 00739 inline int GetDescriptor() const 00740 { 00741 return m_fd; 00742 } 00743 00745 00758 void SetNonBlock(bool fNonBlock) throw (InotifyException); 00759 00761 00774 void SetCloseOnExec(bool fClOnEx) throw (InotifyException); 00775 00777 00782 static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException); 00783 00785 00793 static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException); 00794 00796 00800 inline static uint32_t GetMaxEvents() throw (InotifyException) 00801 { 00802 return GetCapability(IN_MAX_EVENTS); 00803 } 00804 00806 00814 inline static void SetMaxEvents(uint32_t val) throw (InotifyException) 00815 { 00816 SetCapability(IN_MAX_EVENTS, val); 00817 } 00818 00820 00827 inline static uint32_t GetMaxInstances() throw (InotifyException) 00828 { 00829 return GetCapability(IN_MAX_INSTANCES); 00830 } 00831 00833 00841 inline static void SetMaxInstances(uint32_t val) throw (InotifyException) 00842 { 00843 SetCapability(IN_MAX_INSTANCES, val); 00844 } 00845 00847 00854 inline static uint32_t GetMaxWatches() throw (InotifyException) 00855 { 00856 return GetCapability(IN_MAX_WATCHES); 00857 } 00858 00860 00868 inline static void SetMaxWatches(uint32_t val) throw (InotifyException) 00869 { 00870 SetCapability(IN_MAX_WATCHES, val); 00871 } 00872 00873 private: 00874 int m_fd; 00875 IN_WATCH_MAP m_watches; 00876 IN_WP_MAP m_paths; 00877 unsigned char m_buf[INOTIFY_BUFLEN]; 00878 std::deque<InotifyEvent> m_events; 00879 00880 IN_LOCK_DECL 00881 00882 friend class InotifyWatch; 00883 00884 static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException); 00885 }; 00886 00887 00888 #endif //_INOTIFYCXX_H_ 00889