Skip to content

Instantly share code, notes, and snippets.

@schoentoon
Last active February 27, 2024 22:13
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save schoentoon/5173397 to your computer and use it in GitHub Desktop.
Save schoentoon/5173397 to your computer and use it in GitHub Desktop.
Simple example of how to use inotify with libevent. Compile with gcc -o inotify inotify.c -levent
#include <stdio.h>
#include <event.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/inotify.h>
static void displayInotifyEvent(struct inotify_event *i)
{
printf(" wd =%2d; ", i->wd);
if (i->cookie > 0)
printf("cookie =%4d; ", i->cookie);
printf("mask = ");
if (i->mask & IN_ACCESS)
printf("IN_ACCESS ");
if (i->mask & IN_ATTRIB)
printf("IN_ATTRIB ");
if (i->mask & IN_CLOSE_NOWRITE)
printf("IN_CLOSE_NOWRITE ");
if (i->mask & IN_CLOSE_WRITE)
printf("IN_CLOSE_WRITE ");
if (i->mask & IN_CREATE)
printf("IN_CREATE ");
if (i->mask & IN_DELETE)
printf("IN_DELETE ");
if (i->mask & IN_DELETE_SELF)
printf("IN_DELETE_SELF ");
if (i->mask & IN_IGNORED)
printf("IN_IGNORED ");
if (i->mask & IN_ISDIR)
printf("IN_ISDIR ");
if (i->mask & IN_MODIFY)
printf("IN_MODIFY ");
if (i->mask & IN_MOVE_SELF)
printf("IN_MOVE_SELF ");
if (i->mask & IN_MOVED_FROM)
printf("IN_MOVED_FROM ");
if (i->mask & IN_MOVED_TO)
printf("IN_MOVED_TO ");
if (i->mask & IN_OPEN)
printf("IN_OPEN ");
if (i->mask & IN_Q_OVERFLOW)
printf("IN_Q_OVERFLOW ");
if (i->mask & IN_UNMOUNT)
printf("IN_UNMOUNT ");
printf("\n");
if (i->len > 0)
printf(" name = %s\n", i->name);
}
#define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1))
static void readcb(struct bufferevent* bev, void* args)
{
char buf[BUF_LEN];
size_t numRead = bufferevent_read(bev, buf, BUF_LEN);
char *p;
for (p = buf; p < buf + numRead; ) {
struct inotify_event *event = (struct inotify_event*) p;
displayInotifyEvent(event);
p += sizeof(struct inotify_event) + event->len;
}
}
int main(int argc, char **argv)
{
int inotifyFd, wd, j;
if (argc < 2 || strcmp(argv[1], "--help") == 0) {
fprintf(stderr, "%s pathname...\n", argv[0]);
return 1;
}
inotifyFd = inotify_init();
if (inotifyFd == -1) {
fprintf(stderr, "inotify_init");
return 1;
}
for (j = 1; j < argc; j++) {
wd = inotify_add_watch(inotifyFd, argv[j], IN_ALL_EVENTS);
if (wd == -1) {
fprintf(stderr, "inotify_add_watch");
return 1;
}
printf("Watching %s using wd %d\n", argv[j], wd);
}
struct event_base* event_base = event_base_new();
struct bufferevent *tmp = bufferevent_socket_new(event_base, inotifyFd, 0);
bufferevent_setcb(tmp, readcb, NULL, NULL, NULL);
bufferevent_enable(tmp, EV_READ);
event_base_dispatch(event_base);
return 0;
}
@vW7JKDTWMGwhRA
Copy link

Could you please clarify or expand on why you were able to translate the char* p into an inotify_event* at line 60.

There's some non-obvious magic happening there at line 60. I suspect the use of a bufferevent is part of my confusion, because I'm not able to track how the construct of the bufferevent *tmp at line 87, produces the inotify_event* at line 60. Please consider the use of event* instead, may also help bring clarity to this example.

TY,
-- J Jorg.

@vW7JKDTWMGwhRA
Copy link

The magic happening at line 60 is simply a C-style overlay of the structure onto the buf that was filled by the bufferevent_read( ). This is because a read of data from inotify file descriptor (happening at line 57), populates buf with a data set in the form of struct inotify_event. Ref: inotify doc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment