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( int wd ) 30 { 31 auto result = find_if( observed_files_.begin(), observed_files_.end(), 32 [wd] (ObservedFile file) -> bool { 33 return ( wd == file.file_wd_ ) || ( wd == file.symlink_wd_ ); } ); 34 35 if ( result != observed_files_.end() ) 36 return &( *result ); 37 else 38 return nullptr; 39 } 40 41 ObservedFile* ObservedFileList::searchByDirWdAndName( int wd, const char* name ) 42 { 43 auto dir = find_if( observed_dirs_.begin(), observed_dirs_.end(), 44 [wd] (std::pair<std::string,std::weak_ptr<ObservedDir>> d) -> bool { 45 if ( auto dir = d.second.lock() ) { 46 return ( wd == dir->dir_wd_ ); 47 } 48 else { 49 return false; } } ); 50 51 if ( dir != observed_dirs_.end() ) { 52 std::string path = dir->first + "/" + name; 53 54 // LOG(logDEBUG) << "Testing path: " << path; 55 56 // Looking for the path in the files we are watching 57 return searchByName( path ); 58 } 59 else { 60 return nullptr; 61 } 62 } 63 64 ObservedFile* ObservedFileList::addNewObservedFile( ObservedFile new_observed ) 65 { 66 auto new_file = observed_files_.insert( std::begin( observed_files_ ), new_observed ); 67 68 return &( *new_file ); 69 } 70 71 std::shared_ptr<ObservedFile> ObservedFileList::removeCallback( 72 std::shared_ptr<void> callback ) 73 { 74 std::shared_ptr<ObservedFile> returned_file = nullptr; 75 76 for ( auto observer = begin( observed_files_ ); 77 observer != end( observed_files_ ); ) 78 { 79 LOG(logDEBUG) << "Examining entry for " << observer->file_name_; 80 81 std::vector<std::shared_ptr<void>>& callbacks = observer->callbacks; 82 callbacks.erase( std::remove( 83 std::begin( callbacks ), std::end( callbacks ), callback ), 84 std::end( callbacks ) ); 85 86 /* See if all notifications have been deleted for this file */ 87 if ( callbacks.empty() ) { 88 LOG(logDEBUG) << "Empty notification list, removing the watched file"; 89 returned_file = std::make_shared<ObservedFile>( *observer ); 90 observer = observed_files_.erase( observer ); 91 } 92 else { 93 ++observer; 94 } 95 } 96 97 return returned_file; 98 } 99 100 std::shared_ptr<ObservedDir> ObservedFileList::watchedDirectory( 101 const std::string& dir_name ) 102 { 103 std::shared_ptr<ObservedDir> dir = nullptr; 104 105 if ( observed_dirs_.find( dir_name ) != std::end( observed_dirs_ ) ) 106 dir = observed_dirs_[ dir_name ].lock(); 107 108 return dir; 109 } 110 111 std::shared_ptr<ObservedDir> ObservedFileList::addWatchedDirectory( 112 const std::string& dir_name ) 113 { 114 auto dir = std::make_shared<ObservedDir>( dir_name ); 115 116 observed_dirs_[ dir_name ] = std::weak_ptr<ObservedDir>( dir ); 117 118 return dir; 119 } 120 121 std::shared_ptr<ObservedDir> ObservedFileList::watchedDirectoryForFile( 122 const std::string& file_name ) 123 { 124 return watchedDirectory( directory_path( file_name ) ); 125 } 126 127 std::shared_ptr<ObservedDir> ObservedFileList::addWatchedDirectoryForFile( 128 const std::string& file_name ) 129 { 130 return addWatchedDirectory( directory_path( file_name ) ); 131 } 132 133 namespace { 134 std::string directory_path( const std::string& path ) 135 { 136 size_t slash_pos = path.rfind( '/' ); 137 138 #ifdef _WIN32 139 if ( slash_pos == std::string::npos ) { 140 slash_pos = path.rfind( '\\' ); 141 } 142 143 // We need to include the final slash on Windows 144 ++slash_pos; 145 LOG(logDEBUG) << "Pos = " << slash_pos; 146 #endif 147 148 return std::string( path, 0, slash_pos ); 149 } 150 }; 151