(* virt-sysprep * Copyright (C) 2012 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 Utils open Sysprep_operation module G = Guestfs let scriptdir = ref None let set_scriptdir dir = if !scriptdir <> None then ( eprintf "virt-sysprep: --scriptdir cannot be used more than once\n"; exit 1 ); scriptdir := Some dir let scripts = ref [] let add_script script = (* Sanity check that the script is executable. *) let statbuf = stat script in if statbuf.st_perm land 0o555 = 0 then ( eprintf "virt-sysprep: script: %s: script is not executable\n" script; exit 1 ); scripts := script :: !scripts let rec script_perform (g : Guestfs.guestfs) root = let scripts = List.rev !scripts in if scripts <> [] then ( (* Create a temporary directory? *) let scriptdir, cleanup = match !scriptdir with | Some dir -> dir, false | None -> let tmpdir = Filename.temp_dir_name in let tmpdir = tmpdir // string_random8 () in mkdir tmpdir 0o755; tmpdir, true in (* Mount the directory locally. *) g#mount_local scriptdir; (* Run the script(s)/program(s). *) run_scripts scriptdir scripts; (* Run FUSE. *) g#mount_local_run (); (* Remote temporary directory / mountpoint. *) if cleanup then rmdir scriptdir ); [] (* Run the scripts in the background and make sure they call * fusermount afterwards. *) and run_scripts mp scripts = let sh = "/bin/bash" in let cmd = sprintf "\ set -e sysprep_unmount () { cd / count=10 while ! fusermount -u %s && [ $count -gt 0 ]; do sleep 1 ((count--)) done } trap sysprep_unmount INT TERM QUIT EXIT ERR\n" (Filename.quote mp) ^ String.concat "\n" scripts in let args = [| sh; "-c"; cmd |] in let pid = fork () in if pid = 0 then ( (* child *) chdir mp; execv sh args ) let script_op = { name = "script"; pod_description = "\ The C