使用inotify检测文件移动的问题。

时间:2011-06-02 07:41:39

标签: linux inotify

我想使用inotify来监控目录的内容。在我尝试使用mv命令重命名目录中的文件之前,一切似乎都很好。我按预期得到了IN_MOVED_FROM但是没有IN_MOVED_TO。

以下是我的测试程序。编译:

g++ -Wall -o test test.cpp

启动:

./test dir_to_watch
#include <cstdio>
#include <cstring>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/inotify.h>

int main (int argc, char *argv[])
{
  int inotify_fd = inotify_init();

  if (inotify_fd < 0)
  {
    fprintf(stderr, "Unable to init inotify: %m\n");
    return 1;
  }

  int watch_descriptor = inotify_add_watch(inotify_fd,
                       argv[1],
                       IN_ALL_EVENTS);

  if (watch_descriptor < 0)
  {
    fprintf(stderr, "Unable to add inotify watch: %m\n");
    return 1;
  }

  union
  {
    inotify_event event;
    char pad[1024];
  }
  buffer;

  struct events
  {
    int mask;
    const char *name;
  }
  events[] =
  {
    {IN_ACCESS         , "IN_ACCESS        "}, 
    {IN_ATTRIB         , "IN_ATTRIB        "}, 
    {IN_CLOSE_WRITE    , "IN_CLOSE_WRITE   "}, 
    {IN_CLOSE_NOWRITE  , "IN_CLOSE_NOWRITE "}, 
    {IN_CREATE         , "IN_CREATE        "}, 
    {IN_DELETE         , "IN_DELETE        "}, 
    {IN_DELETE_SELF    , "IN_DELETE_SELF   "}, 
    {IN_MODIFY         , "IN_MODIFY        "}, 
    {IN_MOVE_SELF      , "IN_MOVE_SELF     "}, 
    {IN_MOVED_FROM     , "IN_MOVED_FROM    "}, 
    {IN_MOVED_TO       , "IN_MOVED_TO      "}, 
    {IN_OPEN           , "IN_OPEN          "}, 
  };

  while (read(inotify_fd, &buffer, sizeof buffer) > 0)
  {
    for (unsigned i = 0; i < sizeof events / sizeof events[0]; i++)
    {
      if (events[i].mask & buffer.event.mask)
      {
    if (buffer.event.len)
    {
      printf("Inotify %s: %s\n", events[i].name, buffer.event.name);
    }
    else
    {
      printf("Inotify %s\n", events[i].name);
    }
      }
    }
  }
}

1 个答案:

答案 0 :(得分:7)

自我解决:事实证明,inotify可以在单个read()调用中返回多个事件。因此,更正后的源代码如下所示:

#include <cstdio>
#include <cstring>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/inotify.h>

int main (int argc, char *argv[])
{
  int inotify_fd = inotify_init();

  if (inotify_fd < 0)
  {
    fprintf(stderr, "Unable to init inotify: %m\n");
    return 1;
  }

  int watch_descriptor = inotify_add_watch(inotify_fd,
                       argv[1],
                       IN_ALL_EVENTS);

  if (watch_descriptor < 0)
  {
    fprintf(stderr, "Unable to add inotify watch: %m\n");
    return 1;
  }

  struct events
  {
    int mask;
    const char *name;
  }
  events[] =
  {
    {IN_ACCESS         , "IN_ACCESS        "}, 
    {IN_ATTRIB         , "IN_ATTRIB        "}, 
    {IN_CLOSE_WRITE    , "IN_CLOSE_WRITE   "}, 
    {IN_CLOSE_NOWRITE  , "IN_CLOSE_NOWRITE "}, 
    {IN_CREATE         , "IN_CREATE        "}, 
    {IN_DELETE         , "IN_DELETE        "}, 
    {IN_DELETE_SELF    , "IN_DELETE_SELF   "}, 
    {IN_MODIFY         , "IN_MODIFY        "}, 
    {IN_MOVE_SELF      , "IN_MOVE_SELF     "}, 
    {IN_MOVED_FROM     , "IN_MOVED_FROM    "}, 
    {IN_MOVED_TO       , "IN_MOVED_TO      "}, 
    {IN_OPEN           , "IN_OPEN          "}, 
  };

  ssize_t rd;
  char buffer[1024];

  while ((rd = read(inotify_fd, buffer, sizeof buffer)) > 0)
  {
    for (char *ptr = buffer; ptr != buffer + rd; ptr += sizeof(inotify_event) + reinterpret_cast<inotify_event*>(ptr)->len)
    {
      inotify_event *event = reinterpret_cast<inotify_event*>(ptr);

      for (unsigned i = 0; i < sizeof events / sizeof events[0]; i++)
      {
    if (events[i].mask & event->mask)
    {
      if (event->len)
      {
        printf("Inotify %d %s: %s\n", inotify_fd, events[i].name, event->name);
      }
      else
      {
        printf("Inotify %d %s\n", inotify_fd, events[i].name);
      }
    }
      }
    }
  }

  if (rd < 0)
  {
    fprintf(stderr, "inotify read %d event error: %m\n", inotify_fd);
    return 1;
  }
}