Inotify problem in C

I want to track changes in a file, but it doesn't work. Input example:. / es file_to_watch

This is my code:

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

#define BUF_LEN sizeof(struct inotify_event) + NAME_MAX + 1 /*buffer to store the data of events*/

int main( int argc, char *argv[]){
   int fd, wd, length;
   char buffer[BUF_LEN];
   struct inotify_event *event;

   if(argc < 2){    
      exit(1);
   }
   else{
       fd = inotify_init();
       if(fd < 0){
           perror("inotify_init");
       }

       wd = inotify_add_watch(fd, argv[1], IN_OPEN | IN_MODIFY | IN_DELETE);
       if (wd == -1)
           return(1);
       else{

           while(1){
               length = read(fd, buffer, BUF_LEN); 
               if(length == -1)
                    return(0);

               event = (struct inotify_event *) &buffer;    
               if(event->len){
                    if(event->mask & IN_OPEN){
                         printf( "file %s was open.\n", event->name );
                    }
                    else if(event->mask & IN_MODIFY){
                        printf( "file %s was modify.\n", event->name );
                    }
                    else if(event->mask & IN_DELETE){
                        printf( "file %s was delete.\n", event->name );
                    break;
                    }
               }            
           }
           inotify_rm_watch(fd, wd);
           close(fd);
      }
  }
  return(0);
}

      

When I try to open the file, nothing happens. The same thing happens when I try to change it or cancel it. The program should end when the file is deleted. Thank.

+3


source to share


2 answers


You have a couple of problems (from the inotify man page )

  • The field is name

    present only when browsing the catalog. Therefore the use of event->name

    in printf

    is incorrect, you should type argv[1]

    instead.
    The name field is present only when an event is returned for a file
    inside a watched directory; it identifies the file pathname relative
    to the watched directory.  This pathname is null-terminated, and may
    include further null bytes ('\0') to align subsequent reads to a
    suitable address boundary.

      

  1. In your case event->mask

    will never be equal IN_DELETE

    since


    IN_DELETE (+)
        File/directory deleted from watched directory.

  but instead

      

    IN_IGNORED
         Watch was removed explicitly (inotify_rm_watch(2)) or
         automatically (file was deleted, or filesystem was
         unmounted).  See also BUGS.

   when the file is deleted.

      

I suggest you look at the directory instead and check event->name

to make sure it matches the one provided argv[1]

.

You also need to have a loop after read

to read all possible inotify_event *

reads in buffer

. You can do this by specifying a start buffer

and increasing it sizeof(struct inotify_event) + event->len

by each iteration.

+2


source


This website has a good example: http://www.thegeekstuff.com/2010/04/inotify-c-program-example/



/*This is the sample program to notify us for the file creation and file deletion takes place in "/tmp" directory*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <linux/inotify.h>

#define EVENT_SIZE  ( sizeof (struct inotify_event) )
#define EVENT_BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )

int main( )
{
  int length, i = 0;
  int fd;
  int wd;
  char buffer[EVENT_BUF_LEN];

  /*creating the INOTIFY instance*/
  fd = inotify_init();

  /*checking for error*/
  if ( fd < 0 ) {
    perror( "inotify_init" );
  }

  /*adding the "/tmp" directory into watch list. Here, the suggestion is to validate the existence of the directory before adding into monitoring list.*/
  wd = inotify_add_watch( fd, "/tmp", IN_CREATE | IN_DELETE );

  /*read to determine the event change happens on "/tmp" directory. Actually this read blocks until the change event occurs*/ 

  length = read( fd, buffer, EVENT_BUF_LEN ); 

  /*checking for error*/
  if ( length < 0 ) {
    perror( "read" );
  }  

  /*actually read return the list of change events happens. Here, read the change event one by one and process it accordingly.*/
  while ( i < length ) {     
struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];         
if ( event->len ) {
  if ( event->mask & IN_CREATE ) {
    if ( event->mask & IN_ISDIR ) {
      printf( "New directory %s created.\n", event->name );
    }
    else {
      printf( "New file %s created.\n", event->name );
    }
  }
  else if ( event->mask & IN_DELETE ) {
    if ( event->mask & IN_ISDIR ) {
      printf( "Directory %s deleted.\n", event->name );
    }
    else {
      printf( "File %s deleted.\n", event->name );
    }
  }
}
i += EVENT_SIZE + event->len;
  }
  /*removing the "/tmp" directory from the watch list.*/
   inotify_rm_watch( fd, wd );

  /*closing the INOTIFY instance*/
   close( fd );

}

      

0


source







All Articles