Wednesday, December 05, 2007

Linux inotify example


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/inotify.h>

void get_event (int fd, const char * target);
void handle_error (int error);

/* ----------------------------------------------------------------- */

int main (int argc, char *argv[])
{
char target[FILENAME_MAX];
int result;
int fd;
int wd; /* watch descriptor */

if (argc < 2) {
fprintf (stderr, "Watching the current directory\n");
strcpy (target, ".");
}
else {
fprintf (stderr, "Watching %s\n", argv[1]);
strcpy (target, argv[1]);
}

fd = inotify_init();
if (fd < 0) {
handle_error (errno);
return 1;
}

wd = inotify_add_watch (fd, target, IN_ALL_EVENTS);
if (wd < 0) {
handle_error (errno);
return 1;
}

while (1) {
get_event(fd, target);
}

return 0;
}

/* ----------------------------------------------------------------- */
/* Allow for 1024 simultanious events */
#define BUFF_SIZE ((sizeof(struct inotify_event)+FILENAME_MAX)*1024)

void get_event (int fd, const char * target)
{
ssize_t len, i = 0;
char action[81+FILENAME_MAX] = {0};
char buff[BUFF_SIZE] = {0};

len = read (fd, buff, BUFF_SIZE);

while (i < len) {
struct inotify_event *pevent = (struct inotify_event *)&buff[i];
char action[81+FILENAME_MAX] = {0};

if (pevent->len)
strcpy (action, pevent->name);
else
strcpy (action, target);

if (pevent->mask & IN_ACCESS)
strcat(action, " was read");
if (pevent->mask & IN_ATTRIB)
strcat(action, " Metadata changed");
if (pevent->mask & IN_CLOSE_WRITE)
strcat(action, " opened for writing was closed");
if (pevent->mask & IN_CLOSE_NOWRITE)
strcat(action, " not opened for writing was closed");
if (pevent->mask & IN_CREATE)
strcat(action, " created in watched directory");
if (pevent->mask & IN_DELETE)
strcat(action, " deleted from watched directory");
if (pevent->mask & IN_DELETE_SELF)
strcat(action, "Watched file/directory was itself deleted");
if (pevent->mask & IN_MODIFY)
strcat(action, " was modified");
if (pevent->mask & IN_MOVE_SELF)
strcat(action, "Watched file/directory was itself moved");
if (pevent->mask & IN_MOVED_FROM)
strcat(action, " moved out of watched directory");
if (pevent->mask & IN_MOVED_TO)
strcat(action, " moved into watched directory");
if (pevent->mask & IN_OPEN)
strcat(action, " was opened");

/*
printf ("wd=%d mask=%d cookie=%d len=%d dir=%s\n",
pevent->wd, pevent->mask, pevent->cookie, pevent->len,
(pevent->mask & IN_ISDIR)?"yes":"no");

if (pevent->len) printf ("name=%s\n", pevent->name);
*/

printf ("%s\n", action);

i += sizeof(struct inotify_event) + pevent->len;

}

} /* get_event */

/* ----------------------------------------------------------------- */

void handle_error (int error)
{
fprintf (stderr, "Error: %s\n", strerror(error));

} /* handle_error */

/* ----------------------------------------------------------------- */

20 comments:

Peter Teoh said...

Thank you for the example......fantastic sharing....I was searching for it.

Beket said...

Great example! Thanks!

Valeriano Cossu said...

Cool, now I try to run it on lenny

Unknown said...

It's very nice code, Thanks

Unknown said...

Just perfect. It is exactly the example I need.

Valeriano Cossu said...

Hello guys,

someone have a similar example that work on windows, in C or C++ ?

Clive said...

Of course! But the API is different. I'll generate a new post, its too big for a comment.

Naren said...

excellent

shadyabhi said...

Thanx.. I really wanted a code like this..

Debsankha said...

Thanks for this code. The variable size of struct inotify_event causing all sorts of problems in my code and I was totally at a loss until I saw your example.

Unknown said...

I loved your blog article.Really thank you! Will read on…
dotnetgrid

Jaga said...

can you explain this code functionality.i want to write php script to notify files

Unknown said...

hi pal. i seen your program . it working for particular path like /tmp/Untitled Folder.
but i need to monitor subdirectory dynamically with out giving the command line arg.
eg: i monitored the " /media " path when ever i insert the usb(pen-drive) it shows.but i need to monitor that usb (pen-drive ) simultaneously.like if i copy the file from system to pendrive or pen drive to system i need to monitor that thing ..please help me out .thanks in advance.

Sri said...

Hi, am getting the following error, at len = read (fd, buff, BUFF_SIZE);, that `read` was not declared in this scope? help me thanks...

Clive said...

Probably:

#include <unistd.h>

Check with:

man 2 read

Unknown said...
This comment has been removed by the author.
Unknown said...
This comment has been removed by the author.
Unknown said...
This comment has been removed by the author.
Unknown said...

Scrum study also has interesting ways to teach the students for
agile scrum certification ( Scrum Master Certification ) courses. check their website for some free introductory course in scrum.

Nick said...
This comment has been removed by the author.