Skip to content
Advertisement

How to stop the repetition of inotify result?

In this code, I am trying to monitor two paths at the same time. I used while(1) for this purpose. But the problem that I am facing is that whenever I run the code, it gives me the same result two times like this.

Giving result

Pathname1 "file" is modified 
Pathname1 "file" is modified

Expected result

Pathname1 "file" is modified 

I debugged the code. After breaking the main function and stepping over it, the next command stops at this line length = read(fd, buffer, EVENT_BUF_LEN ). Whenever I break a line after this length variable command, the program starts and after modifying the file, the program stops at this line struct inotify_event *event = ( struct inotify_event *)&buffer[i]; Although the program should not break.

I also used IN_CLOSE_WRITE instead of IN_MODIFY but no change in the result.

typedef struct{
    int length, fd, wd1, wd2;
    char buffer[4096] __attribute__ ((aligned(__alignof__(struct inotify_event))));
} notification;
notification inotify;

int getNotified(char *pathname1, char *pathname2){
    inotify.fd = inotify_init();
    inotify.wd1 = inotify_add_watch(inotify.fd, pathname1, IN_MODIFY);
    inotify.wd2 = inotify_add_watch(inotify.fd, pathname2, IN_MODIFY);

    while(1){
        inotify.length = read(inotify.fd, inotify.buffer, EVENT_BUF_LEN); 
        int i = 0;
        while(i < inotify.length){     
            struct inotify_event *event = (struct inotify_event *)&inotify.buffer[i];
            if(event->len){
                if(event->mask & IN_MODIFY){
                    if(event->wd == inotify.wd1){
                        printf("Pathname1 '%s' is modifiedn", event->name);
                        break;
                    }
                    if(event->wd == inotify.wd2){
                        printf("Pathname2 '%s' is modifiedn", event->name);
                        break;
                    }
                }
            }
            i += EVENT_SIZE + event->len;
        }
    }
    inotify_rm_watch(inotify.fd, inotify.wd1);
    inotify_rm_watch(inotify.fd, inotify.wd2);

    close(inotify.fd);
    exit(0);
}

Advertisement

Answer

Some remarks:

  • You should not “break” as you go out of the inside “while” loop and call read() again
  • The IN_MODIFY event does not fill the event->name field (i.e. event->len = 0)
  • The number of IN_MODIFY events depends on how you modify the files (“echo xxx >> file” = write only = 1 IN_MODIFY; “echo xxx > file” = truncate + write = 2 IN_MODIFY)

Here is a proposition for your program (with additional prints):

#include <stdio.h>
#include <sys/inotify.h>
#include <unistd.h>
#include <stdlib.h>

#define EVENT_BUF_LEN 4096
#define EVENT_SIZE sizeof(struct inotify_event)

typedef struct{
  int length, fd, wd1, wd2;
  char buffer[EVENT_BUF_LEN] __attribute__ ((aligned(__alignof__(struct inotify_event))));
} notification;

notification inotify;

int getNotified(char *pathname1, char *pathname2){

  inotify.fd = inotify_init();
  inotify.wd1 = inotify_add_watch(inotify.fd, pathname1, IN_MODIFY);
  printf("wd1 = %dn", inotify.wd1);
  inotify.wd2 = inotify_add_watch(inotify.fd, pathname2, IN_MODIFY);
  printf("wd2 = %dn", inotify.wd2);

  while(1){
    inotify.length = read(inotify.fd, inotify.buffer, EVENT_BUF_LEN); 
    int i = 0;
    printf("read() = %dn", inotify.length);
    while(i < inotify.length){     
      struct inotify_event *event = (struct inotify_event *)&inotify.buffer[i];
      printf("event->len = %un", event->len);
      if(event->mask & IN_MODIFY){
        if(event->wd == inotify.wd1){
          printf("Pathname1 is modifiedn");
        } else if (event->wd == inotify.wd2){
          printf("Pathname2 is modifiedn");
        }
      }
      i += (EVENT_SIZE + event->len);
      printf("i=%dn", i);
    }
  }
  inotify_rm_watch(inotify.fd, inotify.wd1);
  inotify_rm_watch(inotify.fd, inotify.wd2);

  close(inotify.fd);
  exit(0);
}



int main(void)
{
  getNotified("/tmp/foo", "/tmp/bar");

  return 0;

} // main

Here is an example of execution:

$ gcc notif.c -o notif
$ > /tmp/foo
$ > /tmp/bar
$ ./notif 
wd1 = 1
wd2 = 2

====== Upon "> /tmp/foo": 1 event (truncate operation)
read() = 16
event->len = 0
Pathname1 is modified
i=16

====== Upon "echo qwerty > /tmp/foo": 2 events (write operation, one event for truncate operation and one for the write of "qwerty" at the beginning of the file)
read() = 16
event->len = 0
Pathname1 is modified
i=16
read() = 16
event->len = 0
Pathname1 is modified
i=16

====== Upon "echo qwerty >> /tmp/foo": 1 event (write of "qwerty" at the end of the file)
read() = 16
event->len = 0
Pathname1 is modified
i=16
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement