Moved creation of the hash context inside the job block, since there's no reason to serialise its creation.
LOG_ERROR now flushes stdout first, to ensure consistent ordering of output.
Added in the isSolidState() function, from "porneL"'s itunesfixer (https://code.google.com/p/itunesfixer/source/browse/trunk/).
Made ARC-compliant.
Better logging.
Failed attempt to look up I/O registry entries based on UUID.  Whatever NSURLVolumeUUIDStringKey corresponds to has nothing to do with anything in the I/O registry. :(

diskutil uses NSURLVolumeUUIDStringKey UUIDs, but there's no way I'm aware of to actually work with them programmatically, and I dislike the idea of having to fork/exec diskutil and parse its output.
Switched from [non-functional] UUID identification to plain old stat+dev_t.  Now it works!
Updated copyright info.
Prettied up the formatting.
isSolidState() now returns the SSDness in an out parameter, so that its formal return result can be used to signal whether the check was actually successful or not.
Fixed the error logging.
Broke the logging out into its own file so that SSD.m can utilise it.
Made the spindle & SSD concurrency limits into [hidden] flags, and now use one or the other depending on the media each file is sourced from.
Set watermarks on dispatch_io_ts that are no higher that what we're actually going to read (not that I'm sure this makes any practical difference, but it might, and it's more sensible in any case).
Changed the hashing slightly.  It now *always* uses the size of the file as the base "hash", or "hash prefix".  It then *optionally* computes an actual hash up to hashInputSizeLimit, as always, and appends that to the file size bytes.  But if hashInputSizeLimit is zero, it'll now skip that, thus using the size only.

I don't expect this will be used for often, but it could be worthwhile in memory-constrained (i.e. dysfunctional disk cache) scenarios involving lots of small files (where the cost of reading every file twice may outweigh the cost of resolving large numbers of hash collisions).
Don't ask the file enumerator to pre-load the volume UUID for each file, since we're not using that anymore.
Do fewer fflush(stdout)s.  The main thread has nothing better to do while waiting for all the work to finish, so it can issue an fflush(stdout) every third of a second while it's waiting.

This doesn't really have a measurable performance impact; I just don't like all the extra work being done pointlessly.
Whoops, missed a spot.
Change the default hashInputSizeLimit to 512, instead of 1 MiB.  This is basically the smallest possible I/O anyway, and seems more than sufficient - in combination with file length - to uniquely distinguish most JPEGs and NEFs.

In my tests with ~60k image files (averaging ~3 MiB each) on an SSD, it's nearly twice as fast - ~40s instead of ~ 75s.
	- FWIW setting hashInputSizeLimit=0, to just use file size, takes less than two seconds.
	- Conversely, setting hashInputSizeLimit=SIZE_MAX, to force it to hash the entire file, takes over seven minutes (i.e. completely read bandwidth constrained).
Display an ASCII progress bar instead of an indeterminate-length stream of pyramids.

This includes a rudimentary time remaining estimation, which readily and regularly falls afoul of disk caching - i.e. the first few files are in the disk cache and compare very quickly, thus skewing the timings and making it produce Microsoft-time estimates for pretty much the rest of the operation.  A better implementation might be to use a moving window, which won't be able to anticipate changes in basic I/O speed like that, but will at least fairly quickly settle down to accurate estimates once the disk cached portion are compared.