Introduction

The Unix part of Mac OS X is called Darwin. The large additions to Darwin that Apple has made are known as the core technologies.
Apple has released the source code to Darwin and most of the core technologies.

The ideas in this book can be broken into three basic groups.

Unix APIs

There is a set of standard Unix APIs that every programmer should know how to use.
Even if higher-level abstractions alleviate the need to ever call them directly, understanding these functions and structures
will give you a much deeper knowledge of how your system works. Much of what is said here will also be true for Linux.

Framework APIs

Apple has added a whole set of daemons and frameworks to its version of Unix.
These frameworks are exceedingly powerful and sometimes Apple has been slow to document how they work and how they are to be used.

Tools

The Mac OS X developer tools suite, in addition to the system's built-in utilities, provides a veritable toy store for developers.
This book covers lower-level Unix-heritage tools such as gcc, gdb, the linker, and DTrace, as well as higher-level tools such as Instruments.

kqueue and fsevents

fsevents

Watching Directories

If the user adds a file to ~/blah/, modifies a file in there, and deletes another file, you'll only get one “hey, ~/blah/ changed” notification.
It is up to you to decide what to do in that case. In order to figure out which file changed, you will need to have a
cached copy of the contents of the directories and then compare. 

If you are implementing something like drop boxes, where putting a file in a directory causes some action to happen,
you can just scan the directory for new files.

Events

FSEvents are identified by a 64-bit event ID. These event IDs have no relationship with any particular date and time;
they are just guaranteed monotonically increasing values.

Each disk has as an event database on it, which can be discarded if the disk is modified by an older version of OS X.

FSEvents keeps a history of these directory changes and stores them in a database of sorts at the top of each device in a directory named .fseventsd.

FSEvents checks the permissions of directories before telling you about changes.
This way you won't be able to see another user's directory names if they have sufficiently locked-down permissions.

FSEvents API

The FSEvents notification mechanism is a runloop source, sitting around waiting for stuff to happen.
A C callback function is called when a message from fseventsd shows up.
The FSEventsStreamRef type is what you use to reference a particular event stream.

1. Create the stream:
Use FSEventStreamCreate or FSEventStreamCreateRelativeToDevice
- CFAllocator is the typical Core Foundation allocator.
- callback is a C Function pointer to the callback function to call when events are available.
- context is the typical Core Foundation 5 element context pointer.
- Each function takes a CFArray of CFStrings of paths to watch.  You can use an NSArray of NSStrings because they are toll-free bridged.
FSEventStreamCreateRelativeToDevice takes relative paths to the root of the device, and FSEventStreamCreate takes absolute paths from the top of the file system.
- sinceWhen is an eventID.  Pass kFSEventStreamEventIdSinceNow to start seeing new events, or pass an eventID that you have stored previously.
- The latency parameter is the number of seconds that will pass between new events.
- kFSEventStreamCreateFlagUseCFTypes tells FSEvents that your callback function will be given a CFArray containing CFStrings of the paths have been modified. A C array of UTF-8 C strings is passed otherwise.

The stream objects have retain / release semantics. Use FSEventStreamRetain to increment the reference count and FSEventStreamRelease to decrement it.

2. Hook up to the runloop
You need to schedule your stream with a runloop and runloop mode.

FSEventStreamStart() returns True if it succeeds, False if it fails.  If it fails, you won't be getting any events from fseventsd.

3. The FSEvents callback
Various flags are available in the callback.