Created
June 13, 2013 03:30
-
-
Save mmonaco/5771054 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* AVL hashmap | |
* | |
* This is used to map file descriptors from | |
**/ | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <errno.h> | |
#include "avltree.h" | |
struct avl_node** avl_init() { | |
return NULL; | |
} | |
int avl_insert(struct avl_node** root, int key, const char* data) | |
{ | |
struct avl_node* new; | |
/* build new node */ | |
if ((new = malloc(sizeof(struct avl_node))) == NULL) | |
return -errno; | |
new->key = key; | |
new->data = data; | |
new->left = NULL; | |
new->right = NULL; | |
new->height = 0; | |
/* insert new node */ | |
if (*root == NULL) | |
return 0; | |
while (1) { | |
root->height += 1; | |
if (key < root->key) { | |
if (root->left == NULL) { | |
root->left = new; | |
break; | |
} | |
root = root->left; | |
} else if (key > root->key) { | |
if (root->right == NULL) { | |
root->right = new; | |
break; | |
} | |
root = root->right; | |
} else { | |
return -EINVAL; | |
} | |
} | |
return 0; | |
} | |
struct avl_node* avl_lookup_node(struct avl_node* root, int key) | |
{ | |
while (1) { | |
if (root == NULL) | |
return NULL; | |
else if (key == root->key) | |
return root; | |
else if (key < root->key) | |
root = root->left; | |
else | |
root = root->right; | |
} | |
} | |
const char* avl_lookup(struct avl_node* root, int key) | |
{ | |
root = avl_lookup_node(root, key); | |
if (root != NULL) | |
return root->data; | |
} | |
const char* avl_delete(struct avl_node* root, int key) | |
{ | |
return NULL; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __AVLTREE_H__ | |
#define __AVLTREE_H__ | |
struct avl_node { | |
int key; | |
const char* data; | |
struct avl_node* left; | |
struct avl_node* right; | |
int height; | |
}; | |
struct avl_node* avl_init(); | |
int avl_insert(struct avl_node* root, int key, const char* data); | |
const char* avl_lookup(struct avl_node* root, int key); | |
const char* avl_delete(struct avl_node* root, int key); | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <signal.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <unistd.h> | |
#include <sys/inotify.h> | |
#include <linux/fcntl.h> | |
#include <ftw.h> | |
#include "avltree.h" | |
const int AVG_PATH_LEN = 16; | |
const int IN_EVENT_SIZE = sizeof(struct inotify_event); | |
#define IN_BUFFER_SIZE (16 * (IN_EVENT_SIZE + AVG_PATH_LEN)) | |
const uint32_t IN_MASK = IN_ALL_EVENTS - IN_ACCESS - IN_CLOSE_NOWRITE - IN_OPEN; | |
#define ESC "\033[0m" | |
#define BOLD "\033[1m" | |
#define YELLOW "\033[1;33m" | |
#define GREEN "\033[1;34m" | |
#define GREY "\033[1;35m" | |
#define RED "\033[1;31m" | |
static struct avl_node** dirmap; | |
static int in_fd; | |
void signal_handler(int sig) | |
{ | |
fprintf(stderr, "Caught SIGINT, exiting.\n"); | |
exit(EXIT_SUCCESS); | |
} | |
void print_event(struct inotify_event* ep) | |
{ | |
const char* name; | |
int wd; | |
if (ep->len != 0) | |
name = ep->name; | |
else | |
name = avl_lookup(*dirmap, ep->wd); | |
printf(BOLD "%s:" ESC, name); | |
if (ep->mask & IN_ACCESS) fputs(" access", stdout); | |
if (ep->mask & IN_ATTRIB) fputs(" attrib", stdout); | |
if (ep->mask & IN_CLOSE_WRITE) fputs(" close_write", stdout); | |
if (ep->mask & IN_CLOSE_NOWRITE) fputs(" close_nowrite", stdout); | |
if (ep->mask & IN_CREATE) fputs(" create", stdout); | |
if (ep->mask & IN_DELETE) fputs(" delete", stdout); | |
if (ep->mask & IN_DELETE_SELF) fputs(" delete_self", stdout); | |
if (ep->mask & IN_MODIFY) fputs(" modify", stdout); | |
if (ep->mask & IN_MOVE_SELF) fputs(" move_self", stdout); | |
if (ep->mask & IN_MOVED_FROM) fputs(" moved_from", stdout); | |
if (ep->mask & IN_MOVED_TO) fputs(" moved_to", stdout); | |
if (ep->mask & IN_MOVE) printf("(%i)", ep->cookie); | |
if (ep->mask & IN_OPEN) fputs(" open", stdout); | |
if (ep->mask & (IN_IGNORED | IN_ISDIR | IN_UNMOUNT)) | |
fputs(" |", stdout); | |
if (ep->mask & IN_IGNORED) fputs(YELLOW " ignored" ESC, stdout); | |
if (ep->mask & IN_ISDIR) fputs(" isdir", stdout); | |
if (ep->mask & IN_UNMOUNT) fputs(YELLOW " unmount" ESC, stdout); | |
if (ep->mask & IN_Q_OVERFLOW) fputs(YELLOW " !!!q_overflow!!!" ESC, stdout); | |
puts(""); | |
if (ep->mask & (IN_CREATE | IN_ISDIR)) { | |
wd = inotify_add_watch(in_fd, name, IN_MASK | IN_EXCL_UNLINK); | |
if (wd < 0) { | |
printf(GREY "?%s " ESC "%s\n", name, strerror(errno)); | |
} | |
if (avl_insert(*dirmap, wd, name) < 0) { | |
perror("error inserting into the dirmap"); | |
exit(EXIT_FAILURE); | |
} | |
printf(GREEN "+%s" ESC "\n", name); | |
} else if (ep->mask & (IN_DELETE | IN_ISDIR)) { | |
avl_delete(*dirmap, ep->wd); | |
printf(RED "-%s\n" ESC, name); | |
} | |
fflush(stdout); | |
} | |
int ftw_visitor(const char* fpath, const struct stat* sb, int typeflag) | |
{ | |
int wd; | |
if ( ! (typeflag & FTW_D)) | |
return 0; | |
wd = inotify_add_watch(in_fd, fpath, IN_MASK | IN_EXCL_UNLINK); | |
if (wd < 0) { | |
printf(GREY "?%s " ESC "%s\n", fpath, strerror(errno)); | |
if (errno == ENOSPC) | |
return 1; | |
} | |
if (avl_insert(*dirmap, wd, fpath) < 0) { | |
perror("error inserting into the dirmap"); | |
exit(EXIT_FAILURE); | |
} | |
printf(GREEN "+%s" ESC "\n", fpath); | |
return 0; | |
} | |
int main(int argc, char* argv[]) | |
{ | |
int i, len; | |
char buffer[IN_BUFFER_SIZE]; | |
struct inotify_event* event; | |
if (argc != 2) { | |
fprintf(stderr, "usage: %s path\n", argv[0]); | |
return EXIT_FAILURE; | |
} | |
if ((in_fd = inotify_init()) < 0) { | |
perror("inotify_init() has failed"); | |
return EXIT_FAILURE; | |
} | |
if (ftw(argv[1], ftw_visitor, 64) < 0) { | |
perror("error walking subdirs"); | |
return EXIT_FAILURE; | |
} | |
if (signal(SIGINT, signal_handler) == SIG_ERR) { | |
perror("error registering for SIGINT"); | |
return EXIT_FAILURE; | |
} | |
while (1) { | |
i = 0; | |
if ((len = read(in_fd, buffer, IN_BUFFER_SIZE)) <= 1) { | |
perror("error reading inotify event"); | |
break; | |
} | |
while (i < len) { | |
event = (struct inotify_event*) &buffer[i]; | |
print_event(event); | |
i += IN_EVENT_SIZE + event->len; | |
} | |
puts(""); | |
} | |
close(in_fd); | |
return EXIT_FAILURE; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment