mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Linux file watcher: do not dive into flat roots
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user