Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cocoa, FSEvents, kFSEventStreamCreateFlagFileEvents flag and "renamed" events

Tags:

cocoa

fsevents

I've been playing with FSEvents in a little application of mine to synchronize the content of my application with what's on the hard drive (basically, it's a little image viewer, and I want its content to update when the content of the HDD changes)

I create my stream using the kFSEventStreamCreateFlagFileEvents flag, but I have a hard time figuring out how those events are generated by the OS (or the kernel, or whatever) And unfortunately, there is no documentation with the events generated with this flag ... It seems they are new to 10.7, and still not documented.

So, my main problem is "rename". When I'm doing a simple rename, 2 kFSEventStreamEventFlagItemRenamed events are sent to my callback. One contains the old file name, the second contains the new file name. Problem occurs when you are renaming a batch of files, those events might not be sequencial. For example, it the following case :

  1. "file1" -> "new_file_1"
  2. "file2" -> "new_file_2"

I might receive the events in this order :

  1. "renamed" / "file1"
  2. "renamed" / "file2"
  3. "renamed" / "new_file_1"
  4. "renamed" / "new_file_2"

And there doesn't seem to be any way of getting the id of the first rename event when you catch the second one ... So what I did is : when receiving a "renamed" event, I do a stat() with the file name. If the stat returns successfully, it means that it's the new file name. If not, it means it's the old one. I still have NO WAY to link both events, but at least I can work around by deleting the old files and adding the new ones.

So, I basically have 2 questions :

The first is: Am I totally blind, and not seeing the obvious way to correctly catch a "renamed" event through fsevents ?

The second i: I sometimes have a strange bug where instead of only 2 renamed events, 3 are sent ! So I get a file added twice ... I'm not sure if this is a bug, or if this comes from the fact I'm completely missusing the fsevent API with the kFSEventStreamCreateFlagFileEvents flag ...

Any help is welcome, I'm completely out of ideas to fix this !

like image 982
Citron Avatar asked Nov 29 '11 16:11

Citron


2 Answers

You need to use the flag kFSEventStreamCreateFlagUseExtendedData (available since OS X 10.13). A stream created with that flag will include the inode of the event file. That way you can detect "rename chains" that happened in a reported event batch.

P.S. macOS may reuse the inode of a deleted file for a newly created one, although if you process the events right away, the risk is negligible.

like image 146
Tomek Sowiński Avatar answered Sep 30 '22 09:09

Tomek Sowiński


Since these events only deal with paths, you'll have to do some extra work to handle renames. One option is to track the inode numbers of the files you're interested in. So when you do that stat call, also note the inode number and see if it matches any files you're tracking.

Be aware, though, that the OS may reuse the inode number of a deleted file, so depending on them as unique identifiers isn't infallible.

like image 32
Uncommon Avatar answered Sep 30 '22 07:09

Uncommon