Next batch of tweaks
[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
12 type 'a handlertype = Nohandler | Activehandler of 'a | Maskedhandler of 'a
13
14 let wdmap = Hashtbl.create 1024
15
16 let fd = Inotify.init ()
17
18 let handle_dir_event dirname evlist str = 
19     let fname = String.concat "/" [dirname;str] in
20         fprintf logfd "File: %s. " fname;List.iter 
21                   (fun e -> 
22                      fprintf logfd "Event: %s\n" (string_of_event e)) 
23                   evlist;
24         flush logfd
25
26 let add_watch dir events handler =
27   let wd = Inotify.add_watch fd dir events in
28       Hashtbl.add wdmap wd (dir,Activehandler(handler))
29
30 let mask_events wd =
31   let (dirname,handler) = try Hashtbl.find wdmap wd with Not_found->("",Nohandler)
32   in
33     match handler with
34       | Activehandler(func)->
35           Hashtbl.replace wdmap wd (dirname,Maskedhandler(func))
36       | _ ->
37           ()
38
39 let unmask_events wd =
40   let (dirname,handler) = try Hashtbl.find wdmap wd with Not_found->("",Nohandler)
41   in
42     match handler with
43       | Maskedhandler(func)->
44           Hashtbl.replace wdmap wd (dirname,Activehandler(func))
45       | _ ->
46           ()
47
48
49         (* XXX
50 let del_watch dir =
51   fprintf logfd "Removing watch for %s\n" dir;flush logfd;
52   let wd = Inotify.rm_watch fd dir in
53       Hashtbl.remove wdmap wd 
54          *)
55
56 let asciiz s =
57   let rec findfirstnul str idx len =
58     if ((idx==len) || 
59       (str.[idx]==(char_of_int 0))) then idx
60       else
61         findfirstnul str (idx+1) len
62   in
63   let nulterm = findfirstnul s 0 (String.length s) in
64     String.sub s 0 nulterm
65
66 let receive_event (eventdescriptor:fname_and_fd) (bla:fname_and_fd) =
67   let (_,fd) = eventdescriptor in
68       let evs = Inotify.read fd in
69         List.iter (fun x->
70                 match x with
71                   | (wd,evlist,_,Some(str)) ->
72                       let purestr = asciiz(str) in
73                       let (dirname,handler) = 
74                         try Hashtbl.find wdmap wd with Not_found->("",Nohandler)
75                       in
76                         (
77                         match handler with
78                           | Nohandler->fprintf logfd "Unhandled watch descriptor\n";flush logfd
79                           | Activehandler(handler)->handler wd dirname evlist purestr
80                           | Maskedhandler(_)->()
81                         )
82                   | _ -> ()) 
83           evs
84
85 let initialize () =
86   Fdwatcher.add_fd (None,fd) (None,fd) receive_event