Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Monitoring a directory in Cocoa/Cocoa Touch

I am trying to find a way to monitor the contents of a directory for changes. I have tried two approaches.

  1. Use kqueue to monitor the directory
  2. Use GCD to monitor the directory

The problem I am encountering is that I can't find a way to detect which file has changed. I am attempting to monitor a directory with potentially thousands of files in it and I do not want to call stat on every one of them to find out which ones changed. I also do not want to set up a separate dispatch source for every file in that directory. Is this currently possible?

Note: I have documented my experiments monitoring files with kqueue and GCD

like image 863
DHamrick Avatar asked Oct 11 '11 00:10

DHamrick


1 Answers

My advice is to just bite the bullet and do a directory scan in another thread, even if you're talking about thousands of files. But if you insist, here's the answer:

There's no way to do this without rolling up your sleeves and going kernel-diving.

Your first option is to use the FSEvents framework, which sends out notifications when a file is created, edited or deleted (as well as things to do with attributes). Overview is here, and someone wrote an Objective C wrapper around the API, although I haven't tried it. But the overview doesn't mention the part about events surrounding file changes, just directories (like with kqueue). I ended up using the code from here along with the header file here to compile my own logger which I could use to get events at the individual file level. You'd have to write some code in your app to run the logger in the background and monitor it.

Alternatively, take a look at the "fs_usage" command, which constantly monitors all filesystem activity (and I do mean all). This comes with Darwin already, so you don't have to compile it yourself. You can use kqueue to listen for directory changes, while at the same time monitoring the output from "fs_usage". If you get a notification from kqueue that a directory has changed, you can look at the output from fs_usage, see which files were written to, and check the filenames against the directory that was modified. fs_usage is a firehose, so be prepared to use some options along with Grep to tame it.

To make things more fun, both your FSEvents logger and fs_usage require root access, so you'll have to get authorization from the user before you can use them in your OS X app (check out the Authorization Services Programming Guide for info on how to do it).

If this all sounds horribly complicated, that's because it is. But at least you didn't have to find out the hard way!

like image 136
sgress454 Avatar answered Oct 06 '22 01:10

sgress454