+++ /dev/null
-vsys v0.1
----------
-
+++ /dev/null
-1. The executable doesn't get read values
-2. Watch for created files to compile
+++ /dev/null
-When an executable
--- /dev/null
+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.cmi 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)
--- /dev/null
+#include <inotifytools/inotify.h>
+
+int main() {
+ inotify_init();
+}
--- /dev/null
+(*
+ * 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 =
+ | S_Access
+ | S_Attrib
+ | S_Close_write
+ | S_Close_nowrite
+ | S_Create
+ | S_Delete
+ | S_Delete_self
+ | S_Modify
+ | S_Move_self
+ | S_Moved_from
+ | S_Moved_to
+ | S_Open
+ | S_Dont_follow
+ | S_Mask_add
+ | S_Oneshot
+ | S_Onlydir
+ (* convenience *)
+ | S_Move
+ | S_Close
+ | S_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"
+
+let int_of_wd wd = wd
+
+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 -> (wd * 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 toread = 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
--- /dev/null
+(*
+ * 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 =
+| S_Access
+| S_Attrib
+| S_Close_write
+| S_Close_nowrite
+| S_Create
+| S_Delete
+| S_Delete_self
+| S_Modify
+| S_Move_self
+| S_Moved_from
+| S_Moved_to
+| S_Open
+| S_Dont_follow
+| S_Mask_add
+| S_Oneshot
+| S_Onlydir
+| S_Move
+| S_Close
+| S_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
+
+type wd
+type event = wd * type_event list * int32 * string option
+
+val int_of_wd : wd -> int
+val string_of_event : type_event -> string
+
+val init : unit -> Unix.file_descr
+val add_watch : Unix.file_descr -> string -> select_event list -> wd
+val rm_watch : Unix.file_descr -> wd -> unit
+val read : Unix.file_descr -> event list
--- /dev/null
+#ifndef _SYS_INOTIFY_H
+#define _SYS_INOTIFY_H 1
+
+/* no other solution unfortunately ATM. */
+#define __KERNEL__
+
+#include <stdint.h>
+#include <sys/syscall.h>
+#include <asm/unistd.h>
+
+/* Structure describing an inotify event. */
+struct inotify_event
+{
+ int wd;
+ unsigned int mask;
+ unsigned int cookie;
+ unsigned int len;
+ char name[0];
+};
+
+#define IN_ACCESS 0x00000001
+#define IN_MODIFY 0x00000002
+#define IN_ATTRIB 0x00000004
+#define IN_CLOSE_WRITE 0x00000008
+#define IN_CLOSE_NOWRITE 0x00000010
+#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
+#define IN_OPEN 0x00000020
+#define IN_MOVED_FROM 0x00000040
+#define IN_MOVED_TO 0x00000080
+#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO)
+#define IN_CREATE 0x00000100
+#define IN_DELETE 0x00000200
+#define IN_DELETE_SELF 0x00000400
+#define IN_MOVE_SELF 0x00000800
+#define IN_UNMOUNT 0x00002000
+#define IN_Q_OVERFLOW 0x00004000
+#define IN_IGNORED 0x00008000
+#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
+#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO)
+#define IN_ONLYDIR 0x01000000
+#define IN_DONT_FOLLOW 0x02000000
+#define IN_MASK_ADD 0x20000000
+#define IN_ISDIR 0x40000000
+#define IN_ONESHOT 0x80000000
+
+#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE \
+ | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM \
+ | IN_MOVED_TO | IN_CREATE | IN_DELETE \
+ | IN_DELETE_SELF | IN_MOVE_SELF)
+
+#include <errno.h>
+
+_syscall0(long, inotify_init);
+_syscall3(int, inotify_add_watch, int, fd, char *, name, int, mask);
+_syscall2(int, inotify_rm_watch, int, fd, int, wd);
+
+#undef __KERNEL__
+
+#endif /* ! _SYS_INOTIFY_H */
--- /dev/null
+/*
+ * 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 - C glue
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/ioctl.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>
+
+#include <features.h>
+
+#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 4
+#define GLIBC_SUPPORT_INOTIFY 1
+#else
+#define GLIBC_SUPPORT_INOTIFY 0
+#endif
+
+#if GLIBC_SUPPORT_INOTIFY
+#include <inotifytools/inotify.h>
+#else
+#include "inotify_compat.h"
+#endif
+
+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
+};
+
+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);
+}
--- /dev/null
+(* 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
+ ignore (Inotify.add_watch fd Sys.argv.(1) [ Inotify.S_Create ]);
+
+ 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" (Inotify.int_of_wd 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
--- /dev/null
+all: vsyssh
+
+vsyssh: vsyssh.c
+ gcc -g vsyssh.c -o vsyssh
--- /dev/null
+/* gcc -Wall -O2 -g chpid.c -o chpid */
+#define _XOPEN_SOURCE
+#define _XOPEN_SOURCE_EXTENDED
+#define _SVID_SOURCE
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/mount.h>
+#include <sys/vfs.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sched.h>
+#include <stdarg.h>
+#include <dirent.h>
+
+int main(int argc, char **argv, char **envp)
+{
+ if (argc<3) {
+ printf("Usage: vsyssh <vsys entry> <cmd>\n");
+ exit(1);
+ }
+ else {
+ int vfd0,vfd1;
+ char *inf,*outf;
+ inf=(char *)malloc(strlen(argv[1])+3);
+ outf=(char *)malloc(strlen(argv[2])+4);
+ strcpy(inf,argv[1]);
+ strcpy(inf,argv[2]);
+ strcat(inf,".in");
+ strcat(outf,".out");
+
+ vfd1 = open(inf,O_WRONLY);
+ vfd0 = open(outf,O_RDONLY);
+
+ if (vfd0==-1 || vfd1 == -1) {
+ printf("Error opening vsys entry %s\n", argv[1]);
+ exit(1);
+ }
+
+ close(0);
+ close(1);
+
+ dup2(vfd0,0);
+ dup2(vfd1,1);
+
+ execve(argv[3],argv+3,envp);
+ }
+
+ return;
+
+}