Created
June 13, 2013 03:25
-
-
Save mmonaco/5771029 to your computer and use it in GitHub Desktop.
This file contains 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