X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=sources%2Finotify_monitor.c;h=e5e04d9aaf369543a59de9093971197fccb5b563;hp=d2c4f2dd543b684d340442327ff94297349782f9;hb=05e740c9a3031a4359e9a895b0fb3d582b497d2f;hpb=60e20d29c0515f95b8a171fb33c7214c9bf92021 diff --git a/sources/inotify_monitor.c b/sources/inotify_monitor.c index d2c4f2d..e5e04d9 100644 --- a/sources/inotify_monitor.c +++ b/sources/inotify_monitor.c @@ -18,67 +18,73 @@ */ /***************************************************************************** * - * File inotufy_monitor.c: + * File inotify_monitor.c: * - * An example for shared memory use: monitor a directory status, - * saving data in a shared memory segment + * An example of the inotify interface: use inotify to watch the + * status of a directory or a file * * Author: S. Piccardi Jul. 2007 * *****************************************************************************/ #include -#include -#include /* C standard library */ -#include +#include +#include /* Linux inotify interface */ +#include /* Linux epoll interface */ +#include /* C standard library */ +#include /* Unix standard library */ #include /* error definitions and routines */ #include /* standard I/O library */ #include /* string functions */ +#include /* fcntl function */ +#include /* ioctl function */ #include "macros.h" /* Help printing routine */ void usage(void); +void printevent(unsigned int mask); int main(int argc, char *argv[]) { - int i; - int fd; + int i, size, nread; + int fd, wd, epfd; + char buffer[1024 + sizeof(struct inotify_event)]; unsigned int mask=0; + struct inotify_event * event; + struct epoll_event epev; /* * Input section: decode command line parameters * Use getopt function */ opterr = 0; /* don't want writing to stderr */ - while ( (i = getopt(argc, argv, "hrwcda")) != -1) { + while ((i = getopt(argc, argv, "hrwcda")) != -1) { switch (i) { /* * Handling options */ - case 'h': /* help option */ + case 'h': /* help option */ printf("Wrong -h option use\n"); usage(); - return -1; - break; - case 'r': /* read access */ + case 'r': /* read access */ mask |= IN_ACCESS; break; - case 'w': /* write access */ + case 'w': /* write access */ mask |= IN_MODIFY; break; - case 'c': /* creation */ + case 'c': /* creation */ mask |= IN_CREATE; break; - case 'd': /* deletion */ + case 'd': /* deletion */ mask |= IN_DELETE; break; - case 'a': /* all events */ + case 'a': /* all events */ mask |= IN_ALL_EVENTS; break; - case '?': /* unrecognized options */ + case '?': /* unrecognized options */ printf("Unrecognized options -%c\n",optopt); usage(); - default: /* should not reached */ + default: /* should not reached */ usage(); } } @@ -89,24 +95,77 @@ int main(int argc, char *argv[]) * Main code beginning * * ***********************************************************/ - if ((argc - optind) != 1) { /* There must be remaing parameters */ + if ((argc - optind) != 1) { /* There must be one argument */ printf("Wrong number of arguments %d\n", argc - optind); usage(); } - /* initalialize */ - fd = inotify_init (); - if (fd < 0) + epfd = epoll_create(5); /* initialize epoll */ + if (epfd < 0) { + perror("Failing on epoll_create"); + exit(-1); + } + fd = inotify_init(); /* initialize inotify */ + if (fd < 0) { perror("Failing on inotify_init"); - - /* add watch */ - if (inotify_add_watch(fd, argv[1], mask) != 0) { - printf("Failing to add watched file %s; %s\n", - argv[1], strerror(errno)); exit(-1); } - + if (fcntl(fd, F_SETFL, O_NONBLOCK)) { /* no blocking I/O on inotify */ + perror("Cannot set noblocking I/O on inotify fd"); + exit(-1); + } + wd = inotify_add_watch(fd, argv[optind], mask); /* add watch */ + if (wd <= 0) { + printf("Failing to add watched file %s, mask %i; %s\n", + argv[optind], mask, strerror(errno)); + exit(-1); + } + epev.data.fd = fd; /* add inotify fd to epoll */ + epev.events = EPOLLIN; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &epev)) { + perror("Failing on epoll_ctl"); + exit(-1); + } + /* + * Main Loop: read events and print them + */ + while (1) { + if (epoll_wait(epfd, &epev, 1, -1) < 0) { + perror("error on epoll_wait"); + exit(-1); + } + if (epev.data.fd != fd) + printf("something wrong, epoll activity on %i instead of %i\n", + epev.data.fd, fd); + + if (ioctl(fd, FIONREAD, &size)) { + perror("error on getting inotify event size"); + exit(-1); + } + if (size > sizeof(buffer)) { + printf("Too many %i data to read, something wrong\n", size); + exit(-1); + } + i = 0; + while (i < size) { + nread = read(fd, buffer, size); + if (nread < 0) { + perror("error reading inotify data"); + exit(1); + } + i += nread; + event = (struct inotify_event *) buffer; + if (wd != event->wd) { + printf("Getting different watch descriptor, %i and %i\n", + wd, event->wd); + } else { + printf("Observed event on %s\n", argv[optind-1+event->wd]); + if (event->name != NULL) + printf("On file %s\n", event->name); + printevent(event->mask); + } + } + } return 0; - } /* * routine to print usage info and exit @@ -114,7 +173,7 @@ int main(int argc, char *argv[]) void usage(void) { printf("Program inotify_monitor: monitor file changes \n"); printf("Usage:\n"); - printf(" inotify_monitor [-h] -rwcd dirname/filename \n"); + printf(" inotify_monitor [-h] -rwcd dirname/filename dir/file ... \n"); printf(" -h print this help\n"); printf(" -w watch write\n"); printf(" -r watch read\n"); @@ -123,3 +182,34 @@ void usage(void) { printf(" -a watch all\n"); exit(1); } + +void printevent(unsigned int mask) { + int i; + int val; + char * inotify_event[] = { + "IN_ACCESS", + "IN_MODIFY", + "IN_ATTRIB", + "IN_CLOSE_WRITE", + "IN_CLOSE_NOWRITE", + "IN_OPEN", + "IN_MOVED_FROM", + "IN_MOVED_TO", + "IN_CREATE", + "IN_DELETE", + "IN_DELETE_SELF", + "IN_MOVE_SELF", + "ERROR!!!", + "IN_UNMOUNT", + "IN_Q_OVERFLOW", + "IN_IGNORED" + }; + + val=1; + for (i=0; i<16; i++) { + if (mask & val) + printf("%s, ", inotify_event[i]); + val = val << 1; + } + printf("\n"); +}