(**************************************************************************) (* *) (* Copyright (c) 2014 - 2016. *) (* Dynamic Ledger Solutions, Inc. *) (* *) (* All rights reserved. No warranty, explicit or implicit, provided. *) (* *) (**************************************************************************) (* * Copyright (c) 2013-2014 Thomas Gazagnaire * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *) let (>>=) = Lwt.(>>=) let (>|=) = Lwt.(>|=) let (//) = Filename.concat exception Error of string let error = Printf.ksprintf (fun str -> Printf.eprintf "fatal: %s\n%!" str; Lwt.fail (Error str)) let mkdir dir = let safe_mkdir dir = if not (Sys.file_exists dir) then try Unix.mkdir dir 0o755 with Unix.Unix_error(Unix.EEXIST,_,_) -> () in let rec aux dir = if not (Sys.file_exists dir) then begin aux (Filename.dirname dir); safe_mkdir dir; end in aux dir let check_dir root = if Sys.file_exists root && not (Sys.is_directory root) then error "%s is not a directory!" root else begin let mkdir dir = if not (Sys.file_exists dir) then mkdir dir in mkdir root; Lwt.return_unit end let files = Lwt_pool.create 50 (fun () -> Lwt.return_unit) let with_file fn = Lwt_pool.use files fn let read_bigstring fd = Lwt_bytes.map_file ~fd ~shared:false () let with_file_in file fn = with_file (fun () -> let fd = Unix.(openfile file [O_RDONLY; O_NONBLOCK] 0o644) in try let b = read_bigstring fd in fn b >>= fun r -> Unix.close fd; Lwt.return r with e -> Unix.close fd; Lwt.fail e) let write_bigstring fd ba = let rec rwrite fd buf ofs len = Lwt_bytes.write fd buf ofs len >>= fun n -> if n = 0 && len <> 0 then Lwt.fail End_of_file else if n < len then rwrite fd buf (ofs + n) (len - n) else Lwt.return_unit in rwrite fd ba 0 (Bigarray.Array1.dim ba) let with_file_out file ba = mkdir (Filename.dirname file); with_file (fun () -> Lwt_unix.(openfile file [O_RDWR; O_NONBLOCK; O_CREAT] 0o644) >>= fun fd -> try write_bigstring fd ba >>= fun r -> Lwt_unix.close fd >>= fun () -> Lwt.return r with e -> Lwt_unix.close fd >>= fun () -> Lwt.fail e) let remove_file file = if Sys.file_exists file then Unix.unlink file; Lwt.return_unit let is_directory f = try Sys.is_directory f with _ -> false let list_files root = let files = Lwt_unix.files_of_directory root in Lwt_stream.fold_s (fun file accu -> if file = "." || file = ".." then Lwt.return accu else Lwt.return (file :: accu)) files [] >>= fun l -> Lwt.return (List.sort compare l) let rec_files root = let rec aux accu dir = let files = Lwt_unix.files_of_directory (root // dir) in Lwt_stream.fold_s (fun file accu -> if file = "." || file = ".." then Lwt.return accu else let file = if dir = "" then file else dir // file in if is_directory (root // file) then aux accu file else Lwt.return (file :: accu)) files accu in aux [] "" let remove_rec root = let rec aux dir = let files = Lwt_unix.files_of_directory (root // dir) in Lwt_stream.iter_s (fun file -> if file = "." || file = ".." then Lwt.return_unit else let file = if dir = "" then file else dir // file in if is_directory (root // file) then begin aux file >>= fun () -> Lwt.return_unit end else begin Unix.unlink (root // file) ; Lwt.return_unit end) files >>= fun () -> Unix.rmdir (root // dir) ; Lwt.return_unit in if Sys.file_exists root then aux "" else Lwt.return_unit