How to listen for file system changes MAC - kFSEventStreamCreateFlagWatchRoot

cocoa, fsevents

Solution

I had the same problem and I think I figured it out. Apparently `kFSEventStreamCreateFlagWatchRoot` is just simply busted when using `FSEventStreamCreateRelativeToDevice`. You have to use `FSEventStreamCreate`. Since the former form is preferable if you're relying on historical event ids, you might need to create 2 streams. Also, note that it appears that you don't get `kEventFlagChangedRoot` sent to you if your app isn't running, so you'll need to stat the directory when you start up.

Problem

I am listening for Directory and disk changes in a Cocoa project using `FSEvents`. I need to get events when a root folder is renamed or deleted. So, I passed `kFSEventStreamCreateFlagWatchRoot` while creating the `FSEventStream`. But even if I delete or rename the root folder I am not getting corresponding `FSEventStreamEventFlags`. Any idea what could possibly be the issue. I am listening for changes in a USB mounted device. I used both `FSEventStreamCreate` and `FSEventStreamCreateRelativeToDevice`. One thing I notices is when I try with `FSEventStreamCreate` I get the following error message while creating `FSEventStream`: (`CarbonCore.framework`) `FSEventStreamCreate`: `watch_all_parents`: error trying to add kqueue for `fd 7` (`/Volumes/NO NAME`; Operation not supported) But with `FSEventStreamCreateRelativeToDevice` there are no errors but still not getting `kFSEventStreamEventFlagRootChanged` in event flags. Also, while creation using `FSEventStreamCreateRelativeToDevice` apple say's if I want to listen to root path changes pass emty string `""`. But I am not able to listen to root path changes by passing empty string. But when I pass `"/"` it works. But even for `"/"` I do not get any proper `FSEventStreamEventFlags`. I am pasting the code here: ``` -(void) subscribeFileSystemChanges:(NSString*) path { PRINT_FUNCTION_BEGIN; // if already subscribed then unsubscribe if (stream) { FSEventStreamStop(stream); FSEventStreamInvalidate(stream); /* will remove from runloop */ FSEventStreamRelease(stream); } FSEventStreamContext cntxt = {0}; cntxt.info = self; CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void**)&path, 1, NULL); stream = FSEventStreamCreate(NULL, &feCallback, &cntxt, pathsToWatch, kFSEventStreamEventIdSinceNow, 1, kFSEventStreamCreateFlagWatchRoot ); FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); FSEventStreamStart(stream); } ``` Call back function: ``` static void feCallback(ConstFSEventStreamRef streamRef, void* pClientCallBackInfo, size_t numEvents, void* pEventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) { char** ppPaths = (char**)pEventPaths; int i; for (i = 0; i < numEvents; i++) { NSLog(@"Event Flags %lu Event Id %llu", eventFlags[i], eventIds[i]); NSLog(@"Path changed: %@", [NSString stringWithUTF8String:ppPaths[i]]); } } ``` Thanks a lot in advance.

Original source