1 #include "watchtowerlist.h" 2 3 #include "log.h" 4 5 namespace { 6 std::string directory_path( const std::string& path ); 7 }; 8 9 // ObservedFileList class 10 ObservedFile* ObservedFileList::searchByName( const std::string& file_name ) 11 { 12 // Look for an existing observer on this file 13 auto existing_observer = observed_files_.begin(); 14 for ( ; existing_observer != observed_files_.end(); ++existing_observer ) 15 { 16 if ( existing_observer->file_name_ == file_name ) 17 { 18 LOG(logDEBUG) << "Found " << file_name; 19 break; 20 } 21 } 22 23 if ( existing_observer != observed_files_.end() ) 24 return &( *existing_observer ); 25 else 26 return nullptr; 27 } 28 29 ObservedFile* ObservedFileList::searchByFileOrSymlinkWd( 30 INotifyWatchTowerDriver::FileId file_id, 31 INotifyWatchTowerDriver::SymlinkId symlink_id ) 32 { 33 auto result = find_if( observed_files_.begin(), observed_files_.end(), 34 [file_id, symlink_id] (ObservedFile file) -> bool { 35 return ( file_id == file.file_id_ ) || 36 ( symlink_id == file.symlink_id_ ); 37 } ); 38 39 if ( result != observed_files_.end() ) 40 return &( *result ); 41 else 42 return nullptr; 43 } 44 45 ObservedFile* ObservedFileList::searchByDirWdAndName( 46 INotifyWatchTowerDriver::DirId id, const char* name ) 47 { 48 auto dir = find_if( observed_dirs_.begin(), observed_dirs_.end(), 49 [id] (std::pair<std::string,std::weak_ptr<ObservedDir>> d) -> bool { 50 if ( auto dir = d.second.lock() ) { 51 return ( id == dir->dir_id_ ); 52 } 53 else { 54 return false; } } ); 55 56 if ( dir != observed_dirs_.end() ) { 57 std::string path = dir->first + "/" + name; 58 59 // LOG(logDEBUG) << "Testing path: " << path; 60 61 // Looking for the path in the files we are watching 62 return searchByName( path ); 63 } 64 else { 65 return nullptr; 66 } 67 } 68 69 ObservedFile* ObservedFileList::addNewObservedFile( ObservedFile new_observed ) 70 { 71 auto new_file = observed_files_.insert( std::begin( observed_files_ ), new_observed ); 72 73 return &( *new_file ); 74 } 75 76 std::shared_ptr<ObservedFile> ObservedFileList::removeCallback( 77 std::shared_ptr<void> callback ) 78 { 79 std::shared_ptr<ObservedFile> returned_file = nullptr; 80 81 for ( auto observer = begin( observed_files_ ); 82 observer != end( observed_files_ ); ) 83 { 84 LOG(logDEBUG) << "Examining entry for " << observer->file_name_; 85 86 std::vector<std::shared_ptr<void>>& callbacks = observer->callbacks; 87 callbacks.erase( std::remove( 88 std::begin( callbacks ), std::end( callbacks ), callback ), 89 std::end( callbacks ) ); 90 91 /* See if all notifications have been deleted for this file */ 92 if ( callbacks.empty() ) { 93 LOG(logDEBUG) << "Empty notification list, removing the watched file"; 94 returned_file = std::make_shared<ObservedFile>( *observer ); 95 observer = observed_files_.erase( observer ); 96 } 97 else { 98 ++observer; 99 } 100 } 101 102 return returned_file; 103 } 104 105 std::shared_ptr<ObservedDir> ObservedFileList::watchedDirectory( 106 const std::string& dir_name ) 107 { 108 std::shared_ptr<ObservedDir> dir = nullptr; 109 110 if ( observed_dirs_.find( dir_name ) != std::end( observed_dirs_ ) ) 111 dir = observed_dirs_[ dir_name ].lock(); 112 113 return dir; 114 } 115 116 std::shared_ptr<ObservedDir> ObservedFileList::addWatchedDirectory( 117 const std::string& dir_name ) 118 { 119 auto dir = std::make_shared<ObservedDir>( dir_name ); 120 121 observed_dirs_[ dir_name ] = std::weak_ptr<ObservedDir>( dir ); 122 123 return dir; 124 } 125 126 std::shared_ptr<ObservedDir> ObservedFileList::watchedDirectoryForFile( 127 const std::string& file_name ) 128 { 129 return watchedDirectory( directory_path( file_name ) ); 130 } 131 132 std::shared_ptr<ObservedDir> ObservedFileList::addWatchedDirectoryForFile( 133 const std::string& file_name ) 134 { 135 return addWatchedDirectory( directory_path( file_name ) ); 136 } 137 138 namespace { 139 std::string directory_path( const std::string& path ) 140 { 141 size_t slash_pos = path.rfind( '/' ); 142 143 #ifdef _WIN32 144 if ( slash_pos == std::string::npos ) { 145 slash_pos = path.rfind( '\\' ); 146 } 147 148 // We need to include the final slash on Windows 149 ++slash_pos; 150 LOG(logDEBUG) << "Pos = " << slash_pos; 151 #endif 152 153 return std::string( path, 0, slash_pos ); 154 } 155 }; 156