-
Notifications
You must be signed in to change notification settings - Fork 156
/
Copy pathfsevapi.c
151 lines (126 loc) · 4.05 KB
/
fsevapi.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* fsmon -- MIT - Copyright NowSecure 2016 - pancake@nowsecure.com */
#if __APPLE__
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <errno.h>
#include "fsmon.h"
#include <libgen.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <sys/time.h>
#include <unistd.h>
#define FSEVAPI_DEBUG 1
#if TARGET_WATCHOS
#warning No FSEventMonitor API for WatchOS yet
#else
#include <CoreFoundation/CoreFoundation.h>
#if TARGET_IOS
#include <MobileCoreServices/MobileCoreServices.h>
const int kFSEventStreamCreateFlagFileEvents = 0x10;
const int kFSEventStreamEventIdSinceNow = -1;
typedef struct {
CFIndex version;
void *info;
CFAllocatorRetainCallBack retain;
CFAllocatorReleaseCallBack release;
CFAllocatorCopyDescriptionCallBack copyDescription;
} FSEventStreamContext;
typedef void * ConstFSEventStreamRef;
typedef void * FSEventStreamRef;
typedef int FSEventStreamEventFlags;
typedef int FSEventStreamEventId;
typedef int FSEventStreamCreateFlags;
typedef void ( *FSEventStreamCallback )( ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]);
extern FSEventStreamRef FSEventStreamCreate( CFAllocatorRef allocator, FSEventStreamCallback callback, FSEventStreamContext *context, CFArrayRef pathsToWatch, FSEventStreamEventId sinceWhen, CFTimeInterval latency, FSEventStreamCreateFlags flags);
extern Boolean FSEventStreamStart( FSEventStreamRef streamRef);
extern void FSEventStreamScheduleWithRunLoop( FSEventStreamRef streamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode);
#else
#include <CoreServices/CoreServices.h>
#endif
/* TODO: move into event's ctx */
static FileMonitorCallback global_cb;
static void event_cb(ConstFSEventStreamRef streamRef, void *ctx, size_t count, void *paths,
const FSEventStreamEventFlags flags[], const FSEventStreamEventId ids[]) {
FileMonitor *fm = (FileMonitor*)ctx;
FileMonitorEvent ev = {0};
struct stat st;
int i;
if (!fm->running) {
/* TODO: shouldnt wait until the next event */
CFRunLoopStop (CFRunLoopGetCurrent ());
}
for (i = 0; i < count; i++) {
char *path = ((char **)paths)[i];
#if FSEVAPI_DEBUG
/* flags are unsigned long, IDs are uint64_t */
printf ("%d Change 0x%" PRIx64 " in %s, flags %lu",
i, (uint64_t) ids[i], path, (long)flags[i]);
#endif
if (stat (path, &st) != -1) {
if ((S_IFREG & st.st_mode)==S_IFREG) {
ev.type = FSE_CREATE_FILE;
} else {
ev.type = FSE_DELETE;
}
} else {
/* XXX: the path is wrong */
ev.type = FSE_DELETE;
}
ev.file = path;
global_cb (fm, &ev);
}
}
static bool fm_begin (FileMonitor *fm) {
FSEventStreamCreateFlags flags = kFSEventStreamCreateFlagFileEvents;
FSEventStreamContext ctx = {
0,
fm,
NULL,
NULL,
NULL
};
if (!fm->root) {
fm->root = "/";
}
CFMutableArrayRef paths = CFArrayCreateMutable (NULL, 1, NULL);
CFStringRef cfs_path = CFStringCreateWithCString (NULL, fm->root,
kCFStringEncodingUTF8);
CFArrayAppendValue (paths, cfs_path);
FSEventStreamRef stream = FSEventStreamCreate (NULL, &event_cb,
&ctx, paths, kFSEventStreamEventIdSinceNow, 0, flags);
FSEventStreamScheduleWithRunLoop (stream, CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode);
FSEventStreamStart (stream);
return true;
}
static bool fm_loop (FileMonitor *fm, FileMonitorCallback cb) {
global_cb = cb;
CFRunLoopRun ();
return false;
}
static bool fm_end(FileMonitor *fm) {
if (fm && fm->fd != -1) {
close (fm->fd);
fm->fd = -1;
return true;
}
return false;
}
FileMonitorBackend fmb_fsevapi = {
.name = "fsevapi",
.begin = fm_begin,
.loop = fm_loop,
.end = fm_end,
};
#endif
#endif