view watcher.c @ 163:0f6da35b27a0

RLGWebD: overhaul the list of current games. The /status WebSocket now only sends a complete list when opened. At 40-second intervals, it sends a list of games that have been updated in the last minute. The client now uses this to keep its own list.
author John "Elwin" Edwards
date Sun, 04 Jan 2015 16:55:57 -0500
parents 245a2959f504
children 66fef65c34e7
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/select.h>
#include <unistd.h>
#include <limits.h>
#include <dirent.h>

struct watchdir {
  int wd;
  char *name;
};

char ibuf[sizeof(struct inotify_event) + NAME_MAX + 1];

int startwatch(int ifd, char *dir, struct watchdir *w) {
  DIR *dstream;
  struct dirent *ent;

  w->name = dir;
  w->wd = inotify_add_watch(ifd, dir, IN_CREATE|IN_DELETE|IN_DELETE_SELF);
  if (w->wd < 0) {
    fprintf(stderr, "Could not watch %s\n", dir);
    return 1;
  }
  dstream = opendir(dir);
  if (dstream == NULL) {
    fprintf(stderr, "%s is not a readable directory\n", dir);
    inotify_rm_watch(ifd, w->wd);
    w->wd = -1;
    return 1;
  }
  ent = readdir(dstream);
  while (ent != NULL) {
    if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, ".."))
      printf("E %s/%s\n", dir, ent->d_name);
    ent = readdir(dstream);
  }
  closedir(dstream);
  fflush(stdout);
  return 0;
}

int main(int argc, char *argv[]) {
  int ifd, rsize, off, done, nwatchers, i;
  char typecode;
  struct inotify_event *iev;
  fd_set rfds;
  struct watchdir *watchers;

  done = 0;
  nwatchers = argc - 1;
  iev = (struct inotify_event *) ibuf;
  ifd = inotify_init();
  if (nwatchers == 0) {
    watchers = malloc(sizeof(struct watchdir));
    nwatchers = 1;
    startwatch(ifd, ".", watchers);
  }
  else {
    watchers = malloc(nwatchers * sizeof(struct watchdir));
    for (i = 0; i < nwatchers; i++) {
      startwatch(ifd, argv[i+1], watchers + i);
    }
  }

  while (!done) {
    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
    FD_SET(ifd, &rfds);
    select(ifd + 1, &rfds, NULL, NULL, NULL);
    if (FD_ISSET(ifd, &rfds)) {
      off = 0;
      rsize = read(ifd, ibuf, sizeof(struct inotify_event) + NAME_MAX + 1);
      while (off < rsize) {
        iev = (struct inotify_event *) (ibuf + off);
        if (iev->mask & IN_CREATE)
          typecode = 'C';
        else if (iev->mask & IN_DELETE)
          typecode = 'D';
        else
          typecode = '?';
        for (i = 0; i < nwatchers; i++) {
          if (watchers[i].wd == iev->wd)
            printf("%c %s/%s\n", typecode, watchers[i].name, iev->name);
        }
        off += sizeof(struct inotify_event) + iev->len;
      }
      fflush(stdout);
    }
    if (FD_ISSET(0, &rfds)) {
      read(0, &typecode, 1);
      if (typecode == '\n')
        done = 1;
    }
    
  }
  close(ifd);
  return 0;
}