Finished patching things.
[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 oneshot = if (evcheck S_Oneshot) then true else false
32   in
33   let wd = Inotify.add_watch fd dir events in
34     Hashtbl.add masks dir (wd,handler);
35     Hashtbl.add wdmap wd (dir,Some(handler),oneshot)
36
37 let mask_watch dir =
38   try 
39     let wd,_ = Hashtbl.find masks dir in
40       Inotify.rm_watch fd wd;
41       Hashtbl.remove wdmap wd
42   with _ ->
43     ()
44
45 let unmask_watch dir events =
46   let _,handler = Hashtbl.find masks dir in
47     try 
48       Hashtbl.remove masks dir;
49       add_watch dir events handler
50     with Not_found -> ()
51
52 let asciiz s =
53   let rec findfirstnul str idx len =
54     if ((idx==len) || 
55         (str.[idx]==(char_of_int 0))) then idx
56     else
57       findfirstnul str (idx+1) len
58   in
59   let nulterm = findfirstnul s 0 (String.length s) in
60     String.sub s 0 nulterm
61
62 let receive_event (eventdescriptor:fname_and_fd) (bla:fname_and_fd) =
63   let (_,fd) = eventdescriptor in
64   let evs = Inotify.read fd in
65     List.iter (fun x->
66                  match x with
67                    | (wd,evlist,_,Some(str)) ->
68                        let purestr = asciiz(str) in
69                        let (dirname,handler,oneshot) = 
70                          try Hashtbl.find wdmap wd with Not_found->("",None,false)
71                        in
72                          printf "Received event: %s " dirname;
73                          List.iter (fun l->printf "%s " (string_of_event l)) evlist;
74                          printf "\n";flush Pervasives.stdout;
75                          if (oneshot) then Hashtbl.remove wdmap wd;
76                          (
77                            match handler with
78                              | None->fprintf logfd "Unhandled watch descriptor\n";flush logfd
79                              | Some(handler)->handler wd dirname evlist purestr
80                          )
81                    | _ -> ()) 
82       evs
83
84 let initialize () =
85   Fdwatcher.add_fd (None,fd) (None,fd) receive_event