An Objective-C wrapper for Mac OS X’s FSEvents C API.
Revisión | 9b37a8e5eaddd4d4ee8078b5e368d20ab95dad6f (tree) |
---|---|
Tiempo | 2011-08-31 02:26:58 |
Autor | Aron Cedercrantz <aron@cede...> |
Commiter | Aron Cedercrantz |
Merge pull request #2 from ttilley/ttilley
compatibility shim, file level events in lion, runtime version detection
@@ -38,7 +38,6 @@ | ||
38 | 38 | #import <Foundation/Foundation.h> |
39 | 39 | #import <CoreServices/CoreServices.h> |
40 | 40 | |
41 | - | |
42 | 41 | #pragma mark - |
43 | 42 | #pragma mark CDEvent types |
44 | 43 | /** |
@@ -122,6 +121,14 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
122 | 121 | */ |
123 | 122 | @property (readonly) CDEventFlags flags; |
124 | 123 | |
124 | +#pragma mark flag macros | |
125 | + | |
126 | +#define FLAG_CHECK(flags, flag) ((flags) & (flag)) | |
127 | + | |
128 | +#define FLAG_PROPERTY(name, flag) \ | |
129 | +- (BOOL)name \ | |
130 | +{ return (FLAG_CHECK(_flags, flag) ? YES : NO); } | |
131 | + | |
125 | 132 | #pragma mark Specific flag properties |
126 | 133 | /** |
127 | 134 | * Wheter there was some change in the directory at the specific path supplied in this event. |
@@ -354,6 +361,24 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
354 | 361 | @property (readonly) BOOL didVolumeUnmount; |
355 | 362 | |
356 | 363 | |
364 | +/** | |
365 | + * The entirety of the documentation on file level events in lion is 3 sentences | |
366 | + * long. Rename behavior is odd, making the combination of events and flags | |
367 | + * somewhat confusing for atomic writes. It also appears possible to get a | |
368 | + * singular event where a file has been created, modified, and removed. | |
369 | + */ | |
370 | +@property (readonly) BOOL isCreated; | |
371 | +@property (readonly) BOOL isRemoved; | |
372 | +@property (readonly) BOOL isInodeMetadataModified; | |
373 | +@property (readonly) BOOL isRenamed; | |
374 | +@property (readonly) BOOL isModified; | |
375 | +@property (readonly) BOOL isFinderInfoModified; | |
376 | +@property (readonly) BOOL didChangeOwner; | |
377 | +@property (readonly) BOOL isXattrModified; | |
378 | +@property (readonly) BOOL isFile; | |
379 | +@property (readonly) BOOL isDir; | |
380 | +@property (readonly) BOOL isSymlink; | |
381 | + | |
357 | 382 | #pragma mark Class object creators |
358 | 383 | /** @name Creating CDEvent Objects */ |
359 | 384 | /** |
@@ -27,7 +27,7 @@ | ||
27 | 27 | */ |
28 | 28 | |
29 | 29 | #import "CDEvent.h" |
30 | - | |
30 | +#import "compat.h" | |
31 | 31 | |
32 | 32 | @implementation CDEvent |
33 | 33 |
@@ -104,52 +104,33 @@ | ||
104 | 104 | return [self retain]; |
105 | 105 | } |
106 | 106 | |
107 | - | |
108 | 107 | #pragma mark Specific flag properties |
109 | 108 | - (BOOL)isGenericChange |
110 | 109 | { |
111 | 110 | return (kFSEventStreamEventFlagNone == _flags); |
112 | 111 | } |
113 | 112 | |
114 | -- (BOOL)mustRescanSubDirectories | |
115 | -{ | |
116 | - return (_flags & kFSEventStreamEventFlagMustScanSubDirs); | |
117 | -} | |
118 | - | |
119 | -- (BOOL)isUserDropped | |
120 | -{ | |
121 | - return (_flags & kFSEventStreamEventFlagUserDropped); | |
122 | -} | |
123 | - | |
124 | -- (BOOL)isKernelDropped | |
125 | -{ | |
126 | - return (_flags & kFSEventStreamEventFlagKernelDropped); | |
127 | -} | |
128 | - | |
129 | -- (BOOL)isEventIdentifiersWrapped | |
130 | -{ | |
131 | - return (_flags & kFSEventStreamEventFlagEventIdsWrapped); | |
132 | -} | |
133 | - | |
134 | -- (BOOL)isHistoryDone | |
135 | -{ | |
136 | - return (_flags & kFSEventStreamEventFlagHistoryDone); | |
137 | -} | |
138 | - | |
139 | -- (BOOL)isRootChanged | |
140 | -{ | |
141 | - return (_flags & kFSEventStreamEventFlagRootChanged); | |
142 | -} | |
143 | - | |
144 | -- (BOOL)didVolumeMount | |
145 | -{ | |
146 | - return (_flags & kFSEventStreamEventFlagMount); | |
147 | -} | |
148 | - | |
149 | -- (BOOL)didVolumeUnmount | |
150 | -{ | |
151 | - return (_flags & kFSEventStreamEventFlagUnmount); | |
152 | -} | |
113 | +FLAG_PROPERTY(mustRescanSubDirectories, kFSEventStreamEventFlagMustScanSubDirs) | |
114 | +FLAG_PROPERTY(isUserDropped, kFSEventStreamEventFlagUserDropped) | |
115 | +FLAG_PROPERTY(isKernelDropped, kFSEventStreamEventFlagKernelDropped) | |
116 | +FLAG_PROPERTY(isEventIdentifiersWrapped, kFSEventStreamEventFlagEventIdsWrapped) | |
117 | +FLAG_PROPERTY(isHistoryDone, kFSEventStreamEventFlagHistoryDone) | |
118 | +FLAG_PROPERTY(isRootChanged, kFSEventStreamEventFlagRootChanged) | |
119 | +FLAG_PROPERTY(didVolumeMount, kFSEventStreamEventFlagMount) | |
120 | +FLAG_PROPERTY(didVolumeUnmount, kFSEventStreamEventFlagUnmount) | |
121 | + | |
122 | +// file-level events introduced in 10.7 | |
123 | +FLAG_PROPERTY(isCreated, kFSEventStreamEventFlagItemCreated) | |
124 | +FLAG_PROPERTY(isRemoved, kFSEventStreamEventFlagItemRemoved) | |
125 | +FLAG_PROPERTY(isInodeMetadataModified, kFSEventStreamEventFlagItemInodeMetaMod) | |
126 | +FLAG_PROPERTY(isRenamed, kFSEventStreamEventFlagItemRenamed) | |
127 | +FLAG_PROPERTY(isModified, kFSEventStreamEventFlagItemModified) | |
128 | +FLAG_PROPERTY(isFinderInfoModified, kFSEventStreamEventFlagItemFinderInfoMod) | |
129 | +FLAG_PROPERTY(didChangeOwner, kFSEventStreamEventFlagItemChangeOwner) | |
130 | +FLAG_PROPERTY(isXattrModified, kFSEventStreamEventFlagItemXattrMod) | |
131 | +FLAG_PROPERTY(isFile, kFSEventStreamEventFlagItemIsFile) | |
132 | +FLAG_PROPERTY(isDir, kFSEventStreamEventFlagItemIsDir) | |
133 | +FLAG_PROPERTY(isSymlink, kFSEventStreamEventFlagItemIsSymlink) | |
153 | 134 | |
154 | 135 | #pragma mark Misc |
155 | 136 | - (NSString *)description |
@@ -3,10 +3,11 @@ | ||
3 | 3 | archiveVersion = 1; |
4 | 4 | classes = { |
5 | 5 | }; |
6 | - objectVersion = 45; | |
6 | + objectVersion = 46; | |
7 | 7 | objects = { |
8 | 8 | |
9 | 9 | /* Begin PBXBuildFile section */ |
10 | + 6A05775A1400F49900BF73C4 /* compat.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A0577591400F49900BF73C4 /* compat.h */; }; | |
10 | 11 | 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; }; |
11 | 12 | 9C6D03031166AFFA00343E46 /* CDEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6D03011166AFFA00343E46 /* CDEvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; |
12 | 13 | 9C6D03041166AFFA00343E46 /* CDEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C6D03021166AFFA00343E46 /* CDEvent.m */; }; |
@@ -50,6 +51,7 @@ | ||
50 | 51 | 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; }; |
51 | 52 | 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; |
52 | 53 | 32DBCF5E0370ADEE00C91783 /* CDEvents_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDEvents_Prefix.pch; sourceTree = "<group>"; }; |
54 | + 6A0577591400F49900BF73C4 /* compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compat.h; sourceTree = "<group>"; }; | |
53 | 55 | 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; |
54 | 56 | 8DC2EF5B0486A6940098B216 /* CDEvents.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CDEvents.framework; sourceTree = BUILT_PRODUCTS_DIR; }; |
55 | 57 | 9C6D03011166AFFA00343E46 /* CDEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDEvent.h; sourceTree = "<group>"; }; |
@@ -163,6 +165,7 @@ | ||
163 | 165 | 32C88DFF0371C24200C91783 /* Other Sources */ = { |
164 | 166 | isa = PBXGroup; |
165 | 167 | children = ( |
168 | + 6A0577591400F49900BF73C4 /* compat.h */, | |
166 | 169 | 32DBCF5E0370ADEE00C91783 /* CDEvents_Prefix.pch */, |
167 | 170 | ); |
168 | 171 | name = "Other Sources"; |
@@ -188,6 +191,7 @@ | ||
188 | 191 | 9C6D03031166AFFA00343E46 /* CDEvent.h in Headers */, |
189 | 192 | 9C6D051D1166BD5800343E46 /* CDEventsDelegate.h in Headers */, |
190 | 193 | 9C6D05241166BF5300343E46 /* CDEvents.h in Headers */, |
194 | + 6A05775A1400F49900BF73C4 /* compat.h in Headers */, | |
191 | 195 | ); |
192 | 196 | runOnlyForDeploymentPostprocessing = 0; |
193 | 197 | }; |
@@ -237,8 +241,11 @@ | ||
237 | 241 | /* Begin PBXProject section */ |
238 | 242 | 0867D690FE84028FC02AAC07 /* Project object */ = { |
239 | 243 | isa = PBXProject; |
244 | + attributes = { | |
245 | + LastUpgradeCheck = 0420; | |
246 | + }; | |
240 | 247 | buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "CDEvents" */; |
241 | - compatibilityVersion = "Xcode 3.1"; | |
248 | + compatibilityVersion = "Xcode 3.2"; | |
242 | 249 | developmentRegion = English; |
243 | 250 | hasScannedForEncodings = 1; |
244 | 251 | knownRegions = ( |
@@ -326,7 +333,6 @@ | ||
326 | 333 | DYLIB_CURRENT_VERSION = 1; |
327 | 334 | FRAMEWORK_VERSION = A; |
328 | 335 | GCC_DYNAMIC_NO_PIC = NO; |
329 | - GCC_ENABLE_FIX_AND_CONTINUE = YES; | |
330 | 336 | GCC_ENABLE_OBJC_GC = supported; |
331 | 337 | GCC_MODEL_TUNING = G5; |
332 | 338 | GCC_OPTIMIZATION_LEVEL = 0; |
@@ -374,7 +380,6 @@ | ||
374 | 380 | GCC_WARN_UNUSED_VARIABLE = YES; |
375 | 381 | MACOSX_DEPLOYMENT_TARGET = 10.5; |
376 | 382 | ONLY_ACTIVE_ARCH = YES; |
377 | - PREBINDING = NO; | |
378 | 383 | RUN_CLANG_STATIC_ANALYZER = YES; |
379 | 384 | SDKROOT = macosx; |
380 | 385 | }; |
@@ -392,7 +397,6 @@ | ||
392 | 397 | GCC_WARN_ABOUT_RETURN_TYPE = YES; |
393 | 398 | GCC_WARN_UNUSED_VARIABLE = YES; |
394 | 399 | MACOSX_DEPLOYMENT_TARGET = 10.5; |
395 | - PREBINDING = NO; | |
396 | 400 | RUN_CLANG_STATIC_ANALYZER = YES; |
397 | 401 | SDKROOT = macosx; |
398 | 402 | }; |
@@ -404,7 +408,6 @@ | ||
404 | 408 | ALWAYS_SEARCH_USER_PATHS = NO; |
405 | 409 | COPY_PHASE_STRIP = NO; |
406 | 410 | GCC_DYNAMIC_NO_PIC = NO; |
407 | - GCC_ENABLE_FIX_AND_CONTINUE = YES; | |
408 | 411 | GCC_ENABLE_OBJC_GC = unsupported; |
409 | 412 | GCC_MODEL_TUNING = G5; |
410 | 413 | GCC_OPTIMIZATION_LEVEL = 0; |
@@ -420,7 +423,6 @@ | ||
420 | 423 | "-framework", |
421 | 424 | AppKit, |
422 | 425 | ); |
423 | - PREBINDING = NO; | |
424 | 426 | PRODUCT_NAME = CDEventsTestApp; |
425 | 427 | }; |
426 | 428 | name = Debug; |
@@ -431,7 +433,6 @@ | ||
431 | 433 | ALWAYS_SEARCH_USER_PATHS = NO; |
432 | 434 | COPY_PHASE_STRIP = YES; |
433 | 435 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; |
434 | - GCC_ENABLE_FIX_AND_CONTINUE = NO; | |
435 | 436 | GCC_ENABLE_OBJC_GC = unsupported; |
436 | 437 | GCC_MODEL_TUNING = G5; |
437 | 438 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
@@ -446,7 +447,6 @@ | ||
446 | 447 | "-framework", |
447 | 448 | AppKit, |
448 | 449 | ); |
449 | - PREBINDING = NO; | |
450 | 450 | PRODUCT_NAME = CDEventsTestApp; |
451 | 451 | ZERO_LINK = NO; |
452 | 452 | }; |
@@ -31,6 +31,23 @@ | ||
31 | 31 | #import <CDEvents/CDEvents.h> |
32 | 32 | |
33 | 33 | |
34 | +bool systemVersionIsAtLeast(SInt32 major, SInt32 minor) | |
35 | +{ | |
36 | + static SInt32 versionMajor = 0, versionMinor = 0; | |
37 | + | |
38 | + if (versionMajor == 0) { | |
39 | + Gestalt(gestaltSystemVersionMajor, &versionMajor); | |
40 | + } | |
41 | + | |
42 | + if (versionMinor == 0) { | |
43 | + Gestalt(gestaltSystemVersionMinor, &versionMinor); | |
44 | + } | |
45 | + | |
46 | + return ((versionMajor > major) || | |
47 | + ((versionMajor == major) && (versionMinor >= minor))); | |
48 | +} | |
49 | + | |
50 | + | |
34 | 51 | @implementation CDEventsTestAppController |
35 | 52 | |
36 | 53 | - (void)run |
@@ -42,6 +59,16 @@ | ||
42 | 59 | [NSURL URLWithString:[[NSHomeDirectory() stringByAppendingPathComponent:@"Downloads"] |
43 | 60 | stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]; |
44 | 61 | |
62 | + CDEventsEventStreamCreationFlags creationFlags = kCDEventsDefaultEventStreamFlags; | |
63 | + | |
64 | + if (systemVersionIsAtLeast(10,6)) { | |
65 | + creationFlags |= kFSEventStreamCreateFlagIgnoreSelf; | |
66 | + } | |
67 | + | |
68 | + if (systemVersionIsAtLeast(10,7)) { | |
69 | + creationFlags |= kFSEventStreamCreateFlagFileEvents; | |
70 | + } | |
71 | + | |
45 | 72 | _events = [[CDEvents alloc] initWithURLs:watchedURLs |
46 | 73 | delegate:self |
47 | 74 | onRunLoop:[NSRunLoop currentRunLoop] |
@@ -49,7 +76,7 @@ | ||
49 | 76 | notificationLantency:CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY |
50 | 77 | ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS |
51 | 78 | excludeURLs:excludeURLs |
52 | - streamCreationFlags:kCDEventsDefaultEventStreamFlags]; | |
79 | + streamCreationFlags:creationFlags]; | |
53 | 80 | //[_events setIgnoreEventsFromSubDirectories:YES]; |
54 | 81 | |
55 | 82 | NSLog(@"-[CDEventsTestAppController run]:\n%@\n------\n%@", |
@@ -0,0 +1,32 @@ | ||
1 | +/** | |
2 | + * @headerfile compat.h | |
3 | + * FSEventStream flag compatibility shim | |
4 | + * | |
5 | + * In order to compile a binary against an older SDK yet still support the | |
6 | + * features present in later OS releases, we need to define any missing enum | |
7 | + * constants not present in the older SDK. This allows us to safely defer | |
8 | + * feature detection to runtime (and avoid recompilation). | |
9 | + */ | |
10 | + | |
11 | +#import <CoreServices/CoreServices.h> | |
12 | + | |
13 | +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060 | |
14 | +// ignoring events originating from the current process introduced in 10.6 | |
15 | +FSEventStreamCreateFlags kFSEventStreamCreateFlagIgnoreSelf = 0x00000008; | |
16 | +#endif | |
17 | + | |
18 | +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 | |
19 | +// file-level events introduced in 10.7 | |
20 | +FSEventStreamCreateFlags kFSEventStreamCreateFlagFileEvents = 0x00000010; | |
21 | +FSEventStreamEventFlags kFSEventStreamEventFlagItemCreated = 0x00000100, | |
22 | + kFSEventStreamEventFlagItemRemoved = 0x00000200, | |
23 | + kFSEventStreamEventFlagItemInodeMetaMod = 0x00000400, | |
24 | + kFSEventStreamEventFlagItemRenamed = 0x00000800, | |
25 | + kFSEventStreamEventFlagItemModified = 0x00001000, | |
26 | + kFSEventStreamEventFlagItemFinderInfoMod = 0x00002000, | |
27 | + kFSEventStreamEventFlagItemChangeOwner = 0x00004000, | |
28 | + kFSEventStreamEventFlagItemXattrMod = 0x00008000, | |
29 | + kFSEventStreamEventFlagItemIsFile = 0x00010000, | |
30 | + kFSEventStreamEventFlagItemIsDir = 0x00020000, | |
31 | + kFSEventStreamEventFlagItemIsSymlink = 0x00040000; | |
32 | +#endif |