(Almost) new tool: virt-get-kernel

Extract the guest kernel/ramdisk extraction from virt-builder into a
separate utility, so it can be used and improved without cluttering
virt-builder.

Currently it does what virt-builder --get-kernel did, adding also the
options for remote disks and libvirt access, much like other libguestfs
tools.

virt-builder --get-kernel now just spawns virt-get-kernel.
This commit is contained in:
Pino Toscano
2015-06-11 18:07:32 +02:00
parent 533901409e
commit 1183809f4d
13 changed files with 506 additions and 117 deletions

5
.gitignore vendored
View File

@@ -193,6 +193,10 @@ Makefile.in
/generator/generator /generator/generator
/generator/.pod2text.data* /generator/.pod2text.data*
/generator/stamp-generator /generator/stamp-generator
/get-kernel/.depend
/get-kernel/stamp-virt-get-kernel.pod
/get-kernel/virt-get-kernel
/get-kernel/virt-get-kernel.1
/.gitattributes /.gitattributes
/.git-module-status /.git-module-status
/gnulib /gnulib
@@ -245,6 +249,7 @@ Makefile.in
/html/virt-edit.1.html /html/virt-edit.1.html
/html/virt-filesystems.1.html /html/virt-filesystems.1.html
/html/virt-format.1.html /html/virt-format.1.html
/html/virt-get-kernel.1.html
/html/virt-index-validate.1.html /html/virt-index-validate.1.html
/html/virt-inspector.1.html /html/virt-inspector.1.html
/html/virt-list-filesystems.1.html /html/virt-list-filesystems.1.html

View File

@@ -133,6 +133,7 @@ SUBDIRS += \
mllib \ mllib \
customize \ customize \
builder builder/website \ builder builder/website \
get-kernel \
resize \ resize \
sparsify \ sparsify \
sysprep \ sysprep \
@@ -353,7 +354,7 @@ all-local:
grep -v -E '^python/utils.c$$' | \ grep -v -E '^python/utils.c$$' | \
LC_ALL=C sort > po/POTFILES LC_ALL=C sort > po/POTFILES
cd $(srcdir); \ cd $(srcdir); \
find builder customize mllib resize sparsify sysprep v2v -name '*.ml' | \ find builder customize get-kernel mllib resize sparsify sysprep v2v -name '*.ml' | \
LC_ALL=C sort > po/POTFILES-ml LC_ALL=C sort > po/POTFILES-ml
# Try to stop people using 'make install' without 'DESTDIR'. # Try to stop people using 'make install' without 'DESTDIR'.

View File

@@ -39,7 +39,6 @@ CLEANFILES = *~ *.annot *.cmi *.cmo *.cmx *.cmxa *.o virt-builder
SOURCES_MLI = \ SOURCES_MLI = \
cache.mli \ cache.mli \
downloader.mli \ downloader.mli \
get_kernel.mli \
index_parser.mli \ index_parser.mli \
ini_reader.mli \ ini_reader.mli \
languages.mli \ languages.mli \
@@ -56,7 +55,6 @@ SOURCES_ML = \
ini_reader.ml \ ini_reader.ml \
paths.ml \ paths.ml \
languages.ml \ languages.ml \
get_kernel.ml \
cache.ml \ cache.ml \
sources.ml \ sources.ml \
downloader.ml \ downloader.ml \

View File

@@ -91,8 +91,19 @@ let main () =
let mode = let mode =
match mode with match mode with
| `Get_kernel -> (* --get-kernel is really a different program ... *) | `Get_kernel -> (* --get-kernel is really a different program ... *)
Get_kernel.get_kernel ?format ?output arg; let cmd =
exit 0 sprintf "virt-get-kernel%s%s%s%s --add %s"
(if verbose () then " --verbose" else "")
(if trace () then " -x" else "")
(match format with
| None -> ""
| Some format -> sprintf " --format %s" (quote format))
(match output with
| None -> ""
| Some output -> sprintf " --output %s" (quote output))
(quote arg) in
if verbose () then printf "%s\n%!" cmd;
exit (Sys.command cmd)
| `Delete_cache -> (* --delete-cache *) | `Delete_cache -> (* --delete-cache *)
(match cache with (match cache with

View File

@@ -1,92 +0,0 @@
(* virt-builder
* Copyright (C) 2013 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 Common_gettext.Gettext
open Common_utils
open Utils
module G = Guestfs
open Printf
(* Originally:
* http://rwmj.wordpress.com/2013/09/13/get-kernel-and-initramfs-from-a-disk-image/
*)
let rec get_kernel ?format ?output disk =
let g = new G.guestfs () in
if trace () then g#set_trace true;
if verbose () then g#set_verbose true;
g#add_drive_opts ?format ~readonly:true disk;
g#launch ();
let roots = g#inspect_os () in
if Array.length roots = 0 then
error (f_"get-kernel: no operating system found");
if Array.length roots > 1 then
error (f_"get-kernel: dual/multi-boot images are not supported by this tool");
let root = roots.(0) in
(* Mount up the disks. *)
let mps = g#inspect_get_mountpoints root in
let cmp (a,_) (b,_) = compare (String.length a) (String.length b) in
let mps = List.sort cmp mps in
List.iter (
fun (mp, dev) ->
try g#mount_ro dev mp
with Guestfs.Error msg -> warning (f_"%s (ignored)") msg
) mps;
(* Get all kernels and initramfses. *)
let glob w = Array.to_list (g#glob_expand w) in
let kernels = glob "/boot/vmlinuz-*" in
let initrds = glob "/boot/initramfs-*" in
(* Old RHEL: *)
let initrds = if initrds <> [] then initrds else glob "/boot/initrd-*" in
(* Debian/Ubuntu: *)
let initrds = if initrds <> [] then initrds else glob "/boot/initrd.img-*" in
(* Sort by version to get the latest version as first element. *)
let kernels = List.rev (List.sort compare_version kernels) in
let initrds = List.rev (List.sort compare_version initrds) in
if kernels = [] then
error (f_"no kernel found");
(* Download the latest. *)
let outputdir =
match output with
| None -> Filename.current_dir_name
| Some dir -> dir in
let kernel_in = List.hd kernels in
let kernel_out = outputdir // Filename.basename kernel_in in
printf "download: %s -> %s\n%!" kernel_in kernel_out;
g#download kernel_in kernel_out;
if initrds <> [] then (
let initrd_in = List.hd initrds in
let initrd_out = outputdir // Filename.basename initrd_in in
printf "download: %s -> %s\n%!" initrd_in initrd_out;
g#download initrd_in initrd_out
);
(* Shutdown. *)
g#shutdown ();
g#close ()

View File

@@ -1,19 +0,0 @@
(* virt-builder
* Copyright (C) 2013 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.
*)
val get_kernel : ?format:string -> ?output:string -> string -> unit

View File

@@ -1749,6 +1749,7 @@ AC_CONFIG_FILES([Makefile
format/Makefile format/Makefile
fuse/Makefile fuse/Makefile
generator/Makefile generator/Makefile
get-kernel/Makefile
gnulib/lib/Makefile gnulib/lib/Makefile
gnulib/tests/Makefile gnulib/tests/Makefile
gobject/libguestfs-gobject-1.0.pc gobject/libguestfs-gobject-1.0.pc

146
get-kernel/Makefile.am Normal file
View File

@@ -0,0 +1,146 @@
# libguestfs get-kernel tool
# Copyright (C) 2015 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.
include $(top_srcdir)/subdir-rules.mk
EXTRA_DIST = \
$(SOURCES_ML) $(SOURCES_C) \
virt-get-kernel.pod
CLEANFILES = *~ *.annot *.cmi *.cmo *.cmx *.cmxa *.o virt-get-kernel
SOURCES_ML = \
get_kernel.ml
SOURCES_C = \
$(top_srcdir)/mllib/uri-c.c \
$(top_srcdir)/fish/uri.c
man_MANS =
noinst_DATA =
bin_PROGRAMS =
if HAVE_OCAML
bin_PROGRAMS += virt-get-kernel
virt_get_kernel_SOURCES = $(SOURCES_C)
virt_get_kernel_CPPFLAGS = \
-I. \
-I$(top_builddir) \
-I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \
-I$(shell $(OCAMLC) -where) \
-I$(top_srcdir)/gnulib/lib \
-I$(top_srcdir)/src \
-I$(top_srcdir)/fish
virt_get_kernel_CFLAGS = \
-pthread \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
$(LIBXML2_CFLAGS)
BOBJECTS = \
$(top_builddir)/mllib/libdir.cmo \
$(top_builddir)/mllib/config.cmo \
$(top_builddir)/mllib/common_gettext.cmo \
$(top_builddir)/mllib/common_utils.cmo \
$(top_builddir)/mllib/uRI.cmo \
$(SOURCES_ML:.ml=.cmo)
XOBJECTS = $(BOBJECTS:.cmo=.cmx)
# -I $(top_builddir)/src/.libs is a hack which forces corresponding -L
# option to be passed to gcc, so we don't try linking against an
# installed copy of libguestfs.
OCAMLPACKAGES = \
-package str,unix \
-I $(top_builddir)/src/.libs \
-I $(top_builddir)/gnulib/lib/.libs \
-I $(top_builddir)/ocaml \
-I $(top_builddir)/mllib
if HAVE_OCAML_PKG_GETTEXT
OCAMLPACKAGES += -package gettext-stub
endif
OCAMLCLIBS = \
-pthread -lpthread \
-lutils \
$(LIBXML2_LIBS) \
$(LIBINTL) \
-lgnu
OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR)
if !HAVE_OCAMLOPT
OBJECTS = $(BOBJECTS)
BEST = c
OCAMLLINKFLAGS = mlguestfs.cma -custom
else
OBJECTS = $(XOBJECTS)
BEST = opt
OCAMLLINKFLAGS = mlguestfs.cmxa
endif
virt_get_kernel_DEPENDENCIES = $(OBJECTS) $(top_srcdir)/ocaml-link.sh
virt_get_kernel_LINK = \
$(top_srcdir)/ocaml-link.sh -cclib '$(OCAMLCLIBS)' -- \
$(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) $(OCAMLLINKFLAGS) \
$(OBJECTS) -o $@
.mli.cmi:
$(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
.ml.cmo:
$(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
if HAVE_OCAMLOPT
.ml.cmx:
$(OCAMLFIND) ocamlopt $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
endif
# Manual pages and HTML files for the website.
man_MANS += virt-get-kernel.1
noinst_DATA += $(top_builddir)/html/virt-get-kernel.1.html
virt-get-kernel.1 $(top_builddir)/html/virt-get-kernel.1.html: stamp-virt-get-kernel.pod
stamp-virt-get-kernel.pod: virt-get-kernel.pod
$(PODWRAPPER) \
--man virt-get-kernel.1 \
--html $(top_builddir)/html/virt-get-kernel.1.html \
--license GPLv2+ \
$<
touch $@
CLEANFILES += stamp-virt-get-kernel.pod
# Dependencies.
depend: .depend
.depend: $(wildcard $(abs_srcdir)/*.mli) $(wildcard $(abs_srcdir)/*.ml)
rm -f $@ $@-t
$(OCAMLFIND) ocamldep -I ../ocaml -I $(abs_srcdir) -I $(abs_top_builddir)/mllib $^ | \
$(SED) 's/ *$$//' | \
$(SED) -e :a -e '/ *\\$$/N; s/ *\\\n */ /; ta' | \
$(SED) -e 's,$(abs_srcdir)/,$(builddir)/,g' | \
sort > $@-t
mv $@-t $@
-include .depend
endif
DISTCLEANFILES = .depend
.PHONY: depend

185
get-kernel/get_kernel.ml Normal file
View File

@@ -0,0 +1,185 @@
(* virt-get-kernel
* Copyright (C) 2013-2015 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 Common_gettext.Gettext
open Common_utils
module G = Guestfs
open Printf
(* Main program. *)
let main () =
let add, output =
let domain = ref None in
let file = ref None in
let libvirturi = ref "" in
let format = ref "" in
let output = ref "" in
let machine_readable = ref false in
let set_file arg =
if !file <> None then
error (f_"--add option can only be given once");
let uri =
try URI.parse_uri arg
with Invalid_argument "URI.parse_uri" ->
error (f_"error parsing URI '%s'. Look for error messages printed above.") arg in
file := Some uri
and set_domain dom =
if !domain <> None then
error (f_"--domain option can only be given once");
domain := Some dom in
let ditto = " -\"-" in
let argspec = Arg.align [
"-a", Arg.String set_file, s_"file" ^ " " ^ s_"Add disk image file";
"--add", Arg.String set_file, s_"file" ^ " " ^ s_"Add disk image file";
"-c", Arg.Set_string libvirturi, s_"uri" ^ " " ^ s_"Set libvirt URI";
"--connect", Arg.Set_string libvirturi, s_"uri" ^ " " ^ s_"Set libvirt URI";
"-d", Arg.String set_domain, s_"domain" ^ " " ^ s_"Set libvirt guest name";
"--domain", Arg.String set_domain, s_"domain" ^ " " ^ s_"Set libvirt guest name";
"--format", Arg.Set_string format, s_"format" ^ " " ^ s_"Format of input disk";
"--short-options", Arg.Unit display_short_options, " " ^ s_"List short options";
"--long-options", Arg.Unit display_long_options, " " ^ s_"List long options";
"--machine-readable", Arg.Set machine_readable, " " ^ s_"Make output machine readable";
"-o", Arg.Set_string output, s_"directory" ^ " " ^ s_"Output directory";
"--output", Arg.Set_string output, ditto;
"-v", Arg.Unit set_verbose, " " ^ s_"Enable debugging messages";
"--verbose", Arg.Unit set_verbose, ditto;
"-V", Arg.Unit print_version_and_exit,
" " ^ s_"Display version and exit";
"--version", Arg.Unit print_version_and_exit, ditto;
"-x", Arg.Unit set_trace, " " ^ s_"Enable tracing of libguestfs calls";
] in
long_options := argspec;
let anon_fun _ = raise (Arg.Bad (s_"extra parameter on the command line")) in
let usage_msg =
sprintf (f_"\
%s: extract kernel and ramdisk from a guest
A short summary of the options is given below. For detailed help please
read the man page virt-get-kernel(1).
")
prog in
Arg.parse argspec anon_fun usage_msg;
(* Machine-readable mode? Print out some facts about what
* this binary supports.
*)
if !machine_readable then (
printf "virt-get-kernel\n";
exit 0
);
(* Check -a and -d options. *)
let file = !file in
let domain = !domain in
let libvirturi = match !libvirturi with "" -> None | s -> Some s in
let add =
match file, domain with
| None, None ->
error (f_"you must give either -a or -d options. Read virt-get-kernel(1) man page for further information.")
| Some _, Some _ ->
error (f_"you cannot give -a and -d options together. Read virt-get-kernel(1) man page for further information.")
| None, Some dom ->
fun (g : Guestfs.guestfs) ->
let readonlydisk = "ignore" (* ignore CDs, data drives *) in
ignore (g#add_domain
~readonly:true ~allowuuid:true ~readonlydisk
?libvirturi dom)
| Some uri, None ->
fun g ->
let { URI.path = path; protocol = protocol;
server = server; username = username;
password = password } = uri in
let format = match !format with "" -> None | s -> Some s in
g#add_drive
~readonly:true ?format ~protocol ?server ?username ?secret:password
path
in
(* Dereference the rest of the args. *)
let output = match !output with "" -> None | str -> Some str in
add, output in
(* Connect to libguestfs. *)
let g = new G.guestfs () in
if trace () then g#set_trace true;
if verbose () then g#set_verbose true;
add g;
g#launch ();
let roots = g#inspect_os () in
if Array.length roots = 0 then
error (f_"get-kernel: no operating system found");
if Array.length roots > 1 then
error (f_"get-kernel: dual/multi-boot images are not supported by this tool");
let root = roots.(0) in
(* Mount up the disks. *)
let mps = g#inspect_get_mountpoints root in
let cmp (a,_) (b,_) = compare (String.length a) (String.length b) in
let mps = List.sort cmp mps in
List.iter (
fun (mp, dev) ->
try g#mount_ro dev mp
with Guestfs.Error msg -> warning (f_"%s (ignored)") msg
) mps;
(* Get all kernels and initramfses. *)
let glob w = Array.to_list (g#glob_expand w) in
let kernels = glob "/boot/vmlinuz-*" in
let initrds = glob "/boot/initramfs-*" in
(* Old RHEL: *)
let initrds = if initrds <> [] then initrds else glob "/boot/initrd-*" in
(* Debian/Ubuntu: *)
let initrds = if initrds <> [] then initrds else glob "/boot/initrd.img-*" in
(* Sort by version to get the latest version as first element. *)
let kernels = List.rev (List.sort compare_version kernels) in
let initrds = List.rev (List.sort compare_version initrds) in
if kernels = [] then
error (f_"no kernel found");
(* Download the latest. *)
let outputdir =
match output with
| None -> Filename.current_dir_name
| Some dir -> dir in
let kernel_in = List.hd kernels in
let kernel_out = outputdir // Filename.basename kernel_in in
printf "download: %s -> %s\n%!" kernel_in kernel_out;
g#download kernel_in kernel_out;
if initrds <> [] then (
let initrd_in = List.hd initrds in
let initrd_out = outputdir // Filename.basename initrd_in in
printf "download: %s -> %s\n%!" initrd_in initrd_out;
g#download initrd_in initrd_out
);
(* Shutdown. *)
g#shutdown ();
g#close ()
let () = run_main_and_handle_errors main

View File

@@ -0,0 +1,148 @@
=head1 NAME
virt-get-kernel - Extract kernel and ramdisk from guests
=head1 SYNOPSIS
virt-get-kernel [--options] -d domname
virt-get-kernel [--options] -a disk.img
=head1 DESCRIPTION
This option extracts the kernel and initramfs from a guest.
The format of the disk image is automatically detected unless you
specify it by using the I<--format> option.
In the case where the guest contains multiple kernels, the one with
the highest version number is chosen. To extract arbitrary kernels
from the disk image, see L<guestfish(1)>. To extract the entire
C</boot> directory of a guest, see L<virt-copy-out(1)>.
=head1 OPTIONS
=over 4
=item B<--help>
Display help.
=item B<-a> file
=item B<--add> file
Add I<file> which should be a disk image from a virtual machine.
The format of the disk image is auto-detected. To override this and
force a particular format use the I<--format> option.
=item B<-a> URI
=item B<--add> URI
Add a remote disk. The URI format is compatible with guestfish.
See L<guestfish(1)/ADDING REMOTE STORAGE>.
=item B<-c> URI
=item B<--connect> URI
If using libvirt, connect to the given I<URI>. If omitted, then we
connect to the default libvirt hypervisor.
If you specify guest block devices directly (I<-a>), then libvirt is
not used at all.
=item B<-d> guest
=item B<--domain> guest
Add all the disks from the named libvirt guest. Domain UUIDs can be
used instead of names.
=item B<--format> raw|qcow2|..
=item B<--format> auto
The default for the I<-a> option is to auto-detect the format of the
disk image. Using this forces the disk format for the I<-a> option
on the command line.
If you have untrusted raw-format guest disk images, you should use
this option to specify the disk format. This avoids a possible
security problem with malicious guests (CVE-2010-3851).
=item B<--machine-readable>
This option is used to make the output more machine friendly
when being parsed by other programs. See
L</MACHINE READABLE OUTPUT> below.
=item B<-o> directory
=item B<--output> directory
This option specifies the output directory where kernel and initramfs
from the guest are written.
If not specified, the default output is the current directory.
=item B<-v>
=item B<--verbose>
Enable verbose messages for debugging.
=item B<-V>
=item B<--version>
Display version number and exit.
=item B<-x>
Enable tracing of libguestfs API calls.
=back
=head1 MACHINE READABLE OUTPUT
The I<--machine-readable> option can be used to make the output more
machine friendly, which is useful when calling virt-get-kernel from
other programs, GUIs etc.
Use the option on its own to query the capabilities of the
virt-get-kernel binary. Typical output looks like this:
$ virt-get-kernel --machine-readable
virt-get-kernel
A list of features is printed, one per line, and the program exits
with status 0.
=head1 ENVIRONMENT VARIABLES
For other environment variables which affect all libguestfs programs,
see L<guestfs(3)/ENVIRONMENT VARIABLES>.
=head1 EXIT STATUS
This program returns 0 if successful, or non-zero if there was an
error.
=head1 SEE ALSO
L<guestfs(3)>,
L<guestfish(1)>,
L<guestmount(1)>,
L<virt-copy-out(1)>,
L<http://libguestfs.org/>.
=head1 AUTHOR
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT
Copyright (C) 2013-2015 Red Hat Inc.

View File

@@ -2,7 +2,6 @@ builder/builder.ml
builder/cache.ml builder/cache.ml
builder/cmdline.ml builder/cmdline.ml
builder/downloader.ml builder/downloader.ml
builder/get_kernel.ml
builder/index_parser.ml builder/index_parser.ml
builder/ini_reader.ml builder/ini_reader.ml
builder/languages.ml builder/languages.ml
@@ -26,6 +25,7 @@ customize/random_seed.ml
customize/ssh_key.ml customize/ssh_key.ml
customize/timezone.ml customize/timezone.ml
customize/urandom.ml customize/urandom.ml
get-kernel/get_kernel.ml
mllib/JSON.ml mllib/JSON.ml
mllib/JSON_tests.ml mllib/JSON_tests.ml
mllib/common_gettext.ml mllib/common_gettext.ml

1
run.in
View File

@@ -92,6 +92,7 @@ prepend PATH "$b/erlang"
prepend PATH "$b/fish" prepend PATH "$b/fish"
prepend PATH "$b/format" prepend PATH "$b/format"
prepend PATH "$b/fuse" prepend PATH "$b/fuse"
prepend PATH "$b/get-kernel"
prepend PATH "$b/inspector" prepend PATH "$b/inspector"
prepend PATH "$b/make-fs" prepend PATH "$b/make-fs"
prepend PATH "$b/p2v" prepend PATH "$b/p2v"

View File

@@ -4384,6 +4384,10 @@ L<guestmount(1)>, FUSE (userspace filesystem) built on top of libguestfs.
The crucially important generator, used to automatically generate The crucially important generator, used to automatically generate
large amounts of boilerplate C code for things like RPC and bindings. large amounts of boilerplate C code for things like RPC and bindings.
=item F<get-kernel>
L<virt-get-kernel(1)> command and documentation.
=item F<gnulib> =item F<gnulib>
Gnulib is used as a portability library. A copy of gnulib is included Gnulib is used as a portability library. A copy of gnulib is included