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;
}
|