just ME
just ME

Reputation: 1827

inotify problems when running system

I want to monitor a folder.

Every time a notification pops up i want to run a system command line. Problems when using system command. Each new event pops up 3 times though it should pop up one time. EDIT: Thx for you replays. I found the bug. The system executed a folder that was inside the monitored foder. this is why each time i dropped a foder in the monitored folder, the event was printed 3 times.

code-----------

    /*

    Simple example for inotify in Linux.

    */


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

    int main(){
        int fd,wd,wd1,i=0,len=0;
        char pathname[100],buf[1024];
        struct inotify_event *event;

        fd=inotify_init1(IN_NONBLOCK);
        /* watch /test directory for any activity and report it back to me */

 `wd=inotify_add_watch(fd,"/home/folder",IN_ALL_EVENTS`);

        while(1){
            //read 1024  bytes of events from fd into buf
            i=0;
            len=read(fd,buf,1024);
            while(i<len){
                event=(struct inotify_event *) &buf[i];


                /* check for changes */
                if(event->mask & IN_OPEN)
                 {  // printf("\n %s :was opened\n",event->name);
                    char*path="/home/folder/";
                    char*file=event->name;
                    int n=sizeof(path)+sizeof(file);
                    char *result=(char *)malloc(512);
                    strcpy(result,path); // copy string one into the result.
                    strcat(result,file); // append string two to the result
                    puts (result);

                    //printf("RESUULT:");

                    int pp=sizeof(result);
                    char *run="/home/test/./userr ";
                    int l=sizeof(run);

                    char *cmd=(char *)malloc(1000);
                    strcpy(cmd,run);
                    strcat(cmd,result);
                    puts (cmd);

                    system(cmd);
                    printf("\n %s :was opened\n",event->name);
                    //break;

            }
                if(event->mask & IN_MODIFY)
                      printf("%s : modified\n",event->name);

                if(event->mask & IN_ATTRIB)
                      printf("%s :meta data changed\n",event->name);

                if(event->mask & IN_ACCESS)
                      printf("%s :was read\n",event->name);

                if(event->mask & IN_CLOSE_WRITE)
                      printf("%s :file opened for writing was closed\n",event->name);

               // if(event->mask & IN_DELETE)
                //    printf("%s :deleted\n",event->name);

                /* update index to start of next event */
                i+=sizeof(struct inotify_event)+event->len;
            }

        }

    }

EDIT:

HOW CAN I PUT TO SLEEP THE WHILE(1) FOR 1 MINUTE? SPEEP(60); pops the inotify void:was opened instead of folder1:was opened when i dropp a foder in the monitored folder

./exec

 :was opened
/home/folder/
   :file opened not for writing was closed

Without sleep inside while (the code posted) i have:

 1002_copy :was opened
/home/folder/1002_copy
1002_copy :file opened not for writing was closed

Upvotes: 0

Views: 965

Answers (2)

shadyabhi
shadyabhi

Reputation: 17234

You are running system() in the if condition which is called every time a open file is seen.

So, it will run infinitely whenever you open a file. You have to find a way to get out of the loop.

When execution reaches the line break, it breaks out of the inner while but what about the outer while(1)?

AS REQUESTED (working code):

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

int main(){
    int fd,wd,wd1,i=0,len=0;
    char pathname[100],buf[1024];
    struct inotify_event *event;

    fd=inotify_init1(IN_NONBLOCK);
    wd=inotify_add_watch(fd,"/tmp/temp",IN_ALL_EVENTS);
    while(1){
        //read 1024  bytes of events from fd into buf
        i=0;
        len=read(fd,buf,1024);
        while(i<len){
            event=(struct inotify_event *) &buf[i];
            /* check for changes */
            if(event->mask & IN_CREATE){
                system("/bin/date");
            }
            i+=sizeof(struct inotify_event)+event->len;
        }  
    }
}

The above code executes $date command each time a file is added to /tmp/temp. Modify it to suit your needs.

Upvotes: 1

Jon Cage
Jon Cage

Reputation: 37490

What is your system command doing? Is it opening the file you're changing? If so, wouldn't that cause your code to run again and put you into an infinite loop (which is apparently what you're seeing)?

Edit - There's an article in Linux Journal which is doing something very similar to you. I noticed they're using a larger buffer and the comments mention something about structure alignment so is it possible you're getting a bad event length which is causing a buffer overrun and forcing your code to loop for longer than expected.

Ether way, I'd check (with a bit of printf debug logic) that you're looping as expected.

Upvotes: 1

Related Questions