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