rb-fsevent 0.9.2 → 0.11.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/Gemfile +3 -0
- data/Guardfile +8 -0
- data/{LICENSE → LICENSE.txt} +3 -1
- data/README.md +260 -0
- data/Rakefile +33 -0
- data/bin/fsevent_watch +0 -0
- data/ext/{fsevent_watch/LICENSE → LICENSE} +1 -1
- data/ext/fsevent_watch/FSEventsFix.c +626 -0
- data/ext/fsevent_watch/FSEventsFix.h +105 -0
- data/ext/fsevent_watch/{fsevent_watch/TSICTString.c → TSICTString.c} +34 -55
- data/ext/fsevent_watch/{fsevent_watch/TSICTString.h → TSICTString.h} +0 -0
- data/ext/fsevent_watch/{fsevent_watch/cli.c → cli.c} +48 -7
- data/ext/fsevent_watch/{fsevent_watch/cli.h → cli.h} +3 -3
- data/ext/fsevent_watch/{fsevent_watch/common.h → common.h} +1 -13
- data/ext/fsevent_watch/compat.c +41 -0
- data/ext/fsevent_watch/compat.h +100 -0
- data/ext/fsevent_watch/defines.h +42 -0
- data/ext/fsevent_watch/{fsevent_watch/main.c → main.c} +101 -62
- data/ext/fsevent_watch/signal_handlers.c +66 -0
- data/ext/fsevent_watch/signal_handlers.h +16 -0
- data/ext/rakefile.rb +225 -41
- data/lib/otnetstring.rb +85 -0
- data/lib/rb-fsevent/fsevent.rb +53 -7
- data/lib/rb-fsevent/version.rb +3 -1
- data/lib/rb-fsevent.rb +2 -1
- data/rb-fsevent.gemspec +26 -0
- metadata +53 -56
- data/README.rdoc +0 -255
- data/ext/fsevent_watch/Info.plist +0 -38
- data/ext/fsevent_watch/fsevent_watch/compat.c +0 -20
- data/ext/fsevent_watch/fsevent_watch/compat.h +0 -40
- data/ext/fsevent_watch/fsevent_watch.xcodeproj/project.pbxproj +0 -254
- data/ext/fsevent_watch/xcconfig/Common.xcconfig +0 -82
- data/ext/fsevent_watch/xcconfig/Debug.xcconfig +0 -19
- data/ext/fsevent_watch/xcconfig/Release.xcconfig +0 -23
- data/ext/fsevent_watch/xcconfig/fsevent_watch.xcconfig +0 -17
- data/ext/rb-fsevent.xcconfig +0 -33
@@ -0,0 +1,105 @@
|
|
1
|
+
/*
|
2
|
+
* FSEventsFix
|
3
|
+
*
|
4
|
+
* Works around a long-standing bug in realpath() that prevents FSEvents API from
|
5
|
+
* monitoring certain folders on a wide range of OS X releases (10.6-10.10 at least).
|
6
|
+
*
|
7
|
+
* The underlying issue is that for some folders, realpath() call starts returning
|
8
|
+
* a path with incorrect casing (e.g. "/users/smt" instead of "/Users/smt").
|
9
|
+
* FSEvents is case-sensitive and calls realpath() on the paths you pass in, so
|
10
|
+
* an incorrect value returned by realpath() prevents FSEvents from seeing any
|
11
|
+
* change events.
|
12
|
+
*
|
13
|
+
* See the discussion at https://github.com/thibaudgg/rb-fsevent/issues/10 about
|
14
|
+
* the history of this bug and how this library came to exist.
|
15
|
+
*
|
16
|
+
* This library uses Facebook's fishhook to replace a custom implementation of
|
17
|
+
* realpath in place of the system realpath; FSEvents will then invoke our custom
|
18
|
+
* implementation (which does not screw up the names) and will thus work correctly.
|
19
|
+
*
|
20
|
+
* Our implementation of realpath is based on the open-source implementation from
|
21
|
+
* OS X 10.10, with a single change applied (enclosed in "BEGIN WORKAROUND FOR
|
22
|
+
* OS X BUG" ... "END WORKAROUND FOR OS X BUG").
|
23
|
+
*
|
24
|
+
* Include FSEventsFix.{h,c} into your project and call FSEventsFixInstall().
|
25
|
+
*
|
26
|
+
* It is recommended that you install FSEventsFix on demand, using FSEventsFixIsBroken
|
27
|
+
* to check if the folder you're about to pass to FSEventStreamCreate needs the fix.
|
28
|
+
* Note that the fix must be applied before calling FSEventStreamCreate.
|
29
|
+
*
|
30
|
+
* FSEventsFixIsBroken requires a path that uses the correct case for all folder names,
|
31
|
+
* i.e. a path provided by the system APIs or constructed from folder names provided
|
32
|
+
* by the directory enumeration APIs.
|
33
|
+
*
|
34
|
+
* See .c file for license & copyrights, but basically this is available under a mix
|
35
|
+
* of MIT and BSD licenses.
|
36
|
+
*/
|
37
|
+
|
38
|
+
#ifndef __FSEventsFix__
|
39
|
+
#define __FSEventsFix__
|
40
|
+
|
41
|
+
#include <CoreFoundation/CoreFoundation.h>
|
42
|
+
|
43
|
+
/// A library version string (e.g. 1.2.3) for displaying and logging purposes
|
44
|
+
extern const char *const FSEventsFixVersionString;
|
45
|
+
|
46
|
+
/// See FSEventsFixDebugOptionSimulateBroken
|
47
|
+
#define FSEventsFixSimulatedBrokenFolderMarker "__!FSEventsBroken!__"
|
48
|
+
|
49
|
+
typedef CF_OPTIONS(unsigned, FSEventsFixDebugOptions) {
|
50
|
+
/// Always return an uppercase string from realpath
|
51
|
+
FSEventsFixDebugOptionUppercaseReturn = 0x01,
|
52
|
+
|
53
|
+
/// Log all calls to realpath using the logger configured via FSEventsFixConfigure
|
54
|
+
FSEventsFixDebugOptionLogCalls = 0x02,
|
55
|
+
|
56
|
+
/// In addition to the logging block (if any), log everything to stderr
|
57
|
+
FSEventsFixDebugOptionLogToStderr = 0x08,
|
58
|
+
|
59
|
+
/// Report paths containing FSEventsFixSimulatedBrokenFolderMarker as broken
|
60
|
+
FSEventsFixDebugOptionSimulateBroken = 0x10,
|
61
|
+
|
62
|
+
/// Repair paths containing FSEventsFixSimulatedBrokenFolderMarker by renaming them
|
63
|
+
FSEventsFixDebugOptionSimulateRepair = 0x20,
|
64
|
+
};
|
65
|
+
|
66
|
+
typedef CF_ENUM(int, FSEventsFixMessageType) {
|
67
|
+
/// Call logging requested via FSEventsFixDebugOptionLogCalls
|
68
|
+
FSEventsFixMessageTypeCall,
|
69
|
+
|
70
|
+
/// Results of actions like repair, and other pretty verbose, but notable, stuff.
|
71
|
+
FSEventsFixMessageTypeResult,
|
72
|
+
|
73
|
+
/// Enabled/disabled status change
|
74
|
+
FSEventsFixMessageTypeStatusChange,
|
75
|
+
|
76
|
+
/// Expected failure (treat as a warning)
|
77
|
+
FSEventsFixMessageTypeExpectedFailure,
|
78
|
+
|
79
|
+
/// Severe failure that most likely means that the library won't work
|
80
|
+
FSEventsFixMessageTypeFatalError
|
81
|
+
};
|
82
|
+
|
83
|
+
typedef CF_ENUM(int, FSEventsFixRepairStatus) {
|
84
|
+
FSEventsFixRepairStatusNotBroken,
|
85
|
+
FSEventsFixRepairStatusRepaired,
|
86
|
+
FSEventsFixRepairStatusFailed,
|
87
|
+
};
|
88
|
+
|
89
|
+
/// Note that the logging block can be called on any dispatch queue.
|
90
|
+
void FSEventsFixConfigure(FSEventsFixDebugOptions debugOptions, void(^loggingBlock)(FSEventsFixMessageType type, const char *message));
|
91
|
+
|
92
|
+
void FSEventsFixEnable();
|
93
|
+
void FSEventsFixDisable();
|
94
|
+
|
95
|
+
bool FSEventsFixIsOperational();
|
96
|
+
|
97
|
+
bool FSEventsFixIsBroken(const char *path);
|
98
|
+
|
99
|
+
/// If the path is broken, returns a string identifying the root broken folder,
|
100
|
+
/// otherwise, returns NULL. You need to free() the returned string.
|
101
|
+
char *FSEventsFixCopyRootBrokenFolderPath(const char *path);
|
102
|
+
|
103
|
+
FSEventsFixRepairStatus FSEventsFixRepairIfNeeded(const char *path);
|
104
|
+
|
105
|
+
#endif
|
@@ -65,13 +65,13 @@ static inline TStringIRep* TSICTStringCreateWithDataOfTypeAndFormat(CFDataRef da
|
|
65
65
|
if (format == kTSITStringFormatDefault) {
|
66
66
|
format = TSICTStringGetDefaultFormat();
|
67
67
|
}
|
68
|
-
|
68
|
+
|
69
69
|
TStringIRep* rep = calloc(1, sizeof(TStringIRep));
|
70
70
|
rep->data = CFDataCreateCopy(kCFAllocatorDefault, data);
|
71
71
|
rep->type = type;
|
72
72
|
rep->format = format;
|
73
73
|
rep->length = calloc(10, sizeof(char));
|
74
|
-
|
74
|
+
|
75
75
|
CFIndex len = CFDataGetLength(rep->data);
|
76
76
|
if (snprintf(rep->length, 10, "%lu", len)) {
|
77
77
|
return rep;
|
@@ -86,10 +86,10 @@ static inline CFDataRef TSICTStringCreateDataFromIntermediateRepresentation(TStr
|
|
86
86
|
CFIndex len = CFDataGetLength(rep->data);
|
87
87
|
CFMutableDataRef buffer = CFDataCreateMutableCopy(kCFAllocatorDefault, (len + 12), rep->data);
|
88
88
|
UInt8* bufferBytes = CFDataGetMutableBytePtr(buffer);
|
89
|
-
|
89
|
+
|
90
90
|
size_t prefixLength = strlen(rep->length) + 1;
|
91
91
|
CFDataReplaceBytes(buffer, BeginningRange, (const UInt8*)rep->length, (CFIndex)prefixLength);
|
92
|
-
|
92
|
+
|
93
93
|
if (rep->format == kTSITStringFormatTNetstring) {
|
94
94
|
const UInt8 ftag = (UInt8)TNetstringTypes[rep->type];
|
95
95
|
CFDataAppendBytes(buffer, &ftag, 1);
|
@@ -98,10 +98,10 @@ static inline CFDataRef TSICTStringCreateDataFromIntermediateRepresentation(TStr
|
|
98
98
|
const UInt8 ftag = (UInt8)OTNetstringTypes[rep->type];
|
99
99
|
bufferBytes[(prefixLength - 1)] = ftag;
|
100
100
|
}
|
101
|
-
|
101
|
+
|
102
102
|
CFDataRef dataRep = CFDataCreateCopy(kCFAllocatorDefault, buffer);
|
103
103
|
CFRelease(buffer);
|
104
|
-
|
104
|
+
|
105
105
|
return dataRep;
|
106
106
|
}
|
107
107
|
|
@@ -113,41 +113,20 @@ static inline CFStringRef TSICTStringCreateStringFromIntermediateRepresentation(
|
|
113
113
|
return string;
|
114
114
|
}
|
115
115
|
|
116
|
-
static inline CFDataRef TSICTStringCreateDataWithDataOfTypeAndFormat(CFDataRef data, TSITStringTag type, TSITStringFormat format)
|
117
|
-
{
|
118
|
-
CFRetain(data);
|
119
|
-
|
120
|
-
if (format == kTSITStringFormatDefault) {
|
121
|
-
format = TSICTStringGetDefaultFormat();
|
122
|
-
}
|
123
|
-
|
124
|
-
TStringIRep* rep = TSICTStringCreateWithDataOfTypeAndFormat(data, type, format);
|
125
|
-
if (rep == NULL) {
|
126
|
-
return NULL;
|
127
|
-
}
|
128
|
-
|
129
|
-
CFDataRef result = TSICTStringCreateDataFromIntermediateRepresentation(rep);
|
130
|
-
|
131
|
-
TSICTStringDestroy(rep);
|
132
|
-
CFRelease(data);
|
133
|
-
|
134
|
-
return result;
|
135
|
-
}
|
136
|
-
|
137
116
|
static inline void TSICTStringAppendObjectToMutableDataWithFormat(CFTypeRef object, CFMutableDataRef buffer, TSITStringFormat format)
|
138
117
|
{
|
139
118
|
if (object == NULL) {
|
140
119
|
object = kCFNull;
|
141
120
|
}
|
142
|
-
|
121
|
+
|
143
122
|
CFRetain(object);
|
144
|
-
|
123
|
+
|
145
124
|
TStringIRep* objRep = TSICTStringCreateWithObjectAndFormat(object, format);
|
146
125
|
CFDataRef objData = TSICTStringCreateDataFromIntermediateRepresentation(objRep);
|
147
126
|
CFDataAppendBytes(buffer, (CFDataGetBytePtr(objData)), CFDataGetLength(objData));
|
148
127
|
CFRelease(objData);
|
149
128
|
TSICTStringDestroy(objRep);
|
150
|
-
|
129
|
+
|
151
130
|
CFRelease(object);
|
152
131
|
}
|
153
132
|
|
@@ -156,7 +135,7 @@ static void ArrayBufferAppendCallback(const void* item, void* context)
|
|
156
135
|
TStringCollectionCallbackContext* cx = (TStringCollectionCallbackContext*)context;
|
157
136
|
CFMutableDataRef buffer = cx->buffer;
|
158
137
|
TSITStringFormat format = cx->format;
|
159
|
-
|
138
|
+
|
160
139
|
TSICTStringAppendObjectToMutableDataWithFormat(item, buffer, format);
|
161
140
|
}
|
162
141
|
|
@@ -165,7 +144,7 @@ static void DictionaryBufferAppendCallback(const void* key, const void* value, v
|
|
165
144
|
TStringCollectionCallbackContext* cx = (TStringCollectionCallbackContext*)context;
|
166
145
|
CFMutableDataRef buffer = cx->buffer;
|
167
146
|
TSITStringFormat format = cx->format;
|
168
|
-
|
147
|
+
|
169
148
|
TSICTStringAppendObjectToMutableDataWithFormat(key, buffer, format);
|
170
149
|
TSICTStringAppendObjectToMutableDataWithFormat(value, buffer, format);
|
171
150
|
}
|
@@ -181,15 +160,15 @@ CFDataRef TSICTStringCreateRenderedDataFromObjectWithFormat(CFTypeRef object, TS
|
|
181
160
|
if (object == NULL) {
|
182
161
|
object = kCFNull;
|
183
162
|
}
|
184
|
-
|
163
|
+
|
185
164
|
CFRetain(object);
|
186
|
-
|
165
|
+
|
187
166
|
TStringIRep* rep = TSICTStringCreateWithObjectAndFormat(object, format);
|
188
167
|
CFDataRef data = TSICTStringCreateDataFromIntermediateRepresentation(rep);
|
189
|
-
|
168
|
+
|
190
169
|
TSICTStringDestroy(rep);
|
191
170
|
CFRelease(object);
|
192
|
-
|
171
|
+
|
193
172
|
return data;
|
194
173
|
}
|
195
174
|
|
@@ -203,15 +182,15 @@ CFStringRef TSICTStringCreateRenderedStringFromObjectWithFormat(CFTypeRef object
|
|
203
182
|
if (object == NULL) {
|
204
183
|
object = kCFNull;
|
205
184
|
}
|
206
|
-
|
185
|
+
|
207
186
|
CFRetain(object);
|
208
|
-
|
187
|
+
|
209
188
|
TStringIRep* rep = TSICTStringCreateWithObjectAndFormat(object, format);
|
210
189
|
CFStringRef string = TSICTStringCreateStringFromIntermediateRepresentation(rep);
|
211
|
-
|
190
|
+
|
212
191
|
TSICTStringDestroy(rep);
|
213
192
|
CFRelease(object);
|
214
|
-
|
193
|
+
|
215
194
|
return string;
|
216
195
|
}
|
217
196
|
|
@@ -222,10 +201,10 @@ TStringIRep* TSICTStringCreateWithObjectAndFormat(CFTypeRef object, TSITStringFo
|
|
222
201
|
return TSICTStringCreateNullWithFormat(format);
|
223
202
|
}
|
224
203
|
CFRetain(object);
|
225
|
-
|
204
|
+
|
226
205
|
CFTypeID cfType = CFGetTypeID(object);
|
227
206
|
TStringIRep* rep = NULL;
|
228
|
-
|
207
|
+
|
229
208
|
if (cfType == kCFDataTypeID) {
|
230
209
|
rep = TSICTStringCreateWithDataOfTypeAndFormat(object, kTSITStringTagString, format);
|
231
210
|
} else if (cfType == kCFStringTypeID) {
|
@@ -247,7 +226,7 @@ TStringIRep* TSICTStringCreateWithObjectAndFormat(CFTypeRef object, TSITStringFo
|
|
247
226
|
} else {
|
248
227
|
rep = TSICTStringCreateInvalidWithFormat(format);
|
249
228
|
}
|
250
|
-
|
229
|
+
|
251
230
|
CFRelease(object);
|
252
231
|
return rep;
|
253
232
|
}
|
@@ -268,7 +247,7 @@ TStringIRep* TSICTStringCreateWithNumberAndFormat(CFNumberRef number, TSITString
|
|
268
247
|
TSITStringTag tag = kTSITStringTagNumber;
|
269
248
|
CFDataRef data;
|
270
249
|
CFNumberType numType = CFNumberGetType(number);
|
271
|
-
|
250
|
+
|
272
251
|
switch(numType) {
|
273
252
|
case kCFNumberCharType:
|
274
253
|
{
|
@@ -291,7 +270,7 @@ TStringIRep* TSICTStringCreateWithNumberAndFormat(CFNumberRef number, TSITString
|
|
291
270
|
break;
|
292
271
|
}
|
293
272
|
}
|
294
|
-
|
273
|
+
|
295
274
|
if (tag == kTSITStringTagBool) {
|
296
275
|
bool value;
|
297
276
|
CFNumberGetValue(number, kCFNumberIntType, &value);
|
@@ -304,17 +283,17 @@ TStringIRep* TSICTStringCreateWithNumberAndFormat(CFNumberRef number, TSITString
|
|
304
283
|
char buf[32];
|
305
284
|
char *p, *e;
|
306
285
|
double value;
|
307
|
-
|
286
|
+
|
308
287
|
CFNumberGetValue(number, numType, &value);
|
309
288
|
sprintf(buf, "%#.15g", value);
|
310
|
-
|
289
|
+
|
311
290
|
e = buf + strlen(buf);
|
312
291
|
p = e;
|
313
292
|
while (p[-1]=='0' && ('0' <= p[-2] && p[-2] <= '9')) {
|
314
293
|
p--;
|
315
294
|
}
|
316
295
|
memmove(p, e, strlen(e)+1);
|
317
|
-
|
296
|
+
|
318
297
|
data = CFDataCreate(kCFAllocatorDefault, (UInt8*)buf, (CFIndex)strlen(buf));
|
319
298
|
} else {
|
320
299
|
char buf[32];
|
@@ -323,7 +302,7 @@ TStringIRep* TSICTStringCreateWithNumberAndFormat(CFNumberRef number, TSITString
|
|
323
302
|
sprintf(buf, "%lli", value);
|
324
303
|
data = CFDataCreate(kCFAllocatorDefault, (UInt8*)buf, (CFIndex)strlen(buf));
|
325
304
|
}
|
326
|
-
|
305
|
+
|
327
306
|
TStringIRep* rep = TSICTStringCreateWithDataOfTypeAndFormat(data, tag, format);
|
328
307
|
CFRelease(data);
|
329
308
|
CFRelease(number);
|
@@ -365,13 +344,13 @@ TStringIRep* TSICTStringCreateInvalidWithFormat(TSITStringFormat format)
|
|
365
344
|
TStringIRep* TSICTStringCreateWithArrayAndFormat(CFArrayRef array, TSITStringFormat format)
|
366
345
|
{
|
367
346
|
CFRetain(array);
|
368
|
-
|
347
|
+
|
369
348
|
CFMutableDataRef buffer = CFDataCreateMutable(kCFAllocatorDefault, 0);
|
370
|
-
|
349
|
+
|
371
350
|
CFRange all = CFRangeMake(0, CFArrayGetCount(array));
|
372
351
|
TStringCollectionCallbackContext cx = {buffer, format};
|
373
352
|
CFArrayApplyFunction(array, all, ArrayBufferAppendCallback, &cx);
|
374
|
-
|
353
|
+
|
375
354
|
TStringIRep* rep = TSICTStringCreateWithDataOfTypeAndFormat(buffer, kTSITStringTagList, format);
|
376
355
|
CFRelease(buffer);
|
377
356
|
CFRelease(array);
|
@@ -381,12 +360,12 @@ TStringIRep* TSICTStringCreateWithArrayAndFormat(CFArrayRef array, TSITStringFor
|
|
381
360
|
TStringIRep* TSICTStringCreateWithDictionaryAndFormat(CFDictionaryRef dictionary, TSITStringFormat format)
|
382
361
|
{
|
383
362
|
CFRetain(dictionary);
|
384
|
-
|
363
|
+
|
385
364
|
CFMutableDataRef buffer = CFDataCreateMutable(kCFAllocatorDefault, 0);
|
386
|
-
|
365
|
+
|
387
366
|
TStringCollectionCallbackContext cx = {buffer, format};
|
388
367
|
CFDictionaryApplyFunction(dictionary, DictionaryBufferAppendCallback, &cx);
|
389
|
-
|
368
|
+
|
390
369
|
TStringIRep* rep = TSICTStringCreateWithDataOfTypeAndFormat(buffer, kTSITStringTagDict, format);
|
391
370
|
CFRelease(buffer);
|
392
371
|
CFRelease(dictionary);
|
File without changes
|
@@ -6,6 +6,7 @@ const char* cli_info_usage = "Usage: fsevent_watch [OPTIONS]... [PATHS]...";
|
|
6
6
|
const char* cli_info_help[] = {
|
7
7
|
" -h, --help you're looking at it",
|
8
8
|
" -V, --version print version number and exit",
|
9
|
+
" -p, --show-plist display the embedded Info.plist values",
|
9
10
|
" -s, --since-when=EventID fire historical events since ID",
|
10
11
|
" -l, --latency=seconds latency period (default='0.5')",
|
11
12
|
" -n, --no-defer enable no-defer latency modifier",
|
@@ -25,7 +26,8 @@ static void default_args (struct cli_info* args_info)
|
|
25
26
|
args_info->watch_root_flag = false;
|
26
27
|
args_info->ignore_self_flag = false;
|
27
28
|
args_info->file_events_flag = false;
|
28
|
-
args_info->
|
29
|
+
args_info->mark_self_flag = false;
|
30
|
+
args_info->format_arg = kFSEventWatchOutputFormatOTNetstring;
|
29
31
|
}
|
30
32
|
|
31
33
|
static void cli_parser_release (struct cli_info* args_info)
|
@@ -56,12 +58,46 @@ void cli_parser_free (struct cli_info* args_info)
|
|
56
58
|
cli_parser_release(args_info);
|
57
59
|
}
|
58
60
|
|
61
|
+
static void cli_print_info_dict (const void *key,
|
62
|
+
const void *value,
|
63
|
+
void *context)
|
64
|
+
{
|
65
|
+
CFStringRef entry = CFStringCreateWithFormat(NULL, NULL,
|
66
|
+
CFSTR("%@:\n %@"), key, value);
|
67
|
+
if (entry) {
|
68
|
+
CFShow(entry);
|
69
|
+
CFRelease(entry);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
void cli_show_plist (void)
|
74
|
+
{
|
75
|
+
CFBundleRef mainBundle = CFBundleGetMainBundle();
|
76
|
+
CFRetain(mainBundle);
|
77
|
+
CFDictionaryRef mainBundleDict = CFBundleGetInfoDictionary(mainBundle);
|
78
|
+
if (mainBundleDict) {
|
79
|
+
CFRetain(mainBundleDict);
|
80
|
+
printf("Embedded Info.plist metadata:\n\n");
|
81
|
+
CFDictionaryApplyFunction(mainBundleDict, cli_print_info_dict, NULL);
|
82
|
+
CFRelease(mainBundleDict);
|
83
|
+
}
|
84
|
+
CFRelease(mainBundle);
|
85
|
+
printf("\n");
|
86
|
+
}
|
87
|
+
|
59
88
|
void cli_print_version (void)
|
60
89
|
{
|
61
|
-
printf("%s %s\n", CLI_NAME, CLI_VERSION);
|
90
|
+
printf("%s %s\n\n", CLI_NAME, CLI_VERSION);
|
62
91
|
#ifdef COMPILED_AT
|
63
|
-
printf("Compiled %s\n", COMPILED_AT);
|
92
|
+
printf("Compiled at: %s\n", COMPILED_AT);
|
64
93
|
#endif
|
94
|
+
#ifdef COMPILER
|
95
|
+
printf("Compiled with: %s\n", COMPILER);
|
96
|
+
#endif
|
97
|
+
#ifdef TARGET_CPU
|
98
|
+
printf("Compiled for: %s\n", TARGET_CPU);
|
99
|
+
#endif
|
100
|
+
printf("\n");
|
65
101
|
}
|
66
102
|
|
67
103
|
void cli_print_help (void)
|
@@ -83,17 +119,19 @@ int cli_parser (int argc, const char** argv, struct cli_info* args_info)
|
|
83
119
|
static struct option longopts[] = {
|
84
120
|
{ "help", no_argument, NULL, 'h' },
|
85
121
|
{ "version", no_argument, NULL, 'V' },
|
122
|
+
{ "show-plist", no_argument, NULL, 'p' },
|
86
123
|
{ "since-when", required_argument, NULL, 's' },
|
87
124
|
{ "latency", required_argument, NULL, 'l' },
|
88
125
|
{ "no-defer", no_argument, NULL, 'n' },
|
89
126
|
{ "watch-root", no_argument, NULL, 'r' },
|
90
127
|
{ "ignore-self", no_argument, NULL, 'i' },
|
91
128
|
{ "file-events", no_argument, NULL, 'F' },
|
129
|
+
{ "mark-self", no_argument, NULL, 'm' },
|
92
130
|
{ "format", required_argument, NULL, 'f' },
|
93
131
|
{ 0, 0, 0, 0 }
|
94
132
|
};
|
95
133
|
|
96
|
-
const char* shortopts = "
|
134
|
+
const char* shortopts = "hVps:l:nriFf:";
|
97
135
|
|
98
136
|
int c = -1;
|
99
137
|
|
@@ -117,6 +155,9 @@ int cli_parser (int argc, const char** argv, struct cli_info* args_info)
|
|
117
155
|
case 'F': // file-events
|
118
156
|
args_info->file_events_flag = true;
|
119
157
|
break;
|
158
|
+
case 'm': // mark-self
|
159
|
+
args_info->mark_self_flag = true;
|
160
|
+
break;
|
120
161
|
case 'f': // format
|
121
162
|
if (strcmp(optarg, "classic") == 0) {
|
122
163
|
args_info->format_arg = kFSEventWatchOutputFormatClassic;
|
@@ -134,13 +175,14 @@ int cli_parser (int argc, const char** argv, struct cli_info* args_info)
|
|
134
175
|
case 'V': // version
|
135
176
|
cli_print_version();
|
136
177
|
exit(EXIT_SUCCESS);
|
137
|
-
|
178
|
+
case 'p': // show-plist
|
179
|
+
cli_show_plist();
|
180
|
+
exit(EXIT_SUCCESS);
|
138
181
|
case 'h': // help
|
139
182
|
case '?': // invalid option
|
140
183
|
case ':': // missing argument
|
141
184
|
cli_print_help();
|
142
185
|
exit((c == 'h') ? EXIT_SUCCESS : EXIT_FAILURE);
|
143
|
-
break;
|
144
186
|
}
|
145
187
|
}
|
146
188
|
|
@@ -157,4 +199,3 @@ int cli_parser (int argc, const char** argv, struct cli_info* args_info)
|
|
157
199
|
|
158
200
|
return EXIT_SUCCESS;
|
159
201
|
}
|
160
|
-
|
@@ -1,6 +1,8 @@
|
|
1
1
|
#ifndef CLI_H
|
2
2
|
#define CLI_H
|
3
3
|
|
4
|
+
#include "common.h"
|
5
|
+
|
4
6
|
#ifndef CLI_NAME
|
5
7
|
#define CLI_NAME "fsevent_watch"
|
6
8
|
#endif /* CLI_NAME */
|
@@ -10,12 +12,9 @@
|
|
10
12
|
#endif /* PROJECT_VERSION */
|
11
13
|
|
12
14
|
#ifndef CLI_VERSION
|
13
|
-
#define _str(s) #s
|
14
|
-
#define _xstr(s) _str(s)
|
15
15
|
#define CLI_VERSION _xstr(PROJECT_VERSION)
|
16
16
|
#endif /* CLI_VERSION */
|
17
17
|
|
18
|
-
#include "common.h"
|
19
18
|
|
20
19
|
struct cli_info {
|
21
20
|
UInt64 since_when_arg;
|
@@ -24,6 +23,7 @@ struct cli_info {
|
|
24
23
|
bool watch_root_flag;
|
25
24
|
bool ignore_self_flag;
|
26
25
|
bool file_events_flag;
|
26
|
+
bool mark_self_flag;
|
27
27
|
enum FSEventWatchOutputFormat format_arg;
|
28
28
|
|
29
29
|
char** inputs;
|
@@ -9,21 +9,9 @@
|
|
9
9
|
#include <CoreServices/CoreServices.h>
|
10
10
|
#include <unistd.h>
|
11
11
|
#include "compat.h"
|
12
|
+
#include "defines.h"
|
12
13
|
#include "TSICTString.h"
|
13
14
|
|
14
|
-
#define COMPILED_AT __DATE__ " " __TIME__
|
15
|
-
|
16
|
-
#define FLAG_CHECK(flags, flag) ((flags) & (flag))
|
17
|
-
|
18
|
-
#define FPRINTF_FLAG_CHECK(flags, flag, msg, fd) \
|
19
|
-
do { \
|
20
|
-
if (FLAG_CHECK(flags, flag)) { \
|
21
|
-
fprintf(fd, "%s", msg "\n"); } } \
|
22
|
-
while (0)
|
23
|
-
|
24
|
-
#define FLAG_CHECK_STDERR(flags, flag, msg) \
|
25
|
-
FPRINTF_FLAG_CHECK(flags, flag, msg, stderr)
|
26
|
-
|
27
15
|
enum FSEventWatchOutputFormat {
|
28
16
|
kFSEventWatchOutputFormatClassic,
|
29
17
|
kFSEventWatchOutputFormatNIW,
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#include "compat.h"
|
2
|
+
|
3
|
+
|
4
|
+
#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_6) || \
|
5
|
+
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_6_0)
|
6
|
+
FSEventStreamCreateFlags kFSEventStreamCreateFlagIgnoreSelf = 0x00000008;
|
7
|
+
#endif
|
8
|
+
|
9
|
+
#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_7) || \
|
10
|
+
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_6_0)
|
11
|
+
FSEventStreamCreateFlags kFSEventStreamCreateFlagFileEvents = 0x00000010;
|
12
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemCreated = 0x00000100;
|
13
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemRemoved = 0x00000200;
|
14
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemInodeMetaMod = 0x00000400;
|
15
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemRenamed = 0x00000800;
|
16
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemModified = 0x00001000;
|
17
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemFinderInfoMod = 0x00002000;
|
18
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemChangeOwner = 0x00004000;
|
19
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemXattrMod = 0x00008000;
|
20
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemIsFile = 0x00010000;
|
21
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemIsDir = 0x00020000;
|
22
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemIsSymlink = 0x00040000;
|
23
|
+
#endif
|
24
|
+
|
25
|
+
#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_9) || \
|
26
|
+
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_7_0)
|
27
|
+
FSEventStreamCreateFlags kFSEventStreamCreateFlagMarkSelf = 0x00000020;
|
28
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagOwnEvent = 0x00080000;
|
29
|
+
#endif
|
30
|
+
|
31
|
+
#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_10) || \
|
32
|
+
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0)
|
33
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemIsHardlink = 0x00100000;
|
34
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemIsLastHardlink = 0x00200000;
|
35
|
+
#endif
|
36
|
+
|
37
|
+
#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_13) || \
|
38
|
+
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_11_0)
|
39
|
+
FSEventStreamCreateFlags kFSEventStreamCreateFlagUseExtendedData = 0x00000040;
|
40
|
+
FSEventStreamEventFlags kFSEventStreamEventFlagItemCloned = 0x00400000;
|
41
|
+
#endif
|
@@ -0,0 +1,100 @@
|
|
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
|
+
|
12
|
+
#ifndef listen_fsevents_compat_h
|
13
|
+
#define listen_fsevents_compat_h
|
14
|
+
|
15
|
+
#ifndef __CORESERVICES__
|
16
|
+
#include <CoreServices/CoreServices.h>
|
17
|
+
#endif // __CORESERVICES__
|
18
|
+
|
19
|
+
#ifndef __AVAILABILITY__
|
20
|
+
#include <Availability.h>
|
21
|
+
#endif // __AVAILABILITY__
|
22
|
+
|
23
|
+
#ifndef __MAC_10_6
|
24
|
+
#define __MAC_10_6 1060
|
25
|
+
#endif
|
26
|
+
#ifndef __MAC_10_7
|
27
|
+
#define __MAC_10_7 1070
|
28
|
+
#endif
|
29
|
+
#ifndef __MAC_10_9
|
30
|
+
#define __MAC_10_9 1090
|
31
|
+
#endif
|
32
|
+
#ifndef __MAC_10_10
|
33
|
+
#define __MAC_10_10 101000
|
34
|
+
#endif
|
35
|
+
#ifndef __MAC_10_13
|
36
|
+
#define __MAC_10_13 101300
|
37
|
+
#endif
|
38
|
+
#ifndef __IPHONE_6_0
|
39
|
+
#define __IPHONE_6_0 60000
|
40
|
+
#endif
|
41
|
+
#ifndef __IPHONE_7_0
|
42
|
+
#define __IPHONE_7_0 70000
|
43
|
+
#endif
|
44
|
+
#ifndef __IPHONE_9_0
|
45
|
+
#define __IPHONE_9_0 90000
|
46
|
+
#endif
|
47
|
+
#ifndef __IPHONE_11_0
|
48
|
+
#define __IPHONE_11_0 110000
|
49
|
+
#endif
|
50
|
+
|
51
|
+
#ifdef __cplusplus
|
52
|
+
extern "C" {
|
53
|
+
#endif
|
54
|
+
|
55
|
+
|
56
|
+
#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_6) || \
|
57
|
+
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_6_0)
|
58
|
+
extern FSEventStreamCreateFlags kFSEventStreamCreateFlagIgnoreSelf;
|
59
|
+
#endif
|
60
|
+
|
61
|
+
#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_7) || \
|
62
|
+
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_6_0)
|
63
|
+
extern FSEventStreamCreateFlags kFSEventStreamCreateFlagFileEvents;
|
64
|
+
extern FSEventStreamEventFlags kFSEventStreamEventFlagItemCreated,
|
65
|
+
kFSEventStreamEventFlagItemRemoved,
|
66
|
+
kFSEventStreamEventFlagItemInodeMetaMod,
|
67
|
+
kFSEventStreamEventFlagItemRenamed,
|
68
|
+
kFSEventStreamEventFlagItemModified,
|
69
|
+
kFSEventStreamEventFlagItemFinderInfoMod,
|
70
|
+
kFSEventStreamEventFlagItemChangeOwner,
|
71
|
+
kFSEventStreamEventFlagItemXattrMod,
|
72
|
+
kFSEventStreamEventFlagItemIsFile,
|
73
|
+
kFSEventStreamEventFlagItemIsDir,
|
74
|
+
kFSEventStreamEventFlagItemIsSymlink;
|
75
|
+
#endif
|
76
|
+
|
77
|
+
#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_9) || \
|
78
|
+
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_7_0)
|
79
|
+
extern FSEventStreamCreateFlags kFSEventStreamCreateFlagMarkSelf;
|
80
|
+
extern FSEventStreamEventFlags kFSEventStreamEventFlagOwnEvent;
|
81
|
+
#endif
|
82
|
+
|
83
|
+
#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_10) || \
|
84
|
+
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0)
|
85
|
+
extern FSEventStreamEventFlags kFSEventStreamEventFlagItemIsHardlink,
|
86
|
+
kFSEventStreamEventFlagItemIsLastHardlink;
|
87
|
+
#endif
|
88
|
+
|
89
|
+
#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_13) || \
|
90
|
+
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_11_0)
|
91
|
+
extern FSEventStreamCreateFlags kFSEventStreamCreateFlagUseExtendedData;
|
92
|
+
extern FSEventStreamEventFlags kFSEventStreamEventFlagItemCloned;
|
93
|
+
#endif
|
94
|
+
|
95
|
+
|
96
|
+
#ifdef __cplusplus
|
97
|
+
}
|
98
|
+
#endif
|
99
|
+
|
100
|
+
#endif // listen_fsevents_compat_h
|