[ocaml-ctypes] Cheating on Foreign.foreign to use Unix.stat stubs

Andrea Giugliano ag400 at leicester.ac.uk
Mon Oct 27 12:08:39 GMT 2014

Hello everyone,

I am using ctypes in order to passing null pointers as input of Unix 
So far we used the Unix OCaml library to use syscalls (open, chdir, stat),
but it does not allow passing null pointers as input paths of the 
syscalls (i.e. mkdir NULL is not possible using OCaml Unix.mkdir).

The thing is I would like to avoid implementing again the logic of Unix 
operations after having create ctypes stubs,
instead I was successful so far in using the Unix stubs as my C 
functions. For instance I can have:

let my_mkdir = Foreign.foreign "unix_mkdir" ~checkerrno:true (string_opt 
@-> returning int)

Now this does not work with the stat syscall, because it returns a data 
The data structure returned is an OCaml type (indeed it is a Unix C stub 
I am using),
ctypes expects a C structure, and I convert the expected C structure in 
a OCaml type again.

The question is: did anyone of you try to cheat too?
Is that just a completely wrong use case of ctypes (poor -lazy- me I 
must implement again the logic of Unix!)?
Thanks a lot,


P.S: I attach the code I was trying to run for the stat function: it 
worst case it can be used as "don't do this!"
-------------- next part --------------
open Ctypes
open PosixTypes
open Unsigned

type stats
let stats : stats structure typ = structure "Stat"
let ( -:* ) s x = field stats s x
let st_dev = "st_dev" -:* dev_t
let st_ino = "st_ino" -:* int
let st_kind= "st_kind" -:* int
let st_perm= "st_perm" -:* int
let st_nlink = "st_nlink" -:* int
let st_uid = "st_uid" -:* int
let st_gid = "st_gid" -:* int
let st_rdev = "st_rdev" -:* int
let st_size = "st_size" -:* int64_t
let st_atime = "st_atime" -:* double
let st_mtime = "st_mtime" -:* double
let st_ctime = "st_ctime" -:* double
let () = seal stats

let st_dev_int s = UInt64.to_int (coerce dev_t uint64_t (getf s st_dev))
let st_ino_int s =  (getf s st_ino)
let st_nlink_int s = (getf s st_nlink)
let st_perm_int s = (getf s st_perm)
let st_kind_kind s = match (getf s st_kind) with | _ -> S_REG
let st_uid_int s =   (getf s st_uid)
let st_gid_int s =  (getf s st_gid)
let st_rdev_int s = (getf s st_rdev)
let st_size_int s = (getf s st_size)
let st_atime_float s = (getf s st_atime)
let st_mtime_float s = (getf s st_mtime)
let st_ctime_float s =  (getf s st_ctime)

let to_unix t = Ctypes.(Unix.LargeFile.({
                                         st_dev  = st_dev_int t;
                                         st_ino  = st_ino_int t;
                                         st_kind = st_kind_kind t;
                                         st_perm = st_perm_int t;
                                         st_nlink= st_nlink_int t;
                                         st_uid  = st_uid_int t;
                                         st_gid  = st_gid_int t;
                                         st_rdev = st_rdev_int t;
                                         st_size = st_size_int t;
                                         st_atime= st_atime_float t;
                                         st_mtime= st_mtime_float t;
                                         st_ctime= st_ctime_float t;
let stat = Foreign.foreign "unix_stat_64" ~check_errno:true
                           (string_opt @-> returning (ptr stats))

More information about the Ctypes mailing list