Archived
1
0
Fork 0
This repository has been archived on 2026-05-10. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
archived/src/inotify-map.c
Henrik Hautakoski f46ae1970b Change indentation to follow the updated standard.
Alot of mixed indentation. use 4 chars wide soft tabs.
2011-03-19 12:28:48 +02:00

209 lines
4.4 KiB
C

/* inotify-map.c
*
* (C) Copyright 2011 Henrik Hautakoski <henrik@fiktivkod.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <string.h>
#include "xalloc.h"
#include "rbtree.h"
#include "path.h"
#include "inotify-watch.h"
#include "inotify-map.h"
static void wd_free(void *ptr);
static int wd_cmp(const void *a, const void *b);
static int path_cmp(const void *a, const void *b);
static struct watch watch_root;
/* wd -> list of struct watch* */
static rbtree tree_wd_paths = RBTREE_INIT(wd_cmp);
/* path -> struct watch* */
static rbtree tree_path_wd = RBTREE_INIT(path_cmp);
static int wd_cmp(const void *a, const void *b) {
struct watch *n1 = ((struct list*)a)->items[0];
struct watch *n2 = ((struct list*)b)->items[0];
return n1->wd - n2->wd;
}
static int path_cmp(const void *a, const void *b) {
return strcmp(((struct watch*)a)->path, ((struct watch*)b)->path);
}
static void wd_free(void *list) {
list_destroy(list);
}
static struct watch* new_node(int wd, const char *path) {
struct watch s, *p;
s.path = path;
/* find parent */
for(;;) {
s.path = dirname_s(s.path, 1);
p = rbtree_search(&tree_path_wd, &s);
if (p)
break;
if (!strcmp(s.path, "/") ||
!strcmp(s.path, "./")) {
p = &watch_root;
break;
}
}
return inotify_watch_add(p, inotify_watch_new(wd, path));
}
static struct list* wd_lookup(int wd) {
struct watch n, *np = &n;
struct list s = { (void**)&np, 1 };
n.wd = wd;
return rbtree_search(&tree_wd_paths, &s);
}
static void map_path(struct watch *w) {
rbtree_insert(&tree_path_wd, w);
}
static void map_wd(struct watch *w) {
struct list s = { (void**)&w, 1 };
struct list *l = rbtree_search(&tree_wd_paths, &s);
if (l) {
list_insert(l, w);
} else {
l = list_create();
list_insert(l, w);
rbtree_insert(&tree_wd_paths, l);
}
}
void inotify_map(int wd, const char *path) {
struct watch s, *n;
s.path = path;
n = rbtree_search(&tree_path_wd, &s);
if (!n) {
n = new_node(wd, path);
map_path(n);
map_wd(n);
}
}
static void unmap_path(struct watch *watch) {
rbtree_delete(&tree_path_wd, watch);
}
static int unmap_wd(struct watch *watch) {
int index;
struct list s = { (void**)&watch, 1 }, *list;
list = rbtree_search(&tree_wd_paths, &s);
if (list) {
index = list_indexof(list, watch);
if (index >= 0) {
if (list_size(list) == 1) {
list = rbtree_delete(&tree_wd_paths, list);
list_destroy(list);
return 0;
}
list_remove(list, index);
return list_size(list);
}
}
return 0;
}
static void unmap(struct watch *w) {
unmap_wd(w);
unmap_path(w);
}
int inotify_unmap_wd(int wd) {
struct list *l = wd_lookup(wd);
if (l) {
int i;
rbtree_delete(&tree_wd_paths, l);
for(i=0; i < l->nr; i++) {
struct watch *w = l->items[i];
unmap_path(w);
inotify_watch_destroy(w, unmap);
}
list_destroy(l);
return 1;
}
return 0;
}
int inotify_unmap_path(const char *path) {
int ret = 0;
struct watch *w, s;
s.path = path;
w = rbtree_search(&tree_path_wd, &s);
if (w) {
ret = unmap_wd(w);
unmap_path(w);
inotify_watch_destroy(w, unmap);
}
return ret;
}
void inotify_unmap_all() {
rbtree_free(&tree_path_wd, NULL);
rbtree_free(&tree_wd_paths, wd_free);
inotify_watch_destroy((struct watch*)watch_root.tree.child, NULL);
watch_root.tree.child = NULL;
}
int inotify_map_get_wd(const char *path) {
struct watch s, *n;
s.path = path;
n = rbtree_search(&tree_path_wd, &s);
if (n)
return n->wd;
return 0;
}
struct list* inotify_map_get_path(int wd) {
struct list *list = wd_lookup(wd);
if (list)
return list_copy(list);
return NULL;
}
int inotify_map_isempty() {
return rbtree_is_empty(&tree_wd_paths)
&& rbtree_is_empty(&tree_path_wd)
&& watch_root.tree.child == NULL;
}