File: chroot.ml

package info (click to toggle)
libguestfs 1%3A1.44.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 118,932 kB
  • sloc: ansic: 458,017; ml: 51,424; sh: 13,191; java: 9,578; makefile: 7,931; cs: 6,328; haskell: 5,674; python: 3,871; perl: 3,528; erlang: 2,446; xml: 1,347; ruby: 350; pascal: 257; javascript: 157; lex: 135; yacc: 128; cpp: 10
file content (85 lines) | stat: -rw-r--r-- 2,118 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
(* guestfs-inspection
 * Copyright (C) 2009-2020 Red Hat Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *)

open Printf
open Unix

open Std_utils
open Unix_utils

type t = {
  name : string;
  chroot : string;
}

let create ?(name = "<unnamed>") ?(chroot = Sysroot.sysroot ()) () =
  { name = name; chroot = chroot }

let f t func arg =
  if verbose () then
    eprintf "chroot: %s: running '%s'\n%!" t.chroot t.name;

  let rfd, wfd = pipe () in

  let pid = fork () in
  if pid = 0 then (
    (* Child. *)
    close rfd;

    chdir t.chroot;
    chroot t.chroot;

    let ret =
      try Either (func arg)
      with exn -> Or exn in

    try
      let chan = out_channel_of_descr wfd in
      output_value chan ret;
      Pervasives.flush chan;
      Exit._exit 0
    with
      exn ->
        prerr_endline (Printexc.to_string exn);
        Exit._exit 1
  );

  (* Parent. *)
  close wfd;

  let _, status = waitpid [] pid in
  (match status with
   | WEXITED 0 -> ()
   | WEXITED i ->
      close rfd;
      failwithf "chroot ‘%s’ exited with non-zero error %d" t.name i
   | WSIGNALED i ->
      close rfd;
      failwithf "chroot ‘%s’ killed by signal %d" t.name i
   | WSTOPPED i ->
      close rfd;
      failwithf "chroot ‘%s’ stopped by signal %d" t.name i
  );

  let chan = in_channel_of_descr rfd in
  let ret = input_value chan in
  close_in chan;

  match ret with
  | Either ret -> ret
  | Or exn -> raise exn