diff options
author | daMaex <damaex@live.de> | 2019-11-05 18:38:30 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2021-12-19 00:01:13 +0100 |
commit | 97d48751b0192533f2d7b325d1b9a5dabf99ae73 (patch) | |
tree | a77047339244bf29a80a86f9f899496d86463893 /dep/efsw/src | |
parent | dbf347bdd02d2fe897274667d7f76c497293229d (diff) |
Dep/efsw: updated efsw to newest version (#23894)
(cherry picked from commit ed2c2941a74ec720c5e4db3cb33367235e6c3655)
Diffstat (limited to 'dep/efsw/src')
26 files changed, 551 insertions, 248 deletions
diff --git a/dep/efsw/src/efsw/DirWatcherGeneric.cpp b/dep/efsw/src/efsw/DirWatcherGeneric.cpp index b80c14d24ce..a5751148863 100644 --- a/dep/efsw/src/efsw/DirWatcherGeneric.cpp +++ b/dep/efsw/src/efsw/DirWatcherGeneric.cpp @@ -58,7 +58,7 @@ DirWatcherGeneric::~DirWatcherGeneric() DirWatchMap::iterator it = Directories.begin(); - for ( ; it != Directories.end(); it++ ) + for ( ; it != Directories.end(); ++it ) { if ( Deleted ) { @@ -218,7 +218,7 @@ void DirWatcherGeneric::watch( bool reportOwnChange ) } /// Process the subdirectories looking for changes - for ( DirWatchMap::iterator dit = Directories.begin(); dit != Directories.end(); dit++ ) + for ( DirWatchMap::iterator dit = Directories.begin(); dit != Directories.end(); ++dit ) { /// Just watch dit->second->watch(); @@ -293,7 +293,7 @@ DirWatcherGeneric * DirWatcherGeneric::findDirWatcher( std::string dir ) { DirWatcherGeneric * watcher = NULL; - for ( DirWatchMap::iterator it = Directories.begin(); it != Directories.end(); it++ ) + for ( DirWatchMap::iterator it = Directories.begin(); it != Directories.end(); ++it ) { watcher = it->second->findDirWatcher( dir ); @@ -437,7 +437,7 @@ bool DirWatcherGeneric::pathInWatches( std::string path ) return true; } - for ( DirWatchMap::iterator it = Directories.begin(); it != Directories.end(); it++ ) + for ( DirWatchMap::iterator it = Directories.begin(); it != Directories.end(); ++it ) { if ( it->second->pathInWatches( path ) ) { diff --git a/dep/efsw/src/efsw/DirectorySnapshot.cpp b/dep/efsw/src/efsw/DirectorySnapshot.cpp index c0ef747548a..e0680483e6b 100644 --- a/dep/efsw/src/efsw/DirectorySnapshot.cpp +++ b/dep/efsw/src/efsw/DirectorySnapshot.cpp @@ -44,6 +44,8 @@ void DirectorySnapshot::deleteAll( DirectorySnapshotDiff& Diff ) Diff.FilesDeleted.push_back( fi ); } } + + Files.clear(); } void DirectorySnapshot::setDirectoryInfo( std::string directory ) diff --git a/dep/efsw/src/efsw/FileInfo.cpp b/dep/efsw/src/efsw/FileInfo.cpp index 7003afc2a15..f5518225b48 100644 --- a/dep/efsw/src/efsw/FileInfo.cpp +++ b/dep/efsw/src/efsw/FileInfo.cpp @@ -180,22 +180,27 @@ bool FileInfo::operator==( const FileInfo& Other ) const ); } -bool FileInfo::isDirectory() +bool FileInfo::isDirectory() const { return 0 != S_ISDIR(Permissions); } -bool FileInfo::isRegularFile() +bool FileInfo::isRegularFile() const { return 0 != S_ISREG(Permissions); } -bool FileInfo::isReadable() +bool FileInfo::isReadable() const { +#if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 + static bool isRoot = getuid() == 0; + return isRoot || 0 != S_ISRDBL(Permissions); +#else return 0 != S_ISRDBL(Permissions); +#endif } -bool FileInfo::isLink() +bool FileInfo::isLink() const { #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32 return S_ISLNK(Permissions); diff --git a/dep/efsw/src/efsw/FileInfo.hpp b/dep/efsw/src/efsw/FileInfo.hpp index 45cca6a7953..c86e5749a70 100644 --- a/dep/efsw/src/efsw/FileInfo.hpp +++ b/dep/efsw/src/efsw/FileInfo.hpp @@ -29,15 +29,15 @@ class FileInfo FileInfo& operator=( const FileInfo& Other ); - bool isDirectory(); + bool isDirectory() const; - bool isRegularFile(); + bool isRegularFile() const; - bool isReadable(); + bool isReadable() const; bool sameInode( const FileInfo& Other ) const; - bool isLink(); + bool isLink() const; std::string linksTo(); diff --git a/dep/efsw/src/efsw/FileSystem.cpp b/dep/efsw/src/efsw/FileSystem.cpp index e3afa0b4046..1bca40558c6 100644 --- a/dep/efsw/src/efsw/FileSystem.cpp +++ b/dep/efsw/src/efsw/FileSystem.cpp @@ -121,4 +121,14 @@ bool FileSystem::isRemoteFS( const std::string& directory ) return Platform::FileSystem::isRemoteFS( directory ); } +bool FileSystem::changeWorkingDirectory( const std::string& directory ) +{ + return Platform::FileSystem::changeWorkingDirectory( directory ); +} + +std::string FileSystem::getCurrentWorkingDirectory() +{ + return Platform::FileSystem::getCurrentWorkingDirectory(); +} + } diff --git a/dep/efsw/src/efsw/FileSystem.hpp b/dep/efsw/src/efsw/FileSystem.hpp index 4e2e1aeb7cd..07c7ade8baa 100644 --- a/dep/efsw/src/efsw/FileSystem.hpp +++ b/dep/efsw/src/efsw/FileSystem.hpp @@ -33,6 +33,10 @@ class FileSystem static std::string precomposeFileName(const std::string& name); static bool isRemoteFS( const std::string& directory ); + + static bool changeWorkingDirectory( const std::string & path ); + + static std::string getCurrentWorkingDirectory(); }; } diff --git a/dep/efsw/src/efsw/FileWatcherCWrapper.cpp b/dep/efsw/src/efsw/FileWatcherCWrapper.cpp index 2739e756bb2..30a36eacc35 100644 --- a/dep/efsw/src/efsw/FileWatcherCWrapper.cpp +++ b/dep/efsw/src/efsw/FileWatcherCWrapper.cpp @@ -12,12 +12,11 @@ public: efsw_pfn_fileaction_callback mFn; void* mParam; public: - Watcher_CAPI(efsw_watcher watcher, efsw_pfn_fileaction_callback fn, void* param) - { - mWatcher = watcher; - mFn = fn; - mParam = param; - } + Watcher_CAPI(efsw_watcher watcher, efsw_pfn_fileaction_callback fn, void* param) : + mWatcher( watcher ), + mFn( fn ), + mParam( param ) + {} void handleFileAction(efsw::WatchID watchid, const std::string& dir, const std::string& filename, efsw::Action action, std::string oldFilename = "") @@ -34,7 +33,7 @@ static std::vector<Watcher_CAPI*> g_callbacks; Watcher_CAPI* find_callback(efsw_watcher watcher, efsw_pfn_fileaction_callback fn) { - for (std::vector<Watcher_CAPI*>::iterator i = g_callbacks.begin(); i != g_callbacks.end(); i++ ) + for (std::vector<Watcher_CAPI*>::iterator i = g_callbacks.begin(); i != g_callbacks.end(); ++i ) { Watcher_CAPI* callback = *i; @@ -55,7 +54,7 @@ Watcher_CAPI* remove_callback(efsw_watcher watcher) if (callback->mWatcher == watcher) i = g_callbacks.erase(i); else - i++; + ++i; } return NULL; diff --git a/dep/efsw/src/efsw/FileWatcherFSEvents.cpp b/dep/efsw/src/efsw/FileWatcherFSEvents.cpp index 40156674132..5aac14282c9 100644 --- a/dep/efsw/src/efsw/FileWatcherFSEvents.cpp +++ b/dep/efsw/src/efsw/FileWatcherFSEvents.cpp @@ -3,6 +3,7 @@ #include <efsw/System.hpp> #include <efsw/Debug.hpp> #include <efsw/String.hpp> +#include <efsw/Lock.hpp> #if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS @@ -14,11 +15,11 @@ namespace efsw int getOSXReleaseNumber() { static int osxR = -1; - + if ( -1 == osxR ) { struct utsname os; - + if ( -1 != uname( &os ) ) { std::string release( os.release ); @@ -83,6 +84,10 @@ FileWatcherFSEvents::FileWatcherFSEvents( FileWatcher * parent ) : FileWatcherFSEvents::~FileWatcherFSEvents() { + mInitOK = false; + + efSAFE_DELETE( mThread ); + WatchMap::iterator iter = mWatches.begin(); for( ; iter != mWatches.end(); ++iter ) @@ -93,15 +98,6 @@ FileWatcherFSEvents::~FileWatcherFSEvents() } mWatches.clear(); - - mInitOK = false; - - if ( NULL != mRunLoopRef ) - { - CFRunLoopStop( mRunLoopRef ); - } - - efSAFE_DELETE( mThread ); } WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive ) @@ -165,16 +161,15 @@ WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchLi pWatch->init(); - mWatchesLock.lock(); + Lock lock( mWatchesLock ); mWatches.insert(std::make_pair(mLastWatchID, pWatch)); - mWatchesLock.unlock(); return pWatch->ID; } void FileWatcherFSEvents::removeWatch(const std::string& directory) { - mWatchesLock.lock(); + Lock lock( mWatchesLock ); WatchMap::iterator iter = mWatches.begin(); @@ -186,13 +181,11 @@ void FileWatcherFSEvents::removeWatch(const std::string& directory) return; } } - - mWatchesLock.unlock(); } void FileWatcherFSEvents::removeWatch(WatchID watchid) { - mWatchesLock.lock(); + Lock lock( mWatchesLock ); WatchMap::iterator iter = mWatches.find( watchid ); @@ -206,8 +199,6 @@ void FileWatcherFSEvents::removeWatch(WatchID watchid) efDEBUG( "Removed watch %s\n", watch->Directory.c_str() ); efSAFE_DELETE( watch ); - - mWatchesLock.unlock(); } void FileWatcherFSEvents::watch() @@ -227,7 +218,7 @@ void FileWatcherFSEvents::run() { if ( !mNeedInit.empty() ) { - for ( std::list<WatcherFSEvents*>::iterator it = mNeedInit.begin(); it != mNeedInit.end(); it++ ) + for ( std::list<WatcherFSEvents*>::iterator it = mNeedInit.begin(); it != mNeedInit.end(); ++it ) { (*it)->initAsync(); } @@ -237,6 +228,9 @@ void FileWatcherFSEvents::run() CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0.5, kCFRunLoopRunTimedOut ); } + + CFRunLoopStop( mRunLoopRef ); + mRunLoopRef = NULL; } void FileWatcherFSEvents::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename) @@ -248,21 +242,19 @@ std::list<std::string> FileWatcherFSEvents::directories() { std::list<std::string> dirs; - mWatchesLock.lock(); + Lock lock( mWatchesLock ); - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { dirs.push_back( std::string( it->second->Directory ) ); } - mWatchesLock.unlock(); - return dirs; } bool FileWatcherFSEvents::pathInWatches( const std::string& path ) { - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { if ( it->second->Directory == path ) { diff --git a/dep/efsw/src/efsw/FileWatcherFSEvents.hpp b/dep/efsw/src/efsw/FileWatcherFSEvents.hpp index 6aafbc0b5ea..9a2c956ed10 100644 --- a/dep/efsw/src/efsw/FileWatcherFSEvents.hpp +++ b/dep/efsw/src/efsw/FileWatcherFSEvents.hpp @@ -33,9 +33,7 @@ enum FSEventEvents efswFSEventStreamEventFlagItemIsSymlink = 0x00040000, efswFSEventsModified = efswFSEventStreamEventFlagItemFinderInfoMod | efswFSEventStreamEventFlagItemModified | - efswFSEventStreamEventFlagItemInodeMetaMod | - efswFSEventStreamEventFlagItemChangeOwner | - efswFSEventStreamEventFlagItemXattrMod + efswFSEventStreamEventFlagItemInodeMetaMod }; /// Implementation for Win32 based on ReadDirectoryChangesW. diff --git a/dep/efsw/src/efsw/FileWatcherGeneric.cpp b/dep/efsw/src/efsw/FileWatcherGeneric.cpp index 1534b6a9279..fd423b1476b 100644 --- a/dep/efsw/src/efsw/FileWatcherGeneric.cpp +++ b/dep/efsw/src/efsw/FileWatcherGeneric.cpp @@ -1,6 +1,7 @@ #include <efsw/FileWatcherGeneric.hpp> #include <efsw/FileSystem.hpp> #include <efsw/System.hpp> +#include <efsw/Lock.hpp> namespace efsw { @@ -18,14 +19,12 @@ FileWatcherGeneric::~FileWatcherGeneric() { mInitOK = false; - mThread->wait(); - efSAFE_DELETE( mThread ); /// Delete the watches WatchList::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); it++ ) + for ( ; it != mWatches.end(); ++it ) { efSAFE_DELETE( (*it) ); } @@ -75,9 +74,8 @@ WatchID FileWatcherGeneric::addWatch(const std::string& directory, FileWatchList WatcherGeneric * pWatch = new WatcherGeneric( mLastWatchID, dir, watcher, this, recursive ); - mWatchesLock.lock(); + Lock lock( mWatchesLock ); mWatches.push_back(pWatch); - mWatchesLock.unlock(); return pWatch->ID; } @@ -86,20 +84,18 @@ void FileWatcherGeneric::removeWatch( const std::string& directory ) { WatchList::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); it++ ) + for ( ; it != mWatches.end(); ++it ) { if ( (*it)->Directory == directory ) { WatcherGeneric * watch = (*it); - mWatchesLock.lock(); + Lock lock( mWatchesLock ); mWatches.erase( it ); efSAFE_DELETE( watch ) ; - mWatchesLock.unlock(); - return; } } @@ -109,20 +105,18 @@ void FileWatcherGeneric::removeWatch(WatchID watchid) { WatchList::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); it++ ) + for ( ; it != mWatches.end(); ++it ) { if ( (*it)->ID == watchid ) { WatcherGeneric * watch = (*it); - mWatchesLock.lock(); + Lock lock( mWatchesLock ); mWatches.erase( it ); efSAFE_DELETE( watch ) ; - mWatchesLock.unlock(); - return; } } @@ -141,22 +135,22 @@ void FileWatcherGeneric::run() { do { - mWatchesLock.lock(); + { + Lock lock( mWatchesLock); - WatchList::iterator it = mWatches.begin(); + WatchList::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); it++ ) - { - (*it)->watch(); + for ( ; it != mWatches.end(); ++it ) + { + ( *it )->watch(); + } } - mWatchesLock.unlock(); - if ( mInitOK ) System::sleep( 1000 ); } while ( mInitOK ); } -void FileWatcherGeneric::handleAction(Watcher * watch, const std::string& filename, unsigned long action, std::string oldFilename) +void FileWatcherGeneric::handleAction(Watcher *, const std::string&, unsigned long, std::string) { /// Not used } @@ -165,17 +159,15 @@ std::list<std::string> FileWatcherGeneric::directories() { std::list<std::string> dirs; - mWatchesLock.lock(); + Lock lock( mWatchesLock ); WatchList::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); it++ ) + for ( ; it != mWatches.end(); ++it ) { dirs.push_back( (*it)->Directory ); } - mWatchesLock.unlock(); - return dirs; } @@ -183,7 +175,7 @@ bool FileWatcherGeneric::pathInWatches( const std::string& path ) { WatchList::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); it++ ) + for ( ; it != mWatches.end(); ++it ) { if ( (*it)->Directory == path || (*it)->pathInWatches( path ) ) { diff --git a/dep/efsw/src/efsw/FileWatcherInotify.cpp b/dep/efsw/src/efsw/FileWatcherInotify.cpp index 19c20761663..71ae3bcd97d 100644 --- a/dep/efsw/src/efsw/FileWatcherInotify.cpp +++ b/dep/efsw/src/efsw/FileWatcherInotify.cpp @@ -18,6 +18,8 @@ #include <efsw/FileSystem.hpp> #include <efsw/System.hpp> #include <efsw/Debug.hpp> +#include <efsw/Lock.hpp> +#include <efsw/String.hpp> #define BUFF_SIZE ((sizeof(struct inotify_event)+FILENAME_MAX)*1024) @@ -145,9 +147,10 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis pWatch->Recursive = recursive; pWatch->Parent = parent; - mWatchesLock.lock(); - mWatches.insert(std::make_pair(wd, pWatch)); - mWatchesLock.unlock(); + { + Lock lock( mWatchesLock ); + mWatches.insert(std::make_pair(wd, pWatch)); + } if ( NULL == pWatch->Parent ) { @@ -159,13 +162,13 @@ WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchLis std::map<std::string, FileInfo> files = FileSystem::filesInfoFromPath( pWatch->Directory ); std::map<std::string, FileInfo>::iterator it = files.begin(); - for ( ; it != files.end(); it++ ) + for ( ; it != files.end(); ++it ) { - FileInfo fi = it->second; + const FileInfo& cfi = it->second; - if ( fi.isDirectory() && fi.isReadable() ) + if ( cfi.isDirectory() && cfi.isReadable() ) { - addWatch( fi.Filepath, watcher, recursive, pWatch ); + addWatch( cfi.Filepath, watcher, recursive, pWatch ); } } } @@ -194,7 +197,7 @@ void FileWatcherInotify::removeWatchLocked(WatchID watchid) } } - for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); eit++ ) + for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); ++eit ) { removeWatch( *eit ); } @@ -228,7 +231,7 @@ void FileWatcherInotify::removeWatchLocked(WatchID watchid) void FileWatcherInotify::removeWatch(const std::string& directory) { - mWatchesLock.lock(); + Lock lock( mWatchesLock ); WatchMap::iterator iter = mWatches.begin(); @@ -251,7 +254,7 @@ void FileWatcherInotify::removeWatch(const std::string& directory) } } - for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); eit++ ) + for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); ++eit ) { removeWatchLocked( *eit ); } @@ -285,26 +288,20 @@ void FileWatcherInotify::removeWatch(const std::string& directory) break; } } - - mWatchesLock.unlock(); } void FileWatcherInotify::removeWatch( WatchID watchid ) { - mWatchesLock.lock(); + Lock lock( mWatchesLock ); WatchMap::iterator iter = mWatches.find( watchid ); if( iter == mWatches.end() ) { - mWatchesLock.unlock(); - return; } removeWatchLocked( watchid ); - - mWatchesLock.unlock(); } void FileWatcherInotify::watch() @@ -316,6 +313,25 @@ void FileWatcherInotify::watch() } } +Watcher * FileWatcherInotify::watcherContainsDirectory( std::string dir ) +{ + FileSystem::dirRemoveSlashAtEnd( dir ); + std::string watcherPath = FileSystem::pathRemoveFileName( dir ); + FileSystem::dirAddSlashAtEnd( watcherPath ); + + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) + { + Watcher * watcher = it->second; + + if ( watcher->Directory == watcherPath ) + { + return watcher; + } + } + + return NULL; +} + void FileWatcherInotify::run() { static char buff[BUFF_SIZE] = {0}; @@ -333,48 +349,79 @@ void FileWatcherInotify::run() if( select (FD_SETSIZE, &rfds, NULL, NULL, &timeout) > 0 ) { - ssize_t len, i = 0; + ssize_t len; len = read (mFD, buff, BUFF_SIZE); if (len != -1) { + ssize_t i = 0; + while (i < len) { struct inotify_event *pevent = (struct inotify_event *)&buff[i]; - mWatchesLock.lock(); - - wit = mWatches.find( pevent->wd ); - - if ( wit != mWatches.end() ) { - handleAction(wit->second, pevent->name, pevent->mask); + Lock lock( mWatchesLock ); + + wit = mWatches.find( pevent->wd ); - /// Keep track of the IN_MOVED_FROM events to known if the IN_MOVED_TO event is also fired - if ( !wit->second->OldFileName.empty() ) + if ( wit != mWatches.end() ) { - movedOutsideWatches.push_back( wit->second ); + handleAction(wit->second, pevent->name, pevent->mask); + + /// Keep track of the IN_MOVED_FROM events to know if the IN_MOVED_TO event is also fired + if ( !wit->second->OldFileName.empty() ) + { + movedOutsideWatches.push_back( wit->second ); + } } } - mWatchesLock.unlock(); - i += sizeof(struct inotify_event) + pevent->len; } if ( !movedOutsideWatches.empty() ) { /// In case that the IN_MOVED_TO is never fired means that the file was moved to other folder - for ( std::list<WatcherInotify*>::iterator it = movedOutsideWatches.begin(); it != movedOutsideWatches.end(); it++ ) + for ( std::list<WatcherInotify*>::iterator it = movedOutsideWatches.begin(); it != movedOutsideWatches.end(); ++it ) { - if ( !(*it)->OldFileName.empty() ) + Watcher * watch = (*it); + + if ( !watch->OldFileName.empty() ) { - /// So we send a IN_DELETE event for files that where moved outside of our scope - handleAction( *it, (*it)->OldFileName, IN_DELETE ); + /// Check if the file move was a folder already being watched + std::list<Watcher*> eraseWatches; + + for(; wit != mWatches.end(); ++wit) + { + Watcher * oldWatch = wit->second; + + if ( oldWatch != watch && + -1 != String::strStartsWith( watch->Directory + watch->OldFileName + "/", oldWatch->Directory ) ) + { + eraseWatches.push_back( oldWatch ); + } + } + + /// Remove invalid watches + eraseWatches.sort(); + + for ( std::list<Watcher*>::reverse_iterator eit = eraseWatches.rbegin(); eit != eraseWatches.rend(); ++eit ) + { + Watcher * rmWatch = *eit; + + /// Create Delete event for removed watches that have been moved too + if ( Watcher * cntWatch = watcherContainsDirectory( rmWatch->Directory ) ) + { + handleAction( cntWatch, FileSystem::fileNameFromPath( rmWatch->Directory ), IN_DELETE ); + } + + removeWatch( rmWatch->ID ); + } /// Remove the OldFileName - (*it)->OldFileName = ""; + watch->OldFileName = ""; } } @@ -395,7 +442,7 @@ void FileWatcherInotify::checkForNewWatcher( Watcher* watch, std::string fpath ) bool found = false; /// First check if exists - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { if ( it->second->Directory == fpath ) { @@ -411,7 +458,7 @@ void FileWatcherInotify::checkForNewWatcher( Watcher* watch, std::string fpath ) } } -void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename ) +void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filename, unsigned long action, std::string ) { if ( !watch || !watch->Listener ) { @@ -447,7 +494,7 @@ void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filena FileSystem::dirAddSlashAtEnd( opath ); FileSystem::dirAddSlashAtEnd( fpath ); - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { if ( it->second->Directory == opath && it->second->DirInfo.Inode == FileInfo( opath ).Inode ) { @@ -480,7 +527,7 @@ void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filena /// If the file erased is a directory and recursive is enabled, removes the directory erased if ( watch->Recursive ) { - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { if ( it->second->Directory == fpath ) { @@ -496,17 +543,15 @@ std::list<std::string> FileWatcherInotify::directories() { std::list<std::string> dirs; - mWatchesLock.lock(); + Lock lock( mWatchesLock ); WatchMap::iterator it = mRealWatches.begin(); - for ( ; it != mRealWatches.end(); it++ ) + for ( ; it != mRealWatches.end(); ++it ) { dirs.push_back( it->second->Directory ); } - mWatchesLock.unlock(); - return dirs; } @@ -515,7 +560,7 @@ bool FileWatcherInotify::pathInWatches( const std::string& path ) /// Search in the real watches, since it must allow adding a watch already watched as a subdir WatchMap::iterator it = mRealWatches.begin(); - for ( ; it != mRealWatches.end(); it++ ) + for ( ; it != mRealWatches.end(); ++it ) { if ( it->second->Directory == path ) { diff --git a/dep/efsw/src/efsw/FileWatcherInotify.hpp b/dep/efsw/src/efsw/FileWatcherInotify.hpp index 43ee9ca6afc..b68314050a1 100644 --- a/dep/efsw/src/efsw/FileWatcherInotify.hpp +++ b/dep/efsw/src/efsw/FileWatcherInotify.hpp @@ -64,6 +64,8 @@ class FileWatcherInotify : public FileWatcherImpl void removeWatchLocked(WatchID watchid); void checkForNewWatcher( Watcher* watch, std::string fpath ); + + Watcher * watcherContainsDirectory( std::string dir ); }; } diff --git a/dep/efsw/src/efsw/FileWatcherKqueue.cpp b/dep/efsw/src/efsw/FileWatcherKqueue.cpp index 600fd085b35..3373a68d0ce 100644 --- a/dep/efsw/src/efsw/FileWatcherKqueue.cpp +++ b/dep/efsw/src/efsw/FileWatcherKqueue.cpp @@ -15,6 +15,7 @@ #include <efsw/System.hpp> #include <efsw/Debug.hpp> #include <efsw/WatcherGeneric.hpp> +#include <efsw/Lock.hpp> namespace efsw { @@ -44,8 +45,6 @@ FileWatcherKqueue::~FileWatcherKqueue() mInitOK = false; - mThread->wait(); - efSAFE_DELETE( mThread ); } @@ -98,9 +97,10 @@ WatchID FileWatcherKqueue::addWatch(const std::string& directory, FileWatchListe WatcherKqueue * watch = new WatcherKqueue( ++mLastWatchID, dir, watcher, recursive, this ); - mWatchesLock.lock(); - mWatches.insert(std::make_pair(mLastWatchID, watch)); - mWatchesLock.unlock(); + { + Lock lock( mWatchesLock ); + mWatches.insert(std::make_pair(mLastWatchID, watch)); + } watch->addAll(); @@ -118,11 +118,10 @@ WatchID FileWatcherKqueue::addWatch(const std::string& directory, FileWatchListe // Probably the folder has too many files, create a generic watcher if ( EACCES != le ) { - WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive ); + WatcherGeneric * genericWatch = new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive ); - mWatchesLock.lock(); - mWatches.insert(std::make_pair(mLastWatchID, watch)); - mWatchesLock.unlock(); + Lock lock( mWatchesLock ); + mWatches.insert(std::make_pair(mLastWatchID, genericWatch)); } else { @@ -142,9 +141,8 @@ WatchID FileWatcherKqueue::addWatch(const std::string& directory, FileWatchListe WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive ); - mWatchesLock.lock(); + Lock lock( mWatchesLock ); mWatches.insert(std::make_pair(mLastWatchID, watch)); - mWatchesLock.unlock(); } return mLastWatchID; @@ -152,7 +150,7 @@ WatchID FileWatcherKqueue::addWatch(const std::string& directory, FileWatchListe void FileWatcherKqueue::removeWatch(const std::string& directory) { - mWatchesLock.lock(); + Lock lock( mWatchesLock ); WatchMap::iterator iter = mWatches.begin(); @@ -164,13 +162,11 @@ void FileWatcherKqueue::removeWatch(const std::string& directory) return; } } - - mWatchesLock.unlock(); } void FileWatcherKqueue::removeWatch(WatchID watchid) { - mWatchesLock.lock(); + Lock lock( mWatchesLock ); WatchMap::iterator iter = mWatches.find(watchid); @@ -182,8 +178,6 @@ void FileWatcherKqueue::removeWatch(WatchID watchid) mWatches.erase(iter); efSAFE_DELETE( watch ); - - mWatchesLock.unlock(); } bool FileWatcherKqueue::isAddingWatcher() const @@ -204,14 +198,14 @@ void FileWatcherKqueue::run() { do { - mWatchesLock.lock(); - - for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { - it->second->watch(); - } + Lock lock( mWatchesLock ); - mWatchesLock.unlock(); + for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) + { + it->second->watch(); + } + } System::sleep( 500 ); } while( mInitOK ); @@ -225,17 +219,15 @@ std::list<std::string> FileWatcherKqueue::directories() { std::list<std::string> dirs; - mWatchesLock.lock(); + Lock lock( mWatchesLock ); WatchMap::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); it++ ) + for ( ; it != mWatches.end(); ++it ) { dirs.push_back( it->second->Directory ); } - mWatchesLock.unlock(); - return dirs; } @@ -243,7 +235,7 @@ bool FileWatcherKqueue::pathInWatches( const std::string& path ) { WatchMap::iterator it = mWatches.begin(); - for ( ; it != mWatches.end(); it++ ) + for ( ; it != mWatches.end(); ++it ) { if ( it->second->Directory == path ) { diff --git a/dep/efsw/src/efsw/FileWatcherWin32.cpp b/dep/efsw/src/efsw/FileWatcherWin32.cpp index fe78dd122cf..317506fb3e3 100644 --- a/dep/efsw/src/efsw/FileWatcherWin32.cpp +++ b/dep/efsw/src/efsw/FileWatcherWin32.cpp @@ -2,6 +2,7 @@ #include <efsw/FileSystem.hpp> #include <efsw/System.hpp> #include <efsw/String.hpp> +#include <efsw/Lock.hpp> #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 @@ -18,23 +19,9 @@ FileWatcherWin32::FileWatcherWin32( FileWatcher * parent ) : FileWatcherWin32::~FileWatcherWin32() { - WatchVector::iterator iter = mWatches.begin(); - - mWatchesLock.lock(); - - for(; iter != mWatches.end(); ++iter) - { - DestroyWatch((*iter)); - } - - mHandles.clear(); - mWatches.clear(); - mInitOK = false; - - mWatchesLock.unlock(); - efSAFE_DELETE( mThread ); + removeAllWatches(); } WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) @@ -54,9 +41,14 @@ WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListen FileSystem::dirAddSlashAtEnd( dir ); - WatchID watchid = ++mLastWatchID; + Lock lock( mWatchesLock ); + + if ( pathInWatches( dir ) ) + { + return Errors::Log::createLastError( Errors::FileRepeated, dir ); + } - mWatchesLock.lock(); + WatchID watchid = ++mLastWatchID; WatcherStructWin32 * watch = CreateWatch( String::fromUtf8( dir ).toWideString().c_str(), recursive, FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_WRITE | @@ -70,11 +62,6 @@ WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListen return Errors::Log::createLastError( Errors::FileNotFound, dir ); } - if ( pathInWatches( dir ) ) - { - return Errors::Log::createLastError( Errors::FileRepeated, dir ); - } - // Add the handle to the handles vector watch->Watch->ID = watchid; watch->Watch->Watch = this; @@ -82,67 +69,81 @@ WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListen watch->Watch->DirName = new char[dir.length()+1]; strcpy(watch->Watch->DirName, dir.c_str()); - mHandles.push_back( watch->Watch->DirHandle ); - mWatches.push_back( watch ); - mWatchesLock.unlock(); + mWatchesNew.insert( watch ); + mWatches.insert( watch ); return watchid; } void FileWatcherWin32::removeWatch(const std::string& directory) { - mWatchesLock.lock(); + Lock lock( mWatchesLock ); - WatchVector::iterator iter = mWatches.begin(); + Watches::iterator iter = mWatches.begin(); for(; iter != mWatches.end(); ++iter) { if(directory == (*iter)->Watch->DirName) { - removeWatch((*iter)->Watch->ID); - return; + removeWatch(*iter); + break; } } - - mWatchesLock.unlock(); } void FileWatcherWin32::removeWatch(WatchID watchid) { - mWatchesLock.lock(); - - WatchVector::iterator iter = mWatches.begin(); + Lock lock( mWatchesLock ); - WatcherStructWin32* watch = NULL; + Watches::iterator iter = mWatches.begin(); for(; iter != mWatches.end(); ++iter) { // Find the watch ID if ( (*iter)->Watch->ID == watchid ) { - watch = (*iter); + removeWatch(*iter); + return; + } + } +} - mWatches.erase( iter ); +void FileWatcherWin32::removeWatch(WatcherStructWin32* watch) +{ + mWatchesRemoved.insert(watch); - // Remove handle from the handle vector - HandleVector::iterator it = mHandles.begin(); + if( NULL == mThread ) + { + removeWatches(); + } +} - for ( ; it != mHandles.end(); it++ ) - { - if ( watch->Watch->DirHandle == (*it) ) - { - mHandles.erase( it ); - break; - } - } +void FileWatcherWin32::removeWatches() +{ + Lock lock( mWatchesLock ); - DestroyWatch(watch); + Watches::iterator remWatchIter = mWatchesRemoved.begin(); - break; + for( ; remWatchIter != mWatchesRemoved.end(); ++remWatchIter ) + { + Watches::iterator iter = mWatches.find(*remWatchIter); + + if( iter != mWatches.end() ) + { + DestroyWatch(*iter); + + mWatches.erase( iter ); + } + + iter = mWatchesNew.find(*remWatchIter); + + if( iter != mWatchesNew.end() ) + { + mWatchesNew.erase( iter ); } } - mWatchesLock.unlock(); + mWatchesRemoved.clear(); } void FileWatcherWin32::watch() @@ -154,45 +155,47 @@ void FileWatcherWin32::watch() } } -void FileWatcherWin32::run() +void FileWatcherWin32::removeAllWatches() { - if ( mHandles.empty() ) + Lock lock( mWatchesLock ); + + Watches::iterator iter = mWatches.begin(); + + for( ; iter != mWatches.end(); ++iter ) { - return; + DestroyWatch((*iter)); } + mWatches.clear(); + mWatchesRemoved.clear(); + mWatchesNew.clear(); +} + +void FileWatcherWin32::run() +{ do { - if ( !mHandles.empty() ) + if ( !mWatches.empty() ) { - mWatchesLock.lock(); - - for ( std::size_t i = 0; i < mWatches.size(); i++ ) { - WatcherStructWin32 * watch = mWatches[ i ]; - - // If the overlapped struct was cancelled ( because the creator thread doesn't exists anymore ), - // we recreate the overlapped in the current thread and refresh the watch - if ( /*STATUS_CANCELED*/0xC0000120 == watch->Overlapped.Internal ) - { - watch->Overlapped = OVERLAPPED(); - RefreshWatch(watch); - } + Lock lock( mWatchesLock ); - // First ensure that the handle is the same, this means that the watch was not removed. - if ( HasOverlappedIoCompleted( &watch->Overlapped ) && mHandles[ i ] == watch->Watch->DirHandle ) + for( Watches::iterator iter = mWatches.begin() ; iter != mWatches.end(); ++iter ) { - DWORD bytes; + WatcherStructWin32 * watch = *iter; - if ( GetOverlappedResult( watch->Watch->DirHandle, &watch->Overlapped, &bytes, FALSE ) ) + if ( HasOverlappedIoCompleted( &watch->Overlapped ) ) { - WatchCallback( ERROR_SUCCESS, bytes, &watch->Overlapped ); + DWORD bytes; + + if ( GetOverlappedResult( watch->Watch->DirHandle, &watch->Overlapped, &bytes, FALSE ) ) + { + WatchCallback( ERROR_SUCCESS, bytes, &watch->Overlapped ); + } } } } - mWatchesLock.unlock(); - if ( mInitOK ) { System::sleep( 10 ); @@ -203,7 +206,18 @@ void FileWatcherWin32::run() // Wait for a new handle to be added System::sleep( 10 ); } + + removeWatches(); + + for ( Watches::iterator it = mWatchesNew.begin(); it != mWatchesNew.end(); ++it ) + { + RefreshWatch(*it); + } + + mWatchesNew.clear(); } while ( mInitOK ); + + removeAllWatches(); } void FileWatcherWin32::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename) @@ -232,7 +246,7 @@ void FileWatcherWin32::handleAction(Watcher* watch, const std::string& filename, FileSystem::dirAddSlashAtEnd( opath ); FileSystem::dirAddSlashAtEnd( fpath ); - for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { if ( (*it)->Watch->Directory == opath ) { @@ -254,28 +268,36 @@ void FileWatcherWin32::handleAction(Watcher* watch, const std::string& filename, break; }; - watch->Listener->handleFileAction(watch->ID, static_cast<WatcherWin32*>( watch )->DirName, filename, fwAction); + std::string folderPath( static_cast<WatcherWin32*>( watch )->DirName ); + std::string realFilename = filename; + std::size_t sepPos = filename.find_last_of("/\\"); + + if ( sepPos != std::string::npos ) + { + folderPath += filename.substr( 0, sepPos ); + realFilename = filename.substr( sepPos + 1 ); + } + + watch->Listener->handleFileAction(watch->ID, folderPath, realFilename, fwAction); } std::list<std::string> FileWatcherWin32::directories() { std::list<std::string> dirs; - mWatchesLock.lock(); + Lock lock( mWatchesLock ); - for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { dirs.push_back( std::string( (*it)->Watch->DirName ) ); } - mWatchesLock.unlock(); - return dirs; } bool FileWatcherWin32::pathInWatches( const std::string& path ) { - for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ ) + for ( Watches::iterator it = mWatches.begin(); it != mWatches.end(); ++it ) { if ( (*it)->Watch->DirName == path ) { diff --git a/dep/efsw/src/efsw/FileWatcherWin32.hpp b/dep/efsw/src/efsw/FileWatcherWin32.hpp index 505cd772b82..983ee1853d0 100644 --- a/dep/efsw/src/efsw/FileWatcherWin32.hpp +++ b/dep/efsw/src/efsw/FileWatcherWin32.hpp @@ -6,7 +6,7 @@ #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 #include <efsw/WatcherWin32.hpp> -#include <vector> +#include <set> #include <map> namespace efsw @@ -18,8 +18,7 @@ class FileWatcherWin32 : public FileWatcherImpl { public: /// type for a map from WatchID to WatcherWin32 pointer - typedef std::vector<WatcherStructWin32*> WatchVector; - typedef std::vector<HANDLE> HandleVector; + typedef std::set<WatcherStructWin32*> Watches; FileWatcherWin32( FileWatcher * parent ); @@ -44,11 +43,9 @@ class FileWatcherWin32 : public FileWatcherImpl /// @return Returns a list of the directories that are being watched std::list<std::string> directories(); protected: - /// Vector of WatcherWin32 pointers - WatchVector mWatches; - - /// Keeps an updated handles vector - HandleVector mHandles; + Watches mWatches; + Watches mWatchesRemoved; + Watches mWatchesNew; /// The last watchid WatchID mLastWatchID; @@ -58,6 +55,14 @@ class FileWatcherWin32 : public FileWatcherImpl Mutex mWatchesLock; bool pathInWatches( const std::string& path ); + + /// Remove all directory watches. + void removeAllWatches(); + + /// Remove needed directory watches. + void removeWatches(); + + void removeWatch(WatcherStructWin32* watch); private: void run(); }; diff --git a/dep/efsw/src/efsw/Lock.hpp b/dep/efsw/src/efsw/Lock.hpp new file mode 100644 index 00000000000..5dbf11e39ce --- /dev/null +++ b/dep/efsw/src/efsw/Lock.hpp @@ -0,0 +1,27 @@ +#ifndef EFSW_LOCK_HPP +#define EFSW_LOCK_HPP + +#include <efsw/Mutex.hpp> + +namespace efsw { + +/** Simple mutex class */ +class Lock { + public: + explicit Lock( Mutex& mutex ) : + mMutex( mutex ) + { + mMutex.lock(); + } + + ~Lock() + { + mMutex.unlock(); + } + private: + Mutex& mMutex; +}; + +} + +#endif diff --git a/dep/efsw/src/efsw/WatcherFSEvents.cpp b/dep/efsw/src/efsw/WatcherFSEvents.cpp index 3a9700c77ec..a13a743b01e 100644 --- a/dep/efsw/src/efsw/WatcherFSEvents.cpp +++ b/dep/efsw/src/efsw/WatcherFSEvents.cpp @@ -27,14 +27,14 @@ WatcherFSEvents::WatcherFSEvents( WatchID id, std::string directory, FileWatchLi WatcherFSEvents::~WatcherFSEvents() { - if ( initializedAsync ) - { - FSEventStreamStop( FSStream ); - FSEventStreamInvalidate( FSStream ); - } - if ( NULL != FSStream ) { + if ( initializedAsync ) + { + FSEventStreamStop( FSStream ); + } + + FSEventStreamInvalidate( FSStream ); FSEventStreamRelease( FSStream ); } diff --git a/dep/efsw/src/efsw/WatcherWin32.cpp b/dep/efsw/src/efsw/WatcherWin32.cpp index 01d7b0fcd99..4d2dc7e064f 100644 --- a/dep/efsw/src/efsw/WatcherWin32.cpp +++ b/dep/efsw/src/efsw/WatcherWin32.cpp @@ -87,15 +87,9 @@ void DestroyWatch(WatcherStructWin32* pWatch) tWatch->StopNow = true; - CancelIo(tWatch->DirHandle); + CancelIoEx(tWatch->DirHandle, &pWatch->Overlapped); RefreshWatch(pWatch); - - if (!HasOverlappedIoCompleted(&pWatch->Overlapped)) - { - SleepEx(5, TRUE); - } - CloseHandle(pWatch->Overlapped.hEvent); CloseHandle(pWatch->Watch->DirHandle); efSAFE_DELETE_ARRAY( pWatch->Watch->DirName ); diff --git a/dep/efsw/src/efsw/base.hpp b/dep/efsw/src/efsw/base.hpp index 26108c76985..b5a9687dc74 100644 --- a/dep/efsw/src/efsw/base.hpp +++ b/dep/efsw/src/efsw/base.hpp @@ -38,7 +38,12 @@ typedef SOPHIST_uint64 Uint64; #if ( defined( _MSCVER ) || defined( _MSC_VER ) ) #define EFSW_COMPILER_MSVC #endif - + + /// Force windows target version above or equal to Windows Server 2008 or Windows Vista + #if _WIN32_WINNT < 0x600 + #undef _WIN32_WINNT + #define _WIN32_WINNT 0x600 + #endif #elif defined( __FreeBSD__ ) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined( __DragonFly__ ) #define EFSW_OS EFSW_OS_BSD #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE diff --git a/dep/efsw/src/efsw/inotify-nosys.h b/dep/efsw/src/efsw/inotify-nosys.h index 75df5d3ced3..be1e627d962 100644 --- a/dep/efsw/src/efsw/inotify-nosys.h +++ b/dep/efsw/src/efsw/inotify-nosys.h @@ -69,6 +69,11 @@ struct inotify_event { # define __NR_inotify_add_watch (__NR_SYSCALL_BASE+317) # define __NR_inotify_rm_watch (__NR_SYSCALL_BASE+318) +#elif defined (__aarch64__) +# define __NR_inotify_init 1043 +# define __NR_inotify_add_watch 27 +# define __NR_inotify_rm_watch 28 + #elif defined (__frv__) # define __NR_inotify_init 291 # define __NR_inotify_add_watch 292 diff --git a/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp index e061b25d56b..5795d567740 100644 --- a/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp +++ b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp @@ -5,6 +5,7 @@ #include <efsw/FileInfo.hpp> #include <efsw/FileSystem.hpp> #include <dirent.h> +#include <unistd.h> #include <cstring> #ifndef _DARWIN_FEATURE_64_BIT_INODE @@ -17,6 +18,7 @@ #include <sys/stat.h> #include <cstdlib> +#include <climits> #if EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_SOLARIS || EFSW_OS == EFSW_OS_ANDROID #include <sys/vfs.h> @@ -49,8 +51,152 @@ #define S_MAGIC_VMHGFS 0xBACBACBC #define S_MAGIC_VXFS 0xA501FCF5 +#if EFSW_OS == EFSW_OS_LINUX +#include <mntent.h> +#include <cstdio> +#endif + namespace efsw { namespace Platform { +#if EFSW_OS == EFSW_OS_LINUX + +#pragma pack(push, 1) +struct ntfs_super_block +{ + char jump[3]; + char oem_id[8]; +}; +#pragma pack(pop) + +bool isNTFS( std::string device ) +{ + FILE * fd = fopen( device.c_str(), "r" ); + + ntfs_super_block ns; + + if ( fd != NULL ) + { + fread( &ns, 1, sizeof(ntfs_super_block), fd ); + fclose( fd ); + + std::string oemId( ns.oem_id ); + + return oemId.compare(0, 4, "NTFS") == 0; + } + + return false; +} + +std::string findMountPoint( std::string file ) +{ + std::string cwd = FileSystem::getCurrentWorkingDirectory(); + struct stat last_stat; + struct stat file_stat; + + stat( file.c_str(), &file_stat ); + + std::string mp; + + if ( efsw::FileSystem::isDirectory( file ) ) { + last_stat = file_stat; + + if ( !FileSystem::changeWorkingDirectory( file ) ) + return ""; + } else { + std::string dir = efsw::FileSystem::pathRemoveFileName( file ); + + if ( !FileSystem::changeWorkingDirectory( dir ) ) + return ""; + + if (stat (".", &last_stat) < 0) + return ""; + } + + while (true) + { + struct stat st; + + if ( stat("..", &st) < 0 ) + goto done; + + if ( st.st_dev != last_stat.st_dev || st.st_ino == last_stat.st_ino ) + break; + + if ( !FileSystem::changeWorkingDirectory("..") ) + { + goto done; + } + + last_stat = st; + } + + /* Finally reached a mount point, see what it's called. */ + mp = FileSystem::getCurrentWorkingDirectory(); + +done: + FileSystem::changeWorkingDirectory( cwd ); + + return mp; +} + +std::string findDevicePath( const std::string& directory ) +{ + struct mntent *ent; + FILE *aFile; + + aFile = setmntent("/proc/mounts", "r"); + + if ( aFile == NULL ) + return ""; + + while ( NULL != ( ent = getmntent( aFile ) ) ) + { + std::string dirName( ent->mnt_dir ); + + if ( dirName == directory ) + { + std::string fsName( ent->mnt_fsname ); + + endmntent(aFile); + + return fsName; + } + } + + endmntent(aFile); + + return ""; +} + +bool isLocalFUSEDirectory( std::string directory ) +{ + efsw::FileSystem::dirRemoveSlashAtEnd( directory ); + + directory = findMountPoint( directory ); + + if ( !directory.empty() ) + { + std::string devicePath = findDevicePath( directory ); + + return ( !devicePath.empty() && isNTFS( devicePath ) ); + } + + return false; +} + +#endif + +bool FileSystem::changeWorkingDirectory( const std::string & path ) +{ + return -1 != chdir( path.c_str() ); +} + +std::string FileSystem::getCurrentWorkingDirectory() { + char dir[PATH_MAX + 1]; + getcwd( dir, PATH_MAX + 1 ); + return std::string( dir ); +} + FileInfoMap FileSystem::filesInfoFromPath( const std::string& path ) { FileInfoMap files; @@ -104,13 +250,18 @@ bool FileSystem::isRemoteFS( const std::string& directory ) switch ( statfsbuf.f_type | 0UL ) { + case S_MAGIC_FUSEBLK: /* 0x65735546 remote */ + { + #if EFSW_OS == EFSW_OS_LINUX + return !isLocalFUSEDirectory( directory ); + #endif + } case S_MAGIC_AFS: /* 0x5346414F remote */ case S_MAGIC_AUFS: /* 0x61756673 remote */ case S_MAGIC_CEPH: /* 0x00C36400 remote */ case S_MAGIC_CIFS: /* 0xFF534D42 remote */ case S_MAGIC_CODA: /* 0x73757245 remote */ case S_MAGIC_FHGFS: /* 0x19830326 remote */ - case S_MAGIC_FUSEBLK: /* 0x65735546 remote */ case S_MAGIC_FUSECTL: /* 0x65735543 remote */ case S_MAGIC_GFS: /* 0x01161970 remote */ case S_MAGIC_GPFS: /* 0x47504653 remote */ diff --git a/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp index 865b3f8dfdf..7353d81cf3f 100644 --- a/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp +++ b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp @@ -18,6 +18,10 @@ class FileSystem static bool isDirectory( const std::string& path ); static bool isRemoteFS( const std::string& directory ); + + static bool changeWorkingDirectory( const std::string & path ); + + static std::string getCurrentWorkingDirectory(); }; }} diff --git a/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp b/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp index 376a474e662..cf27eb7a0f6 100644 --- a/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp +++ b/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp @@ -2,6 +2,7 @@ #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 +#include <climits> #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif @@ -9,10 +10,44 @@ #ifndef EFSW_COMPILER_MSVC #include <dirent.h> +#else +#include <direct.h> #endif namespace efsw { namespace Platform { +bool FileSystem::changeWorkingDirectory( const std::string & path ) +{ + int res; +#ifdef EFSW_COMPILER_MSVC + #ifdef UNICODE + res = _wchdir( String::fromUtf8( path.c_str() ).toWideString().c_str() ); + #else + res = _chdir( String::fromUtf8( path.c_str() ).toAnsiString().c_str() ); + #endif +#else + res = chdir( path.c_str() ); +#endif + return -1 != res; +} + +std::string FileSystem::getCurrentWorkingDirectory() +{ +#ifdef EFSW_COMPILER_MSVC + #if defined( UNICODE ) AND !defined( EFSW_NO_WIDECHAR ) + wchar_t dir[_MAX_PATH]; + return ( 0 != GetCurrentDirectoryW( _MAX_PATH, dir ) ) ? String( dir ).toUtf8() : std::string(); + #else + char dir[_MAX_PATH]; + return ( 0 != GetCurrentDirectory( _MAX_PATH, dir ) ) ? String( dir, std::locale() ).toUtf8() : std::string(); + #endif +#else + char dir[PATH_MAX + 1]; + getcwd( dir, PATH_MAX + 1 ); + return std::string( dir ); +#endif +} + FileInfoMap FileSystem::filesInfoFromPath( const std::string& path ) { FileInfoMap files; diff --git a/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp b/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp index 597edc4a647..8f6c5ad1837 100644 --- a/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp +++ b/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp @@ -19,6 +19,10 @@ class FileSystem static bool isDirectory( const std::string& path ); static bool isRemoteFS( const std::string& directory ); + + static bool changeWorkingDirectory( const std::string & path ); + + static std::string getCurrentWorkingDirectory(); }; }} diff --git a/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp b/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp index 2fa30f30060..48c9456adab 100644 --- a/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp +++ b/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp @@ -18,6 +18,14 @@ ThreadImpl::ThreadImpl( Thread *owner ) } } +ThreadImpl::~ThreadImpl() +{ + if ( mThread ) + { + CloseHandle( mThread ); + } +} + void ThreadImpl::wait() { // Wait for the thread to finish, no timeout diff --git a/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp b/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp index 506c659c675..45e4505897a 100644 --- a/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp +++ b/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp @@ -21,6 +21,8 @@ class ThreadImpl { public: ThreadImpl( Thread * owner ); + + ~ThreadImpl(); void wait(); |