forked from vincenthz/ocaml-inotify
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit cac0bd8
Showing
4 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
CC = gcc | ||
CFLAGS = -Wall -O2 | ||
OCAMLC = ocamlc | ||
OCAMLOPT = ocamlopt | ||
|
||
OCAMLOPTFLAGS = | ||
|
||
OCAML_TEST_INC = -I `ocamlfind query oUnit` | ||
OCAML_TEST_LIB = `ocamlfind query oUnit`/oUnit.cmxa | ||
|
||
LIBS = inotify.cmxa inotify.cma | ||
PROGRAMS = test.inotify | ||
|
||
all: $(LIBS) $(PROGRAMS) | ||
|
||
bins: $(PROGRAMS) | ||
|
||
libs: $(LIBS) | ||
|
||
inotify.cma: inotify_stubs.o inotify.cmo | ||
$(OCAMLC) -a -o $@ -custom $+ | ||
|
||
inotify.cmxa: inotify_stubs.o inotify.cmx | ||
$(OCAMLOPT) $(OCAMLOPTFLAGS) -a -o $@ $+ | ||
|
||
%.cmo: %.ml | ||
$(OCAMLC) -c -o $@ $< | ||
|
||
%.cmi: %.mli | ||
$(OCAMLC) -c -o $@ $< | ||
|
||
%.cmx: %.ml | ||
$(OCAMLOPT) $(OCAMLOPTFLAGS) -c -o $@ $< | ||
|
||
%.o: %.c | ||
$(CC) $(CFLAGS) -c -o $@ $< | ||
|
||
test.inotify: inotify.cmxa test.inotify.ml | ||
$(OCAMLOPT) -o $@ unix.cmxa $+ | ||
|
||
clean: | ||
rm -f *.o *.a *.cmo *.cmi *.cma *.cmx *.cmxa $(LIBS) $(PROGRAMS) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
(* | ||
* Copyright (C) 2006 Vincent Hanquez <vincent@snarc.org> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published | ||
* by the Free Software Foundation; version 2 only. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* Inotify OCaml binding | ||
*) | ||
|
||
type select_event = | ||
| Access | ||
| Attrib | ||
| Close_write | ||
| Close_nowrite | ||
| Create | ||
| Delete | ||
| Delete_self | ||
| Modify | ||
| Move_self | ||
| Moved_from | ||
| Moved_to | ||
| Open | ||
| Dont_follow | ||
| Mask_add | ||
| Oneshot | ||
| Onlydir | ||
(* convenience *) | ||
| Move | ||
| Close | ||
| All | ||
|
||
type type_event = | ||
| Access | ||
| Attrib | ||
| Close_write | ||
| Close_nowrite | ||
| Create | ||
| Delete | ||
| Delete_self | ||
| Modify | ||
| Move_self | ||
| Moved_from | ||
| Moved_to | ||
| Open | ||
| Ignored | ||
| Isdir | ||
| Q_overflow | ||
| Unmount | ||
|
||
let string_of_event = function | ||
| Access -> "ACCESS" | ||
| Attrib -> "ATTRIB" | ||
| Close_write -> "CLOSE_WRITE" | ||
| Close_nowrite -> "CLOSE_NOWRITE" | ||
| Create -> "CREATE" | ||
| Delete -> "DELETE" | ||
| Delete_self -> "DELETE_SELF" | ||
| Modify -> "MODIFY" | ||
| Move_self -> "MOVE_SELF" | ||
| Moved_from -> "MOVED_FROM" | ||
| Moved_to -> "MOVED_TO" | ||
| Open -> "OPEN" | ||
| Ignored -> "IGNORED" | ||
| Isdir -> "ISDIR" | ||
| Q_overflow -> "Q_OVERFLOW" | ||
| Unmount -> "UNMOUNT" | ||
|
||
type wd = int | ||
type event = wd * type_event list * int32 * string option | ||
|
||
external init : unit -> Unix.file_descr = "stub_inotify_init" | ||
external add_watch : Unix.file_descr -> string -> select_event list -> wd | ||
= "stub_inotify_add_watch" | ||
external rm_watch : Unix.file_descr -> wd -> unit = "stub_inotify_rm_watch" | ||
external convert : string -> (int * type_event list * int32 * int) | ||
= "stub_inotify_convert" | ||
external struct_size : unit -> int = "stub_inotify_struct_size" | ||
|
||
external to_read : Unix.file_descr -> int = "stub_inotify_ioctl_fionread" | ||
|
||
let read fd = | ||
let ss = struct_size () in | ||
let toread = to_read fd in | ||
|
||
let ret = ref [] in | ||
let buf = String.make toread '\000' in | ||
let rd = Unix.read fd buf 0 toread in | ||
|
||
let i = ref 0 in | ||
|
||
|
||
while !i < toread | ||
do | ||
let wd, l, cookie, len = convert (String.sub buf !i ss) in | ||
let s = if len > 0 then Some (String.sub buf (!i + ss) len) else None in | ||
ret := (wd, l, cookie, s) :: !ret; | ||
i := !i + (ss + len); | ||
done; | ||
|
||
List.rev !ret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
/* | ||
* Copyright (C) 2006 Vincent Hanquez <vincent@snarc.org> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published | ||
* by the Free Software Foundation; version 2 only. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* Inotify Ocaml binding - C glue | ||
*/ | ||
|
||
#include <string.h> | ||
#include <stdio.h> | ||
#include <unistd.h> | ||
#include <sys/ioctl.h> | ||
#include <sys/inotify.h> | ||
#include <caml/mlvalues.h> | ||
#include <caml/memory.h> | ||
#include <caml/alloc.h> | ||
#include <caml/custom.h> | ||
#include <caml/fail.h> | ||
#include <caml/signals.h> | ||
|
||
static int inotify_flag_table[] = { | ||
IN_ACCESS, IN_ATTRIB, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, | ||
IN_CREATE, IN_DELETE, IN_DELETE_SELF, IN_MODIFY, | ||
IN_MOVE_SELF, IN_MOVED_FROM, IN_MOVED_TO, IN_OPEN, | ||
IN_DONT_FOLLOW, IN_MASK_ADD, IN_ONESHOT, IN_ONLYDIR, | ||
IN_MOVE, IN_CLOSE, IN_ALL_EVENTS, 0 | ||
}; | ||
|
||
static int inotify_return_table[] = { | ||
IN_ACCESS, IN_ATTRIB, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, | ||
IN_CREATE, IN_DELETE, IN_DELETE_SELF, IN_MODIFY, | ||
IN_MOVE_SELF, IN_MOVED_FROM, IN_MOVED_TO, IN_OPEN, | ||
IN_IGNORED, IN_ISDIR, IN_Q_OVERFLOW, IN_UNMOUNT, 0 | ||
}; | ||
|
||
#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0])) | ||
|
||
value stub_inotify_init(value unit) | ||
{ | ||
CAMLparam1(unit); | ||
int fd; | ||
|
||
fd = inotify_init(); | ||
CAMLreturn(Val_int(fd)); | ||
} | ||
|
||
value stub_inotify_ioctl_fionread(value fd) | ||
{ | ||
CAMLparam1(fd); | ||
int rc, bytes; | ||
|
||
rc = ioctl(Int_val(fd), FIONREAD, &bytes); | ||
if (rc == -1) | ||
caml_failwith("ioctl fionread"); | ||
|
||
CAMLreturn(Val_int(bytes)); | ||
} | ||
|
||
value stub_inotify_add_watch(value fd, value path, value mask) | ||
{ | ||
CAMLparam3(fd, path, mask); | ||
int cv_mask, wd; | ||
|
||
cv_mask = caml_convert_flag_list(mask, inotify_flag_table); | ||
wd = inotify_add_watch(Int_val(fd), String_val(path), cv_mask); | ||
if (wd < 0) | ||
caml_failwith("inotify_add_watch"); | ||
CAMLreturn(Val_int(wd)); | ||
} | ||
|
||
value stub_inotify_rm_watch(value fd, value wd) | ||
{ | ||
CAMLparam2(fd, wd); | ||
int ret; | ||
|
||
ret = inotify_rm_watch(Int_val(fd), Int_val(wd)); | ||
if (ret == -1) | ||
caml_failwith("inotify_rm_watch"); | ||
CAMLreturn(Val_unit); | ||
} | ||
|
||
value stub_inotify_struct_size(void) | ||
{ | ||
CAMLparam0(); | ||
CAMLreturn(Val_int(sizeof(struct inotify_event))); | ||
} | ||
|
||
value stub_inotify_convert(value buf) | ||
{ | ||
CAMLparam1(buf); | ||
CAMLlocal3(event, l, tmpl); | ||
struct inotify_event ev; | ||
int i; | ||
|
||
l = Val_emptylist; | ||
tmpl = Val_emptylist; | ||
|
||
memcpy(&ev, String_val(buf), sizeof(struct inotify_event)); | ||
|
||
for (i = 0; inotify_return_table[i]; i++) { | ||
if (!(ev.mask & inotify_return_table[i])) | ||
continue; | ||
tmpl = caml_alloc_small(2, Tag_cons); | ||
Field(tmpl, 0) = Val_int(i); | ||
Field(tmpl, 1) = l; | ||
l = tmpl; | ||
} | ||
|
||
event = caml_alloc_tuple(4); | ||
Store_field(event, 0, Val_int(ev.wd)); | ||
Store_field(event, 1, l); | ||
Store_field(event, 2, caml_copy_int32(ev.cookie)); | ||
Store_field(event, 3, Val_int(ev.len)); | ||
|
||
CAMLreturn(event); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
(* unit testing inotify *) | ||
|
||
open Printf | ||
|
||
let _ = | ||
if Array.length Sys.argv < 2 then ( | ||
eprintf "usage: %s <path>\n" Sys.argv.(0); | ||
exit 1 | ||
); | ||
|
||
let fd = Inotify.init () in | ||
let wd = Inotify.add_watch fd Sys.argv.(1) [ Inotify.All ] in | ||
|
||
let string_of_event ev = | ||
let wd,mask,cookie,s = ev in | ||
let mask = String.concat ":" (List.map Inotify.string_of_event mask) in | ||
let s = match s with Some s -> s | None -> "\"\"" in | ||
sprintf "wd [%u] mask[%s] cookie[%ld] %s" wd mask cookie s | ||
in | ||
|
||
let nb = ref 0 in | ||
while true | ||
do | ||
let _, _, _ = Unix.select [ fd ] [] [] (-1.) in | ||
let evs = Inotify.read fd in | ||
List.iter (fun ev -> | ||
printf "[%d] %s\n%!" !nb (string_of_event ev)) evs; | ||
incr nb | ||
done; | ||
|
||
Unix.close fd |