I was trying to create a temporary directory in OCaml. I cannot find a function similar to
Filename.temp_file, and also I try to avoid calling platform-dependent system commands, so here is a naive version I write:
let mk_temp_dir () =
let rand_num = Random.int 1000000 |> string_of_int in
let tmp_dir = Filename.get_temp_dir_name () ^ "/" ^ rand_num in
Unix.mkdir tmp_dir 0o600;
with _ -> raise (Sys_error "Cannot create temp dir")
It works OK, but I suspect if it is as robust as
Filename.temp_file, or if there is already any existing common practice to create temporary directories. Any help will be much appreciated. Thanks!
bos could be a good solution for you, see specially this function.
Your approach is in essence what bos does, with some caveats.
Note that catching all exceptions is not good practice (though it’s very easy to forget) - you may catch
Sys.break which you definitely don’t mean to in a library function like this.
Unsurprisingly, the bos code is a textbook demonstration of how exceptions around a Unix syscall should be dealt with: see src/bos_os_dir.ml#L153-155
Thanks you both so much for the help!
Here is a revised version according to the implementation of
let rand_digits () =
let rand = Random.State.(bits (make_self_init ()) land 0xFFFFFF) in
Printf.sprintf "%06x" rand
let mk_temp_dir ?(mode=0o700) ?dir pat =
let dir = match dir with
| Some d -> d
| None -> Filename.get_temp_dir_name ()
let raise_err msg = raise (Sys_error msg) in
let rec loop count =
if count < 0 then raise_err "mk_temp_dir: too many failing attemps" else
let dir = Printf.sprintf "%s/%s%s" dir pat (rand_digits ()) in
try (Unix.mkdir dir mode; dir) with
| Unix.Unix_error (Unix.EEXIST, _, _) -> loop (count - 1)
| Unix.Unix_error (Unix.EINTR, _, _) -> loop count
| Unix.Unix_error (e, _, _) ->
raise_err ("mk_temp_dir: " ^ (Unix.error_message e))
It returns the name of a fresh temporary directory: “/tmp/patXXXXXX”, with permissions 0o700. The temporary directory is guaranteed to be different from any other directory that exists when
mk_temp_dir was called; raise
Sys_error if the directory could not be created.
There is also this medium post by @lindig with mkdir in ocaml and what can go wrong