2 Stimmen

Problem bei der Erkennung von Dateiverschiebungen mit inotify.

Ich wollte inotify verwenden, um den Inhalt eines Verzeichnisses zu überwachen. Alles scheint gut zu funktionieren, bis ich versuche, eine Datei im Verzeichnis mit dem Befehl mv umzubenennen. Ich erhalte IN_MOVED_FROM wie erwartet, aber IN_MOVED_TO kommt nicht.

Unten ist mein Testprogramm. Kompilieren mit:

g++ -Wall -o test test.cpp

Starten mit:

./test dir_to_watch

#include 
#include 
#include 
#include 
#include 
#include 
#include 

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

  if (inotify_fd < 0)
  {
    fprintf(stderr, "Inotify-Initialisierung fehlgeschlagen: %m\n");
    return 1;
  }

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

  if (watch_descriptor < 0)
  {
    fprintf(stderr, "Inotify-Überwachung konnte nicht hinzugefügt werden: %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);
    }
      }
    }
  }
}

7voto

kyku Punkte 5658

Self gelöst: Es stellt sich heraus, dass inotify mehrere Events in einem einzigen read() Aufruf zurückgeben kann. Daher sieht der korrigierte Quellcode so aus:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

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

  if (inotify_fd < 0)
  {
    fprintf(stderr, "Fehler beim Initialisieren von inotify: %m\n");
    return 1;
  }

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

  if (watch_descriptor < 0)
  {
    fprintf(stderr, "Fehler beim Hinzufügen des 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(ptr)->len)
    {
      inotify_event *event = reinterpret_cast(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, "Fehler bei inotify read %d event: %m\n", inotify_fd);
    return 1;
  }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X