implement Inotify; include "sys.m"; sys: Sys; include "bufio.m"; bufio : Bufio; Iobuf : import bufio; include "string.m"; str : String; include "inotify.m"; Event.matches(e : self ref Event, m : big) : int { return (e.mask & m) == m; } Watcher.kill(w : self ref Watcher) { if(w.ctl != nil) w.ctl.close(); } Watcher.watch(w : self ref Watcher, log : chan of string) { n := int w.ctl.gets('\n'); log <- = sys->sprint("/cmd/%d", n); log <- = "exec iwatchdir " + w.path; w.ctl.puts("exec iwatchdir " + w.path); w.ctl.flush(); data := bufio->open(sys->sprint("/cmd/%d/data", n), sys->ORDWR); if(data == nil) { log <- = "data == nil"; return; } line := data.gets('\n'); if(line == nil) { err := bufio->open(sys->sprint("/cmd/%d/stderr", n), sys->OREAD); if(err == nil) log <- = sys->sprint("/cmd/%d/stderr unavilable", n); else log <- = err.gets('\n'); } args : list of string; w.ctl.puts("killonclose"); do { args = str->unquoted(line); if(len(args) == 3) w.events <- = ref Event(hd args, big hd tl args, hd tl tl args); else log <- = "Bad notification : " + line; ; } while ((line = data.gets('\n')) != nil); w.events <- = nil; } new_watcher(path : string, log : chan of string) : ref Watcher { if(sys == nil) sys = load Sys Sys->PATH; if(str == nil) str = load String String->PATH; if(bufio == nil) bufio = load Bufio Bufio->PATH; w := ref Watcher; w.ctl = bufio->open("/cmd/clone", bufio->ORDWR); if(w.ctl == nil) { sys->fprint(sys->fildes(2), "inotify: clone failed, maybe you didn't do bind -a '#C' \n"); raise("inotify: clone failed"); } w.path = path; w.events = chan of ref Event; spawn w.watch(log); return w; }