entangler 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +28 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/entangler.gemspec +26 -0
- data/exe/entangler +21 -0
- data/lib/entangler/entangled_file.rb +139 -0
- data/lib/entangler/executor/base.rb +242 -0
- data/lib/entangler/executor/master.rb +45 -0
- data/lib/entangler/executor/slave.rb +17 -0
- data/lib/entangler/version.rb +3 -0
- data/lib/entangler.rb +23 -0
- data/lib/notifier/bin/darwin/notify +0 -0
- data/lib/notifier/bin/linux/notify +0 -0
- data/lib/notifier/src/darwin/BUILD +7 -0
- data/lib/notifier/src/darwin/README +12 -0
- data/lib/notifier/src/darwin/notify.c +63 -0
- data/lib/notifier/src/linux/BUILD +4 -0
- data/lib/notifier/src/linux/README +18 -0
- data/lib/notifier/src/linux/notify.c +296 -0
- data/lib/notifier/src/linux/old/BUILD +11 -0
- data/lib/notifier/src/linux/old/README +14 -0
- data/lib/notifier/src/linux/old/kernel-filesystem-monitor-daemon-cat.cpp +165 -0
- data/lib/notifier/src/linux/old/kernel-filesystem-monitor-daemon.cpp +727 -0
- data/lib/notifier/src/linux/old/kernel-filesystem-monitor-daemon.hh +212 -0
- metadata +132 -0
data/lib/entangler.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'entangler/version'
|
2
|
+
require 'entangler/entangled_file'
|
3
|
+
|
4
|
+
module Entangler
|
5
|
+
class << self
|
6
|
+
attr_accessor :executor
|
7
|
+
|
8
|
+
def run(base_dir, opts = {})
|
9
|
+
opts = {mode: 'master'}.merge(opts)
|
10
|
+
|
11
|
+
require 'entangler/executor/base'
|
12
|
+
if opts[:mode] == 'master'
|
13
|
+
require 'entangler/executor/master'
|
14
|
+
self.executor = Entangler::Executor::Master.new(base_dir, opts)
|
15
|
+
elsif opts[:mode] == 'slave'
|
16
|
+
require 'entangler/executor/slave'
|
17
|
+
self.executor = Entangler::Executor::Slave.new(base_dir, opts)
|
18
|
+
end
|
19
|
+
|
20
|
+
self.executor.run
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,12 @@
|
|
1
|
+
The notify utility continiously prints changes in a specified directory in the following format:
|
2
|
+
|
3
|
+
M changed/path/1
|
4
|
+
M changed/path/2
|
5
|
+
-
|
6
|
+
|
7
|
+
|
8
|
+
Where M stands for "Modifed", and "-" is the indicator of end of changeset
|
9
|
+
|
10
|
+
Utility only returns specific directories that have changed, it does not print
|
11
|
+
the files/directories that have been modified: you need to determine them
|
12
|
+
yourself
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#include <CoreServices/CoreServices.h>
|
2
|
+
#include <CoreFoundation/CoreFoundation.h>
|
3
|
+
#include <sys/stat.h>
|
4
|
+
|
5
|
+
static void printChangesFunc(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
|
6
|
+
char **paths = eventPaths;
|
7
|
+
int i;
|
8
|
+
for (i = 0; i < numEvents; i++) {
|
9
|
+
printf("M %s\n", paths[i]);
|
10
|
+
}
|
11
|
+
printf("-\n");
|
12
|
+
fflush(stdout);
|
13
|
+
}
|
14
|
+
|
15
|
+
void initFSEvents(const char *path) {
|
16
|
+
|
17
|
+
/* Define variables and create a CFArray object containing
|
18
|
+
CFString objects containing paths to watch.
|
19
|
+
*/
|
20
|
+
|
21
|
+
CFStringRef mypath = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8);
|
22
|
+
CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&mypath, 1, NULL);
|
23
|
+
void *callbackInfo = NULL; // could put stream-specific data here.
|
24
|
+
FSEventStreamRef stream;
|
25
|
+
CFAbsoluteTime latency = 0.1; /* Latency in seconds */
|
26
|
+
|
27
|
+
/* Create the stream, passing in a callback */
|
28
|
+
stream = FSEventStreamCreate(NULL,
|
29
|
+
&printChangesFunc,
|
30
|
+
callbackInfo,
|
31
|
+
pathsToWatch,
|
32
|
+
kFSEventStreamEventIdSinceNow, /* Or a previous event ID */
|
33
|
+
latency,
|
34
|
+
kFSEventStreamCreateFlagNone /* Flags explained in reference */
|
35
|
+
);
|
36
|
+
|
37
|
+
CFRelease(pathsToWatch);
|
38
|
+
CFRelease(mypath);
|
39
|
+
|
40
|
+
/* Create the stream before calling this. */
|
41
|
+
FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
42
|
+
FSEventStreamStart(stream);
|
43
|
+
}
|
44
|
+
|
45
|
+
int main (int argc, const char * argv[]) {
|
46
|
+
|
47
|
+
if(argc != 2) {
|
48
|
+
printf("Usage: %s <path>\n", argv[0]);
|
49
|
+
return 1;
|
50
|
+
}
|
51
|
+
|
52
|
+
struct stat tmp;
|
53
|
+
|
54
|
+
if(stat(argv[1], &tmp) != 0) {
|
55
|
+
perror("Invalid path");
|
56
|
+
return 2;
|
57
|
+
}
|
58
|
+
|
59
|
+
initFSEvents(argv[1]);
|
60
|
+
CFRunLoopRun();
|
61
|
+
|
62
|
+
return 0;
|
63
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
The notify utility continiously prints changes in a specified directory in the following format:
|
2
|
+
|
3
|
+
M changed/path/1
|
4
|
+
M changed/path/2
|
5
|
+
-
|
6
|
+
|
7
|
+
Where M stands for "Modifed", and "-" is the indicator of end of changeset
|
8
|
+
|
9
|
+
Utility only returns specific directories that have changed, it does not print
|
10
|
+
the files/directories that have been modified: you need to determine them
|
11
|
+
yourself.
|
12
|
+
|
13
|
+
Linux-specific notes:
|
14
|
+
|
15
|
+
1. You might need to adjust '/proc/sys/fs/inotify/max_user_watches' to allow more directories to be watched
|
16
|
+
2. If you have a lot of changes you might also want to increase queue size in /proc/sys/fs/inotify/max_queued_events
|
17
|
+
3. Watched queue can overflow and notify utility can run out of watched directories.
|
18
|
+
When you get exit code 3, you need to restart the daemon and re-process all directories you are interested in.
|
@@ -0,0 +1,296 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <sys/types.h>
|
4
|
+
#include <sys/stat.h>
|
5
|
+
#include <sys/inotify.h>
|
6
|
+
#include <unistd.h>
|
7
|
+
#include <dirent.h>
|
8
|
+
#include <errno.h>
|
9
|
+
#include <stdlib.h>
|
10
|
+
#include <fcntl.h>
|
11
|
+
#include <sys/ioctl.h>
|
12
|
+
|
13
|
+
/* gcc should be able to optimize strlen() for constant strings */
|
14
|
+
#define PRINT(str) write(1, str, strlen(str))
|
15
|
+
#define ERROR(str) write(2, str, strlen(str))
|
16
|
+
|
17
|
+
#define EVENT_MASK (IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MODIFY|IN_MOVE_SELF\
|
18
|
+
|IN_MOVED_FROM|IN_MOVED_TO|IN_DONT_FOLLOW|IN_ONLYDIR|IN_ATTRIB)
|
19
|
+
|
20
|
+
#ifdef DEBUG
|
21
|
+
#define DEBUG_PRINT printf
|
22
|
+
#else
|
23
|
+
#define DEBUG_PRINT(...) /* printf actually adds about 7k to binary size :) */
|
24
|
+
#endif
|
25
|
+
|
26
|
+
typedef struct {
|
27
|
+
int wd;
|
28
|
+
int parent_wd;
|
29
|
+
char *name;
|
30
|
+
} _watchstruct;
|
31
|
+
|
32
|
+
char events_buf[PATH_MAX + sizeof(struct inotify_event) + 1];
|
33
|
+
static _watchstruct *watches;
|
34
|
+
int ifd = 0, max_watches;
|
35
|
+
char *watch_dir;
|
36
|
+
|
37
|
+
/* make directory path for watch descriptor (recursively) */
|
38
|
+
static void wd_path(int wd, char *path)
|
39
|
+
{
|
40
|
+
if (wd == 0) {
|
41
|
+
strcpy(path, watch_dir);
|
42
|
+
strcat(path, "/");
|
43
|
+
return;
|
44
|
+
}
|
45
|
+
|
46
|
+
if (wd < 0 || !watches[wd].name) {
|
47
|
+
DEBUG_PRINT("Recusive %d, %x\n", wd, watches[wd].name);
|
48
|
+
ERROR("Memory corrupted: asked path of deleted event\n");
|
49
|
+
exit(1);
|
50
|
+
}
|
51
|
+
|
52
|
+
wd_path(watches[wd].parent_wd, path);
|
53
|
+
if (watches[wd].name[0] == 0) return;
|
54
|
+
|
55
|
+
strcat(path, watches[wd].name);
|
56
|
+
strcat(path, "/");
|
57
|
+
}
|
58
|
+
|
59
|
+
static int add_dir_watch(int parent_wd, char *dir, char *dir_name, int no_print)
|
60
|
+
{
|
61
|
+
int wd = inotify_add_watch(ifd, dir, EVENT_MASK);
|
62
|
+
if (wd < 0) {
|
63
|
+
ERROR("Cannot add watch to '");
|
64
|
+
ERROR(dir);
|
65
|
+
ERROR("' using inotify: ");
|
66
|
+
if (errno == ENOSPC) {
|
67
|
+
ERROR("too many watches\nYou can increase number of user watches using /proc/sys/fs/inotify/max_user_watches");
|
68
|
+
} else {
|
69
|
+
ERROR(strerror(errno));
|
70
|
+
}
|
71
|
+
ERROR("\n");
|
72
|
+
if (errno != EACCES && errno != ENOENT) exit(1);
|
73
|
+
return wd;
|
74
|
+
}
|
75
|
+
|
76
|
+
if (wd >= max_watches) {
|
77
|
+
ERROR("\nToo many events; restart required to prevent watch descriptor overflow.\n");
|
78
|
+
exit(3);
|
79
|
+
}
|
80
|
+
|
81
|
+
dir_name = strdup(dir_name);
|
82
|
+
if (!dir_name) {
|
83
|
+
ERROR("Cannot strdup(dir_name)\n");
|
84
|
+
exit(1);
|
85
|
+
}
|
86
|
+
|
87
|
+
watches[wd].wd = wd;
|
88
|
+
watches[wd].parent_wd = parent_wd;
|
89
|
+
if (watches[wd].name) free(watches[wd].name);
|
90
|
+
watches[wd].name = dir_name;
|
91
|
+
|
92
|
+
if (!no_print) {
|
93
|
+
PRINT("M ");
|
94
|
+
PRINT(dir);
|
95
|
+
PRINT("\n");
|
96
|
+
}
|
97
|
+
|
98
|
+
return wd;
|
99
|
+
}
|
100
|
+
|
101
|
+
static void add_dir(int dir_wd, char *dir, int errors_fatal, int no_print)
|
102
|
+
{
|
103
|
+
char path[PATH_MAX + 1];
|
104
|
+
DIR *dh = opendir(dir);
|
105
|
+
struct dirent *ent;
|
106
|
+
struct stat st;
|
107
|
+
int dirl = strlen(dir), n = sizeof(path) - 1 - dirl, had_errors = 0, wd;
|
108
|
+
|
109
|
+
if (dirl > sizeof(path) - 3) {
|
110
|
+
ERROR("Too long path (not watched): ");
|
111
|
+
ERROR(dir);
|
112
|
+
ERROR("\n");
|
113
|
+
|
114
|
+
if (errors_fatal) exit(1);
|
115
|
+
return;
|
116
|
+
}
|
117
|
+
|
118
|
+
if (!dh) {
|
119
|
+
ERROR("Cannot opendir(");
|
120
|
+
ERROR(dir);
|
121
|
+
ERROR("): ");
|
122
|
+
ERROR(strerror(errno));
|
123
|
+
ERROR("\n");
|
124
|
+
|
125
|
+
if (errors_fatal) exit(1);
|
126
|
+
return;
|
127
|
+
}
|
128
|
+
|
129
|
+
strcpy(path, dir);
|
130
|
+
|
131
|
+
while ((ent = readdir(dh)) != NULL) {
|
132
|
+
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, ".unrealsync")) continue;
|
133
|
+
|
134
|
+
path[dirl] = '/';
|
135
|
+
path[dirl + 1] = 0;
|
136
|
+
strncat(path + dirl, ent->d_name, n);
|
137
|
+
path[sizeof(path) - 1] = 0;
|
138
|
+
if (lstat(path, &st)) {
|
139
|
+
ERROR("Cannot lstat(");
|
140
|
+
ERROR(path);
|
141
|
+
ERROR("): ");
|
142
|
+
ERROR(strerror(errno));
|
143
|
+
ERROR("\n");
|
144
|
+
had_errors = 1;
|
145
|
+
continue;
|
146
|
+
}
|
147
|
+
|
148
|
+
if (S_ISDIR(st.st_mode)) {
|
149
|
+
wd = add_dir_watch(dir_wd, path, ent->d_name, no_print);
|
150
|
+
if (wd < 0) continue;
|
151
|
+
add_dir(wd, path, errors_fatal, no_print);
|
152
|
+
}
|
153
|
+
}
|
154
|
+
|
155
|
+
closedir(dh);
|
156
|
+
|
157
|
+
if (errors_fatal && had_errors) exit(1);
|
158
|
+
}
|
159
|
+
|
160
|
+
void debug_print_mask(uint32_t mask)
|
161
|
+
{
|
162
|
+
if (mask & IN_DELETE_SELF) DEBUG_PRINT("IN_DELETE_SELF ");
|
163
|
+
if (mask & IN_MOVE_SELF) DEBUG_PRINT("IN_MOVE_SELF ");
|
164
|
+
if (mask & IN_MOVED_FROM) DEBUG_PRINT("IN_MOVED_FROM ");
|
165
|
+
if (mask & IN_MOVED_TO) DEBUG_PRINT("IN_MOVED_TO ");
|
166
|
+
if (mask & IN_CLOSE_WRITE) DEBUG_PRINT("IN_CLOSE_WRITE ");
|
167
|
+
if (mask & IN_MODIFY) DEBUG_PRINT("IN_MODIFY ");
|
168
|
+
if (mask & IN_IGNORED) DEBUG_PRINT("IN_IGNORED ");
|
169
|
+
if (mask & IN_ISDIR) DEBUG_PRINT("IN_ISDIR ");
|
170
|
+
if (mask & IN_Q_OVERFLOW) DEBUG_PRINT("IN_Q_OVERFLOW ");
|
171
|
+
if (mask & IN_UNMOUNT) DEBUG_PRINT("IN_UNMOUNT ");
|
172
|
+
if (mask & IN_CREATE) DEBUG_PRINT("IN_CREATE ");
|
173
|
+
}
|
174
|
+
|
175
|
+
static int do_watch(int max_watches)
|
176
|
+
{
|
177
|
+
struct inotify_event *ev = (struct inotify_event*)events_buf;
|
178
|
+
ssize_t n = 0, wd;
|
179
|
+
char path[PATH_MAX + 1];
|
180
|
+
|
181
|
+
watches = (_watchstruct*) calloc(max_watches, sizeof(_watchstruct));
|
182
|
+
if (!watches) {
|
183
|
+
ERROR("Cannot allocate memory\n");
|
184
|
+
exit(1);
|
185
|
+
}
|
186
|
+
|
187
|
+
DEBUG_PRINT("Doing initial watches setup\n");
|
188
|
+
|
189
|
+
ifd = inotify_init();
|
190
|
+
if (ifd == -1) {
|
191
|
+
perror("Cannot init inotify");
|
192
|
+
exit(1);
|
193
|
+
}
|
194
|
+
|
195
|
+
wd = add_dir_watch(0, watch_dir, "", 1);
|
196
|
+
if (wd < 0) {
|
197
|
+
ERROR("Cannot add dir watch\n");
|
198
|
+
exit(1);
|
199
|
+
}
|
200
|
+
add_dir(wd, watch_dir, 1, 1);
|
201
|
+
|
202
|
+
while ((n = read(ifd, events_buf, sizeof(events_buf))) > 0) {
|
203
|
+
ev = (struct inotify_event*)events_buf;
|
204
|
+
while (n > 0) {
|
205
|
+
if (ev->mask & IN_Q_OVERFLOW) {
|
206
|
+
ERROR("Queue overflow, restart needed\n");
|
207
|
+
exit(3);
|
208
|
+
}
|
209
|
+
|
210
|
+
if (ev->mask & IN_IGNORED) {
|
211
|
+
free(watches[ev->wd].name);
|
212
|
+
watches[ev->wd].parent_wd = -1;
|
213
|
+
watches[ev->wd].name = NULL;
|
214
|
+
goto loop_end;
|
215
|
+
}
|
216
|
+
|
217
|
+
wd_path(ev->wd, path);
|
218
|
+
PRINT("M ");
|
219
|
+
PRINT(path);
|
220
|
+
PRINT("\n");
|
221
|
+
#ifdef DEBUG
|
222
|
+
if (ev->len) {
|
223
|
+
DEBUG_PRINT(" | ");
|
224
|
+
DEBUG_PRINT("%s", ev->name);
|
225
|
+
}
|
226
|
+
DEBUG_PRINT(" | ");
|
227
|
+
debug_print_mask(ev->mask);
|
228
|
+
#endif
|
229
|
+
|
230
|
+
if ((ev->mask & IN_DELETE) || (ev->mask & IN_MOVED_FROM)) {
|
231
|
+
goto loop_end;
|
232
|
+
}
|
233
|
+
|
234
|
+
if (ev->mask & IN_ISDIR) {
|
235
|
+
if (ev->len + strlen(path) > sizeof(path) - 1) {
|
236
|
+
ERROR("Too deep directory: ");
|
237
|
+
ERROR(path);
|
238
|
+
ERROR(ev->name);
|
239
|
+
ERROR("\n");
|
240
|
+
goto loop_end;
|
241
|
+
}
|
242
|
+
strcat(path, ev->name);
|
243
|
+
wd = add_dir_watch(ev->wd, path, ev->name, 0);
|
244
|
+
if (wd < 0) goto loop_end;
|
245
|
+
add_dir(ev->wd, path, 0, 0);
|
246
|
+
}
|
247
|
+
|
248
|
+
loop_end:
|
249
|
+
n -= sizeof(struct inotify_event) + ev->len;
|
250
|
+
ev = (struct inotify_event*) ((char*)ev + sizeof(struct inotify_event) + ev->len);
|
251
|
+
}
|
252
|
+
|
253
|
+
PRINT("-\n");
|
254
|
+
}
|
255
|
+
|
256
|
+
perror("Cannot read() inotify queue");
|
257
|
+
exit(1);
|
258
|
+
}
|
259
|
+
|
260
|
+
int main(int argc, char *argv[])
|
261
|
+
{
|
262
|
+
int fd, n;
|
263
|
+
char buf[12];
|
264
|
+
|
265
|
+
if (argc != 2) {
|
266
|
+
ERROR("Usage: notify <dir>\n");
|
267
|
+
return 1;
|
268
|
+
}
|
269
|
+
|
270
|
+
fd = open("/proc/sys/fs/inotify/max_user_watches", O_RDONLY);
|
271
|
+
if (fd < 0) {
|
272
|
+
perror("Cannot open /proc/sys/fs/inotify/max_user_watches");
|
273
|
+
return 1;
|
274
|
+
}
|
275
|
+
|
276
|
+
if ( (n = read(fd, buf, sizeof(buf) - 1)) < 0) {
|
277
|
+
perror("Cannot read() /proc/sys/fs/inotify/max_user_watches");
|
278
|
+
return 1;
|
279
|
+
}
|
280
|
+
|
281
|
+
buf[n] = 0;
|
282
|
+
max_watches = atoi(buf) * 2;
|
283
|
+
if (max_watches <= 0) {
|
284
|
+
ERROR("Incorrect number of watches: ");
|
285
|
+
ERROR(buf);
|
286
|
+
ERROR("\n");
|
287
|
+
return 1;
|
288
|
+
} else {
|
289
|
+
DEBUG_PRINT("Max watches: %d\n", max_watches);
|
290
|
+
}
|
291
|
+
|
292
|
+
watch_dir = argv[1];
|
293
|
+
do_watch(max_watches);
|
294
|
+
|
295
|
+
return 0;
|
296
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
The utility has been built using the following command under Ubuntu Linux 11.10 32-bit:
|
2
|
+
|
3
|
+
g++ -static -s -I. *.cpp /usr/lib/libpopt.a -o notify
|
4
|
+
|
5
|
+
Or, to achieve the minimal size of the binary:
|
6
|
+
|
7
|
+
g++ -static -s -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -I. *.cpp /usr/lib/libpopt.a -o notify
|
8
|
+
|
9
|
+
You might need to change path to libpopt to whatever location it is on your system.
|
10
|
+
Libpopt is the only dependency aside from g++ if you want to build the utility.
|
11
|
+
It comes pre-built statically with realsync, so it will most probably just work
|
@@ -0,0 +1,14 @@
|
|
1
|
+
This is a daemon that notifies about filesystem changes in the following form:
|
2
|
+
|
3
|
+
M /path/to/changed/file
|
4
|
+
M /path/to/other/changed/file
|
5
|
+
-
|
6
|
+
|
7
|
+
The daemon is based on kfsmd-0.3.3 and tuned a little bit to be more realtime
|
8
|
+
The original kfsmd-0.3.3 could be found at http://sourceforge.net/projects/witme/files/kfsmd/
|
9
|
+
The preferred way to use this daemon is to run the following:
|
10
|
+
|
11
|
+
./notify watch /path/to/watch | uniq
|
12
|
+
|
13
|
+
You can get rid of "| uniq", but in this case you will get multiple lines per each file
|
14
|
+
for each type of event (e.g. OPEN/WRITE/CLOSE)
|
@@ -0,0 +1,165 @@
|
|
1
|
+
/******************************************************************************
|
2
|
+
*******************************************************************************
|
3
|
+
*******************************************************************************
|
4
|
+
|
5
|
+
|
6
|
+
kernel-filesystem-monitor-daemon-cat
|
7
|
+
Copyright (C) 2005 Ben Martin
|
8
|
+
|
9
|
+
This program is free software; you can redistribute it and/or modify
|
10
|
+
it under the terms of the GNU General Public License as published by
|
11
|
+
the Free Software Foundation; either version 2 of the License, or
|
12
|
+
(at your option) any later version.
|
13
|
+
|
14
|
+
This program is distributed in the hope that it will be useful,
|
15
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17
|
+
GNU General Public License for more details.
|
18
|
+
|
19
|
+
You should have received a copy of the GNU General Public License
|
20
|
+
along with this program; if not, write to the Free Software
|
21
|
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
22
|
+
|
23
|
+
For more details see the COPYING file in the root directory of this
|
24
|
+
distribution.
|
25
|
+
|
26
|
+
$Id: kernel-filesystem-monitor-daemon-cat.cpp,v 1.3 2008/05/25 21:30:52 ben Exp $
|
27
|
+
|
28
|
+
*******************************************************************************
|
29
|
+
*******************************************************************************
|
30
|
+
******************************************************************************/
|
31
|
+
|
32
|
+
#include <iostream>
|
33
|
+
#include "kernel-filesystem-monitor-daemon.hh"
|
34
|
+
#include <stdlib.h>
|
35
|
+
|
36
|
+
using namespace std;
|
37
|
+
|
38
|
+
|
39
|
+
const char* PROGRAM_NAME = "kernel-filesystem-monitor-cat";
|
40
|
+
|
41
|
+
void usage(poptContext optCon, int exitcode, char *error, char *addl)
|
42
|
+
{
|
43
|
+
poptPrintUsage(optCon, stderr, 0);
|
44
|
+
if (error) fprintf(stderr, "%s: %s0", error, addl);
|
45
|
+
exit(exitcode);
|
46
|
+
}
|
47
|
+
|
48
|
+
/********************************************************************************/
|
49
|
+
/********************************************************************************/
|
50
|
+
/********************************************************************************/
|
51
|
+
/********************************************************************************/
|
52
|
+
/********************************************************************************/
|
53
|
+
/********************************************************************************/
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
class KernelFileSystemMonitorDaemonCat
|
58
|
+
:
|
59
|
+
public KernelFileSystemMonitorDaemon
|
60
|
+
{
|
61
|
+
protected:
|
62
|
+
|
63
|
+
virtual void handle_event( struct inotify_event *pevent, time_t tt );
|
64
|
+
virtual void Closedown();
|
65
|
+
virtual void setupWorkingDirToPersistentDirIDMapping( long wd, const string& earl );
|
66
|
+
|
67
|
+
void
|
68
|
+
event_batch_start( time_t tt )
|
69
|
+
{}
|
70
|
+
|
71
|
+
void
|
72
|
+
event_batch_end( time_t tt )
|
73
|
+
{}
|
74
|
+
|
75
|
+
|
76
|
+
public:
|
77
|
+
|
78
|
+
string homedir;
|
79
|
+
|
80
|
+
KernelFileSystemMonitorDaemonCat()
|
81
|
+
{}
|
82
|
+
};
|
83
|
+
|
84
|
+
|
85
|
+
void
|
86
|
+
KernelFileSystemMonitorDaemonCat::setupWorkingDirToPersistentDirIDMapping(
|
87
|
+
long wd, const string& earl )
|
88
|
+
{
|
89
|
+
}
|
90
|
+
|
91
|
+
void
|
92
|
+
KernelFileSystemMonitorDaemonCat::handle_event( struct inotify_event *pevent, time_t tt )
|
93
|
+
{
|
94
|
+
print_event( pevent );
|
95
|
+
fflush(stdout);
|
96
|
+
}
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
void
|
101
|
+
KernelFileSystemMonitorDaemonCat::Closedown()
|
102
|
+
{
|
103
|
+
}
|
104
|
+
|
105
|
+
int main( int argc, char** argv )
|
106
|
+
{
|
107
|
+
unsigned long RunInForground = 0;
|
108
|
+
const char* homedir_CSTR = 0;
|
109
|
+
|
110
|
+
KernelFileSystemMonitorDaemonCat* daemon
|
111
|
+
= new KernelFileSystemMonitorDaemonCat();
|
112
|
+
|
113
|
+
struct poptOption optionsTable[] =
|
114
|
+
{
|
115
|
+
{ "forground", 'F', POPT_ARG_NONE, &RunInForground, 0,
|
116
|
+
"Don't run the daemon in the background", "" },
|
117
|
+
|
118
|
+
{ "homedir", 'H', POPT_ARG_STRING, &homedir_CSTR, 0,
|
119
|
+
"Home directory for user doing the monitoring", "" },
|
120
|
+
|
121
|
+
{ 0, 0, POPT_ARG_INCLUDE_TABLE, daemon->getPopTable(), \
|
122
|
+
0, "generic kfsmd daemon options:", 0 },
|
123
|
+
|
124
|
+
{ "verbose", 'v', POPT_ARG_NONE, &Verbose, 0,
|
125
|
+
"output more info", "" },
|
126
|
+
|
127
|
+
|
128
|
+
POPT_AUTOHELP
|
129
|
+
POPT_TABLEEND
|
130
|
+
};
|
131
|
+
poptContext optCon;
|
132
|
+
|
133
|
+
optCon = poptGetContext(PROGRAM_NAME, argc, (const char**)argv, optionsTable, 0);
|
134
|
+
poptSetOtherOptionHelp(optCon, "[OPTIONS]* [IGNOREPFX URL]* [WATCH URL]+ ...");
|
135
|
+
|
136
|
+
|
137
|
+
/* Now do options processing */
|
138
|
+
char c=-1;
|
139
|
+
while ((c = poptGetNextOpt(optCon)) >= 0)
|
140
|
+
{
|
141
|
+
}
|
142
|
+
|
143
|
+
daemon->ParseWatchOptions( optCon );
|
144
|
+
daemon->setRunInForground( true );
|
145
|
+
daemon->setupSignalHandlers();
|
146
|
+
|
147
|
+
daemon->homedir = getHomeDir( homedir_CSTR );
|
148
|
+
|
149
|
+
try
|
150
|
+
{
|
151
|
+
if( Verbose )
|
152
|
+
cerr << "setting up watches" << endl;
|
153
|
+
daemon->setupWatches();
|
154
|
+
if( Verbose )
|
155
|
+
cerr << "calling run" << endl;
|
156
|
+
return daemon->run();
|
157
|
+
}
|
158
|
+
catch( exception& e )
|
159
|
+
{
|
160
|
+
cerr << "Exiting due to error reason:" << e.what() << endl;
|
161
|
+
}
|
162
|
+
|
163
|
+
return 0;
|
164
|
+
}
|
165
|
+
|