From 8d9db3cbe9b3e80d19c373abbec8360e020d68e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Tue, 3 Sep 2024 01:52:22 -0300 Subject: [PATCH] Fixes issue #181. --- project/qtcreator-osx/efsw.creator.user | 48 +++++++++++-------------- src/efsw/FileSystem.hpp | 1 - src/efsw/FileWatcherFSEvents.cpp | 43 ++++++++++++++++++++-- src/efsw/FileWatcherFSEvents.hpp | 2 ++ src/efsw/WatcherFSEvents.cpp | 8 +++-- src/efsw/WatcherFSEvents.hpp | 4 ++- 6 files changed, 72 insertions(+), 34 deletions(-) diff --git a/project/qtcreator-osx/efsw.creator.user b/project/qtcreator-osx/efsw.creator.user index cc08407..c1e8795 100644 --- a/project/qtcreator-osx/efsw.creator.user +++ b/project/qtcreator-osx/efsw.creator.user @@ -1,10 +1,10 @@ - + EnvironmentId - {1e2eacf3-3fa1-45d9-bcd5-871df4d12ee9} + {49267ae2-f136-4b84-8041-cf11a20f6a32} ProjectExplorer.Project.ActiveTarget @@ -37,6 +37,7 @@ true true 1 + 0 false true false @@ -54,6 +55,7 @@ *.md, *.MD, Makefile false true + true @@ -77,6 +79,7 @@ true Builtin.DefaultTidyAndClazy 4 + false @@ -88,9 +91,9 @@ ProjectExplorer.Project.Target.0 Desktop - Desktop - Desktop - {03ce7d1a-f943-45a1-9d10-661febc7fb89} + Desktop (arm-darwin-generic-mach_o-64bit) + Desktop (arm-darwin-generic-mach_o-64bit) + {6d6b6d62-1e99-4e76-b5e2-cf731a0dbd92} 0 0 0 @@ -99,13 +102,12 @@ true - --file=../../premake4.lua --thread-sanitizer gmake + --file=../../premake4.lua --thread-sanitizer --verbose gmake /usr/local/bin/premake4 %{buildDir} ProjectExplorer.ProcessStep - -j4 true GenericProjectManager.GenericMakeStep @@ -147,7 +149,6 @@ ProjectExplorer.ProcessStep - -j4 config=release true GenericProjectManager.GenericMakeStep @@ -194,49 +195,42 @@ 1 - dwarf - - cpu-cycles - - -F true - 0 + 0 true true 2 - efsw-test-debug + false + /Users/prognoz/programming/efsw/bin/efsw-test-debug debug ProjectExplorer.CustomExecutableRunConfiguration - true + true + 0 false - false - true + 1 + false false - %{buildDir}/../../bin/ + %{buildDir}/../../bin - dwarf - - cpu-cycles - - -F true - 0 + 0 true true 2 + false efsw-test release ProjectExplorer.CustomExecutableRunConfiguration - true + false + 1 false - false true false %{buildDir}/../../bin/ diff --git a/src/efsw/FileSystem.hpp b/src/efsw/FileSystem.hpp index 6c24386..d8e11a0 100644 --- a/src/efsw/FileSystem.hpp +++ b/src/efsw/FileSystem.hpp @@ -3,7 +3,6 @@ #include #include -#include namespace efsw { diff --git a/src/efsw/FileWatcherFSEvents.cpp b/src/efsw/FileWatcherFSEvents.cpp index 0fa7452..523d0ed 100644 --- a/src/efsw/FileWatcherFSEvents.cpp +++ b/src/efsw/FileWatcherFSEvents.cpp @@ -41,6 +41,32 @@ bool FileWatcherFSEvents::isGranular() { return getOSXReleaseNumber() >= 11; } +static std::string convertCFStringToStdString( CFStringRef cfString ) { + // Try to get the C string pointer directly + const char* cStr = CFStringGetCStringPtr( cfString, kCFStringEncodingUTF8 ); + + if ( cStr ) { + // If the pointer is valid, directly return a std::string from it + return std::string( cStr ); + } else { + // If not, manually convert it + CFIndex length = CFStringGetLength( cfString ); + CFIndex maxSize = CFStringGetMaximumSizeForEncoding( length, kCFStringEncodingUTF8 ) + + 1; // +1 for null terminator + + char* buffer = new char[maxSize]; + + if ( CFStringGetCString( cfString, buffer, maxSize, kCFStringEncodingUTF8 ) ) { + std::string result( buffer ); + delete[] buffer; + return result; + } else { + delete[] buffer; + return ""; + } + } +} + void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef streamRef, void* userData, size_t numEvents, void* eventPaths, const FSEventStreamEventFlags eventFlags[], @@ -51,8 +77,21 @@ void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef streamRef, void events.reserve( numEvents ); for ( size_t i = 0; i < numEvents; i++ ) { - events.push_back( FSEvent( std::string( ( (char**)eventPaths )[i] ), (long)eventFlags[i], - (Uint64)eventIds[i] ) ); + if ( isGranular() ) { + CFDictionaryRef pathInfoDict = + static_cast( CFArrayGetValueAtIndex( (CFArrayRef)eventPaths, i ) ); + CFStringRef path = static_cast( + CFDictionaryGetValue( pathInfoDict, kFSEventStreamEventExtendedDataPathKey ) ); + CFNumberRef cfInode = static_cast( + CFDictionaryGetValue( pathInfoDict, kFSEventStreamEventExtendedFileIDKey ) ); + unsigned long inode = 0; + CFNumberGetValue( cfInode, kCFNumberLongType, &inode ); + events.push_back( FSEvent( convertCFStringToStdString( path ), (long)eventFlags[i], + (Uint64)eventIds[i], inode ) ); + } else { + events.push_back( FSEvent( std::string( ( (char**)eventPaths )[i] ), + (long)eventFlags[i], (Uint64)eventIds[i] ) ); + } } watcher->handleActions( events ); diff --git a/src/efsw/FileWatcherFSEvents.hpp b/src/efsw/FileWatcherFSEvents.hpp index 5ad182e..2a192a5 100644 --- a/src/efsw/FileWatcherFSEvents.hpp +++ b/src/efsw/FileWatcherFSEvents.hpp @@ -19,8 +19,10 @@ namespace efsw { /* OSX < 10.7 has no file events */ /* So i declare the events constants */ enum FSEventEvents { + efswFSEventStreamCreateFlagUseCFTypes = 0x00000001, efswFSEventStreamCreateFlagNoDefer = 0x00000002, efswFSEventStreamCreateFlagFileEvents = 0x00000010, + efswFSEventStreamCreateFlagUseExtendedData = 0x00000040, efswFSEventStreamEventFlagItemCreated = 0x00000100, efswFSEventStreamEventFlagItemRemoved = 0x00000200, efswFSEventStreamEventFlagItemInodeMetaMod = 0x00000400, diff --git a/src/efsw/WatcherFSEvents.cpp b/src/efsw/WatcherFSEvents.cpp index 3621df7..e3fcf2d 100644 --- a/src/efsw/WatcherFSEvents.cpp +++ b/src/efsw/WatcherFSEvents.cpp @@ -35,7 +35,9 @@ void WatcherFSEvents::init() { Uint32 streamFlags = kFSEventStreamCreateFlagNone; if ( FileWatcherFSEvents::isGranular() ) { - streamFlags = efswFSEventStreamCreateFlagFileEvents | efswFSEventStreamCreateFlagNoDefer; + streamFlags = efswFSEventStreamCreateFlagFileEvents | efswFSEventStreamCreateFlagNoDefer | + efswFSEventStreamCreateFlagUseExtendedData | + efswFSEventStreamCreateFlagUseCFTypes; } else { WatcherGen = new WatcherGeneric( ID, Directory, Listener, FWatcher.load(), Recursive ); } @@ -128,12 +130,12 @@ void WatcherFSEvents::handleActions( std::vector& events ) { // been added modified and erased, but i can't know if first was erased and then added // and modified, or added, then modified and then erased. I don't know what they were // thinking by doing this... - efDEBUG( "Event in: %s - flags: %ld\n", event.Path.c_str(), event.Flags ); + efDEBUG( "Event in: %s - flags: 0x%x\n", event.Path.c_str(), event.Flags ); if ( event.Flags & efswFSEventStreamEventFlagItemRenamed ) { if ( ( i + 1 < esize ) && ( events[i + 1].Flags & efswFSEventStreamEventFlagItemRenamed ) && - ( events[i + 1].Id == event.Id + 1 ) ) { + ( events[i + 1].inode == event.inode ) ) { FSEvent& nEvent = events[i + 1]; std::string newDir( FileSystem::pathRemoveFileName( nEvent.Path ) ); std::string newFilepath( FileSystem::fileNameFromPath( nEvent.Path ) ); diff --git a/src/efsw/WatcherFSEvents.hpp b/src/efsw/WatcherFSEvents.hpp index a18c06d..1c6047c 100644 --- a/src/efsw/WatcherFSEvents.hpp +++ b/src/efsw/WatcherFSEvents.hpp @@ -18,11 +18,13 @@ class FileWatcherFSEvents; class FSEvent { public: - FSEvent( std::string path, long flags, Uint64 id ) : Path( path ), Flags( flags ), Id( id ) {} + FSEvent( std::string path, long flags, Uint64 id, Uint64 inode = 0 ) : + Path( path ), Flags( flags ), Id( id ), inode( inode ) {} std::string Path; long Flags; Uint64 Id; + Uint64 inode{ 0 }; }; class WatcherFSEvents : public Watcher {