Bug squashes
[vsys.git] / dirwatcher.ml
1 (** Watches directories for events. Agnostic to vsys semantics of backends and
2   frontends *)
3 open Inotify
4 open Fdwatcher
5 open Printf
6 open Globals
7
8 (* I don't know if a wd corresponding to a deleted directory is evicted or just
9  * leaks - fix implementation of rmdir accordingly
10  *)
11 let wdmap = Hashtbl.create 1024
12 let masks = Hashtbl.create 1024
13
14 let fd = Inotify.init ()
15
16 let rec list_check lst elt =
17   match lst with
18     | [] -> false
19     | car::cdr -> if (car==elt) then true else list_check cdr elt
20
21 let handle_dir_event dirname evlist str = 
22   let fname = String.concat "/" [dirname;str] in
23     fprintf logfd "File: %s. " fname;List.iter 
24                                        (fun e -> 
25                                           fprintf logfd "Event: %s\n" (string_of_event e)) 
26                                        evlist;
27     flush logfd
28
29 let add_watch dir events handler =
30   let evcheck = list_check events in
31   let wd = Inotify.add_watch fd dir events in
32     Hashtbl.add masks dir (wd,handler);
33     Hashtbl.add wdmap wd (dir,Some(handler))
34
35       (* Ignore the possibility that the whole directory can disappear and come
36        * back while it is masked *)
37
38 let mask_watch dir =
39   try 
40     let wd,_ = Hashtbl.find masks dir in
41       Inotify.rm_watch fd wd;
42       Hashtbl.remove wdmap wd
43   with _ ->
44     ()
45
46 let unmask_watch dir events =
47   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
48     try 
49       Hashtbl.remove masks dir;
50       add_watch dir events handler
51     with Not_found -> ()
52
53 let asciiz s =
54   let rec findfirstnul str idx len =
55     if ((idx==len) || 
56         (str.[idx]==(char_of_int 0))) then idx
57     else
58       findfirstnul str (idx+1) len
59   in
60   let nulterm = findfirstnul s 0 (String.length s) in
61     String.sub s 0 nulterm
62
63 let receive_event (eventdescriptor:fname_and_fd) (bla:fname_and_fd) =
64   let (_,fd) = eventdescriptor in
65   let evs = Inotify.read fd in
66     List.iter (fun x->
67                  match x with
68                    | (wd,evlist,_,Some(str)) ->
69                        begin
70                                let purestr = asciiz(str) in
71                                let (dirname,handler) = 
72                                  try Hashtbl.find wdmap wd with Not_found->("",None)
73                                in
74                                    match handler with
75                                      | None->fprintf logfd "Unhandled watch descriptor\n";flush logfd
76                                      | Some(handler)->handler wd dirname evlist purestr
77                        end
78                    | _ -> ()) 
79       evs
80
81 let initialize () =
82   Fdwatcher.add_fd (None,fd) (None,fd) receive_event