2 * Copyright (C) 2009-2010 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 let (//) = Filename.concat
24 let file_exists name =
25 try access name [F_OK]; true
26 with Unix_error _ -> false
29 try (stat name).st_kind = S_DIR
30 with Unix_error _ -> false
32 let rec uniq ?(cmp = Pervasives.compare) = function
35 | x :: y :: xs when cmp x y = 0 ->
38 x :: uniq ~cmp (y :: xs)
40 let sort_uniq ?(cmp = Pervasives.compare) xs =
41 let xs = List.sort cmp xs in
42 let xs = uniq ~cmp xs in
45 let rec input_all_lines chan =
46 try let line = input_line chan in line :: input_all_lines chan
47 with End_of_file -> []
49 let run_command_get_lines cmd =
50 let chan = open_process_in cmd in
51 let lines = input_all_lines chan in
52 let stat = close_process_in chan in
56 eprintf "febootstrap: command '%s' failed (returned %d), see earlier error messages\n" cmd i;
59 eprintf "febootstrap: command '%s' killed by signal %d" cmd i;
62 eprintf "febootstrap: command '%s' stopped by signal %d" cmd i;
68 if Sys.command cmd <> 0 then (
69 eprintf "febootstrap: %s: command failed, see earlier errors\n" cmd;
73 let run_python code args =
74 let cmd = sprintf "python -c %s %s"
76 (String.concat " " (List.map Filename.quote args)) in
77 if Sys.command cmd <> 0 then (
78 eprintf "febootstrap: external python program failed, see earlier error messages\n";
83 let chan = open_in "/dev/urandom" in
84 let data = String.create 16 in
85 really_input chan data 0 (String.length data);
87 let data = Digest.to_hex (Digest.string data) in
88 (* Note this is secure, because if the name already exists, even as a
89 * symlink, mkdir(2) will fail.
91 let tmpdir = Filename.temp_dir_name // sprintf "febootstrap%s.tmp" data in
92 Unix.mkdir tmpdir 0o700;
95 let cmd = sprintf "rm -rf %s" (Filename.quote tmpdir) in
96 ignore (Sys.command cmd));
100 let len = String.length s in
101 let sublen = String.length sub in
103 if i <= len-sublen then (
106 if s.[i+j] = sub.[j] then loop2 (j+1)
112 if r = -1 then loop (i+1) else r
118 let rec string_split sep str =
119 let len = String.length str in
120 let seplen = String.length sep in
121 let i = find str sep in
124 let s' = String.sub str 0 i in
125 let s'' = String.sub str (i+seplen) (len-i-seplen) in
126 s' :: string_split sep s''
129 let string_prefix p str =
130 let len = String.length str in
131 let plen = String.length p in
132 len >= plen && String.sub str 0 plen = p
134 let path_prefix p path =
135 let len = String.length path in
136 let plen = String.length p in
137 path = p || (len > plen && String.sub path 0 (plen+1) = (p ^ "/"))
139 let rec filter_map f = function
144 | None -> filter_map f xs
145 | Some x -> x :: filter_map f xs