+(** Watches directories for events. Agnostic to vsys semantics of backends and
+ frontends *)
open Inotify
open Fdwatcher
open Printf
(* I don't know if a wd corresponding to a deleted directory is evicted or just
* leaks - fix implementation of rmdir accordingly
*)
-
let wdmap = Hashtbl.create 1024
+let masks = Hashtbl.create 1024
let fd = Inotify.init ()
+let rec list_check lst elt =
+ match lst with
+ | [] -> false
+ | car::cdr -> if (car==elt) then true else list_check cdr elt
+
let handle_dir_event dirname evlist str =
- let fname = String.concat "/" [dirname;str] in
- printf "File: %s. " fname;List.iter
- (fun e ->
- printf "Event: %s\n" (string_of_event e))
- evlist;
- flush Pervasives.stdout
+ let fname = String.concat "/" [dirname;str] in
+ fprintf logfd "File: %s. " fname;List.iter
+ (fun e ->
+ fprintf logfd "Event: %s\n" (string_of_event e))
+ evlist;
+ flush logfd
let add_watch dir events handler =
- printf "Adding watch for %s\n" dir;
+ let evcheck = list_check events in
let wd = Inotify.add_watch fd dir events in
- Hashtbl.add wdmap wd (dir,handler)
+ Hashtbl.add masks dir (wd,handler);
+ Hashtbl.add wdmap wd (dir,Some(handler))
+
+ (* Ignore the possibility that the whole directory can disappear and come
+ * back while it is masked *)
+
+let mask_watch dir =
+ try
+ let wd,_ = Hashtbl.find masks dir in
+ Inotify.rm_watch fd wd;
+ Hashtbl.remove wdmap wd
+ with _ ->
+ ()
+
+let unmask_watch dir events =
+ let _,handler = try Hashtbl.find masks dir with Not_found->fprintf logfd "unmask called without mask: %s\n" dir;flush logfd;raise Not_found in
+ try
+ Hashtbl.remove masks dir;
+ add_watch dir events handler
+ with Not_found -> ()
let asciiz s =
let rec findfirstnul str idx len =
if ((idx==len) ||
- (str.[idx]==(char_of_int 0))) then idx
- else
- findfirstnul str (idx+1) len
+ (str.[idx]==(char_of_int 0))) then idx
+ else
+ findfirstnul str (idx+1) len
in
let nulterm = findfirstnul s 0 (String.length s) in
String.sub s 0 nulterm
-let receive_event (eventdescriptor:fd_and_fname) (bla:fd_and_fname) =
+let receive_event (eventdescriptor:fname_and_fd) (bla:fname_and_fd) =
let (_,fd) = eventdescriptor in
- let evs = Inotify.read fd in
- List.iter (fun x->
- match x with
- | (wd,evlist,_,Some(str)) ->
- let purestr = asciiz(str) in
- let (dirname,handler) =
- try Hashtbl.find wdmap wd with Not_found->printf "Unknown watch descriptor\n";raise Not_found
- in
- (
- match handler with
- | None->handle_dir_event dirname evlist purestr
- | Some(handler)->handler dirname evlist purestr
- )
- | _ -> ())
- evs
+ let evs = Inotify.read fd in
+ List.iter (fun x->
+ match x with
+ | (wd,evlist,_,Some(str)) ->
+ begin
+ let purestr = asciiz(str) in
+ let (dirname,handler) =
+ try Hashtbl.find wdmap wd with Not_found->("",None)
+ in
+ match handler with
+ | None->fprintf logfd "Unhandled watch descriptor\n";flush logfd
+ | Some(handler)->handler wd dirname evlist purestr
+ end
+ | _ -> ())
+ evs
let initialize () =
Fdwatcher.add_fd (None,fd) (None,fd) receive_event