Skip to content

Instantly share code, notes, and snippets.

@hroptatyr
Created December 4, 2012 07:22
Show Gist options
  • Save hroptatyr/4201517 to your computer and use it in GitHub Desktop.
Save hroptatyr/4201517 to your computer and use it in GitHub Desktop.
some snippets to watch directories
*.o
watchdir
watchdir-clo.[ch]
RM = rm -f
CC = icc -static-intel -static-libgcc -std=c99
CFLAGS = -g -O3
all: watchdir
clean:
$(RM) watchdir *.o watchdir-clo.c watchdir-clo.h
watchdir: watchdir-clo.c watchdir.o
$(CC) $(CFLAGS) -o $@ $@.o
.SUFFIXES: .c .o .h .ggo
.c.o:
$(CC) $(CFLAGS) -c -o $@ $< -DVERSION='"0.0"' -D_POSIX_C_SOURCE=200112L -D_BSD_SOURCE
.ggo.c:
gengetopt -F $* -i $<
args "--unamed-opts --no-help --long-help --no-handle-error -a wd_args_info -f wd_parser"
package "watchdir"
usage "watchdir DIR..."
description "Watch directory for creation/deletion."
option "help" h
"Show this help message."
optional
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/inotify.h>
#include <sys/epoll.h>
static void
fputt(FILE *where)
{
static char buf[64];
struct timeval tv[1];
struct tm *tm;
char *p = buf;
#define R(p) (sizeof(buf) - ((p) - buf))
(void)gettimeofday(tv, NULL);
tm = gmtime(&tv->tv_sec);
p += strftime(p, R(p), "%FT%T", tm);
snprintf(p, R(p), ".%06lu", tv->tv_usec);
fputs(buf, where);
#undef R
return;
}
static int
got_beef(int fd, const char *const *dirs)
{
static uint8_t buf[4096];
struct inotify_event *restrict inev = (void*)buf;
ssize_t nrd;
while ((nrd = read(fd, buf, sizeof(buf))) >= 0) {
if (nrd < sizeof(*inev)) {
return -1;
}
/* prepend time stamp */
fputt(stdout);
fputc('\t', stdout);
fputs(dirs[inev->wd - 1], stdout);
fputc('\t', stdout);
if (inev->mask & (IN_CREATE | IN_MOVED_TO)) {
fputc('c', stdout);
}
if (inev->mask & IN_MOVED_TO) {
fputc('i', stdout);
}
if (inev->mask & (IN_DELETE | IN_MOVED_FROM)) {
fputc('x', stdout);
}
if (inev->mask & IN_MOVED_FROM) {
fputc('o', stdout);
}
if (inev->len > 0) {
fputc('\t', stdout);
fputs(inev->name, stdout);
}
fputc('\n', stdout);
}
return 0;
}
static int
watchdir(int inofd, const char *dir)
{
int dirfd = inotify_add_watch(
inofd, dir,
IN_CREATE | IN_DELETE |
IN_MOVED_FROM | IN_MOVED_TO);
return dirfd;
}
#include "watchdir-clo.h"
#include "watchdir-clo.c"
int
main(int argc, char *argv[])
{
struct wd_args_info argi[1];
struct epoll_event ev[1];
int inofd;
int epfd;
if (wd_parser(argc, argv, argi)) {
return 1;
} else if (argi->help_given) {
wd_parser_print_help();
return 0;
} else if (argi->inputs_num == 0) {
wd_parser_print_help();
return 1;
}
/* prepare watches */
inofd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
for (unsigned int i = 0; i < argi->inputs_num; i++) {
watchdir(inofd, argi->inputs[i]);
}
/* prepare main loop */
epfd = epoll_create1(EPOLL_CLOEXEC);
ev->events = EPOLLIN | EPOLLHUP | EPOLLET;
ev->data.fd = inofd;
epoll_ctl(epfd, EPOLL_CTL_ADD, inofd, ev);
/* main loop */
while (epoll_wait(epfd, ev, 1, -1)) {
if (ev->events & EPOLLIN &&
got_beef(ev->data.fd, argi->inputs) < 0) {
break;
} else if (ev->events & EPOLLHUP) {
break;
}
}
/* clean up */
epoll_ctl(epfd, EPOLL_CTL_DEL, inofd, ev);
close(epfd);
close(inofd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment