int get_inotify_fd();
int get_watch_count();
bool watch_limit_reached();
-int watch(const char* root);
+int watch(const char* root, array* mounts);
void unwatch(int id);
bool process_inotify_input();
void close_inotify();
// reads one line from stream, trims trailing carriage return if any
-// returns pointer to the internal buffer (will be overwriten on next call)
+// returns pointer to the internal buffer (will be overwritten on next call)
char* read_line(FILE* stream);
+
+// path comparison
+bool is_parent_path(const char* parent_path, const char* child_path);
+
+
#endif
}
-static int walk_tree(const char* path, watch_node* parent, bool recursive) {
+static int walk_tree(const char* path, watch_node* parent, bool recursive, array* mounts) {
+ for (int j=0; j<array_size(mounts); j++) {
+ char* mount = array_get(mounts, j);
+ if (strncmp(path, mount, strlen(mount)) == 0) {
+ userlog(LOG_DEBUG, "watch path '%s' crossed mount point '%s' - skipping", path, mount);
+ return ERR_IGNORE;
+ }
+ }
+
DIR* dir = NULL;
if (recursive) {
if ((dir = opendir(path)) == NULL) {
strcpy(p, entry->d_name);
- int subdir_id = walk_tree(subdir, table_get(watches, id), recursive);
+ int subdir_id = walk_tree(subdir, table_get(watches, id), recursive, mounts);
if (subdir_id < 0 && subdir_id != ERR_IGNORE) {
rm_watch(id, true);
id = subdir_id;
}
-int watch(const char* root) {
+int watch(const char* root, array* mounts) {
bool recursive = true;
if (root[0] == '|') {
root++;
return ERR_IGNORE;
}
- return walk_tree(root, NULL, recursive);
+ return walk_tree(root, NULL, recursive, mounts);
}
}
if (is_dir && ((event->mask & IN_CREATE) == IN_CREATE || (event->mask & IN_MOVED_TO) == IN_MOVED_TO)) {
- int result = walk_tree(path, node, true);
+ int result = walk_tree(path, node, true, NULL);
if (result < 0 && result != ERR_IGNORE) {
return false;
}
continue;
}
- char* skip = NULL;
+ array* inner_mounts = array_create(5);
+ CHECK_NULL(inner_mounts, false);
+
+ bool skip = false;
for (int j=0; j<array_size(mounts); j++) {
char* mount = array_get(mounts, j);
- if (strncmp(mount, unflattened, strlen(mount)) == 0) {
- userlog(LOG_DEBUG, "path %s is under unwatchable %s - ignoring", unflattened, mount);
- skip = strdup(unflattened);
- CHECK_NULL(skip, false);
+ if (is_parent_path(mount, unflattened)) {
+ userlog(LOG_DEBUG, "watch root '%s' is under mount point '%s' - skipping", unflattened, mount);
+ CHECK_NULL(array_push(unwatchable, strdup(unflattened)), false);
+ skip = true;
break;
}
+ else if (is_parent_path(unflattened, mount)) {
+ userlog(LOG_DEBUG, "watch root '%s' contains mount point '%s' - partial watch", unflattened, mount);
+ char* copy = strdup(mount);
+ CHECK_NULL(array_push(unwatchable, copy), false);
+ CHECK_NULL(array_push(inner_mounts, copy), false);
+ }
}
- if (skip != NULL) {
- CHECK_NULL(array_push(unwatchable, skip), false);
+ if (skip) {
continue;
}
- // todo: consider a mount point under a watch root?
- int id = watch(new_root);
+ int id = watch(new_root, inner_mounts);
+ array_delete(inner_mounts);
if (id >= 0) {
watch_root* root = malloc(sizeof(watch_root));
if [ $? -eq 0 ] ; then
echo "compiling 64-bit version"
clang -m64 -O2 -Wall -std=c99 -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -o fsnotifier64 main.c inotify.c util.c
+ if [ $? -eq 0 ] ; then
+ chmod 755 fsnotifier fsnotifier64
+ fi
fi
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
}
return input_buf;
}
+
+
+bool is_parent_path(const char* parent_path, const char* child_path) {
+ size_t parent_len = strlen(parent_path);
+ return strncmp(parent_path, child_path, parent_len) == 0 &&
+ (parent_len == strlen(child_path) || child_path[parent_len] == '/');
+}