Update dmon from septag/dmon commit 74bbd93b
The new version includes fixes from jgmdev, github PR: https://github.com/septag/dmon/pull/11 to solve incorrect behavior on linux not reporting directory creation. Includes also a further revision from septag.
This commit is contained in:
parent
31479a4ad7
commit
5f06a0a871
94
src/dmon.h
94
src/dmon.h
|
@ -753,6 +753,10 @@ _DMON_PRIVATE void dmon__watch_recursive(const char* dirname, int fd, uint32_t m
|
||||||
|
|
||||||
dmon__watch_subdir subdir;
|
dmon__watch_subdir subdir;
|
||||||
dmon__strcpy(subdir.rootdir, sizeof(subdir.rootdir), watchdir);
|
dmon__strcpy(subdir.rootdir, sizeof(subdir.rootdir), watchdir);
|
||||||
|
if (strstr(subdir.rootdir, watch->rootdir) == subdir.rootdir) {
|
||||||
|
dmon__strcpy(subdir.rootdir, sizeof(subdir.rootdir), watchdir + strlen(watch->rootdir));
|
||||||
|
}
|
||||||
|
|
||||||
stb_sb_push(watch->subdirs, subdir);
|
stb_sb_push(watch->subdirs, subdir);
|
||||||
stb_sb_push(watch->wds, wd);
|
stb_sb_push(watch->wds, wd);
|
||||||
|
|
||||||
|
@ -763,6 +767,19 @@ _DMON_PRIVATE void dmon__watch_recursive(const char* dirname, int fd, uint32_t m
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_DMON_PRIVATE const char* dmon__find_subdir(const dmon__watch_state* watch, int wd)
|
||||||
|
{
|
||||||
|
const int* wds = watch->wds;
|
||||||
|
for (int i = 0, c = stb_sb_count(wds); i < c; i++) {
|
||||||
|
if (wd == wds[i]) {
|
||||||
|
return watch->subdirs[i].rootdir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DMON_ASSERT(0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
_DMON_PRIVATE void dmon__inotify_process_events(void)
|
_DMON_PRIVATE void dmon__inotify_process_events(void)
|
||||||
{
|
{
|
||||||
for (int i = 0, c = stb_sb_count(_dmon.events); i < c; i++) {
|
for (int i = 0, c = stb_sb_count(_dmon.events); i < c; i++) {
|
||||||
|
@ -772,43 +789,54 @@ _DMON_PRIVATE void dmon__inotify_process_events(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove redundant modify events on a single file
|
// remove redundant modify events on a single file
|
||||||
if (ev->mask == IN_MODIFY) {
|
if (ev->mask & IN_MODIFY) {
|
||||||
for (int j = i + 1; j < c; j++) {
|
for (int j = i + 1; j < c; j++) {
|
||||||
dmon__inotify_event* check_ev = &_dmon.events[j];
|
dmon__inotify_event* check_ev = &_dmon.events[j];
|
||||||
if (check_ev->mask == IN_MODIFY && strcmp(ev->filepath, check_ev->filepath) == 0) {
|
if ((check_ev->mask & IN_MODIFY) && strcmp(ev->filepath, check_ev->filepath) == 0) {
|
||||||
|
ev->skip = true;
|
||||||
|
break;
|
||||||
|
} else if ((ev->mask & IN_ISDIR) && (check_ev->mask & (IN_ISDIR|IN_MODIFY))) {
|
||||||
|
// in some cases, particularly when created files under sub directories
|
||||||
|
// there can be two modify events for a single subdir one with trailing slash and one without
|
||||||
|
// remove traling slash from both cases and test
|
||||||
|
int l1 = strlen(ev->filepath);
|
||||||
|
int l2 = strlen(check_ev->filepath);
|
||||||
|
if (ev->filepath[l1-1] == '/') ev->filepath[l1-1] = '\0';
|
||||||
|
if (check_ev->filepath[l2-1] == '/') check_ev->filepath[l2-1] = '\0';
|
||||||
|
if (strcmp(ev->filepath, check_ev->filepath) == 0) {
|
||||||
ev->skip = true;
|
ev->skip = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (ev->mask == IN_CREATE) {
|
}
|
||||||
|
} else if (ev->mask & IN_CREATE) {
|
||||||
bool loop_break = false;
|
bool loop_break = false;
|
||||||
for (int j = i + 1; j < c && !loop_break; j++) {
|
for (int j = i + 1; j < c && !loop_break; j++) {
|
||||||
dmon__inotify_event* check_ev = &_dmon.events[j];
|
dmon__inotify_event* check_ev = &_dmon.events[j];
|
||||||
if (check_ev->mask == IN_MOVED_FROM &&
|
if ((check_ev->mask & IN_MOVED_FROM) && strcmp(ev->filepath, check_ev->filepath) == 0) {
|
||||||
strcmp(ev->filepath, check_ev->filepath) == 0) {
|
|
||||||
// there is a case where some programs (like gedit):
|
// there is a case where some programs (like gedit):
|
||||||
// when we save, it creates a temp file, and moves it to the file being modified
|
// when we save, it creates a temp file, and moves it to the file being modified
|
||||||
// search for these cases and remove all of them
|
// search for these cases and remove all of them
|
||||||
for (int k = j + 1; k < c; k++) {
|
for (int k = j + 1; k < c; k++) {
|
||||||
dmon__inotify_event* third_ev = &_dmon.events[k];
|
dmon__inotify_event* third_ev = &_dmon.events[k];
|
||||||
if (third_ev->mask == IN_MOVED_TO && check_ev->cookie == third_ev->cookie) {
|
if (third_ev->mask & IN_MOVED_TO && check_ev->cookie == third_ev->cookie) {
|
||||||
third_ev->mask = IN_MODIFY; // change to modified
|
third_ev->mask = IN_MODIFY; // change to modified
|
||||||
ev->skip = check_ev->skip = true;
|
ev->skip = check_ev->skip = true;
|
||||||
loop_break = true;
|
loop_break = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (check_ev->mask == IN_MODIFY && strcmp(ev->filepath, check_ev->filepath) == 0) {
|
} else if ((check_ev->mask & IN_MODIFY) && strcmp(ev->filepath, check_ev->filepath) == 0) {
|
||||||
// Another case is that file is copied. CREATE and MODIFY happens sequentially
|
// Another case is that file is copied. CREATE and MODIFY happens sequentially
|
||||||
// so we ignore MODIFY event
|
// so we ignore MODIFY event
|
||||||
check_ev->skip = true;
|
check_ev->skip = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (ev->mask == IN_MOVED_FROM) {
|
} else if (ev->mask & IN_MOVED_FROM) {
|
||||||
bool move_valid = false;
|
bool move_valid = false;
|
||||||
for (int j = i + 1; j < c; j++) {
|
for (int j = i + 1; j < c; j++) {
|
||||||
dmon__inotify_event* check_ev = &_dmon.events[j];
|
dmon__inotify_event* check_ev = &_dmon.events[j];
|
||||||
if (check_ev->mask == IN_MOVED_TO && ev->cookie == check_ev->cookie) {
|
if (check_ev->mask & IN_MOVED_TO && ev->cookie == check_ev->cookie) {
|
||||||
move_valid = true;
|
move_valid = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -820,11 +848,11 @@ _DMON_PRIVATE void dmon__inotify_process_events(void)
|
||||||
if (!move_valid) {
|
if (!move_valid) {
|
||||||
ev->mask = IN_DELETE;
|
ev->mask = IN_DELETE;
|
||||||
}
|
}
|
||||||
} else if (ev->mask == IN_MOVED_TO) {
|
} else if (ev->mask & IN_MOVED_TO) {
|
||||||
bool move_valid = false;
|
bool move_valid = false;
|
||||||
for (int j = 0; j < i; j++) {
|
for (int j = 0; j < i; j++) {
|
||||||
dmon__inotify_event* check_ev = &_dmon.events[j];
|
dmon__inotify_event* check_ev = &_dmon.events[j];
|
||||||
if (check_ev->mask == IN_MOVED_FROM && ev->cookie == check_ev->cookie) {
|
if (check_ev->mask & IN_MOVED_FROM && ev->cookie == check_ev->cookie) {
|
||||||
move_valid = true;
|
move_valid = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -851,26 +879,45 @@ _DMON_PRIVATE void dmon__inotify_process_events(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ev->mask) {
|
if (ev->mask & IN_CREATE) {
|
||||||
case IN_CREATE:
|
if (ev->mask & IN_ISDIR) {
|
||||||
|
if (watch->watch_flags & DMON_WATCHFLAGS_RECURSIVE) {
|
||||||
|
char watchdir[DMON_MAX_PATH];
|
||||||
|
dmon__strcpy(watchdir, sizeof(watchdir), watch->rootdir);
|
||||||
|
dmon__strcat(watchdir, sizeof(watchdir), ev->filepath);
|
||||||
|
dmon__strcat(watchdir, sizeof(watchdir), "/");
|
||||||
|
uint32_t mask = IN_MOVED_TO | IN_CREATE | IN_MOVED_FROM | IN_DELETE | IN_MODIFY;
|
||||||
|
int wd = inotify_add_watch(watch->fd, watchdir, mask);
|
||||||
|
_DMON_UNUSED(wd);
|
||||||
|
DMON_ASSERT(wd != -1);
|
||||||
|
|
||||||
|
dmon__watch_subdir subdir;
|
||||||
|
dmon__strcpy(subdir.rootdir, sizeof(subdir.rootdir), watchdir);
|
||||||
|
if (strstr(subdir.rootdir, watch->rootdir) == subdir.rootdir) {
|
||||||
|
dmon__strcpy(subdir.rootdir, sizeof(subdir.rootdir), watchdir + strlen(watch->rootdir));
|
||||||
|
}
|
||||||
|
|
||||||
|
stb_sb_push(watch->subdirs, subdir);
|
||||||
|
stb_sb_push(watch->wds, wd);
|
||||||
|
}
|
||||||
|
}
|
||||||
watch->watch_cb(ev->watch_id, DMON_ACTION_CREATE, watch->rootdir, ev->filepath, NULL, watch->user_data);
|
watch->watch_cb(ev->watch_id, DMON_ACTION_CREATE, watch->rootdir, ev->filepath, NULL, watch->user_data);
|
||||||
break;
|
}
|
||||||
case IN_MODIFY:
|
else if (ev->mask & IN_MODIFY) {
|
||||||
watch->watch_cb(ev->watch_id, DMON_ACTION_MODIFY, watch->rootdir, ev->filepath, NULL, watch->user_data);
|
watch->watch_cb(ev->watch_id, DMON_ACTION_MODIFY, watch->rootdir, ev->filepath, NULL, watch->user_data);
|
||||||
break;
|
}
|
||||||
case IN_MOVED_FROM: {
|
else if (ev->mask & IN_MOVED_FROM) {
|
||||||
for (int j = i + 1; j < c; j++) {
|
for (int j = i + 1; j < c; j++) {
|
||||||
dmon__inotify_event* check_ev = &_dmon.events[j];
|
dmon__inotify_event* check_ev = &_dmon.events[j];
|
||||||
if (check_ev->mask == IN_MOVED_TO && ev->cookie == check_ev->cookie) {
|
if (check_ev->mask & IN_MOVED_TO && ev->cookie == check_ev->cookie) {
|
||||||
watch->watch_cb(check_ev->watch_id, DMON_ACTION_MOVE, watch->rootdir,
|
watch->watch_cb(check_ev->watch_id, DMON_ACTION_MOVE, watch->rootdir,
|
||||||
check_ev->filepath, ev->filepath, watch->user_data);
|
check_ev->filepath, ev->filepath, watch->user_data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
case IN_DELETE:
|
else if (ev->mask & IN_DELETE) {
|
||||||
watch->watch_cb(ev->watch_id, DMON_ACTION_DELETE, watch->rootdir, ev->filepath, NULL, watch->user_data);
|
watch->watch_cb(ev->watch_id, DMON_ACTION_DELETE, watch->rootdir, ev->filepath, NULL, watch->user_data);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,7 +975,8 @@ static void* dmon__thread(void* arg)
|
||||||
struct inotify_event* iev = (struct inotify_event*)&buff[offset];
|
struct inotify_event* iev = (struct inotify_event*)&buff[offset];
|
||||||
|
|
||||||
char filepath[DMON_MAX_PATH];
|
char filepath[DMON_MAX_PATH];
|
||||||
dmon__strcpy(filepath, sizeof(filepath), iev->name);
|
dmon__strcpy(filepath, sizeof(filepath), dmon__find_subdir(watch, iev->wd));
|
||||||
|
dmon__strcat(filepath, sizeof(filepath), iev->name);
|
||||||
|
|
||||||
// TODO: ignore directories if flag is set
|
// TODO: ignore directories if flag is set
|
||||||
|
|
||||||
|
@ -1068,7 +1116,7 @@ DMON_API_IMPL dmon_watch_id dmon_watch(const char* rootdir,
|
||||||
return dmon__make_id(0);
|
return dmon__make_id(0);
|
||||||
}
|
}
|
||||||
dmon__watch_subdir subdir;
|
dmon__watch_subdir subdir;
|
||||||
dmon__strcpy(subdir.rootdir, sizeof(subdir.rootdir), watch->rootdir);
|
dmon__strcpy(subdir.rootdir, sizeof(subdir.rootdir), ""); // root dir is just a dummy entry
|
||||||
stb_sb_push(watch->subdirs, subdir);
|
stb_sb_push(watch->subdirs, subdir);
|
||||||
stb_sb_push(watch->wds, wd);
|
stb_sb_push(watch->wds, wd);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue