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

发布于 2024-11-12 05:45:12 字数 2023 浏览 4 评论 0原文

我想使用 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);
    }
      }
    }
  }
}

I wanted to use inotify to monitor contents of a directory. Everything seems fine until I try to rename a file in the directory using mv command. I get IN_MOVED_FROM as expected but IN_MOVED_TO doesn't come.

Below is my test program. Compile with:

g++ -Wall -o test test.cpp

Launch with:

./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);
    }
      }
    }
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

热情消退 2024-11-19 05:45:12

自我解决:事实证明 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;
  }
}

Self solved: it turns out that inotify can return multiple events in a single read() call. So the corrected source code looks like this:

#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;
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文