mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 02:30:03 +01:00
We are currently on OCaml 4.02 as minimum version. To make the followup optimizations compile backport these functions from OCaml 4.06. This implementation is less efficient than the one in the 4.06 standard library which has access to the internals of the Map. Signed-off-by: Edwin Török <edvin.torok@citrix.com> Acked-by: Christian Lindig <christian.lindig@citrix.com>
156 lines
4.2 KiB
OCaml
156 lines
4.2 KiB
OCaml
(*
|
|
* Copyright (C) 2006-2007 XenSource Ltd.
|
|
* Copyright (C) 2008-2010 Citrix Ltd.
|
|
* Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
|
|
* Author Dave Scott <dave.scott@eu.citrix.com>
|
|
*
|
|
* 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.1 only. with the special
|
|
* exception on linking described in file LICENSE.
|
|
*
|
|
* 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 Lesser General Public License for more details.
|
|
*)
|
|
|
|
type ('a, 'b) either = Right of 'a | Left of 'b
|
|
|
|
(** apply the clean_f function after fct function has been called.
|
|
* Even if fct raises an exception, clean_f is applied
|
|
*)
|
|
let exnhook = ref None
|
|
|
|
let finally fct clean_f =
|
|
let result = try
|
|
fct ();
|
|
with
|
|
exn ->
|
|
(match !exnhook with None -> () | Some f -> f exn);
|
|
clean_f (); raise exn in
|
|
clean_f ();
|
|
result
|
|
|
|
(** if v is not none, apply f on it and return some value else return none. *)
|
|
let may f v =
|
|
match v with Some x -> Some (f x) | None -> None
|
|
|
|
(** default value to d if v is none. *)
|
|
let default d v =
|
|
match v with Some x -> x | None -> d
|
|
|
|
(** apply f on v if not none *)
|
|
let maybe f v =
|
|
match v with None -> () | Some x -> f x
|
|
|
|
module Filename = struct
|
|
include Filename
|
|
let quote_command cmd args =
|
|
cmd :: args |> List.map quote |> String.concat " "
|
|
end
|
|
|
|
module Map = struct
|
|
module Make(Ord: Map.OrderedType) = struct
|
|
|
|
include Map.Make(Ord)
|
|
|
|
let find_opt k t = try Some (find k t) with Not_found -> None
|
|
|
|
let update k f t =
|
|
let r = find_opt k t in
|
|
let r' = f r in
|
|
match r, r' with
|
|
| None, None -> t
|
|
| Some _, None -> remove k t
|
|
| Some r, Some r' when r == r' -> t
|
|
| _, Some r' -> add k r' t
|
|
|
|
end
|
|
end
|
|
|
|
module String = struct include String
|
|
|
|
let of_char c = String.make 1 c
|
|
|
|
let rec split ?limit:(limit=(-1)) c s =
|
|
let i = try String.index s c with Not_found -> -1 in
|
|
let nlimit = if limit = -1 || limit = 0 then limit else limit - 1 in
|
|
if i = -1 || nlimit = 0 then
|
|
[ s ]
|
|
else
|
|
let a = String.sub s 0 i
|
|
and b = String.sub s (i + 1) (String.length s - i - 1) in
|
|
a :: (split ~limit: nlimit c b)
|
|
|
|
let fold_left f accu string =
|
|
let accu = ref accu in
|
|
for i = 0 to length string - 1 do
|
|
accu := f !accu string.[i]
|
|
done;
|
|
!accu
|
|
|
|
(** True if string 'x' starts with prefix 'prefix' *)
|
|
let startswith prefix x =
|
|
let x_l = String.length x and prefix_l = String.length prefix in
|
|
prefix_l <= x_l && String.sub x 0 prefix_l = prefix
|
|
end
|
|
|
|
module Unixext = struct
|
|
|
|
(** remove a file, but doesn't raise an exception if the file is already removed *)
|
|
let unlink_safe file =
|
|
try Unix.unlink file with (* Unix.Unix_error (Unix.ENOENT, _ , _)*) _ -> ()
|
|
|
|
(** create a directory but doesn't raise an exception if the directory already exist *)
|
|
let mkdir_safe dir perm =
|
|
try Unix.mkdir dir perm with Unix.Unix_error (Unix.EEXIST, _, _) -> ()
|
|
|
|
(** create a directory, and create parent if doesn't exist *)
|
|
let mkdir_rec dir perm =
|
|
let rec p_mkdir dir =
|
|
let p_name = Filename.dirname dir in
|
|
if p_name <> "/" && p_name <> "."
|
|
then p_mkdir p_name;
|
|
mkdir_safe dir perm in
|
|
p_mkdir dir
|
|
|
|
(** daemonize a process *)
|
|
(* !! Must call this before spawning any threads !! *)
|
|
let daemonize () =
|
|
match Unix.fork () with
|
|
| 0 ->
|
|
if Unix.setsid () == -1 then
|
|
failwith "Unix.setsid failed";
|
|
|
|
begin match Unix.fork () with
|
|
| 0 ->
|
|
let nullfd = Unix.openfile "/dev/null" [ Unix.O_RDWR ] 0 in
|
|
begin try
|
|
Unix.dup2 nullfd Unix.stdin;
|
|
Unix.dup2 nullfd Unix.stdout;
|
|
Unix.dup2 nullfd Unix.stderr;
|
|
with exn -> Unix.close nullfd; raise exn
|
|
end;
|
|
Unix.close nullfd
|
|
| _ -> exit 0
|
|
end
|
|
| _ -> exit 0
|
|
|
|
(** write a pidfile file *)
|
|
let pidfile_write filename =
|
|
let fd = Unix.openfile filename
|
|
[ Unix.O_WRONLY; Unix.O_CREAT; Unix.O_TRUNC; ]
|
|
0o640 in
|
|
finally
|
|
(fun () ->
|
|
let pid = Unix.getpid () in
|
|
let buf = string_of_int pid ^ "\n" in
|
|
let len = String.length buf in
|
|
if Unix.write_substring fd buf 0 len <> len
|
|
then failwith "pidfile_write failed";
|
|
)
|
|
(fun () -> Unix.close fd)
|
|
|
|
end
|