Chinaunix首页 | 论坛 | 博客
  • 博客访问: 177652
  • 博文数量: 42
  • 博客积分: 2185
  • 博客等级: 大尉
  • 技术积分: 455
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-11 21:32
文章分类

全部博文(42)

文章存档

2012年(5)

2011年(13)

2010年(6)

2009年(18)

我的朋友

分类: LINUX

2010-01-05 13:42:12

using inotify to monitor/watch file events

#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;
}


sample output:


$ ./tinotify1 lis.c icmiss.c tgen1.c

watched fds: 1 2 3

receive watch fd: 1 event: OPEN

receive watch fd: 1 event: ACCESS

receive watch fd: 1 event: CLOSE_NOWRITE

receive watch fd: 3 event: ATTRIB


阅读(1171) | 评论(0) | 转发(0) |
0

上一篇:Regarding cache miss

下一篇:cacheline_aligned

给主人留下些什么吧!~~