diff --git a/bin/linux/fsnotifier b/bin/linux/fsnotifier index e248974f4a94..f7a73126a13e 100755 Binary files a/bin/linux/fsnotifier and b/bin/linux/fsnotifier differ diff --git a/bin/linux/fsnotifier64 b/bin/linux/fsnotifier64 index efba253b08b3..1fc4f32ff7ef 100755 Binary files a/bin/linux/fsnotifier64 and b/bin/linux/fsnotifier64 differ diff --git a/native/fsNotifier/linux/fsnotifier.h b/native/fsNotifier/linux/fsnotifier.h index 0ee04cd12639..f3234e2fde9d 100644 --- a/native/fsNotifier/linux/fsnotifier.h +++ b/native/fsNotifier/linux/fsnotifier.h @@ -1,5 +1,5 @@ /* - * 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. @@ -24,6 +24,8 @@ // logging void userlog(int priority, const char* format, ...); +#define CHECK_NULL(p, r) if (p == NULL) { userlog(LOG_ERR, "out of memory"); return r; } + // variable-length array typedef struct __array array; @@ -38,7 +40,7 @@ void array_delete(array* a); void array_delete_vs_data(array* a); -// key/value pairs table +// poor man's hash table typedef struct __table table; table* table_create(int capacity); diff --git a/native/fsNotifier/linux/inotify.c b/native/fsNotifier/linux/inotify.c index ab605424d66c..04d749e48d83 100644 --- a/native/fsNotifier/linux/inotify.c +++ b/native/fsNotifier/linux/inotify.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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. @@ -32,8 +32,6 @@ #define DEFAULT_SUBDIR_COUNT 5 -#define CHECK_NULL(p) if (p == NULL) { userlog(LOG_ERR, "out of memory"); return ERR_ABORT; } - typedef struct __watch_node { char* name; int wd; @@ -153,9 +151,9 @@ static int add_watch(const char* path, watch_node* parent) { node = malloc(sizeof(watch_node)); - CHECK_NULL(node); + CHECK_NULL(node, ERR_ABORT); node->name = strdup(path); - CHECK_NULL(node->name); + CHECK_NULL(node->name, ERR_ABORT); node->wd = wd; node->parent = parent; node->kids = NULL; @@ -163,9 +161,9 @@ static int add_watch(const char* path, watch_node* parent) { if (parent != NULL) { if (parent->kids == NULL) { parent->kids = array_create(DEFAULT_SUBDIR_COUNT); - CHECK_NULL(parent->kids); + CHECK_NULL(parent->kids, ERR_ABORT); } - CHECK_NULL(array_push(parent->kids, node)); + CHECK_NULL(array_push(parent->kids, node), ERR_ABORT); } if (table_put(watches, wd, node) == NULL) { @@ -238,25 +236,31 @@ static bool is_ignored(const char* path, array* ignores) { return false; } -static int walk_tree(const char* path, watch_node* parent, array* ignores) { +static int walk_tree(const char* path, watch_node* parent, array* ignores, bool recursive) { if (is_ignored(path, ignores)) { return ERR_IGNORE; } - DIR* dir = opendir(path); - if (dir == NULL) { - if (errno == EACCES) { - return ERR_IGNORE; + DIR* dir; + if (recursive) { + dir = opendir(path); + if (dir == NULL) { + if (errno == EACCES) { + return ERR_IGNORE; + } + else if (errno == ENOTDIR) { // "future" root + return add_watch(path, parent); + } + userlog(LOG_ERR, "opendir(%s): %s", path, strerror(errno)); + return ERR_CONTINUE; } - else if (errno == ENOTDIR) { // flat root - return add_watch(path, parent); - } - userlog(LOG_ERR, "opendir(%s): %s", path, strerror(errno)); - return ERR_CONTINUE; } int id = add_watch(path, parent); - if (id < 0) { + if (!recursive) { + return id; + } + else if (id < 0) { closedir(dir); return id; } @@ -279,7 +283,7 @@ static int walk_tree(const char* path, watch_node* parent, array* ignores) { continue; } - int subdir_id = walk_tree(subdir, table_get(watches, id), ignores); + int subdir_id = walk_tree(subdir, table_get(watches, id), ignores, recursive); if (subdir_id < 0 && subdir_id != ERR_IGNORE) { rm_watch(id, true); id = subdir_id; @@ -293,9 +297,15 @@ static int walk_tree(const char* path, watch_node* parent, array* ignores) { int watch(const char* root, array* ignores) { + bool recursive = true; + if (root[0] == '|') { + root++; + recursive = false; + } + char buf[PATH_MAX]; const char* normalized = realpath(root, buf); - return walk_tree((normalized != NULL ? normalized : root), NULL, ignores); + return walk_tree((normalized != NULL ? normalized : root), NULL, ignores, recursive); } @@ -323,7 +333,7 @@ static bool process_inotify_event(struct inotify_event* event) { } if ((event->mask & IN_CREATE || event->mask & IN_MOVED_TO) && event->mask & IN_ISDIR) { - int result = walk_tree(path, node, NULL); + int result = walk_tree(path, node, NULL, true); if (result < 0 && result != ERR_IGNORE) { return false; } diff --git a/native/fsNotifier/linux/main.c b/native/fsNotifier/linux/main.c index 3bef18521151..81dcdfead702 100644 --- a/native/fsNotifier/linux/main.c +++ b/native/fsNotifier/linux/main.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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. @@ -33,7 +33,7 @@ #define LOG_ENV_ERROR "error" #define LOG_ENV_OFF "off" -#define VERSION "1.0" +#define VERSION "1.1" #define VERSION_MSG "fsnotifier " VERSION "\n" #define USAGE_MSG \ @@ -58,11 +58,8 @@ typedef struct { static array* roots = NULL; static bool show_warning = true; - static bool self_test = false; -#define CHECK_NULL(p) if (p == NULL) { userlog(LOG_ERR, "out of memory"); return false; } - static void init_log(); static void run_self_test(); static void main_loop(); @@ -223,7 +220,7 @@ static bool read_input() { if (strcmp(line, "ROOTS") == 0) { array* new_roots = array_create(20); - CHECK_NULL(new_roots); + CHECK_NULL(new_roots, false); while (1) { line = read_line(stdin); @@ -235,12 +232,9 @@ static bool read_input() { break; } else { - if (line[0] == '|') line++; // flat roots will be differentiated later - int l = strlen(line); if (l > 1 && line[l-1] == '/') line[l-1] = '\0'; - - CHECK_NULL(array_push(new_roots, strdup(line))); + CHECK_NULL(array_push(new_roots, strdup(line)), false); } } @@ -266,7 +260,7 @@ static bool update_roots(array* new_roots) { } array* unwatchable = array_create(20); - CHECK_NULL(unwatchable); + CHECK_NULL(unwatchable, false); if (!unwatchable_mounts(unwatchable)) { return false; } @@ -312,10 +306,10 @@ static bool register_roots(array* new_roots, array* unwatchable) { } else if (id >= 0) { watch_root* root = malloc(sizeof(watch_root)); - CHECK_NULL(root); + CHECK_NULL(root, false); root->id = id; root->name = new_root; - CHECK_NULL(array_push(roots, root)); + CHECK_NULL(array_push(roots, root), false); } else { if (show_warning && watch_limit_reached()) { @@ -324,7 +318,7 @@ static bool register_roots(array* new_roots, array* unwatchable) { output("MESSAGE\n" INOTIFY_LIMIT_MSG, limit); show_warning = false; // warn only once } - CHECK_NULL(array_push(unwatchable, new_root)); + CHECK_NULL(array_push(unwatchable, new_root), false); } } @@ -362,7 +356,7 @@ static bool unwatchable_mounts(array* mounts) { } if (!is_watchable(dev, point, fs)) { - CHECK_NULL(array_push(mounts, strdup(point))); + CHECK_NULL(array_push(mounts, strdup(point)), false); } }