#include <sys/inotify.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <glib.h>
static GList* watch_list;
static const my_event_mask = IN_ACCESS | IN_ATTRIB | IN_CLOSE_WRITE |
IN_CLOSE_NOWRITE | IN_CREATE | IN_DELETE |
IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF |
IN_MOVED_FROM | IN_MOVED_TO | IN_OPEN;
static volatile int app_exit;
static void print_list(gpointer data, gpointer udata)
{
int wfd = *(int*)data;
printf("%d ", wfd);
}
static void free_list(gpointer data, gpointer udata)
{
int* wp = (int*)data;
g_free(wp);
}
static int my_watch_remove(int ifd, int wfd)
{
return inotify_rm_watch(ifd, wfd);
}
static void my_remove_watch(gpointer data, gpointer udata)
{
int wfd = *(int*)data;
int ifd = *(int*)udata;
if (my_watch_remove(ifd, wfd) < 0) {
fprintf(stderr, "unable to remove watch fd: %d, inotify fd: %d\n"
"error: %s\n", wfd, ifd, strerror(errno));
}
}
static int my_watch_file(int ifd, const char* path)
{
int mask = my_event_mask;
inotify_add_watch(ifd, path, mask);
}
static int my_watch_init(void)
{
return inotify_init();
}
static void my_watch_remove_all(int ifd)
{
g_list_foreach(watch_list, my_remove_watch, &ifd);
}
static void my_watch_destroy(int ifd)
{
my_watch_remove_all(ifd);
}
static void print_event(struct inotify_event* ev)
{
const int size = 256;
char buffer[size];
int n = 0, mask = ev->mask;
if (mask & IN_ACCESS) {
n += snprintf(buffer + n, size - n, "%s|", "ACCESS");
}
if (mask & IN_ATTRIB) {
n += snprintf(buffer + n, size - n, "%s|", "ATTRIB");
}
if (mask & IN_CLOSE_WRITE) {
n += snprintf(buffer + n, size - n, "%s|", "CLOSE_WRITE");
}
if (mask & IN_CLOSE_NOWRITE) {
n += snprintf(buffer + n, size - n, "%s|", "CLOSE_NOWRITE");
}
if (mask & IN_CREATE) {
n += snprintf(buffer + n, size - n, "%s|", "CREATE");
}
if (mask & IN_DELETE) {
n += snprintf(buffer + n, size - n, "%s|", "DELETE");
}
if (mask & IN_DELETE_SELF) {
n += snprintf(buffer + n, size - n, "%s|", "DELETE_SELF");
}
if (mask & IN_MODIFY) {
n += snprintf(buffer + n, size - n, "%s|", "MODIFY");
}
if (mask & IN_MOVE_SELF) {
n += snprintf(buffer + n, size - n, "%s|", "MOVE_SELF");
}
if (mask & IN_MOVED_FROM) {
n += snprintf(buffer + n, size - n, "%s|", "MOVED_FROM");
}
if (mask & IN_MOVED_TO) {
n += snprintf(buffer + n, size - n, "%s|", "MOVED_TO");
}
if (mask & IN_OPEN) {
n += snprintf(buffer + n, size - n, "%s|", "OPEN");
}
/* more events to be added.. */
if (buffer[n - 1] == '|')
buffer[n - 1] = '\0';
printf("%s\n", buffer);
}
static void my_watch_start(int ifd)
{
struct inotify_event ev;
int n;
while (!app_exit) {
n = read(ifd, &ev, sizeof(ev));
if (n == 0) {
break;
} else if (n < 0) {
if (errno == EINTR) {
continue; /* interrupted syscall */
} else {
fprintf(stderr, "read error: %s\n", strerror(errno));
break;
}
} else {
printf("receive watch fd: %d event:\n", ev.wd);
print_event(&ev);
}
}
}
static void my_sig_action(int signo, siginfo_t* si, void* ucontext)
{
fprintf(stderr, "caught signal %d, cleaning up..\n", signo);
app_exit = 1;
}
static void my_sig_handler(void)
{
struct sigaction sa;
sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_RESETHAND;
sa.sa_sigaction = my_sig_action;
if (sigaction(SIGINT, &sa, NULL) < 0) {
fprintf(stderr, "sigaction1: %s\n", strerror(errno));
exit (1);
}
if (sigaction(SIGQUIT, &sa, NULL) < 0) {
fprintf(stderr, "sigaction2: %s\n", strerror(errno));
exit (1);
}
}
int main(int argc, char* argv[])
{
GList* L = NULL;
int i, ifd, wfd;
int* wd;
if (argc < 2) {
fprintf(stderr, "%s \n", argv[0]);
exit(1);
}
my_sig_handler();
ifd = my_watch_init();
for (i = 1; i < argc; i++) {
wd = g_new(int, 1);
if ((wfd = my_watch_file(ifd, argv[i])) < 0) {
fprintf(stderr, "unable to watch file: %s, "
"error: %s\n", argv[1], strerror(errno));
break;
}
*wd = wfd;
L = g_list_append(L, wd);
}
watch_list = L;
printf("watched fds: ");
g_list_foreach(L, print_list, NULL);
printf("\n");
my_watch_start(ifd);
my_watch_destroy(ifd);
g_list_foreach(L, free_list, NULL);
g_list_free(L);
watch_list = NULL;
return 0;
}
|