[Libguestfs] [PATCH 2/2] configure: output paths where java is searched in

2017-08-09 Thread Pino Toscano
Output each path where we attempt to find 'java', so it is easier to
spot whether the location for the current OS is missing.  This also
removes the need to print the location next to the version, since the
location was already printed above.
---
 m4/guestfs_java.m4 | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/m4/guestfs_java.m4 b/m4/guestfs_java.m4
index 347cab6da..b86f0c423 100644
--- a/m4/guestfs_java.m4
+++ b/m4/guestfs_java.m4
@@ -50,9 +50,13 @@ if test "x$with_java" != "xno"; then
 /usr/lib/jvm/java-7-openjdk \
 /usr/lib/jvm/java-6-openjdk
 do
+AC_MSG_CHECKING([for 'java' in $d])
 if test -d $d && test -f $d/bin/java; then
+AC_MSG_RESULT([found])
 JAVA=$d
 break
+else
+AC_MSG_RESULT([not found])
 fi
 done
 fi
@@ -85,7 +89,7 @@ if test "x$with_java" != "xno"; then
 JAR="$JAVA/bin/jar"
 fi
 java_version=`$JAVA_EXE -version 2>&1 | $AWK -F '"' '/^(java|openjdk) 
version/ {print $2;}'`
-AC_MSG_RESULT(found $java_version in $JAVA)
+AC_MSG_RESULT(found $java_version)
 
 dnl Find jni.h.
 AC_MSG_CHECKING([for jni.h])
-- 
2.13.4

___
Libguestfs mailing list
Libguestfs@redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs


[Libguestfs] [PATCH 1/2] configure: visually split the blocks of checks

2017-08-09 Thread Pino Toscano
Add sort of "headers" to split most of the logical sections of the
configure, so it is easier to get feedback on the progress of configure.
---
 configure.ac | 46 ++
 1 file changed, 46 insertions(+)

diff --git a/configure.ac b/configure.ac
index 7f9c1dac0..5ccf6f821 100644
--- a/configure.ac
+++ b/configure.ac
@@ -76,11 +76,15 @@ 
AC_DEFINE_UNQUOTED([PACKAGE_VERSION_FULL],["$PACKAGE_VERSION_FULL"],[Full versio
 AC_SUBST([PACKAGE_VERSION_FULL])
 
 dnl Early gnulib initialization.
+AS_ECHO
+AS_ECHO(["Configuring Gnulib:"])
 gl_EARLY
 gl_INIT
 
 dnl Check for external programs required to either build or run
 dnl libguestfs.
+AS_ECHO
+AS_ECHO(["Checking for external programs:"])
 m4_include([m4/guestfs_progs.m4])
 
 dnl Find the release date for this version.  This is used in
@@ -99,43 +103,83 @@ AS_IF([test "x$RELEASE_DATE" != "x"],[
 AC_SUBST([RELEASE_DATE])
 
 dnl The C compiler environment.
+AS_ECHO
+AS_ECHO(["Checking for the C compiler environment:"])
 m4_include([m4/guestfs_c.m4])
 
 dnl Any C libraries required by the libguestfs C library (not the daemon).
+AS_ECHO
+AS_ECHO(["Checking for libraries used by libguestfs:"])
 m4_include([m4/guestfs_libraries.m4])
 
 dnl Check for FUSE.
+AS_ECHO
+AS_ECHO(["Checking for FUSE:"])
 m4_include([m4/guestfs_fuse.m4])
 
 dnl The daemon and any dependencies.
+AS_ECHO
+AS_ECHO(["Checking the daemon and its dependencies:"])
 m4_include([m4/guestfs_daemon.m4])
 
 dnl The appliance and any dependencies.
+AS_ECHO
+AS_ECHO(["Checking the appliance and its dependencies:"])
 m4_include([m4/guestfs_appliance.m4])
 
 dnl Check for QEMU.
+AS_ECHO
+AS_ECHO(["Checking for QEMU:"])
 m4_include([m4/guestfs_qemu.m4])
 
 dnl Miscellaneous libraries used by other programs.
+AS_ECHO
+AS_ECHO(["Checking for other libraries:"])
 m4_include([m4/guestfs_misc_libraries.m4])
 
 dnl Check for language bindings.
+AS_ECHO
+AS_ECHO(["Checking for OCaml:"])
 m4_include([m4/guestfs_ocaml.m4])
+AS_ECHO
+AS_ECHO(["Checking for Perl:"])
 m4_include([m4/guestfs_perl.m4])
+AS_ECHO
+AS_ECHO(["Checking for Python:"])
 m4_include([m4/guestfs_python.m4])
+AS_ECHO
+AS_ECHO(["Checking for Ruby:"])
 m4_include([m4/guestfs_ruby.m4])
+AS_ECHO
+AS_ECHO(["Checking for Java:"])
 m4_include([m4/guestfs_java.m4])
+AS_ECHO
+AS_ECHO(["Checking for Haskell:"])
 m4_include([m4/guestfs_haskell.m4])
+AS_ECHO
+AS_ECHO(["Checking for PHP:"])
 m4_include([m4/guestfs_php.m4])
+AS_ECHO
+AS_ECHO(["Checking for Erlang:"])
 m4_include([m4/guestfs_erlang.m4])
+AS_ECHO
+AS_ECHO(["Checking for Lua:"])
 m4_include([m4/guestfs_lua.m4])
+AS_ECHO
+AS_ECHO(["Checking for Go:"])
 m4_include([m4/guestfs_golang.m4])
+AS_ECHO
+AS_ECHO(["Checking for GObject Introspection:"])
 m4_include([m4/guestfs_gobject.m4])
 
 dnl Bash completion.
+AS_ECHO
+AS_ECHO(["Checking for bash completion:"])
 m4_include([m4/guestfs_bash_completion.m4])
 
 dnl Miscellaneous configuration that doesn't fit anywhere else.
+AS_ECHO
+AS_ECHO(["Performing additional configuration:"])
 m4_include([m4/guestfs_misc.m4])
 
 dnl Work around autoconf's lack of expanded variables.
@@ -145,6 +189,8 @@ SYSCONFDIR="${my_sysconfdir}"
 AC_SUBST(SYSCONFDIR)
 
 dnl Produce output files.
+AS_ECHO
+AS_ECHO(["Generating output files:"])
 
 AC_CONFIG_HEADERS([config.h])
 
-- 
2.13.4

___
Libguestfs mailing list
Libguestfs@redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs


Re: [Libguestfs] [PATCH 2/2] configure: output paths where java is searched in

2017-08-09 Thread Richard W.M. Jones
Good idea, ACK series.

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-df lists disk usage of guests without needing to install any
software inside the virtual machine.  Supports Linux and Windows.
http://people.redhat.com/~rjones/virt-df/

___
Libguestfs mailing list
Libguestfs@redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs


Re: [Libguestfs] [PATCH] build: Add a common script for generating OCaml dependencies correctly.

2017-08-09 Thread Pino Toscano
On Tuesday, 8 August 2017 16:34:49 CEST Richard W.M. Jones wrote:
> These are generated in many different ways in the various
> subdirectories, and sometimes not generated correctly.  Introduce a
> script to do this in one place, and hopefully correctly.
> 
> This is mostly simple refactoring, but I got rid of a couple of
> things:
> 
> (1) The ‘make depend’ rule doesn't appear to be needed.  automake (or
> make?)  seems to rebuild the ‘.depend’ file automatically just because
> it is included.
> 
> (2) I got rid of the hairy path rewriting sed expression.  Possibly
> that is needed for srcdir != builddir.
> ---

Mostly LGTM, just one note:

> +echo "  OCAMLDEP $output"

I'd remove this, since it the makefile will output the ocaml-dep.sh
invocation anyway -- a better solution should be done by taking the
silent build configuration into account.

BTW, unrelated to this patch, just because I'm noticing them: what are
all the "docs" dependencies in .PHONY?  At least for newer Makefile's
I guess they were just copied from existing ones, but I did not find
any reference/reason for the ones in older tools.  Do you remember more
about them?

-- 
Pino Toscano

signature.asc
Description: This is a digitally signed message part.
___
Libguestfs mailing list
Libguestfs@redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs

[Libguestfs] check-release success (was: Re: [PATCH] build: Add a common script for generating OCaml dependencies correctly.)

2017-08-09 Thread Richard Jones
]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/erlang'
make[3]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/erlang'
PASS: tests/010-load.erl
PASS: tests/030-config.erl
PASS: run-bindtests
PASS: tests/070-optargs.erl
PASS: tests/050-lvcreate.erl
PASS: tests/060-readdir.erl

Testsuite summary for libguestfs 1.37.20

# TOTAL: 6
# PASS:  6
# SKIP:  0
# XFAIL: 0
# FAIL:  0
# XPASS: 0
# ERROR: 0

make[3]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/erlang'
make[2]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/erlang'
make[1]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/erlang'
Making check in erlang/examples
make[1]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/erlang/examples'
make[1]: Nothing to be done for 'check'.
make[1]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/erlang/examples'
Making check in lua
make[1]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/lua'
ln -sf .libs/libluaguestfs.so guestfs.so
make  check-TESTS
make[2]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/lua'
make[3]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/lua'
PASS: tests/015-globals.lua
PASS: run-bindtests
PASS: tests/020-create.lua
PASS: tests/025-create-flags.lua
PASS: tests/010-load.lua
PASS: tests/030-config.lua
PASS: tests/400-events.lua
PASS: tests/027-create-multiple.lua
PASS: tests/070-optargs.lua
PASS: tests/900-errors.lua
PASS: tests/060-readdir.lua
PASS: tests/050-lvcreate.lua
PASS: tests/400-progress.lua

Testsuite summary for libguestfs 1.37.20

# TOTAL: 13
# PASS:  13
# SKIP:  0
# XFAIL: 0
# FAIL:  0
# XPASS: 0
# ERROR: 0

make[3]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/lua'
make[2]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/lua'
make[1]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/lua'
Making check in lua/examples
make[1]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/lua/examples'
make[1]: Nothing to be done for 'check'.
make[1]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/lua/examples'
Making check in gobject
make[1]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/gobject'
make  check-am
make[2]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/gobject'
make  check-TESTS
make[3]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/gobject'
make[4]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/gobject'
SKIP: run-tests
PASS: run-tests-retvalues
PASS: run-live-tests

Testsuite summary for libguestfs 1.37.20

# TOTAL: 3
# PASS:  2
# SKIP:  1
# XFAIL: 0
# FAIL:  0
# XPASS: 0
# ERROR: 0

make[4]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/gobject'
make[3]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/gobject'
make[2]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/gobject'
make[1]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/gobject'
Making check in csharp
make[1]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/csharp'
make[1]: Nothing to be done for 'check'.
make[1]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/csharp'
Making check in common/mlprogress
make[1]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/common/mlprogress'
make[1]: Nothing to be done for 'check'.
make[1]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/common/mlprogress'
Making check in common/mlvisit
make[1]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/common/mlvisit'
make  visit_tests
make[2]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/common/mlvisit'
  CC   dummy.o
  OCAMLOPT visit_tests.cmx
File "visit_tests.ml", line 111, characters 25-31:
Warning 52: Code should not depend on the actual values of
this constructor's arguments. They are only for information
and may change in future versions. (See manual section 8.5)
File "visit_tests.ml", line 119, characters 16-23:
Warning 52: Code should not depend on the actual values of
this constructor's arguments. They are only for information
and may change in future versions. (See manual section 8.5)
  GEN  visit_tests
make[2]: Leaving directory '/var/tmp/tmpAS0SwB/libguestfs/common/mlvisit'
make  check-TESTS
make[2]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/common/mlvisit'
make[3]: Entering directory '/var/tmp/tmpAS0SwB/libguestfs/common/mlvisit'
PASS: visit_tests

Testsuite summary for libguestfs 1.37.20
===

Re: [Libguestfs] [PATCH] build: Add a common script for generating OCaml dependencies correctly.

2017-08-09 Thread Richard W.M. Jones
On Wed, Aug 09, 2017 at 03:40:54PM +0200, Pino Toscano wrote:
> BTW, unrelated to this patch, just because I'm noticing them: what are
> all the "docs" dependencies in .PHONY?  At least for newer Makefile's
> I guess they were just copied from existing ones, but I did not find
> any reference/reason for the ones in older tools.  Do you remember more
> about them?

I'm guessing they are left over from something and no longer
used/useful.

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-p2v converts physical machines to virtual machines.  Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v

___
Libguestfs mailing list
Libguestfs@redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs


[Libguestfs] [PATCH v12 05/11] daemon: Implement umount_all in OCaml.

2017-08-09 Thread Richard W.M. Jones
Unlike previous ‘daemon: Reimplement ...’ patches, this does not
reimplement the umount_all API completely (yet, but this
implementation could be completed in future and then replace the C
one).  However it is necessary to have a version of umount_all which
we can call from the OCaml inspection code.
---
 daemon/mount.ml  | 61 
 daemon/mount.mli |  2 ++
 2 files changed, 63 insertions(+)

diff --git a/daemon/mount.ml b/daemon/mount.ml
index 3391ffc11..fbf4ddc39 100644
--- a/daemon/mount.ml
+++ b/daemon/mount.ml
@@ -60,3 +60,64 @@ let mount_vfs options vfs mountable mountpoint =
 let mount = mount_vfs None None
 let mount_ro = mount_vfs (Some "ro") None
 let mount_options options = mount_vfs (Some options) None
+
+(* Unmount everything mounted under /sysroot.
+ *
+ * We have to unmount in the correct order, so we sort the paths by
+ * longest first to ensure that child paths are unmounted by parent
+ * paths.
+ *
+ * This call is more important than it appears at first, because it
+ * is widely used by both test and production code in order to
+ * get back to a known state (nothing mounted, everything synchronized).
+ *)
+let rec umount_all () =
+  (* This is called from internal_autosync and generally as a cleanup
+   * function, and since the umount will definitely fail if any
+   * handles are open, we may as well close them.
+   *)
+  (* XXX
+  aug_finalize ();
+  hivex_finalize ();
+  journal_finalize ();
+  *)
+
+  let sysroot = Sysroot.sysroot () in
+  let sysroot_len = String.length sysroot in
+
+  let info = read_whole_file "/proc/self/mountinfo" in
+  let info = String.nsplit "\n" info in
+
+  let mps = ref [] in
+  List.iter (
+fun line ->
+  let line = String.nsplit " " line in
+  (* The field of interest is the 5th field.  Whitespace is escaped
+   * with octal sequences like \040 (for space).
+   * See fs/seq_file.c:mangle_path.
+   *)
+  if List.length line >= 5 then (
+let mp = List.nth line 4 in
+let mp = proc_unmangle_path mp in
+
+(* Allow a mount directory like "/sysroot" or "/sysroot/..." *)
+if (sysroot_len > 0 && String.is_prefix mp sysroot) ||
+   (String.is_prefix mp sysroot &&
+String.length mp > sysroot_len &&
+mp.[sysroot_len] = '/') then
+  push_front mp mps
+  )
+  ) info;
+
+  let mps = !mps in
+  let mps = List.sort compare_longest_first mps in
+
+  (* Unmount them. *)
+  List.iter (
+fun mp -> ignore (command "umount" [mp])
+  ) mps
+
+and compare_longest_first s1 s2 =
+  let n1 = String.length s1 in
+  let n2 = String.length s2 in
+  n2 - n1
diff --git a/daemon/mount.mli b/daemon/mount.mli
index e43d97c42..abf538521 100644
--- a/daemon/mount.mli
+++ b/daemon/mount.mli
@@ -20,3 +20,5 @@ val mount : Mountable.t -> string -> unit
 val mount_ro : Mountable.t -> string -> unit
 val mount_options : string -> Mountable.t -> string -> unit
 val mount_vfs : string option -> string option -> Mountable.t -> string -> unit
+
+val umount_all : unit -> unit
-- 
2.13.2

___
Libguestfs mailing list
Libguestfs@redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs

[Libguestfs] [PATCH v12 09/11] daemon: Implement inspection of Linux and other Unix-like operating systems.

2017-08-09 Thread Richard W.M. Jones
This is essentially a line-for-line translation of the C inspection
code.
---
 daemon/Makefile.am   |   8 +
 daemon/inspect.ml| 396 +
 daemon/inspect.mli   |  41 +++
 daemon/inspect_fs.ml | 363 +++
 daemon/inspect_fs.mli|  23 ++
 daemon/inspect_fs_unix.ml| 745 +++
 daemon/inspect_fs_unix.mli   |  44 +++
 daemon/inspect_fs_unix_fstab.ml  | 533 
 daemon/inspect_fs_unix_fstab.mli |  34 ++
 9 files changed, 2187 insertions(+)

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 51737e511..f035add2b 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -252,6 +252,10 @@ SOURCES_MLI = \
file.mli \
filearch.mli \
findfs.mli \
+   inspect.mli \
+   inspect_fs.mli \
+   inspect_fs_unix.mli \
+   inspect_fs_unix_fstab.mli \
inspect_types.mli \
inspect_utils.mli \
is.mli \
@@ -291,6 +295,10 @@ SOURCES_ML = \
realpath.ml \
inspect_types.ml \
inspect_utils.ml \
+   inspect_fs_unix_fstab.ml \
+   inspect_fs_unix.ml \
+   inspect_fs.ml \
+   inspect.ml \
callbacks.ml \
daemon.ml
 
diff --git a/daemon/inspect.ml b/daemon/inspect.ml
new file mode 100644
index 0..0f5bcfc10
--- /dev/null
+++ b/daemon/inspect.ml
@@ -0,0 +1,396 @@
+(* guestfs-inspection
+ * Copyright (C) 2009-2017 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 Std_utils
+
+open Utils
+open Mountable
+open Inspect_types
+
+let re_primary_partition = PCRE.compile "^/dev/(?:h|s|v)d.[1234]$"
+
+let rec inspect_os () =
+  Mount.umount_all ();
+
+  (* Iterate over all detected filesystems.  Inspect each one in turn. *)
+  let fses = Listfs.list_filesystems () in
+
+  let fses =
+filter_map (
+  fun (mountable, vfs_type) ->
+Inspect_fs.check_for_filesystem_on mountable vfs_type
+  ) fses in
+  if verbose () then (
+eprintf "inspect_os: fses:\n";
+List.iter (fun fs -> eprintf "%s" (string_of_fs fs)) fses;
+flush stderr
+  );
+
+  (* The OS inspection information for CoreOS are gathered by inspecting
+   * multiple filesystems. Gather all the inspected information in the
+   * inspect_fs struct of the root filesystem.
+   *)
+  let fses = collect_coreos_inspection_info fses in
+
+  (* Check if the same filesystem was listed twice as root in fses.
+   * This may happen for the *BSD root partition where an MBR partition
+   * is a shadow of the real root partition probably /dev/sda5
+   *)
+  let fses = check_for_duplicated_bsd_root fses in
+
+  (* For Linux guests with a separate /usr filesystem, merge some of the
+   * inspected information in that partition to the inspect_fs struct
+   * of the root filesystem.
+   *)
+  let fses = collect_linux_inspection_info fses in
+
+  (* Save what we found in a global variable. *)
+  Inspect_types.inspect_fses := fses;
+
+  (* At this point we have, in the handle, a list of all filesystems
+   * found and data about each one.  Now we assemble the list of
+   * filesystems which are root devices.
+   *
+   * Fall through to inspect_get_roots to do that.
+   *)
+  inspect_get_roots ()
+
+(* Traverse through the filesystem list and find out if it contains
+ * the [/] and [/usr] filesystems of a CoreOS image. If this is the
+ * case, sum up all the collected information on the root fs.
+ *)
+and collect_coreos_inspection_info fses =
+  (* Split the list into CoreOS root(s), CoreOS usr(s), and
+   * everything else.
+   *)
+  let rec loop roots usrs others = function
+| [] -> roots, usrs, others
+| ({ role = RoleRoot { distro = Some DISTRO_COREOS } } as r) :: rest ->
+   loop (r::roots) usrs others rest
+| ({ role = RoleUsr { distro = Some DISTRO_COREOS } } as u) :: rest ->
+   loop roots (u::usrs) others rest
+| o :: rest ->
+   loop roots usrs (o::others) rest
+  in
+  let roots, usrs, others = loop [] [] [] fses in
+
+  match roots with
+  (* If there are no CoreOS roots, then there's nothing to do. *)
+  | [] -> fses
+  (* If there are more than one CoreOS roots, we cannot inspect the guest. *)
+  | _::_::_ -> failwith "multiple CoreOS root filesyste

[Libguestfs] [PATCH v12 04/11] New API: Deprecate hivex_value_utf8 and replace with hivex_value_string.

2017-08-09 Thread Richard W.M. Jones
hivex has a function hivex_value_string.  We were not calling it under
the mistaken belief that because hivex implements this using iconv,
the function wouldn't work inside the daemon.  Instead we
reimplemented the functionality in the library.

This commit deprecates hivex_value_utf8 and removes the library side
code.  It replaces it with a plain wrapper around hivex_value_string.

Thanks: Pino Toscano
---
 daemon/hivex.c |  23 +++
 docs/C_SOURCE_FILES|   1 -
 examples/virt-dhcp-address.c   |   2 +-
 generator/Makefile.am  |   3 +
 generator/actions.ml   |   2 +-
 generator/actions_hivex.ml |  35 +--
 generator/actions_hivex.mli|   1 -
 generator/actions_hivex_deprecated.ml  |  43 +
 generator/actions_hivex_deprecated.mli |  21 +++
 generator/proc_nr.ml   |   2 +
 lib/MAX_PROC_NR|   2 +-
 lib/Makefile.am|   1 -
 lib/hivex.c| 111 -
 lib/inspect-apps.c |  12 ++--
 lib/inspect-fs-windows.c   |   8 +--
 v2v/convert_windows.ml |   6 +-
 16 files changed, 124 insertions(+), 149 deletions(-)

diff --git a/daemon/hivex.c b/daemon/hivex.c
index 1cbfb3458..2d0913f43 100644
--- a/daemon/hivex.c
+++ b/daemon/hivex.c
@@ -335,6 +335,29 @@ do_hivex_value_value (int64_t valueh, size_t *size_r)
   return r;
 }
 
+char *
+do_hivex_value_string (int64_t valueh)
+{
+  char *r;
+
+  NEED_HANDLE (NULL);
+
+  r = hivex_value_string (h, valueh);
+  if (r == NULL) {
+reply_with_perror ("failed");
+return NULL;
+  }
+
+  return r;
+}
+
+/* Deprecated alias for hivex_value_string. */
+char *
+do_hivex_value_utf8 (int64_t valueh)
+{
+  return do_hivex_value_string (valueh);
+}
+
 int
 do_hivex_commit (const char *filename)
 {
diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES
index 65e62f643..d5e358140 100644
--- a/docs/C_SOURCE_FILES
+++ b/docs/C_SOURCE_FILES
@@ -310,7 +310,6 @@ lib/guestfs-internal.h
 lib/guestfs.h
 lib/guid.c
 lib/handle.c
-lib/hivex.c
 lib/info.c
 lib/inspect-apps.c
 lib/inspect-fs-unix.c
diff --git a/examples/virt-dhcp-address.c b/examples/virt-dhcp-address.c
index 0c7e763ff..caf89b88e 100644
--- a/examples/virt-dhcp-address.c
+++ b/examples/virt-dhcp-address.c
@@ -266,7 +266,7 @@ print_dhcp_address_windows (guestfs_h *g, char *root_fs)
   /* Get the string and use libguestfs's auto-conversion to convert it
* to UTF-8 for output.
*/
-  p = guestfs_hivex_value_utf8 (g, value);
+  p = guestfs_hivex_value_string (g, value);
   if (!p)
 exit (EXIT_FAILURE);
 
diff --git a/generator/Makefile.am b/generator/Makefile.am
index 35b7a4209..7c1ac9ee2 100644
--- a/generator/Makefile.am
+++ b/generator/Makefile.am
@@ -31,6 +31,8 @@ sources = \
actions_debug.mli \
actions_hivex.ml \
actions_hivex.mli \
+   actions_hivex_deprecated.ml \
+   actions_hivex_deprecated.mli \
actions_inspection.ml \
actions_inspection.mli \
actions_inspection_deprecated.ml \
@@ -122,6 +124,7 @@ objects = \
actions_core_deprecated.cmo \
actions_debug.cmo \
actions_hivex.cmo \
+   actions_hivex_deprecated.cmo \
actions_inspection.cmo \
actions_inspection_deprecated.cmo \
actions_internal_tests.cmo \
diff --git a/generator/actions.ml b/generator/actions.ml
index 75742397a..79e2265d2 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -33,7 +33,6 @@ let non_daemon_functions =
   Actions_core.non_daemon_functions @
   Actions_core_deprecated.non_daemon_functions @
   Actions_debug.non_daemon_functions @
-  Actions_hivex.non_daemon_functions @
   Actions_inspection.non_daemon_functions @
   Actions_inspection_deprecated.non_daemon_functions @
   Actions_properties.non_daemon_functions @
@@ -51,6 +50,7 @@ let daemon_functions =
   Actions_core_deprecated.daemon_functions @
   Actions_debug.daemon_functions @
   Actions_hivex.daemon_functions @
+  Actions_hivex_deprecated.daemon_functions @
   Actions_tsk.daemon_functions @
   Actions_yara.daemon_functions
 
diff --git a/generator/actions_hivex.ml b/generator/actions_hivex.ml
index 0a3d6dd20..6ccb65fa6 100644
--- a/generator/actions_hivex.ml
+++ b/generator/actions_hivex.ml
@@ -22,25 +22,6 @@ open Types
 
 (* Hivex APIs. *)
 
-let non_daemon_functions = [
-  { defaults with
-name = "hivex_value_utf8"; added = (1, 19, 35);
-style = RString (RPlainString, "databuf"), [Int64 "valueh"], [];
-optional = Some "hivex";
-shortdesc = "return the data field from the (key, datatype, data) tuple";
-longdesc = "\
-This calls C (which returns the
-data field from a hivex value tuple).  It then assumes that
-the field is a UTF-16LE string and converts the result to
-UTF-8 (or if this is not possible, it returns an error).
-
-This is useful for reading strin

[Libguestfs] [PATCH v12 03/11] daemon: utils: New functions and tests.

2017-08-09 Thread Richard W.M. Jones
These utility functions will be used in the OCaml inspection code.
---
 daemon/daemon_utils_tests.ml | 10 ++
 daemon/utils.ml  | 17 +
 daemon/utils.mli | 11 +++
 3 files changed, 38 insertions(+)

diff --git a/daemon/daemon_utils_tests.ml b/daemon/daemon_utils_tests.ml
index 892509d89..db94161a0 100644
--- a/daemon/daemon_utils_tests.ml
+++ b/daemon/daemon_utils_tests.ml
@@ -46,3 +46,13 @@ let () =
 let () =
   assert (proc_unmangle_path "\\040" = " ");
   assert (proc_unmangle_path "\\040\\040" = "  ")
+
+(* Test unix_canonical_path. *)
+let () =
+  assert (unix_canonical_path "/" = "/");
+  assert (unix_canonical_path "/usr" = "/usr");
+  assert (unix_canonical_path "/usr/" = "/usr");
+  assert (unix_canonical_path "/usr/local" = "/usr/local");
+  assert (unix_canonical_path "///" = "/");
+  assert (unix_canonical_path "///usr//local//" = "/usr/local");
+  assert (unix_canonical_path "/usr///" = "/usr")
diff --git a/daemon/utils.ml b/daemon/utils.ml
index ecf967966..d87ad75db 100644
--- a/daemon/utils.ml
+++ b/daemon/utils.ml
@@ -212,3 +212,20 @@ let proc_unmangle_path path =
 let is_small_file path =
   is_regular_file path &&
 (stat path).st_size <= 2 * 1048 * 1024
+
+let read_small_file filename =
+  if not (is_small_file filename) then (
+eprintf "%s: not a regular file or too large\n" filename;
+None
+  )
+  else (
+let content = read_whole_file filename in
+let lines = String.nsplit "\n" content in
+Some lines
+  )
+
+let unix_canonical_path path =
+  let is_absolute = String.length path > 0 && path.[0] = '/' in
+  let path = String.nsplit "/" path in
+  let path = List.filter ((<>) "") path in
+  (if is_absolute then "/" else "") ^ String.concat "/" path
diff --git a/daemon/utils.mli b/daemon/utils.mli
index 9f9f91a49..f312bde41 100644
--- a/daemon/utils.mli
+++ b/daemon/utils.mli
@@ -86,5 +86,16 @@ val commandr : ?fold_stdout_on_stderr:bool -> string -> 
string list -> (int * st
 val is_small_file : string -> bool
 (** Return true if the path is a small regular file. *)
 
+val read_small_file : string -> string list option
+(** If [filename] is a small file (see {!is_small_file}) then read it
+split into lines.  Otherwise emits a debug message and returns
+[None]. *)
+
+val unix_canonical_path : string -> string
+(** Canonicalize a Unix path, so "///usr//local//" -> "/usr/local"
+
+The path is modified in place because the result is always
+the same length or shorter than the argument passed. *)
+
 (**/**)
 val get_verbose_flag : unit -> bool
-- 
2.13.2

___
Libguestfs mailing list
Libguestfs@redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs


[Libguestfs] [PATCH v12 01/11] inspection: Deprecate APIs and remove support for inspecting installer CDs.

2017-08-09 Thread Richard W.M. Jones
This just duplicated libosinfo information, and because it was never
tested it didn't work most of the time.
---
 docs/C_SOURCE_FILES|   2 -
 generator/actions_inspection.ml|  67 ---
 generator/actions_inspection_deprecated.ml |  61 +++
 inspector/Makefile.am  |  11 +-
 inspector/example-debian-netinst-cd.xml|  23 -
 inspector/example-debian.xml   |   1 -
 inspector/example-fedora-dvd.xml   |  23 -
 inspector/example-fedora-netinst-cd.xml|  21 -
 inspector/example-fedora.xml   |   1 -
 inspector/example-rhel-6-dvd.xml   |  23 -
 inspector/example-rhel-6-netinst-cd.xml|  21 -
 inspector/example-rhel-6.xml   |   1 -
 inspector/example-ubuntu-live-cd.xml   |  23 -
 inspector/example-ubuntu.xml   |   1 -
 inspector/example-windows-2003-x64-cd.xml  |  24 --
 inspector/example-windows-2003-x86-cd.xml  |  24 --
 inspector/example-windows-xp-cd.xml|  24 --
 inspector/example-windows.xml  |   1 -
 inspector/expected-archlinux.img.xml   |   1 -
 inspector/expected-coreos.img.xml  |   1 -
 inspector/expected-debian.img.xml  |   1 -
 inspector/expected-fedora.img.xml  |   1 -
 inspector/expected-ubuntu.img.xml  |   1 -
 inspector/expected-windows.img.xml |   1 -
 inspector/inspector.c  |  31 +-
 inspector/virt-inspector.pod   |  22 -
 inspector/virt-inspector.rng   |  15 -
 lib/Makefile.am|   3 -
 lib/guestfs-internal.h |  31 --
 lib/guestfs.pod|   9 -
 lib/inspect-fs-cd.c| 607 --
 lib/inspect-fs.c   |  40 --
 lib/osinfo.c   | 655 -
 33 files changed, 63 insertions(+), 1708 deletions(-)

diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES
index 1336dbfc5..91226415c 100644
--- a/docs/C_SOURCE_FILES
+++ b/docs/C_SOURCE_FILES
@@ -312,7 +312,6 @@ lib/handle.c
 lib/hivex.c
 lib/info.c
 lib/inspect-apps.c
-lib/inspect-fs-cd.c
 lib/inspect-fs-unix.c
 lib/inspect-fs-windows.c
 lib/inspect-fs.c
@@ -330,7 +329,6 @@ lib/libvirt-is-version.c
 lib/lpj.c
 lib/match.c
 lib/mountable.c
-lib/osinfo.c
 lib/private-data.c
 lib/proto.c
 lib/qemu.c
diff --git a/generator/actions_inspection.ml b/generator/actions_inspection.ml
index b7ea5a4de..cd8b9da18 100644
--- a/generator/actions_inspection.ml
+++ b/generator/actions_inspection.ml
@@ -566,73 +566,6 @@ string C is returned.
 Please read L for more details." };
 
   { defaults with
-name = "inspect_get_format"; added = (1, 9, 4);
-style = RString (RPlainString, "format"), [String (Mountable, "root")], [];
-shortdesc = "get format of inspected operating system";
-longdesc = "\
-This returns the format of the inspected operating system.  You
-can use it to detect install images, live CDs and similar.
-
-Currently defined formats are:
-
-=over 4
-
-=item \"installed\"
-
-This is an installed operating system.
-
-=item \"installer\"
-
-The disk image being inspected is not an installed operating system,
-but a I install disk, live CD, or similar.
-
-=item \"unknown\"
-
-The format of this disk image is not known.
-
-=back
-
-Future versions of libguestfs may return other strings here.
-The caller should be prepared to handle any string.
-
-Please read L for more details." };
-
-  { defaults with
-name = "inspect_is_live"; added = (1, 9, 4);
-style = RBool "live", [String (Mountable, "root")], [];
-shortdesc = "get live flag for install disk";
-longdesc = "\
-If C returns C (this
-is an install disk), then this returns true if a live image
-was detected on the disk.
-
-Please read L for more details." };
-
-  { defaults with
-name = "inspect_is_netinst"; added = (1, 9, 4);
-style = RBool "netinst", [String (Mountable, "root")], [];
-shortdesc = "get netinst (network installer) flag for install disk";
-longdesc = "\
-If C returns C (this
-is an install disk), then this returns true if the disk is
-a network installer, ie. not a self-contained install CD but
-one which is likely to require network access to complete
-the install.
-
-Please read L for more details." };
-
-  { defaults with
-name = "inspect_is_multipart"; added = (1, 9, 4);
-style = RBool "multipart", [String (Mountable, "root")], [];
-shortdesc = "get multipart flag for install disk";
-longdesc = "\
-If C returns C (this
-is an install disk), then this returns true if the disk is
-part of a set.
-
-Please read L for more details." };
-
-  { defaults with
 name = "inspect_get_product_variant"; added = (1, 9, 13);
 style = RString (RPlainString, "variant"), [String (Mountable, "root")], 
[];
 shortdesc = "get product variant of inspected operating system";
diff --git a/generator/actions_inspection_deprecated.ml 
b

[Libguestfs] [PATCH v12 07/11] lib: inspect: Remove ‘fs’ parameter from ‘guestfs_int_download_to_tmp’.

2017-08-09 Thread Richard W.M. Jones
After we move inspection code to the daemon, the library will no
longer have access to ‘struct inspect_fs’, and so we won't be able to
prefix downloads with the "root filesystem number".

Just remove this prefix (it's internal only).  However it does mean
that this function can no longer cache downloaded files.
---
 lib/guestfs-internal.h |  2 +-
 lib/inspect-apps.c | 10 +-
 lib/inspect-icon.c | 10 +-
 lib/inspect.c  | 11 ++-
 4 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/lib/guestfs-internal.h b/lib/guestfs-internal.h
index 6dbaba9bd..585dac706 100644
--- a/lib/guestfs-internal.h
+++ b/lib/guestfs-internal.h
@@ -855,7 +855,7 @@ extern int guestfs_int_set_backend (guestfs_h *g, const 
char *method);
 
 /* inspect.c */
 extern void guestfs_int_free_inspect_info (guestfs_h *g);
-extern char *guestfs_int_download_to_tmp (guestfs_h *g, struct inspect_fs *fs, 
const char *filename, const char *basename, uint64_t max_size);
+extern char *guestfs_int_download_to_tmp (guestfs_h *g, const char *filename, 
const char *basename, uint64_t max_size);
 extern int guestfs_int_parse_unsigned_int (guestfs_h *g, const char *str);
 extern int guestfs_int_parse_unsigned_int_ignore_trailing (guestfs_h *g, const 
char *str);
 extern struct inspect_fs *guestfs_int_search_for_root (guestfs_h *g, const 
char *root);
diff --git a/lib/inspect-apps.c b/lib/inspect-apps.c
index 0ea962a73..86cf82333 100644
--- a/lib/inspect-apps.c
+++ b/lib/inspect-apps.c
@@ -393,13 +393,13 @@ list_applications_rpm (guestfs_h *g, struct inspect_fs 
*fs)
   struct guestfs_application2_list *apps = NULL;
   struct read_package_data data;
 
-  Name = guestfs_int_download_to_tmp (g, fs,
+  Name = guestfs_int_download_to_tmp (g,
  "/var/lib/rpm/Name", "rpm_Name",
  MAX_PKG_DB_SIZE);
   if (Name == NULL)
 goto error;
 
-  Packages = guestfs_int_download_to_tmp (g, fs,
+  Packages = guestfs_int_download_to_tmp (g,
  "/var/lib/rpm/Packages", 
"rpm_Packages",
  MAX_PKG_DB_SIZE);
   if (Packages == NULL)
@@ -452,7 +452,7 @@ list_applications_deb (guestfs_h *g, struct inspect_fs *fs)
   char **continuation_field = NULL;
   size_t continuation_field_len = 0;
 
-  status = guestfs_int_download_to_tmp (g, fs, "/var/lib/dpkg/status", 
"status",
+  status = guestfs_int_download_to_tmp (g, "/var/lib/dpkg/status", "status",
MAX_PKG_DB_SIZE);
   if (status == NULL)
 return NULL;
@@ -628,7 +628,7 @@ list_applications_pacman (guestfs_h *g, struct inspect_fs 
*fs)
 fname = safe_malloc (g, strlen (curr->name) + path_len + 1);
 sprintf (fname, "/var/lib/pacman/local/%s/desc", curr->name);
 free (desc_file);
-desc_file = guestfs_int_download_to_tmp (g, fs, fname, curr->name, 8192);
+desc_file = guestfs_int_download_to_tmp (g, fname, curr->name, 8192);
 
 /* The desc files are small (4K). If the desc file does not exist or is
  * larger than the 8K limit we've used, the database is probably corrupted,
@@ -736,7 +736,7 @@ list_applications_apk (guestfs_h *g, struct inspect_fs *fs)
   CLEANUP_FREE char *name = NULL, *version = NULL, *release = NULL, *arch = 
NULL,
 *url = NULL, *description = NULL;
 
-  installed = guestfs_int_download_to_tmp (g, fs, "/lib/apk/db/installed",
+  installed = guestfs_int_download_to_tmp (g, "/lib/apk/db/installed",
"installed", MAX_PKG_DB_SIZE);
   if (installed == NULL)
 return NULL;
diff --git a/lib/inspect-icon.c b/lib/inspect-icon.c
index 89c232f5b..89f5da082 100644
--- a/lib/inspect-icon.c
+++ b/lib/inspect-icon.c
@@ -270,7 +270,7 @@ get_png (guestfs_h *g, struct inspect_fs *fs, const char 
*filename,
   if (max_size == 0)
 max_size = 4 * w * h;
 
-  local = guestfs_int_download_to_tmp (g, fs, real, "icon", max_size);
+  local = guestfs_int_download_to_tmp (g, real, "icon", max_size);
   if (!local)
 return NOT_FOUND;
 
@@ -421,7 +421,7 @@ icon_cirros (guestfs_h *g, struct inspect_fs *fs, size_t 
*size_r)
   if (!STRPREFIX (type, "ASCII text"))
 return NOT_FOUND;
 
-  local = guestfs_int_download_to_tmp (g, fs, CIRROS_LOGO, "icon", 1024);
+  local = guestfs_int_download_to_tmp (g, CIRROS_LOGO, "icon", 1024);
   if (!local)
 return NOT_FOUND;
 
@@ -505,7 +505,7 @@ icon_windows_xp (guestfs_h *g, struct inspect_fs *fs, 
size_t *size_r)
   if (r == 0)
 return NOT_FOUND;
 
-  filename_downloaded = guestfs_int_download_to_tmp (g, fs, filename_case,
+  filename_downloaded = guestfs_int_download_to_tmp (g, filename_case,
 "explorer.exe",
 MAX_WINDOWS_EXPLORER_SIZE);
   if (filename_downloaded == NULL)
@@ -575,7 +575,7 @@ icon_windows_7 (guestfs_h *g, struct inspect_fs *fs, size_t 
*size_r)
   if (w

[Libguestfs] [PATCH v12 00/11] Reimplement inspection in the daemon.

2017-08-09 Thread Richard W.M. Jones
This fixes almost everything.  Note that it adds an extra commit which
fixes the whole utf8/iconv business.

It's probably better to list what isn't fixed:

(1) I didn't leave the osinfo code around because I'm still haven't
looked too closely at virt-builder-repository.  Can't we just fetch
this code from the git history when we need it?

(2) I didn't change the way that parse_os_release work fundamentally
to reduce the risk of adding new bugs in this series.  However I do
agree that we need to improve them after this series.

Rich.

___
Libguestfs mailing list
Libguestfs@redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs


[Libguestfs] [PATCH v12 06/11] generator: daemon: Implement RStringList (RMountable, _) and RHashtable (RPlainString, RMountable, _).

2017-08-09 Thread Richard W.M. Jones
Implement returning these two types from OCaml daemon functions.
---
 daemon/daemon-c.c   | 52 
 daemon/daemon-c.h   |  2 ++
 generator/daemon.ml | 13 +++--
 3 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/daemon/daemon-c.c b/daemon/daemon-c.c
index 4d04dc0dc..533bf7ce7 100644
--- a/daemon/daemon-c.c
+++ b/daemon/daemon-c.c
@@ -151,6 +151,30 @@ guestfs_int_daemon_return_string_mountable (value retv)
   }
 }
 
+/* Implement RStringList (RMountable, _). */
+char **
+guestfs_int_daemon_return_string_mountable_list (value retv)
+{
+  CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (ret);
+  value v;
+  char *m;
+
+  while (retv != Val_int (0)) {
+v = Field (retv, 0);
+m = guestfs_int_daemon_return_string_mountable (v);
+if (m == NULL)
+  return NULL;
+if (add_string_nodup (&ret, m) == -1)
+  return NULL;
+retv = Field (retv, 1);
+  }
+
+  if (end_stringsbuf (&ret) == -1)
+return NULL;
+
+  return take_stringsbuf (&ret); /* caller frees */
+}
+
 /* Implement RHashtable (RPlainString, RPlainString, _). */
 char **
 guestfs_int_daemon_return_hashtable_string_string (value retv)
@@ -202,3 +226,31 @@ guestfs_int_daemon_return_hashtable_mountable_string 
(value retv)
 
   return take_stringsbuf (&ret); /* caller frees */
 }
+
+/* Implement RHashtable (RPlainString, RMountable, _). */
+char **
+guestfs_int_daemon_return_hashtable_string_mountable (value retv)
+{
+  CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (ret);
+  value sv, v, mv;
+  char *m;
+
+  while (retv != Val_int (0)) {
+v = Field (retv, 0);/* (string, Mountable.t) */
+sv = Field (v, 0);  /* string */
+if (add_string (&ret, String_val (sv)) == -1)
+  return NULL;
+mv = Field (v, 1);  /* Mountable.t */
+m = guestfs_int_daemon_return_string_mountable (mv);
+if (m == NULL)
+  return NULL;
+if (add_string_nodup (&ret, m) == -1)
+  return NULL;
+retv = Field (retv, 1);
+  }
+
+  if (end_stringsbuf (&ret) == -1)
+return NULL;
+
+  return take_stringsbuf (&ret); /* caller frees */
+}
diff --git a/daemon/daemon-c.h b/daemon/daemon-c.h
index 1fcfd707c..9b7085bce 100644
--- a/daemon/daemon-c.h
+++ b/daemon/daemon-c.h
@@ -31,7 +31,9 @@ extern void guestfs_int_daemon_exn_to_reply_with_error (const 
char *func, value
 extern value guestfs_int_daemon_copy_mountable (const mountable_t *mountable);
 extern char **guestfs_int_daemon_return_string_list (value retv);
 extern char *guestfs_int_daemon_return_string_mountable (value retv);
+extern char **guestfs_int_daemon_return_string_mountable_list (value retv);
 extern char **guestfs_int_daemon_return_hashtable_string_string (value retv);
 extern char **guestfs_int_daemon_return_hashtable_mountable_string (value 
retv);
+extern char **guestfs_int_daemon_return_hashtable_string_mountable (value 
retv);
 
 #endif /* GUESTFSD_DAEMON_C_H */
diff --git a/generator/daemon.ml b/generator/daemon.ml
index b4d4cfe8e..2e8d6c830 100644
--- a/generator/daemon.ml
+++ b/generator/daemon.ml
@@ -761,9 +761,13 @@ let generate_daemon_caml_stubs () =
   pr "  char *ret =\n";
   pr "guestfs_int_daemon_return_string_mountable (retv);\n";
   pr "  CAMLreturnT (char *, ret); /* caller frees */\n"
-   | RStringList _ ->
+   | RStringList ((RPlainString|RDevice), _) ->
   pr "  char **ret = guestfs_int_daemon_return_string_list (retv);\n";
   pr "  CAMLreturnT (char **, ret); /* caller frees */\n"
+   | RStringList (RMountable, _) ->
+  pr "  char **ret =\n";
+  pr "guestfs_int_daemon_return_string_mountable_list (retv);\n";
+  pr "  CAMLreturnT (char **, ret); /* caller frees */\n"
| RStruct (_, typ) ->
   pr "  guestfs_int_%s *ret =\n" typ;
   pr "return_%s (retv);\n" typ;
@@ -774,7 +778,8 @@ let generate_daemon_caml_stubs () =
   pr "return_%s_list (retv);\n" typ;
   pr "  /* caller frees */\n";
   pr "  CAMLreturnT (guestfs_int_%s_list *, ret);\n" typ
-   | RHashtable (RPlainString, RPlainString, _) ->
+   | RHashtable (RPlainString, RPlainString, _)
+   | RHashtable (RPlainString, RDevice, _) ->
   pr "  char **ret =\n";
   pr "guestfs_int_daemon_return_hashtable_string_string (retv);\n";
   pr "  CAMLreturnT (char **, ret); /* caller frees */\n"
@@ -782,6 +787,10 @@ let generate_daemon_caml_stubs () =
   pr "  char **ret =\n";
   pr "guestfs_int_daemon_return_hashtable_mountable_string 
(retv);\n";
   pr "  CAMLreturnT (char **, ret); /* caller frees */\n"
+   | RHashtable (RPlainString, RMountable, _) ->
+  pr "  char **ret =\n";
+  pr "guestfs_int_daemon_return_hashtable_string_mountable 
(retv);\n";
+  pr "  CAMLreturnT (char **, ret); /* caller frees */\n"
| RHashtable _ -> assert false
| RBufferOut _ -> assert false

[Libguestfs] [PATCH v12 02/11] common: Bundle the ocaml-augeas library for use by the daemon.

2017-08-09 Thread Richard W.M. Jones
This commit bundles the ocaml-augeas library (upstream here:
http://git.annexia.org/?p=ocaml-augeas.git;a=summary).  It's identical
to the upstream version and should remain so.

We can work towards using system ocaml-augeas, when it's more widely
available.
---
 .gitignore|   1 +
 Makefile.am   |   1 +
 common/mlaugeas/Makefile.am   |  91 +
 common/mlaugeas/augeas-c.c| 288 ++
 common/mlaugeas/augeas.README |   8 ++
 common/mlaugeas/augeas.ml |  59 +
 common/mlaugeas/augeas.mli|  95 ++
 configure.ac  |   1 +
 daemon/Makefile.am|   7 +-
 daemon/daemon-c.c |   2 +
 docs/C_SOURCE_FILES   |   1 +
 docs/guestfs-hacking.pod  |   5 +
 ocaml-dep.sh.in   |   1 +
 13 files changed, 559 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index 4d738d10f..8446d3af5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -123,6 +123,7 @@ Makefile.in
 /common/errnostring/errnostring-gperf.gperf
 /common/errnostring/errnostring.h
 /common/miniexpect/miniexpect.3
+/common/mlaugeas/.depend
 /common/mlpcre/.depend
 /common/mlpcre/pcre_tests
 /common/mlprogress/.depend
diff --git a/Makefile.am b/Makefile.am
index e71328a58..e62f2678e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -45,6 +45,7 @@ SUBDIRS += lib docs examples po
 
 # The daemon and the appliance.
 SUBDIRS += common/mlutils
+SUBDIRS += common/mlaugeas
 SUBDIRS += common/mlpcre
 if ENABLE_DAEMON
 SUBDIRS += daemon
diff --git a/common/mlaugeas/Makefile.am b/common/mlaugeas/Makefile.am
new file mode 100644
index 0..ed1abe7ec
--- /dev/null
+++ b/common/mlaugeas/Makefile.am
@@ -0,0 +1,91 @@
+# libguestfs OCaml tools common code
+# Copyright (C) 2011-2017 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_MLI) \
+   $(SOURCES_ML) \
+   $(SOURCES_C)
+
+SOURCES_MLI = \
+   augeas.mli
+
+SOURCES_ML = \
+   augeas.ml
+
+SOURCES_C = \
+   augeas-c.c
+
+# We pretend that we're building a C library.  automake handles the
+# compilation of the C sources for us.  At the end we take the C
+# objects and OCaml objects and link them into the OCaml library.
+# This C library is never used.
+
+noinst_LIBRARIES = libmlaugeas.a
+
+if !HAVE_OCAMLOPT
+MLAUGEAS_CMA = mlaugeas.cma
+else
+MLAUGEAS_CMA = mlaugeas.cmxa
+endif
+
+noinst_DATA = $(MLAUGEAS_CMA)
+
+libmlaugeas_a_SOURCES = $(SOURCES_C)
+libmlaugeas_a_CPPFLAGS = \
+   -I. \
+   -I$(top_builddir) \
+   -I$(shell $(OCAMLC) -where)
+libmlaugeas_a_CFLAGS = \
+   $(WARN_CFLAGS) $(WERROR_CFLAGS) \
+   $(LIBVIRT_CFLAGS) $(LIBXML2_CFLAGS) \
+   -fPIC
+
+BOBJECTS = $(SOURCES_ML:.ml=.cmo)
+XOBJECTS = $(BOBJECTS:.cmo=.cmx)
+
+OCAMLPACKAGES =
+OCAMLFLAGS = $(OCAML_FLAGS) $(OCAML_WARN_ERROR)
+
+if !HAVE_OCAMLOPT
+OBJECTS = $(BOBJECTS)
+else
+OBJECTS = $(XOBJECTS)
+endif
+
+libmlaugeas_a_DEPENDENCIES = $(OBJECTS)
+
+$(MLAUGEAS_CMA): $(OBJECTS) libmlaugeas.a
+   $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
+   $(OBJECTS) $(libmlaugeas_a_OBJECTS) -cclib -laugeas -o mlaugeas
+
+# Dependencies.
+depend: .depend
+
+.depend: $(wildcard $(abs_srcdir)/*.mli) $(wildcard $(abs_srcdir)/*.ml)
+   rm -f $@ $@-t
+   $(OCAMLFIND) ocamldep -I ../../ocaml -I $(abs_srcdir) $^ | \
+ $(SED) 's/ *$$//' | \
+ $(SED) -e :a -e '/ *\\$$/N; s/ *\\\n */ /; ta' | \
+ $(SED) -e 's,$(abs_srcdir)/,$(builddir)/,g' | \
+ sort > $@-t
+   mv $@-t $@
+
+-include .depend
+
+.PHONY: depend docs
diff --git a/common/mlaugeas/augeas-c.c b/common/mlaugeas/augeas-c.c
new file mode 100644
index 0..c06bf92da
--- /dev/null
+++ b/common/mlaugeas/augeas-c.c
@@ -0,0 +1,288 @@
+/* Augeas OCaml bindings
+ * Copyright (C) 2008-2012 Red Hat Inc., Richard W.M. Jones
+ *
+ * This library 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; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty o

[Libguestfs] [PATCH v12 08/11] daemon: Implement inspection types and utility functions.

2017-08-09 Thread Richard W.M. Jones
Define the types which will be used to communicate between the
different parts of the inspection code.  The main types are:

  fscorresponds to ‘struct inspect_fs’ in C code

  root  no direct correspondence with the C code, but in the C
code, ‘inspect_fs’ was overloaded to store roots

  inspection_data
the inspection data which is incrementally collected about
each filesystem as we perform inspection steps

Other types have simple and obvious correspondences with the
equivalent C code.

Add some utility function which will be used by inspection.

Note that this commit has no effect on its own, it just links extra
dead code into the daemon.
---
 daemon/Makefile.am   |   4 +
 daemon/inspect_types.ml  | 314 +++
 daemon/inspect_types.mli | 182 +++
 daemon/inspect_utils.ml  | 187 
 daemon/inspect_utils.mli |  53 
 5 files changed, 740 insertions(+)

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 3e8bdb44f..51737e511 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -252,6 +252,8 @@ SOURCES_MLI = \
file.mli \
filearch.mli \
findfs.mli \
+   inspect_types.mli \
+   inspect_utils.mli \
is.mli \
ldm.mli \
link.mli \
@@ -287,6 +289,8 @@ SOURCES_ML = \
parted.ml \
listfs.ml \
realpath.ml \
+   inspect_types.ml \
+   inspect_utils.ml \
callbacks.ml \
daemon.ml
 
diff --git a/daemon/inspect_types.ml b/daemon/inspect_types.ml
new file mode 100644
index 0..4570349ba
--- /dev/null
+++ b/daemon/inspect_types.ml
@@ -0,0 +1,314 @@
+(* guestfs-inspection
+ * Copyright (C) 2009-2017 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 Std_utils
+
+type fs = {
+  fs_location : location;
+  role : role; (** Special cases: root filesystem or /usr *)
+}
+and root = {
+  root_location : location;
+  inspection_data : inspection_data;
+}
+and location = {
+  mountable : Mountable.t; (** The device name or other mountable object.*)
+  vfs_type : string;   (** Returned from [vfs_type] API. *)
+}
+
+and role =
+  | RoleRoot of inspection_data
+  | RoleUsr of inspection_data
+  | RoleSwap
+  | RoleOther
+and inspection_data = {
+  mutable os_type : os_type option;
+  mutable distro : distro option;
+  mutable package_format : package_format option;
+  mutable package_management : package_management option;
+  mutable product_name : string option;
+  mutable product_variant : string option;
+  mutable version : version option;
+  mutable arch : string option;
+  mutable hostname : string option;
+  mutable fstab : fstab_entry list;
+  mutable windows_systemroot : string option;
+  mutable windows_software_hive : string option;
+  mutable windows_system_hive : string option;
+  mutable windows_current_control_set : string option;
+  mutable drive_mappings : drive_mapping list;
+}
+and os_type =
+  | OS_TYPE_DOS
+  | OS_TYPE_FREEBSD
+  | OS_TYPE_HURD
+  | OS_TYPE_LINUX
+  | OS_TYPE_MINIX
+  | OS_TYPE_NETBSD
+  | OS_TYPE_OPENBSD
+  | OS_TYPE_WINDOWS
+and distro =
+  | DISTRO_ALPINE_LINUX
+  | DISTRO_ALTLINUX
+  | DISTRO_ARCHLINUX
+  | DISTRO_BUILDROOT
+  | DISTRO_CENTOS
+  | DISTRO_CIRROS
+  | DISTRO_COREOS
+  | DISTRO_DEBIAN
+  | DISTRO_FEDORA
+  | DISTRO_FREEBSD
+  | DISTRO_FREEDOS
+  | DISTRO_FRUGALWARE
+  | DISTRO_GENTOO
+  | DISTRO_LINUX_MINT
+  | DISTRO_MAGEIA
+  | DISTRO_MANDRIVA
+  | DISTRO_MEEGO
+  | DISTRO_NETBSD
+  | DISTRO_OPENBSD
+  | DISTRO_OPENSUSE
+  | DISTRO_ORACLE_LINUX
+  | DISTRO_PARDUS
+  | DISTRO_PLD_LINUX
+  | DISTRO_REDHAT_BASED
+  | DISTRO_RHEL
+  | DISTRO_SCIENTIFIC_LINUX
+  | DISTRO_SLACKWARE
+  | DISTRO_SLES
+  | DISTRO_SUSE_BASED
+  | DISTRO_TTYLINUX
+  | DISTRO_UBUNTU
+  | DISTRO_VOID_LINUX
+  | DISTRO_WINDOWS
+and package_format =
+  | PACKAGE_FORMAT_APK
+  | PACKAGE_FORMAT_DEB
+  | PACKAGE_FORMAT_EBUILD
+  | PACKAGE_FORMAT_PACMAN
+  | PACKAGE_FORMAT_PISI
+  | PACKAGE_FORMAT_PKGSRC
+  | PACKAGE_FORMAT_RPM
+  | PACKAGE_FORMAT_XBPS
+and package_management =
+  | PACKAGE_MANAGEMENT_APK
+  | PACKAGE_MANAGEMENT_APT
+  | PACKAGE_MANAGEMENT_DNF
+  | PACKAGE_MANAGEMENT_PACMAN
+  | PACKAGE_MANAGEMENT_PISI
+  

[Libguestfs] [PATCH v12 10/11] daemon: Implement inspection of Windows.

2017-08-09 Thread Richard W.M. Jones
Mostly a line-for-line translation of the C inspection code.
---
 daemon/Makefile.am|   2 +
 daemon/inspect_fs.ml  |   6 +
 daemon/inspect_fs_windows.ml  | 480 ++
 daemon/inspect_fs_windows.mli |  24 +++
 4 files changed, 512 insertions(+)

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index f035add2b..f9de758dc 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -256,6 +256,7 @@ SOURCES_MLI = \
inspect_fs.mli \
inspect_fs_unix.mli \
inspect_fs_unix_fstab.mli \
+   inspect_fs_windows.mli \
inspect_types.mli \
inspect_utils.mli \
is.mli \
@@ -297,6 +298,7 @@ SOURCES_ML = \
inspect_utils.ml \
inspect_fs_unix_fstab.ml \
inspect_fs_unix.ml \
+   inspect_fs_windows.ml \
inspect_fs.ml \
inspect.ml \
callbacks.ml \
diff --git a/daemon/inspect_fs.ml b/daemon/inspect_fs.ml
index 9153e68a5..10a15827b 100644
--- a/daemon/inspect_fs.ml
+++ b/daemon/inspect_fs.ml
@@ -192,6 +192,12 @@ and check_filesystem mountable =
 debug_matching "Linux /var";
 ()
   )
+  (* Windows root? *)
+  else if Inspect_fs_windows.is_windows_systemroot () then (
+debug_matching "Windows root";
+role := `Root;
+Inspect_fs_windows.check_windows_root data;
+  )
   (* Windows volume with installed applications (but not root)? *)
   else if is_dir_nocase "/System Volume Information" &&
   is_dir_nocase "/Program Files" then (
diff --git a/daemon/inspect_fs_windows.ml b/daemon/inspect_fs_windows.ml
new file mode 100644
index 0..78af7f048
--- /dev/null
+++ b/daemon/inspect_fs_windows.ml
@@ -0,0 +1,480 @@
+(* guestfs-inspection
+ * Copyright (C) 2009-2017 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 Std_utils
+
+open Utils
+open Inspect_types
+open Inspect_utils
+
+(* Check a predefined list of common windows system root locations. *)
+let systemroot_paths =
+  [ "/windows"; "/winnt"; "/win32"; "/win"; "/reactos" ]
+
+let re_boot_ini_os =
+  PCRE.compile 
"^(multi|scsi)\\((\\d+)\\)disk\\((\\d+)\\)rdisk\\((\\d+)\\)partition\\((\\d+)\\)([^=]+)="
+
+let rec check_windows_root data =
+  let systemroot =
+match get_windows_systemroot () with
+| None -> assert false (* Should never happen - see caller. *)
+| Some systemroot -> systemroot in
+
+  data.os_type <- Some OS_TYPE_WINDOWS;
+  data.distro <- Some DISTRO_WINDOWS;
+  data.windows_systemroot <- Some systemroot;
+  data.arch <- Some (check_windows_arch systemroot);
+
+  (* Load further fields from the Windows registry. *)
+  check_windows_registry systemroot data
+
+and is_windows_systemroot () =
+  get_windows_systemroot () <> None
+
+and get_windows_systemroot () =
+  let rec loop = function
+| [] -> None
+| path :: paths ->
+   let path = case_sensitive_path_silently path in
+   match path with
+   | None -> loop paths
+   | Some path ->
+  if is_systemroot path then Some path
+  else loop paths
+  in
+  let systemroot = loop systemroot_paths in
+
+  let systemroot =
+match systemroot with
+| Some systemroot -> Some systemroot
+| None ->
+   (* If the fs contains boot.ini, check it for non-standard
+* systemroot locations.
+*)
+   let boot_ini_path = case_sensitive_path_silently "/boot.ini" in
+   match boot_ini_path with
+   | None -> None
+   | Some boot_ini_path ->
+  get_windows_systemroot_from_boot_ini boot_ini_path in
+
+  match systemroot with
+  | None -> None
+  | Some systemroot ->
+ if verbose () then
+   eprintf "get_windows_systemroot: windows %%SYSTEMROOT%% = %s\n%!"
+   systemroot;
+ Some systemroot
+
+and get_windows_systemroot_from_boot_ini boot_ini_path =
+  let chroot = Chroot.create ~name:"get_windows_systemroot_from_boot_ini" () in
+  let lines = Chroot.f chroot (fun () -> read_small_file boot_ini_path) () in
+  match lines with
+  | None -> None
+  | Some lines ->
+ (* Find:
+  *   [operating systems]
+  * followed by multiple lines starting with "multi" or "scsi".
+  *)
+ let rec loop = function
+   | [] -> None
+   | str :: rest when String.is_prefix str "[operating systems]" ->
+  le