1 /* 2 * Copyright (C) 2015 Nicolas Bonnefon and other contributors 3 * 4 * This file is part of glogg. 5 * 6 * glogg is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * glogg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with glogg. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef INOTIFYWATCHTOWERDRIVER_H 21 #define INOTIFYWATCHTOWERDRIVER_H 22 23 #include <memory> 24 #include <mutex> 25 #include <vector> 26 27 template <typename Driver> 28 class ObservedFile; 29 template <typename Driver> 30 class ObservedFileList; 31 32 class INotifyWatchTowerDriver { 33 public: 34 class FileId { 35 public: 36 friend class INotifyWatchTowerDriver; 37 38 FileId() { wd_ = -1; } 39 bool operator==( const FileId& other ) const 40 { return wd_ == other.wd_; } 41 private: 42 FileId( int wd ) { wd_ = wd; } 43 int wd_; 44 }; 45 class DirId { 46 public: 47 friend class INotifyWatchTowerDriver; 48 49 DirId() { wd_ = -1; } 50 bool operator==( const DirId& other ) const 51 { return wd_ == other.wd_; } 52 bool valid() const 53 { return (wd_ != -1); } 54 private: 55 DirId( int wd ) { wd_ = wd; } 56 int wd_; 57 }; 58 class SymlinkId { 59 public: 60 friend class INotifyWatchTowerDriver; 61 62 SymlinkId() { wd_ = -1; } 63 bool operator==( const SymlinkId& other ) const 64 { return wd_ == other.wd_; } 65 private: 66 SymlinkId( int wd ) { wd_ = wd; } 67 int wd_; 68 }; 69 70 // Dummy class for inotify 71 class FileChangeToken { 72 public: 73 FileChangeToken() {} 74 FileChangeToken( const std::string& ) {} 75 76 void readFromFile( const std::string& ) {} 77 78 bool operator!=( const FileChangeToken& ) 79 { return true; } 80 }; 81 82 #ifdef HAS_TEMPLATE_ALIASES 83 using INotifyObservedFile = ObservedFile<INotifyWatchTowerDriver>; 84 using INotifyObservedFileList = ObservedFileList<INotifyWatchTowerDriver>; 85 #else 86 typedef ObservedFile<INotifyWatchTowerDriver> INotifyObservedFile; 87 typedef ObservedFileList<INotifyWatchTowerDriver> INotifyObservedFileList; 88 #endif 89 90 // Default constructor 91 INotifyWatchTowerDriver(); 92 ~INotifyWatchTowerDriver(); 93 94 // No copy/assign/move please 95 INotifyWatchTowerDriver( const INotifyWatchTowerDriver& ) = delete; 96 INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver& ) = delete; 97 INotifyWatchTowerDriver( const INotifyWatchTowerDriver&& ) = delete; 98 INotifyWatchTowerDriver& operator=( const INotifyWatchTowerDriver&& ) = delete; 99 100 FileId addFile( const std::string& file_name ); 101 SymlinkId addSymlink( const std::string& file_name ); 102 DirId addDir( const std::string& file_name ); 103 104 void removeFile( const FileId& file_id ); 105 void removeSymlink( const SymlinkId& symlink_id ); 106 void removeDir( const DirId& dir_id ); 107 108 // Wait for an event for the OS, treat it and 109 // return a list of files to notify about. 110 // This must be called with the lock on the list held, 111 // the function will unlock it temporary whilst blocking. 112 // Also returns a list of file that need readding 113 // (because of renames/symlink...) 114 std::vector<INotifyObservedFile*> waitAndProcessEvents( 115 INotifyObservedFileList* list, 116 std::unique_lock<std::mutex>* list_mutex, 117 std::vector<INotifyObservedFile*>* files_needing_readding, 118 int timeout_ms ); 119 120 // Interrupt waitAndProcessEvents if it is blocking. 121 void interruptWait(); 122 123 private: 124 // Only written at initialisation so no protection needed. 125 const int inotify_fd_; 126 127 // Breaking pipe 128 int breaking_pipe_read_fd_; 129 int breaking_pipe_write_fd_; 130 131 // Private member functions 132 size_t processINotifyEvent( const struct inotify_event* event, 133 INotifyObservedFileList* list, 134 std::vector<INotifyObservedFile*>* files_to_notify, 135 std::vector<INotifyObservedFile*>* files_needing_readding ); 136 }; 137 138 #endif 139