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