Ответ 1
Насколько я могу судить, вам придется искать либо kFSEventStreamEventFlagItemRemoved
, либо kFSEventStreamEventFlagItemCreated
, а затем использовать stat()
или аналогичный, чтобы проверить, действительно ли файл был добавлен или удален. Документация FSEvents, похоже, намекает как таковая.
Похоже, что API объединяет биты событий... так что это OR всех изменений, сделанных с момента создания FSEventsListener. Так как это похоже, другой вариант может заключаться в создании нового FSEventListener каждый раз (и использовать параметр таймера слияния).
Я сделал некоторый Googling, но не нашел других примеров этой проблемы или даже кода примера Apple, но я не слишком долго тратил на это.
Я ранее использовал API-интерфейс kqueue: https://gist.github.com/nielsbot/5155671 (Этот супруг является обходной оболочкой obj-c вокруг kqueue)
Я изменил ваш пример кода, чтобы показать все флаги, установленные для каждого FSEvent:
#include <CoreServices/CoreServices.h>
#include <stdio.h>
#include <string.h>
static int __count = 0 ;
void eventCallback(FSEventStreamRef stream, void* callbackInfo, size_t numEvents, void* paths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
char **pathsList = paths;
printf("callback #%u\n", ++__count ) ;
const char * flags[] = {
"MustScanSubDirs",
"UserDropped",
"KernelDropped",
"EventIdsWrapped",
"HistoryDone",
"RootChanged",
"Mount",
"Unmount",
"ItemCreated",
"ItemRemoved",
"ItemInodeMetaMod",
"ItemRenamed",
"ItemModified",
"ItemFinderInfoMod",
"ItemChangeOwner",
"ItemXattrMod",
"ItemIsFile",
"ItemIsDir",
"ItemIsSymlink",
"OwnEvent"
} ;
for(int i = 0; i<numEvents; i++)
{
printf("%u\n", i ) ;
printf("\tpath %s\n", pathsList[i]) ;
printf("\tflags: ") ;
long bit = 1 ;
for( int index=0, count = sizeof( flags ) / sizeof( flags[0]); index < count; ++index )
{
if ( ( eventFlags[i] & bit ) != 0 )
{
printf("%s ", flags[ index ] ) ;
}
bit <<= 1 ;
}
printf("\n") ;
}
FSEventStreamFlushSync( stream ) ;
}
int main(int argc, const char * argv[])
{
CFStringRef path = CFStringCreateWithCString( kCFAllocatorDefault, argv[1], kCFStringEncodingUTF8 ) ;
CFArrayRef paths = CFArrayCreate(NULL, (const void **)&path, 1, &kCFTypeArrayCallBacks );
if ( path ) { CFRelease( path ) ; }
CFRunLoopRef loop = CFRunLoopGetCurrent() ;
FSEventStreamRef stream = FSEventStreamCreate(NULL, (FSEventStreamCallback)eventCallback, NULL, paths, kFSEventStreamEventIdSinceNow, 0, kFSEventStreamCreateFlagFileEvents );
if ( paths ) { CFRelease( paths ) ; }
FSEventStreamScheduleWithRunLoop(stream, loop, kCFRunLoopDefaultMode);
FSEventStreamStart(stream);
CFRunLoopRun() ;
FSEventStreamStop(stream);
FSEventStreamInvalidate(stream);
FSEventStreamRelease(stream);
return 0;
}