view dglwatcher.c @ 212:e6af951def94

rlgwebd: use some newer Javascript features.
author John "Elwin" Edwards
date Fri, 03 Apr 2020 15:15:02 -0400
parents fba1b34e7554
children
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, result;
  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);
    result = select(ifd + 1, &rfds, NULL, NULL, NULL);
    if (result < 0) {
      /* Something went wrong. */
      break;
    }
    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)) {
      result = read(0, &typecode, 1);
      if (result <= 0) {
        /* EOF on stdin: controlling process probably died. */
        done = 1;
      }
      if (typecode == '\n')
        done = 1;
    }
    
  }
  close(ifd);
  return 0;
}