[Libguestfs] [PATCH 4/5] Add/adapt all the files to build

Pino Toscano ptoscano at redhat.com
Tue Jul 9 14:05:17 UTC 2019


Add various files, and adapt the existing Makefile.am, to make virt-p2v
build:
- add all the various autotools files for bootstrapping, configuring,
  and building
- add the POD build & checking scripts (imported from libguestfs)
- add the scripts for testing (run script, and test macros)
---
 .gitignore          |   1 -
 AUTHORS             |  16 ++
 Makefile.am         |  52 ++--
 autogen.sh          |  51 ++++
 bootstrap           | 124 ++++++++
 configure.ac        | 109 +++++++
 m4/p2v-c.m4         | 179 ++++++++++++
 m4/p2v-libraries.m4 |  79 ++++++
 m4/p2v-progs.m4     |  63 ++++
 m4/p2v-tests.m4     |  45 +++
 podcheck.pl         | 273 ++++++++++++++++++
 podwrapper.pl.in    | 678 ++++++++++++++++++++++++++++++++++++++++++++
 run.in              | 118 ++++++++
 subdir-rules.mk     |  60 ++++
 test-functions.sh   | 120 ++++++++
 15 files changed, 1949 insertions(+), 19 deletions(-)
 create mode 100644 AUTHORS
 create mode 100755 autogen.sh
 create mode 100755 bootstrap
 create mode 100644 configure.ac
 create mode 100644 m4/p2v-c.m4
 create mode 100644 m4/p2v-libraries.m4
 create mode 100644 m4/p2v-progs.m4
 create mode 100644 m4/p2v-tests.m4
 create mode 100755 podcheck.pl
 create mode 100755 podwrapper.pl.in
 create mode 100755 run.in
 create mode 100644 subdir-rules.mk
 create mode 100755 test-functions.sh

diff --git a/.gitignore b/.gitignore
index 22ac25a..8495f6c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,7 +8,6 @@ Makefile
 Makefile.in
 
 /about-authors.c
-/AUTHORS
 /blank-part.img
 /config.c
 /dependencies.archlinux
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..2642291
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,16 @@
+Cédric Bosdonnat
+John Eckersberg
+Junqin Zhou
+Kean Li
+Kun Wei
+Laura Bailey
+Matthew Booth
+Mike Latimer
+Ming Xie
+Pino Toscano
+Richard W.M. Jones
+Roman Kagan
+Shahar Havivi
+Tingting Zheng
+Xiang Hua Chen
+Yehuda Zimmerman
diff --git a/Makefile.am b/Makefile.am
index 0d67dbf..ac7e62f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -17,15 +17,19 @@
 
 include $(top_srcdir)/subdir-rules.mk
 
-generator_built = \
-	AUTHORS
+ACLOCAL_AMFLAGS = -I m4
 
-BUILT_SOURCES = \
-	$(generator_built)
+SUBDIRS = gnulib/lib
+if ENABLE_GNULIB_TESTS
+SUBDIRS += gnulib/tests
+endif
 
 EXTRA_DIST = \
 	$(BUILT_SOURCES) \
-	$(TESTS) $(APPLIANCE_TESTS) $(SLOW_TESTS) \
+	$(TESTS) $(LIBGUESTFS_TESTS) $(SLOW_TESTS) \
+	AUTHORS \
+	autogen.sh \
+	bootstrap \
 	contrib/aux-scripts/do-build.sh \
 	contrib/build-p2v-iso.sh \
 	contrib/patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch \
@@ -42,6 +46,8 @@ EXTRA_DIST = \
 	miniexpect/README \
 	p2v.ks.in \
 	p2v.service \
+	podcheck.pl \
+	test-functions.sh \
 	test-virt-p2v-docs.sh \
 	test-virt-p2v-pxe.sshd_config.in \
 	test-virt-p2v-scp.sh \
@@ -70,7 +76,8 @@ CLEANFILES += \
 	test-virt-p2v-pxe.sshd_config \
 	virt-p2v.img \
 	virt-p2v-kernel-config.pod \
-	virt-p2v.xz
+	virt-p2v.xz \
+	website/*.html
 
 # Although virt-p2v is a regular binary, it is not usually installed
 # in /usr/bin since it only functions when contained in an ISO or PXE
@@ -90,6 +97,14 @@ virt-p2v.xz: virt-p2v
 noinst_PROGRAMS = virt-p2v
 
 virt_p2v_SOURCES = \
+	miniexpect/miniexpect.c \
+	miniexpect/miniexpect.h \
+	libguestfs/cleanups.c \
+	libguestfs/cleanups.h \
+	libguestfs/guestfs-utils.c \
+	libguestfs/guestfs-utils.h \
+	libguestfs/libxml2-cleanups.c \
+	libguestfs/libxml2-writer-macros.h \
 	conversion.c \
 	cpuid.c \
 	gui.c \
@@ -119,10 +134,9 @@ nodist_virt_p2v_SOURCES = \
 
 virt_p2v_CPPFLAGS = \
 	-DLOCALEBASEDIR=\""$(datadir)/locale"\" \
-	-I$(top_srcdir)/common/utils -I$(top_builddir)/common/utils \
-	-I$(top_srcdir)/lib -I$(top_builddir)/lib \
-	-I$(top_srcdir)/common/miniexpect -I$(top_builddir)/common/miniexpect \
-	-I$(srcdir)/../gnulib/lib -I../gnulib/lib
+	-I$(srcdir)/libguestfs \
+	-I$(srcdir)/miniexpect \
+	-I$(srcdir)/gnulib/lib -Ignulib/lib
 
 virt_p2v_CFLAGS = \
 	-pthread \
@@ -133,13 +147,11 @@ virt_p2v_CFLAGS = \
 	$(DBUS_CFLAGS)
 
 virt_p2v_LDADD = \
-	$(top_builddir)/common/utils/libutils.la \
-	$(top_builddir)/common/miniexpect/libminiexpect.la \
 	$(PCRE_LIBS) \
 	$(LIBXML2_LIBS) \
 	$(GTK_LIBS) \
 	$(DBUS_LIBS) \
-	../gnulib/lib/libgnu.la \
+	gnulib/lib/libgnu.a \
 	-lm
 
 $(generated_sources) virt-p2v-kernel-config.pod: $(srcdir)/generate-p2v-config.pl
@@ -157,7 +169,7 @@ dependencies_files = \
 	dependencies.redhat \
 	dependencies.suse
 
-$(dependencies_files): dependencies.m4 ../config.status
+$(dependencies_files): dependencies.m4 config.status
 	define=`echo $@ | $(SED) 's/dependencies.//;y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`; \
 	m4 -D$$define=1 -DGTK_VERSION=$(GTK_VERSION) $< > $@-t
 	mv $@-t $@
@@ -239,8 +251,12 @@ PHYSICAL_MACHINE = $(abs_builddir)/fedora.img
 BLANK_DISK = blank-part.img
 
 check_DATA = \
+	$(NULL)
+if HAVE_LIBGUESTFS
+check_DATA += \
 	$(PHYSICAL_MACHINE) \
 	$(BLANK_DISK)
+endif HAVE_LIBGUESTFS
 
 run-virt-p2v-directly: $(PHYSICAL_MACHINE)
 	$(top_builddir)/run virt-p2v --test-disk=$(PHYSICAL_MACHINE)
@@ -290,15 +306,15 @@ TESTS = \
 	test-virt-p2v-cmdline.sh \
 	test-virt-p2v-docs.sh
 
-APPLIANCE_TESTS = \
+LIBGUESTFS_TESTS = \
 	test-virt-p2v.sh \
 	test-virt-p2v-nbdkit.sh
 
-if ENABLE_APPLIANCE
+if HAVE_LIBGUESTFS
 TESTS += \
-	$(APPLIANCE_TESTS) \
+	$(LIBGUESTFS_TESTS) \
 	$(SLOW_TESTS)
-endif ENABLE_APPLIANCE
+endif HAVE_LIBGUESTFS
 
 check-valgrind:
 	make VG="@VG@" check
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..fcdd0ce
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,51 @@
+#!/bin/bash -
+# libguestfs
+# Copyright (C) 2009 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.
+#
+# Rebuild the autotools environment.
+
+set -e
+set -v
+
+# Ensure that whenever we pull in a gnulib update or otherwise change to a
+# different version (i.e., when switching branches), we also rerun ./bootstrap.
+curr_status=.git-module-status
+t=$(git submodule status|sed 's/^[ +-]//;s/ .*//')
+if test "$t" = "$(cat $curr_status 2>/dev/null)"; then
+    : # good, it's up to date
+else
+    echo running bootstrap...
+    ./bootstrap && echo "$t" > $curr_status
+fi
+
+CONFIGUREDIR=.
+
+# Run configure in BUILDDIR if it's set
+if [ ! -z "$BUILDDIR" ]; then
+    mkdir -p $BUILDDIR
+    cd $BUILDDIR
+
+    CONFIGUREDIR=..
+fi
+
+# If no arguments were specified and configure has run before, use the previous
+# arguments
+if test $# -eq 0 && test -x ./config.status; then
+    ./config.status --recheck
+else
+    $CONFIGUREDIR/configure "$@"
+fi
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..db9c8e1
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,124 @@
+#!/bin/sh
+
+usage() {
+  echo >&2 "\
+Usage: $0 [OPTION]...
+Bootstrap this package from the checked-out sources.
+
+Options:
+ --gnulib-srcdir=DIRNAME  specify the local directory where gnulib
+                          sources reside.  Use this if you already
+                          have gnulib sources on your machine, and
+                          do not want to waste your bandwidth downloading
+                          them again.  Defaults to \$GNULIB_SRCDIR
+"
+}
+
+for option
+do
+  case $option in
+  --help)
+    usage
+    exit;;
+  --gnulib-srcdir=*)
+    GNULIB_SRCDIR=${option#--gnulib-srcdir=};;
+  *)
+    echo >&2 "$0: $option: unknown option"
+    exit 1;;
+  esac
+done
+
+cleanup_gnulib() {
+  status=$?
+  rm -fr "$gnulib_path"
+  exit $status
+}
+
+git_modules_config () {
+  test -f .gitmodules && git config --file .gitmodules "$@"
+}
+
+gnulib_path=$(git_modules_config submodule.gnulib.path)
+test -z "$gnulib_path" && gnulib_path=gnulib
+
+# Get gnulib files.  Populate $GNULIB_SRCDIR, possibly updating a
+# submodule, for use in the rest of the script.
+
+case ${GNULIB_SRCDIR--} in
+-)
+  if git_modules_config submodule.gnulib.url >/dev/null; then
+    echo "$0: getting gnulib files..."
+    git submodule init -- "$gnulib_path" || exit $?
+    git submodule update -- "$gnulib_path" || exit $?
+
+  elif [ ! -d "$gnulib_path" ]; then
+    echo "$0: getting gnulib files..."
+
+    trap cleanup_gnulib 1 2 13 15
+
+    shallow=
+    git clone -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2'
+    git clone $shallow git://git.sv.gnu.org/gnulib "$gnulib_path" ||
+      cleanup_gnulib
+
+    trap - 1 2 13 15
+  fi
+  GNULIB_SRCDIR=$gnulib_path
+  ;;
+*)
+  # Use GNULIB_SRCDIR directly or as a reference.
+  if test -d "$GNULIB_SRCDIR"/.git && \
+        git_modules_config submodule.gnulib.url >/dev/null; then
+    echo "$0: getting gnulib files..."
+    if git submodule -h|grep -- --reference > /dev/null; then
+      # Prefer the one-liner available in git 1.6.4 or newer.
+      git submodule update --init --reference "$GNULIB_SRCDIR" \
+        "$gnulib_path" || exit $?
+    else
+      # This fallback allows at least git 1.5.5.
+      if test -f "$gnulib_path"/gnulib-tool; then
+        # Since file already exists, assume submodule init already complete.
+        git submodule update -- "$gnulib_path" || exit $?
+      else
+        # Older git can't clone into an empty directory.
+        rmdir "$gnulib_path" 2>/dev/null
+        git clone --reference "$GNULIB_SRCDIR" \
+          "$(git_modules_config submodule.gnulib.url)" "$gnulib_path" \
+          && git submodule init -- "$gnulib_path" \
+          && git submodule update -- "$gnulib_path" \
+          || exit $?
+      fi
+    fi
+    GNULIB_SRCDIR=$gnulib_path
+  fi
+  ;;
+esac
+
+gnulib_tool=$GNULIB_SRCDIR/gnulib-tool
+<$gnulib_tool || exit
+
+modules='
+c-ctype
+error
+getprogname
+ignore-value
+manywarnings
+ptsname_r
+sys_types
+xstrtoll
+'
+
+# If any tests fail, avoid including them by adding them to
+# this list.
+avoid=""
+
+$gnulib_tool			\
+  $avoid			\
+  --with-tests			\
+  --m4-base=m4			\
+  --source-base=gnulib/lib	\
+  --tests-base=gnulib/tests	\
+  --import $modules
+
+# Disable autopoint, since it was already done above.
+AUTOPOINT=true autoreconf --verbose --install
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..dbd46cb
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,109 @@
+# virt-p2v
+# Copyright (C) 2009-2019 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.
+
+# The major, minor, and release fields MUST be numbers.  Packagers can
+# add extra information using --with-extra="..." which may be any
+# freeform string.
+m4_define([p2v_major],   [1])
+m4_define([p2v_minor],   [40])
+m4_define([p2v_release], [0])
+
+AC_INIT([virt-p2v],p2v_major.p2v_minor.p2v_release)
+
+# Headings within the configure script output.
+m4_define([HEADING],
+          [AS_ECHO
+           AS_ECHO(["--- $1 ---"])])
+
+AC_CONFIG_AUX_DIR([build-aux])
+
+AC_USE_SYSTEM_EXTENSIONS
+
+dnl Initialize automake.
+AM_INIT_AUTOMAKE(foreign subdir-objects tar-pax) dnl NB: Do not [quote] this parameter.
+
+m4_ifndef([AM_SILENT_RULES], [m4_define([AM_SILENT_RULES],[])])
+AM_SILENT_RULES([yes]) # make --enable-silent-rules the default.
+
+AC_CONFIG_MACRO_DIR([m4])
+
+dnl Extra string, a freeform string defined by packagers.
+AC_ARG_WITH([extra],
+    [AS_HELP_STRING([--with-extra],
+                    [extra version string (for use by packagers)])],
+    [p2v_extra="$withval"],
+    [p2v_extra=]
+)
+
+AC_MSG_NOTICE([virt-p2v version p2v_major.p2v_minor.p2v_release$p2v_extra])
+
+dnl Split up the version string.
+AC_DEFINE([PACKAGE_VERSION_MAJOR],[p2v_major],[Major version number.])
+AC_DEFINE([PACKAGE_VERSION_MINOR],[p2v_minor],[Minor version number.])
+AC_DEFINE([PACKAGE_VERSION_RELEASE],[p2v_release],[Release number.])
+AC_DEFINE_UNQUOTED([PACKAGE_VERSION_EXTRA],["$p2v_extra"],[Extra version string.])
+PACKAGE_VERSION_FULL="p2v_major.p2v_minor.p2v_release${p2v_extra}"
+AC_DEFINE_UNQUOTED([PACKAGE_VERSION_FULL],["$PACKAGE_VERSION_FULL"],[Full version string.])
+AC_SUBST([PACKAGE_VERSION_FULL])
+
+dnl Early gnulib initialization.
+HEADING([Configuring Gnulib])
+gl_EARLY
+gl_INIT
+
+dnl Check for external programs required to either build or run
+dnl virt-p2v.
+HEADING([Checking for external programs])
+m4_include([m4/p2v-progs.m4])
+
+dnl The C compiler environment.
+HEADING([Checking for the C compiler environment])
+m4_include([m4/p2v-c.m4])
+
+dnl Any C libraries required by virt-p2v.
+HEADING([Checking for libraries used by virt-p2v])
+m4_include([m4/p2v-libraries.m4])
+
+dnl All the programs used for tests.
+HEADING([Checking for programs for tests])
+m4_include([m4/p2v-tests.m4])
+
+dnl Produce output files.
+HEADING([Generating output files])
+
+AC_CONFIG_HEADERS([config.h])
+
+dnl http://www.mail-archive.com/automake@gnu.org/msg10204.html
+AC_CONFIG_FILES([virt-p2v-make-disk],
+                [chmod +x,-w virt-p2v-make-disk])
+AC_CONFIG_FILES([virt-p2v-make-kickstart],
+                [chmod +x,-w virt-p2v-make-kickstart])
+AC_CONFIG_FILES([virt-p2v-make-kiwi],
+                [chmod +x,-w virt-p2v-make-kiwi])
+AC_CONFIG_FILES([podwrapper.pl],
+                [chmod +x,-w podwrapper.pl])
+AC_CONFIG_FILES([run],
+                [chmod +x,-w run])
+
+AC_CONFIG_FILES([Makefile
+                 gnulib/lib/Makefile
+                 gnulib/tests/Makefile])
+
+AC_CONFIG_COMMANDS([p2v-config.h],
+                   [${ac_srcdir}/generate-p2v-config.pl --file=p2v-config.h --output=p2v-config.h])
+
+AC_OUTPUT
diff --git a/m4/p2v-c.m4 b/m4/p2v-c.m4
new file mode 100644
index 0000000..e3d045f
--- /dev/null
+++ b/m4/p2v-c.m4
@@ -0,0 +1,179 @@
+# libguestfs
+# Copyright (C) 2009-2019 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.
+
+dnl The C compiler environment.
+dnl Define the host CPU architecture (defines 'host_cpu')
+AC_CANONICAL_HOST
+
+dnl Check for basic C environment.
+AC_PROG_CC_STDC
+AC_PROG_INSTALL
+AC_PROG_CPP
+
+AC_ARG_ENABLE([werror],
+    [AS_HELP_STRING([--enable-werror],
+                    [turn GCC warnings into errors (for developers)])],
+    [case $enableval in
+     yes|no) ;;
+     *)      AC_MSG_ERROR([bad value $enableval for werror option]) ;;
+     esac
+     gl_gcc_werror=$enableval],
+    [gl_gcc_werror=no]
+)
+
+if test "$gl_gcc_werror" = yes; then
+    gl_WARN_ADD([-Werror], [WERROR_CFLAGS])
+    AC_SUBST([WERROR_CFLAGS])
+fi
+
+dnl This, $nw, is the list of warnings we disable.
+nw=
+nw="$nw -Waggregate-return"          # anachronistic
+nw="$nw -Wundef"                     # Warns on '#if GNULIB_FOO' etc in gnulib
+nw="$nw -Wtraditional"               # Warns on #elif which we use often
+nw="$nw -Wsystem-headers"            # Don't let system headers trigger warnings
+nw="$nw -Wpadded"                    # Our structs are not padded
+nw="$nw -Wvla"                       # Allow variable length arrays.
+nw="$nw -Wvla-larger-than=4031"
+nw="$nw -Winline"                    # inline functions in Python binding
+nw="$nw -Wshadow"                    # Not useful, as it applies to global vars
+nw="$nw -Wunsafe-loop-optimizations" # just a warning that an optimization
+                                     # was not possible, safe to ignore
+nw="$nw -Wstack-protector"           # Useless warning when stack protector
+                                     # cannot being used in a function.
+nw="$nw -Wcast-align"                # Useless warning on arm >= 7, intel
+nw="$nw -Wabi"                       # Broken in GCC 8.1.
+dnl things I might fix soon:
+nw="$nw -Wpacked"                    # Allow attribute((packed)) on structs
+nw="$nw -Wlong-long"                 # Allow long long since it's required
+                                     # by Python, Ruby and xstrtoll.
+nw="$nw -Wsuggest-attribute=pure"    # Don't suggest pure functions.
+nw="$nw -Wsuggest-attribute=const"   # Don't suggest const functions.
+nw="$nw -Wsuggest-attribute=malloc"  # Don't suggest malloc functions.
+nw="$nw -Wunsuffixed-float-constants" # Don't care about these.
+nw="$nw -Wswitch-default"            # This warning is actively dangerous.
+nw="$nw -Woverlength-strings"        # Who cares about stupid ISO C99 limit.
+
+gl_MANYWARN_ALL_GCC([ws])
+gl_MANYWARN_COMPLEMENT([ws], [$ws], [$nw])
+for w in $ws; do
+    gl_WARN_ADD([$w])
+done
+
+dnl Normally we disable warnings in $nw above.  However $nw only
+dnl filters out exact matching warning strings from a list inside
+dnl gnulib (see m4/manywarnings.m4).  So we need to explicitly list a
+dnl few disabled warnings below.
+
+dnl Unused parameters are not a bug.
+gl_WARN_ADD([-Wno-unused-parameter])
+
+dnl Missing field initializers is not a bug in C.
+gl_WARN_ADD([-Wno-missing-field-initializers])
+
+dnl Display the name of the warning option with the warning.
+gl_WARN_ADD([-fdiagnostics-show-option])
+
+dnl Now some warnings we want to enable and/or customize ...
+
+dnl Warn about large stack frames.  This does not include alloca and
+dnl variable length arrays.  Coverity warns about 10000 byte frames.
+gl_WARN_ADD([-Wframe-larger-than=5000])
+
+dnl Warn about large stack frames, including estimates for alloca
+dnl and variable length arrays.
+dnl gl_WARN_ADD([-Wstack-usage=10000])
+
+dnl Warn about implicit fallthrough in case statements, but suppress
+dnl the warning if /*FALLTHROUGH*/ comment is used.
+gl_WARN_ADD([-Wimplicit-fallthrough=4])
+
+dnl GCC level 2 gives incorrect warnings, so use level 1.
+gl_WARN_ADD([-Wformat-truncation=1])
+
+dnl GCC 9 at level 2 gives apparently bogus errors when %.*s is used.
+gl_WARN_ADD([-Wformat-overflow=1])
+
+AC_SUBST([WARN_CFLAGS])
+
+AC_DEFINE([lint], [1], [Define to 1 if the compiler is checking for lint.])
+AC_DEFINE([GNULIB_PORTCHECK], [1], [Enable some gnulib portability checks.])
+
+AC_C_PROTOTYPES
+test "x$U" != "x" && AC_MSG_ERROR([Compiler not ANSI compliant])
+
+AM_PROG_CC_C_O
+
+# Provide a global place to set CFLAGS.  (Note that setting AM_CFLAGS
+# is no use because it doesn't override target_CFLAGS).
+#---
+# Kill -fstrict-overflow which is a license for the C compiler to make
+# dubious and often unsafe optimizations, in a time-wasting attempt to
+# deal with CPU architectures that do not exist.
+CFLAGS="$CFLAGS -fno-strict-overflow -Wno-strict-overflow"
+
+dnl Check support for 64 bit file offsets.
+AC_SYS_LARGEFILE
+
+dnl Check sizeof long.
+AC_CHECK_SIZEOF([long])
+
+dnl Check if __attribute__((cleanup(...))) works.
+dnl Set -Werror, otherwise gcc will only emit a warning for attributes
+dnl that it doesn't understand.
+acx_nbdkit_save_CFLAGS="${CFLAGS}"
+CFLAGS="${CFLAGS} -Werror"
+AC_MSG_CHECKING([if __attribute__((cleanup(...))) works with this compiler])
+AC_COMPILE_IFELSE([
+AC_LANG_SOURCE([[
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+freep (void *ptr)
+{
+  exit (EXIT_SUCCESS);
+}
+
+void
+test (void)
+{
+  __attribute__((cleanup(freep))) char *ptr = malloc (100);
+}
+
+int
+main (int argc, char *argv[])
+{
+  test ();
+  exit (EXIT_FAILURE);
+}
+]])
+    ],[
+    AC_MSG_RESULT([yes])
+    AC_DEFINE([HAVE_ATTRIBUTE_CLEANUP],[1],[Define to 1 if '__attribute__((cleanup(...)))' works with this compiler.])
+    ],[
+    AC_MSG_WARN(
+['__attribute__((cleanup(...)))' does not work.
+
+You may not be using a sufficiently recent version of GCC or CLANG, or
+you may be using a C compiler which does not support this attribute,
+or the configure test may be wrong.
+
+The code will still compile, but is likely to leak memory and other
+resources when it runs.])])
+dnl restore CFLAGS
+CFLAGS="${acx_nbdkit_save_CFLAGS}"
diff --git a/m4/p2v-libraries.m4 b/m4/p2v-libraries.m4
new file mode 100644
index 0000000..3f85958
--- /dev/null
+++ b/m4/p2v-libraries.m4
@@ -0,0 +1,79 @@
+# libguestfs
+# Copyright (C) 2009-2019 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.
+
+dnl Any C libraries required by virt-p2v.
+
+dnl Define a C symbol for the host CPU architecture.
+AC_DEFINE_UNQUOTED([host_cpu],["$host_cpu"],[Host architecture.])
+
+dnl Headers.
+AC_CHECK_HEADERS([\
+    linux/rtc.h])
+
+dnl Which header file defines major, minor, makedev.
+AC_HEADER_MAJOR
+
+dnl Check for PCRE (required)
+PKG_CHECK_MODULES([PCRE], [libpcre], [], [
+    AC_CHECK_PROGS([PCRE_CONFIG], [pcre-config pcre2-config], [no])
+    AS_IF([test "x$PCRE_CONFIG" = "xno"], [
+        AC_MSG_ERROR([Please install the pcre devel package])
+    ])
+    PCRE_CFLAGS=`$PCRE_CONFIG --cflags`
+    PCRE_LIBS=`$PCRE_CONFIG --libs`
+])
+
+dnl libxml2 (required)
+PKG_CHECK_MODULES([LIBXML2], [libxml-2.0])
+
+dnl Check for Gtk 2 or 3 library, used by virt-p2v.
+AC_MSG_CHECKING([for --with-gtk option])
+AC_ARG_WITH([gtk],
+    [AS_HELP_STRING([--with-gtk=2|3|check|no],
+        [prefer Gtk version 2 or 3. @<:@default=check@:>@])],
+    [with_gtk="$withval"
+     AC_MSG_RESULT([$withval])],
+    [with_gtk="check"
+     AC_MSG_RESULT([not set, will check for installed Gtk])]
+)
+
+if test "x$with_gtk" = "x3"; then
+    PKG_CHECK_MODULES([GTK], [gtk+-3.0], [
+        GTK_VERSION=3
+    ])
+elif test "x$with_gtk" = "x2"; then
+    PKG_CHECK_MODULES([GTK], [gtk+-2.0], [
+        GTK_VERSION=2
+    ], [])
+elif test "x$with_gtk" = "xcheck"; then
+    PKG_CHECK_MODULES([GTK], [gtk+-3.0], [
+        GTK_VERSION=3
+    ], [
+        PKG_CHECK_MODULES([GTK], [gtk+-2.0], [
+            GTK_VERSION=2
+        ])
+    ])
+fi
+
+dnl D-Bus is an optional dependency of virt-p2v.
+PKG_CHECK_MODULES([DBUS], [dbus-1], [
+    AC_SUBST([DBUS_CFLAGS])
+    AC_SUBST([DBUS_LIBS])
+    AC_DEFINE([HAVE_DBUS],[1],[D-Bus found at compile time.])
+],[
+    AC_MSG_WARN([D-Bus not found, virt-p2v will not be able to inhibit power saving during P2V conversions])
+])
diff --git a/m4/p2v-progs.m4 b/m4/p2v-progs.m4
new file mode 100644
index 0000000..d54b391
--- /dev/null
+++ b/m4/p2v-progs.m4
@@ -0,0 +1,63 @@
+# libguestfs
+# Copyright (C) 2009-2019 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.
+
+# Check for external programs required to either build or run
+# virt-p2v.
+#
+# AC_CHECK_PROG(S) or AC_PATH_PROG(S)?
+#
+# Use AC_CHECK_PROG(S) for programs which are only used during build.
+#
+# Use AC_PATH_PROG(S) for program names which are compiled into the
+# binary and used at run time.  The reason is so that we know which
+# programs the binary actually uses.
+
+# Define $(SED).
+m4_ifdef([AC_PROG_SED],[
+    AC_PROG_SED
+],[
+    dnl ... else hope for the best
+    AC_SUBST([SED], "sed")
+])
+
+# Define $(AWK).
+AC_PROG_AWK
+
+AC_PROG_LN_S
+
+dnl Check for perl (required).
+AC_CHECK_PROG([PERL],[perl],[perl],[no])
+test "x$PERL" = "xno" &&
+    AC_MSG_ERROR([perl must be installed])
+
+dnl Check for Pod::Man, Pod::Simple (for man pages).
+AC_MSG_CHECKING([for Pod::Man])
+if ! $PERL -MPod::Man -e1 >&AS_MESSAGE_LOG_FD 2>&1; then
+    AC_MSG_ERROR([perl Pod::Man must be installed])
+else
+    AC_MSG_RESULT([yes])
+fi
+AC_MSG_CHECKING([for Pod::Simple])
+if ! $PERL -MPod::Simple -e1 >&AS_MESSAGE_LOG_FD 2>&1; then
+    AC_MSG_ERROR([perl Pod::Simple must be installed])
+else
+    AC_MSG_RESULT([yes])
+fi
+
+dnl Define the path to the podwrapper program.
+PODWRAPPER="\$(guestfs_am_v_podwrapper)$PERL $(pwd)/podwrapper.pl"
+AC_SUBST([PODWRAPPER])
diff --git a/m4/p2v-tests.m4 b/m4/p2v-tests.m4
new file mode 100644
index 0000000..f679bc4
--- /dev/null
+++ b/m4/p2v-tests.m4
@@ -0,0 +1,45 @@
+# libguestfs
+# Copyright (C) 2009-2019 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.
+
+dnl Should we run the gnulib tests?
+AC_MSG_CHECKING([if we should run the GNUlib tests])
+AC_ARG_ENABLE([gnulib-tests],
+    [AS_HELP_STRING([--disable-gnulib-tests],
+        [disable running GNU Portability library tests @<:@default=yes@:>@])],
+        [ENABLE_GNULIB_TESTS="$enableval"],
+        [ENABLE_GNULIB_TESTS=yes])
+AM_CONDITIONAL([ENABLE_GNULIB_TESTS],[test "x$ENABLE_GNULIB_TESTS" = "xyes"])
+AC_MSG_RESULT([$ENABLE_GNULIB_TESTS])
+
+dnl Check libguestfs tools (needed for create the test images).
+AC_CHECK_PROG([GUESTFISH],[guestfish],[guestfish],[no])
+AC_CHECK_PROG([VIRT_BUILDER],[virt-builder],[virt-builder],[no])
+AM_CONDITIONAL([HAVE_LIBGUESTFS],
+    [test "x$GUESTFISH" != "xno" && test "x$VIRT_BUILDER" != "xno"])
+
+dnl Check for valgrind
+AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind],[no])
+AS_IF([test "x$VALGRIND" != "xno"],[
+    # Substitute the whole valgrind command.
+    # --read-inline-info=no is a temporary workaround for RHBZ#1662656.
+    VG='$(VALGRIND) --vgdb=no --log-file=$(abs_top_builddir)/valgrind-%q{T}-%p.log --leak-check=full --error-exitcode=119 --suppressions=$(abs_top_srcdir)/valgrind-suppressions --trace-children=no --child-silent-after-fork=yes --run-libc-freeres=no --read-inline-info=no'
+    ],[
+    # No valgrind, so substitute VG with something that will break.
+    VG=VALGRIND_IS_NOT_INSTALLED
+])
+AC_SUBST([VG])
+AM_SUBST_NOTMAKE([VG])
diff --git a/podcheck.pl b/podcheck.pl
new file mode 100755
index 0000000..527a2e4
--- /dev/null
+++ b/podcheck.pl
@@ -0,0 +1,273 @@
+#!/usr/bin/env perl
+# podcheck.pl
+# Copyright (C) 2016 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.
+
+use warnings;
+use strict;
+
+use Pod::Usage;
+use Getopt::Long;
+use Pod::Man;
+
+=head1 NAME
+
+podcheck.pl - Compare man page and tools to check all arguments are documented
+
+=head1 SYNOPSIS
+
+ podcheck.pl virt-foo.pod ./virt-foo [--ignore=--arg,--arg,...]
+
+=head1 DESCRIPTION
+
+This script compares a manual page (eg. C<virt-foo.pod>) and the
+corresponding tool (eg. C<./virt-foo>) and checks that each command
+line argument is documented in the manual, and that there is no rogue
+documentation for arguments which do not exist.  It works by running
+the tool with the standard C<--long-options> and C<--short-options>
+parameters and comparing their output with the man page.
+
+You can also ignore options, in case this script gets things wrong or
+if there are options that you don't intend to document.
+
+=head1 OPTIONS
+
+=over 4
+
+=cut
+
+my $help;
+
+=item B<--help>
+
+Display brief help.
+
+=cut
+
+my $ignore = "";
+
+=item B<--ignore=--arg,--arg,...>
+
+Ignore the comma-separated list of arguments given.
+
+=cut
+
+my @inserts;
+
+=item B<--insert filename:__PATTERN__>
+
+This works like the L<podwrapper.pl(1)> I<--insert> option and should be
+used where the POD includes patterns which podwrapper would substitute.
+
+=cut
+
+my @verbatims;
+
+=item B<--verbatim filename:__PATTERN__>
+
+This works like the podwrapper I<--verbatim> option and should be
+used where the POD includes patterns which podwrapper would substitute.
+
+=cut
+
+# Clean up the program name.
+my $progname = $0;
+$progname =~ s{.*/}{};
+
+# Parse options.
+GetOptions ("help|?" => \$help,
+            "ignore=s" => \$ignore,
+            "insert=s" => \@inserts,
+            "verbatim=s" => \@verbatims,
+    ) or pod2usage (2);
+pod2usage (1) if $help;
+
+die "$progname: missing argument: podcheck.pl input.pod tool\n"
+    unless @ARGV == 2;
+my $input = $ARGV[0];
+my $tool = $ARGV[1];
+
+my %ignore = ();
+$ignore{$_} = 1 foreach (split /,/, $ignore);
+
+# Open the man page and slurp it in.
+my $content = read_whole_file ($input);
+
+# Perform @inserts.
+foreach (@inserts) {
+    my @a = split /:/, $_, 2;
+    die "$progname: $input: no colon in parameter of --insert\n" unless @a >= 2;
+    my $replacement = read_whole_file ($a[0]);
+    my $oldcontent = $content;
+    $content =~ s/$a[1]/$replacement/ge;
+    die "$progname: $input: could not find pattern '$a[1]' in input file\n"
+        if $content eq $oldcontent;
+}
+
+# Perform @verbatims.
+foreach (@verbatims) {
+    my @a = split /:/, $_, 2;
+    die "$progname: $input: no colon in parameter of --verbatim\n" unless @a >= 2;
+    my $replacement = read_verbatim_file ($a[0]);
+    my $oldcontent = $content;
+    $content =~ s/$a[1]/$replacement/ge;
+    die "$progname: $input: could not find pattern '$a[1]' in input file\n"
+        if $content eq $oldcontent;
+}
+
+# Run the tool with --long-options and --short-options.
+my @tool_options = ();
+open PIPE, "$tool --long-options |"
+    or die "$progname: $tool --long-options: $!";
+while (<PIPE>) {
+    chomp;
+    push @tool_options, $_;
+}
+close PIPE;
+open PIPE, "$tool --short-options |"
+    or die "$progname: $tool --short-options: $!";
+while (<PIPE>) {
+    chomp;
+    push @tool_options, $_;
+}
+close PIPE;
+
+my %tool_option_exists = ();
+$tool_option_exists{$_} = 1 foreach @tool_options;
+
+# There are some tool options which we automatically ignore.
+delete $tool_option_exists{"--color"};
+delete $tool_option_exists{"--colour"};
+delete $tool_option_exists{"--debug-gc"};
+
+# Run the tool with --help.
+my $help_content;
+open PIPE, "LANG=C $tool --help |"
+    or die "$progname: $tool --help: $!";
+{
+    local $/ = undef;
+    $help_content = <PIPE>;
+}
+close PIPE;
+
+# Do the tests.
+my $errors = 0;
+
+# Check each option exists in the manual.
+my $tool_options_checked = 0;
+
+foreach (sort keys %tool_option_exists) {
+    unless ($ignore{$_}) {
+        $tool_options_checked++;
+        unless ($content =~ /^=item.*B<$_(?:=.*)?>/m) {
+            $errors++;
+            warn "$progname: $input does not define $_\n";
+        }
+    }
+}
+
+# Check there are no extra options defined in the manual which
+# don't exist in the tool.
+my $pod_options_checked = 0;
+
+my %pod_options = ();
+$pod_options{$_} = 1 foreach ( $content =~ /^=item.*B<(-[-\w]+)(?:=.*)?>/gm );
+foreach (sort keys %pod_options) {
+    unless ($ignore{$_}) {
+        $pod_options_checked++;
+        unless (exists $tool_option_exists{$_}) {
+            $errors++;
+            warn "$progname: $input defines option $_ which does not exist in the tool\n"
+        }
+    }
+}
+
+# Check the tool's --help output mentions all the options.  (For OCaml
+# tools this is a waste of time since the --help output is generated,
+# but for C tools it is a genuine test).
+my $help_options_checked = 0;
+
+my %help_options = ();
+$help_options{$_} = 1 foreach ( $help_content =~ /(?<!\w)(-[-\w]+)/g );
+
+# There are some help options which we automatically ignore.
+delete $help_options{"--color"};
+delete $help_options{"--colour"};
+# "[--options]" is used as a placeholder for options in the synopsis
+# text, so ignore it.
+delete $help_options{"--options"};
+
+foreach (sort keys %tool_option_exists) {
+    unless ($ignore{$_}) {
+        unless (exists $help_options{$_}) {
+            $errors++;
+            warn "$progname: $tool: option $_ does not appear in --help output\n"
+        }
+    }
+}
+
+foreach (sort keys %help_options) {
+    unless ($ignore{$_}) {
+        $help_options_checked++;
+        unless (exists $tool_option_exists{$_}) {
+            $errors++;
+            warn "$progname: $tool: unknown option $_ appears in --help output\n"
+        }
+    }
+}
+
+exit 1 if $errors > 0;
+
+printf "$progname: $tool: checked $tool_options_checked tool options, $pod_options_checked documented options, $help_options_checked help options\n";
+
+exit 0;
+
+sub read_whole_file
+{
+    my $input = shift;
+    local $/ = undef;
+
+    open FILE, $input or die "$progname: $input: $!";
+    $_ = <FILE>;
+    close FILE;
+    $_;
+}
+
+sub read_verbatim_file
+{
+    my $input = shift;
+    my $r = "";
+
+    open FILE, $input or die "$progname: $input: $!";
+    while (<FILE>) {
+        $r .= " $_";
+    }
+    close FILE;
+    $r;
+}
+
+=head1 SEE ALSO
+
+L<podwrapper.pl(1)>,
+libguestfs.git/README.
+
+=head1 AUTHOR
+
+Richard W.M. Jones.
+
+=head1 COPYRIGHT
+
+Copyright (C) 2016 Red Hat Inc.
diff --git a/podwrapper.pl.in b/podwrapper.pl.in
new file mode 100755
index 0000000..2b276c4
--- /dev/null
+++ b/podwrapper.pl.in
@@ -0,0 +1,678 @@
+#!/usr/bin/env perl
+# podwrapper.pl
+# Copyright (C) 2010-2019 Red Hat Inc.
+# @configure_input@
+#
+# 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.
+
+use warnings;
+use strict;
+
+use Pod::Usage;
+use Getopt::Long;
+use Pod::Man;
+use Pod::Simple;
+use Pod::Simple::Text;
+use Pod::Simple::XHTML;
+use File::Basename;
+
+# https://www.redhat.com/archives/libguestfs/2013-May/thread.html#00088
+eval { $Text::Wrap::huge = "overflow" };
+
+=head1 NAME
+
+podwrapper.pl - Generate libguestfs documentation from POD input files
+
+=head1 SYNOPSIS
+
+ man_MANS = virt-foo.1
+ 
+ virt-foo.1 $(top_builddir)/website/virt-foo.1.html: stamp-virt-foo.pod
+ 
+ stamp-virt-foo.pod: virt-foo.pod
+         $(PODWRAPPER) \
+           --section 1 \
+           --man virt-foo.1 \
+           --html $(top_builddir)/website/virt-foo.1.html \
+           --license GPLv2+ \
+           --warning general \
+           $<
+         touch $@
+
+=head1 DESCRIPTION
+
+podwrapper.pl is a Perl script that generates various output formats
+from POD input files that libguestfs uses for most documentation.
+
+You must specify one input file, and one or more output formats.  The
+output options are I<--man>, I<--html> and I<--text> (see below).
+
+In C<Makefile.am> files, use a variation of the boilerplate shown in
+the L</SYNOPSIS> section above.
+
+For information about the POD format, see L<perlpod(1)>.
+
+=head1 OPTIONS
+
+=over 4
+
+=cut
+
+my $help;
+
+=item B<--help>
+
+Display brief help.
+
+=cut
+
+my $html;
+
+=item B<--html output.html>
+
+Write a web page to C<output.html>.  If this option is not
+given, then no web page output is produced.
+
+=cut
+
+my @inserts;
+
+=item B<--insert filename:__PATTERN__>
+
+In the input file, replace the literal text C<__PATTERN__> with the
+replacement file C<filename>.  You can give this option multiple
+times.
+
+The contents of C<filename> are treated as POD.
+Compare and contrast with I<--verbatim>.
+
+Although it is conventional to use C<__...__> (double underscores) for
+patterns, in fact you can use any string as the pattern.
+
+=cut
+
+my @licenses;
+
+=item B<--license GPLv2+>
+
+=item B<--license LGPLv2+>
+
+=item B<--license examples>
+
+Add the given license to the end of the man page.  This parameter
+is required.  The parameter may be given multiple times (eg. for
+mixed content).
+
+=cut
+
+my $man;
+
+=item B<--man output.n>
+
+Write a man page to C<output.n> (C<n> is the manual section number).
+If this option is not given, then no man page output is produced.
+
+=cut
+
+my $name;
+
+=item B<--name name>
+
+Set the name of the man page.  If not set, defaults to the basename
+of the input file.
+
+=cut
+
+my $section;
+
+=item B<--section N>
+
+Set the section of the man page (a number such as C<1> for
+command line utilities or C<3> for C API documentation).  If
+not set, defaults to C<1>.
+
+=cut
+
+my $strict_checks = 1;
+
+=item B<--no-strict-checks>
+
+Disable strict checks of the man page.  This is only used
+when generating the translated man pages in the C<po-docs>
+subdirectory.
+
+=cut
+
+my $text;
+
+=item B<--text output.txt>
+
+Write a text file to C<output.txt>.  If this option is not
+given, then no text output is produced.
+
+=cut
+
+my @verbatims;
+
+=item B<--verbatim filename:__PATTERN__>
+
+In the input file, replace the literal text C<__PATTERN__> with the
+replacement file C<filename>.  You can give this option multiple
+times.
+
+The contents of C<filename> are inserted as verbatim text, and
+are I<not> interpreted as POD.
+Compare and contrast with I<--insert>.
+
+Although it is conventional to use C<__...__> (double underscores) for
+patterns, in fact you can use any string as the pattern.
+
+=cut
+
+my $warning = "not-set";
+
+=item B<--warning general>
+
+=item B<--warning ro-option>
+
+Add a standard warning section near the top of the manual page,
+warning the user not to use the tool in write mode or concurrently.
+
+There are two variations of the warning: The I<--warning ro-option>
+variation should be used with tools such as L<guestfish(1)> which have
+an I<--ro> option.  The I<--warning general> variation should be used
+with other tools that open the disk image for writes, with no
+read-only option.
+
+=item B<--warning custom>
+
+Use I<--warning custom> if there is already a warning section in the
+manual page.
+
+=item B<--warning safe>
+
+Use I<--warning safe> for tools which are safe, ie. only open disk
+images in read-only mode, or just don't need a warning section.
+
+=back
+
+=cut
+
+# Clean up the program name.
+my $progname = $0;
+$progname =~ s{.*/}{};
+
+# Parse options.
+GetOptions ("help|?" => \$help,
+            "html=s" => \$html,
+            "license=s" => \@licenses,
+            "insert=s" => \@inserts,
+            "man=s" => \$man,
+            "name=s" => \$name,
+            "section=s" => \$section,
+            "strict-checks!" => \$strict_checks,
+            "text=s" => \$text,
+            "verbatim=s" => \@verbatims,
+            "warning=s" => \$warning,
+    ) or pod2usage (2);
+pod2usage (1) if $help;
+
+die "$progname: missing argument: podwrapper input.pod\n" unless @ARGV == 1;
+my $input = $ARGV[0];
+
+die "$progname: $input: missing argument: --license parameter is required\n"
+    if $strict_checks && @licenses == 0;
+
+# There should be at least one output.
+die "$progname: $input: no output format specified.  Use --man and/or --html and/or --text.\n"
+    unless defined $man || defined $html || defined $text;
+
+# Default for $name and $section.
+$name = basename ($input, ".pod") unless defined $name;
+$section = 1 unless defined $section;
+
+# Is it a user command line tool?
+my $cli_tool = $section == 1 && $name !~ /^guestfs-/;
+
+# Warning parameter is mandatory for user tools in section 1.
+if ($strict_checks && $cli_tool) {
+    die "$progname: $input: missing argument: --warning parameter is missing or invalid\n"
+        unless $warning eq "general" || $warning eq "ro-option" ||
+               $warning eq "custom" || $warning eq "safe";
+}
+
+# Note that these @...@ are substituted by ./configure.
+my $abs_top_srcdir = "@abs_top_srcdir@";
+my $abs_top_builddir = "@abs_top_builddir@";
+my $package_name = "@PACKAGE_NAME@";
+my $package_version = "@PACKAGE_VERSION@";
+
+die "$progname: ./configure substitutions were not performed"
+    unless $abs_top_srcdir && $abs_top_builddir &&
+    $package_name && $package_version;
+
+# Create a stable date (thanks Hilko Bengen).
+my $date;
+my $filename = "$abs_top_srcdir/ChangeLog";
+if (-r $filename) {
+    open FILE, $filename or die "$progname: $filename: $!";
+    while (<FILE>) {
+        if (/^Date:\s+...\s+(...)\s+(\d+)\s+..:..:..\s+(\d{4})\s+.*$/) {
+            my $i = 0;
+            my %month =
+              map { $_ => ++$i }
+                (qw< Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec >);
+            $date = sprintf '%04d-%02d-%02d', $3, $month{$1}, $2;
+            last;
+        }
+    }
+    close FILE;
+}
+$filename = "$abs_top_srcdir/.git";
+if (!$date && -d $filename) {
+    local $ENV{GIT_DIR} = $filename;
+    $_ = `git show -s --format=%ci`;
+    $date = $1 if /^(\d+-\d+-\d+)\s/;
+}
+if (!$date) {
+    my ($day, $month, $year) = (localtime)[3,4,5];
+    $date = sprintf ("%04d-%02d-%02d", $year+1900, $month+1, $day);
+}
+
+# Create a release string.
+my $release = "$package_name-$package_version";
+
+#print "input=$input\n";
+#print "name=$name\n";
+#print "section=$section\n";
+#print "date=$date\n";
+#print "warning=$warning\n";
+
+# Read the input.
+my $content = read_whole_file ($input);
+
+# Perform @inserts.
+foreach (@inserts) {
+    my @a = split /:/, $_, 2;
+    die "$progname: $input: no colon in parameter of --insert\n" unless @a >= 2;
+    my $replacement = read_whole_file ($a[0]);
+    my $oldcontent = $content;
+    $content =~ s/$a[1]/$replacement/ge;
+    die "$progname: $input: could not find pattern '$a[1]' in input file\n"
+        if $content eq $oldcontent;
+}
+
+# Turn external links to this man page into simple cross-section links.
+$content =~ s,\QL<$name($section)/\E,L</,g;
+
+# Perform @verbatims.
+foreach (@verbatims) {
+    my @a = split /:/, $_, 2;
+    die "$progname: $input: no colon in parameter of --verbatim\n" unless @a >= 2;
+    my $replacement = read_verbatim_file ($a[0]);
+    my $oldcontent = $content;
+    $content =~ s/$a[1]/$replacement/ge;
+    die "$progname: $input: could not find pattern '$a[1]' in input file\n"
+        if $content eq $oldcontent;
+}
+
+# There should be no =encoding line present in the content (we will add one).
+die "$progname: $input: =encoding must not be present in input\n"
+    if $content =~ /^=encoding/m;
+
+$content =~ s/^=(.*)/\n=encoding utf8\n\n=$1/m;
+
+if ($strict_checks) {
+    # Verify sections present / not present.
+    die "$progname: $input: missing DESCRIPTION section\n"
+        if $cli_tool && $content !~ /^=head1 DESCRIPTION/m;
+    die "$progname: $input: missing AUTHOR or AUTHORS section\n"
+        unless $content =~ /^=head1 AUTHOR/m;
+    die "$progname: $input: missing SEE ALSO section\n"
+        unless $content =~ /^=head1 SEE ALSO/m;
+    die "$progname: $input: missing COPYRIGHT section\n"
+        unless $content =~ /^=head1 COPYRIGHT/m;
+    die "$progname: $input: BUGS is now added automatically, do not add it to the POD file\n"
+        if $content =~ /^=head1 (REPORTING )?BUGS/m;
+    die "$progname: $input: LICENSE is now added automatically, do not add it to the POD file\n"
+        if $content =~ /^=head1 LICENSE/m;
+    die "$progname: $input: GPL/LGPL should be specified using the --license parameter, not included in the POD file\n"
+        if $content =~ /^This program is free software/ ||
+        $content =~ /^This library is free software/;
+    if ($warning eq "general" || $warning eq "ro-option" ||
+        $warning eq "safe") {
+        die "$progname: $input: WARNING is now added automatically using the --warning parameter\n"
+            if $content =~ /^=head1 WARNING/m
+    }
+    elsif ($warning eq "custom") {
+        die "$progname: $input: missing WARNING section\n"
+            unless $content =~ /^=head1 WARNING/m;
+    }
+}
+
+# Add standard LICENSE, BUGS and WARNING sections.
+my $LGPLv2plus =
+"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 of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA
+";
+
+my $GPLv2plus =
+"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.
+";
+
+my $examples_license =
+"This manual page contains examples which we hope you will use in
+your programs.  The examples may be freely copied, modified and
+distributed for any purpose without any restrictions.
+";
+
+my $reporting_bugs =
+"=head1 BUGS
+
+To get a list of bugs against libguestfs, use this link:
+L<https://bugzilla.redhat.com/buglist.cgi?component=libguestfs&product=Virtualization+Tools>
+
+To report a new bug against libguestfs, use this link:
+L<https://bugzilla.redhat.com/enter_bug.cgi?component=libguestfs&product=Virtualization+Tools>
+
+When reporting a bug, please supply:
+
+\=over 4
+
+\=item *
+
+The version of libguestfs.
+
+\=item *
+
+Where you got libguestfs (eg. which Linux distro, compiled from source, etc)
+
+\=item *
+
+Describe the bug accurately and give a way to reproduce it.
+
+\=item *
+
+Run L<libguestfs-test-tool(1)> and paste the B<complete, unedited>
+output into the bug report.
+
+\=back
+";
+
+my $warning_general =
+"Using C<$name>
+on live virtual machines, or concurrently with other
+disk editing tools, can be dangerous, potentially causing disk
+corruption.  The virtual machine must be shut down before you use this
+command, and disk images must not be edited concurrently.";
+
+my $warning_ro_option =
+"Using C<$name> in write mode
+on live virtual machines, or concurrently with other
+disk editing tools, can be dangerous, potentially causing disk
+corruption.  The virtual machine must be shut down before you use this
+command, and disk images must not be edited concurrently.
+
+Use the I<--ro> (read-only) option to use C<$name> safely if the disk
+image or virtual machine might be live.  You may see strange or
+inconsistent results if running concurrently with other changes, but
+with this option you won't risk disk corruption.";
+
+$content .= "\n\n=head1 LICENSE\n\n";
+
+foreach (@licenses) {
+    if ($_ eq "LGPLv2+") {
+        $content .= $LGPLv2plus . "\n\n";
+    }
+    elsif ($_ eq "GPLv2+") {
+        $content .= $GPLv2plus . "\n\n";
+    }
+    elsif ($_ eq "examples") {
+        $content .= $examples_license . "\n\n";
+    }
+    else {
+        die "$progname: $input: invalid --license parameter: $_\n";
+    }
+}
+
+$content .= "\n\n$reporting_bugs";
+
+if ($warning eq "general") {
+    $content =~ s/^=head1 DESCRIPTION/=head1 WARNING\n\n$warning_general\n\n=head1 DESCRIPTION/m or die;
+}
+elsif ($warning eq "ro-option") {
+    $content =~ s/^=head1 DESCRIPTION/=head1 WARNING\n\n$warning_ro_option\n\n=head1 DESCRIPTION/m or die;
+}
+# else do nothing for $warning "custom", "safe" or "not-set"
+
+# Output man page.
+SUBMAN: {
+    package Podwrapper::Man;
+
+    use vars qw(@ISA $VERSION);
+    @ISA = qw(Pod::Man);
+    $VERSION = $package_version;
+
+    # Override the L<> method.
+    sub cmd_l
+    {
+        my ($self, $attrs, $text) = @_;
+        return $text;
+    }
+}
+
+if ($man) {
+    my $parser = Podwrapper::Man->new (
+        name => $name,
+        release => $release, section => $section,
+        center => "Virtualization Support",
+        date => $date,
+        stderr => 1, utf8 => 1
+    );
+    my $output;
+    $parser->no_errata_section (1);
+    $parser->complain_stderr (1);
+    $parser->output_string (\$output);
+    $parser->parse_string_document ($content)
+        or die "$progname: could not parse input document";
+    open OUT, ">$man" or die "$progname: $man: $!";
+    print OUT $output or die "$progname: $man: $!";
+    close OUT or die "$progname: $man: $!";
+    if ($parser->any_errata_seen) {
+        unlink $man;
+        die "$input: errors or warnings in this POD file, see messages above\n"
+    }
+    #print "$progname: wrote $man\n";
+}
+
+# Output HTML.
+SUBHTML: {
+    # Subclass Pod::Simple::XHTML.  See the documentation.
+    package Podwrapper::XHTML;
+
+    use vars qw(@ISA $VERSION);
+    @ISA = qw(Pod::Simple::XHTML);
+    $VERSION = $package_version;
+
+    # Pod::Simple::XHTML returns uppercase identifiers, whereas the
+    # old pod2html returns lowercase ones.
+    sub idify
+    {
+        my $self = shift;
+        my $id = $self->SUPER::idify (@_);
+        lc ($id);
+    }
+
+    sub is_a_libguestfs_page
+    {
+        local $_ = shift;
+
+        return 1 if /^Sys::Guestfs/;
+        return 0 if /^virt-install/;
+        return 1 if /^virt-/;
+        return 1 if /^libguestf/;
+        return 1 if /^guestf/;
+        return 1 if /^guestmount/;
+        return 1 if /^guestunmount/;
+        return 1 if /^hivex/;
+        return 1 if /^supermin/;
+        return 1 if /^nbdkit/;
+        return 0;
+    }
+
+    sub resolve_pod_page_link
+    {
+        my $self = shift;
+        my $podname = $_[0]; # eg. "Sys::Guestfs", can be undef
+        my $anchor = $_[1];  # eg. "SYNOPSIS", can be undef
+        my $r = "";
+        if (defined $podname) {
+            return $self->SUPER::resolve_pod_page_link (@_)
+                unless is_a_libguestfs_page ($podname);
+            $r .= "$podname.3.html"
+        }
+        $r .= "#" . $self->idify ($anchor, 1) if defined $anchor;
+        $r;
+    }
+
+    sub resolve_man_page_link
+    {
+        my $self = shift;
+        my $name = $_[0];   # eg. "virt-make-fs(1)", can be undef
+        my $anchor = $_[1]; # eg. "SYNOPSIS", can be undef
+        my $r = "";
+        if (defined $name) {
+            return $self->SUPER::resolve_man_page_link (@_)
+                unless is_a_libguestfs_page ($name);
+            $name =~ s/\((.*)\)$/.$1/;
+            $r .= "$name.html";
+        }
+        $r .= "#" . $self->idify ($anchor, 1) if defined $anchor;
+        $r;
+    }
+
+    # For some reason Pod::Simple::XHTML usually cannot find a
+    # title for the page.  This defaults the HTML <title> field
+    # to the same as the man page name.
+    sub default_title { $name }
+}
+
+if ($html) {
+    mkdir "$abs_top_builddir/website";
+
+    my $parser = Podwrapper::XHTML->new;
+    my $output;
+    $parser->no_errata_section (1);
+    $parser->complain_stderr (1);
+    $parser->output_string (\$output);
+    # Added in Pod::Simple 3.16, 2011-03-14.
+    eval { $parser->html_charset ("UTF-8") };
+    $parser->html_css ("pod.css");
+    $parser->index (1);
+    $parser->parse_string_document ($content);
+
+    # Hack for Perl 5.16.
+    $output =~ s{/>pod.css<}{/>\n<};
+
+    open OUT, ">$html" or die "$progname: $html: $!";
+    print OUT $output or die "$progname: $html: $!";
+    close OUT or die "$progname: $html: $!";
+    if ($parser->any_errata_seen) {
+        unlink $html;
+        die "$input: errors or warnings in this POD file, see messages above\n"
+    }
+    #print "$progname: wrote $html\n";
+}
+
+# Output text.
+if ($text) {
+    my $parser = Pod::Simple::Text->new;
+    my $output;
+    $parser->no_errata_section (1);
+    $parser->complain_stderr (1);
+    $parser->output_string (\$output);
+    $parser->parse_string_document ($content);
+    open OUT, ">$text" or die "$progname: $text: $!";
+    binmode OUT, ":utf8";
+    print OUT $output or die "$progname: $text: $!";
+    close OUT or die "$progname: $text: $!";
+    if ($parser->any_errata_seen) {
+        unlink $text;
+        die "$input: errors or warnings in this POD file, see messages above\n"
+    }
+    #print "$progname: wrote $text\n";
+}
+
+sub read_whole_file
+{
+    my $input = shift;
+    local $/ = undef;
+
+    open FILE, $input or die "$progname: $input: $!";
+    $_ = <FILE>;
+    close FILE;
+    $_;
+}
+
+sub read_verbatim_file
+{
+    my $input = shift;
+    my $r = "";
+
+    open FILE, $input or die "$progname: $input: $!";
+    while (<FILE>) {
+        $r .= " $_";
+    }
+    close FILE;
+    $r;
+}
+
+=head1 SEE ALSO
+
+L<perlpod(1)>,
+L<Pod::Simple(3pm)>,
+libguestfs.git/README.
+
+=head1 AUTHOR
+
+Richard W.M. Jones.
+
+=head1 COPYRIGHT
+
+Copyright (C) 2012-2019 Red Hat Inc.
diff --git a/run.in b/run.in
new file mode 100755
index 0000000..a3def1d
--- /dev/null
+++ b/run.in
@@ -0,0 +1,118 @@
+#!/bin/bash -
+# libguestfs 'run' programs locally script
+# Copyright (C) 2011-2019 Red Hat Inc.
+#
+# @configure_input@
+#
+# 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 of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#----------------------------------------------------------------------
+
+# With this script you can run all the virt tools without needing to
+# install them first.  You just have to do for example:
+#
+#   ./run virt-inspector [args ...]
+#
+# This works for any C program, virt tools, and most non-C bindings
+# and programs in the libguestfs distribution.
+#
+# For lots more ways to use this script, see the libguestfs
+# guestfs-building(1) man page.
+#
+# The script should also be used for tests like this:
+#
+#   TESTS_ENVIRONMENT = ... $(top_builddir)/run --test
+#
+# The --test parameter introduces a timeout, stopping tests from
+# running forever.
+
+#----------------------------------------------------------------------
+
+if [ "$1" = "--test" ]; then
+    timeout_mode=1
+    shift
+fi
+
+# Function to intelligently prepend a path to an environment variable.
+# See http://stackoverflow.com/a/9631350
+prepend()
+{
+    eval $1="$2\${$1:+:\$$1}"
+}
+
+# Source and build directories (absolute paths so this works from any
+# directory).
+s="$(cd @abs_srcdir@ && pwd)"
+b="$(cd @abs_builddir@ && pwd)"
+
+# Set T to current date & time (mainly for valgrind logfile name).
+T=`date +%Y%m%d.%H.%M.%S`
+export T
+
+prepend PATH "$b"
+export PATH
+
+# virt-p2v-make-* data directory.
+if [ -z "$VIRT_P2V_DATA_DIR" ]; then
+    VIRT_P2V_DATA_DIR="$s"
+    export VIRT_P2V_DATA_DIR
+fi
+
+# This is a cheap way to find some use-after-free and uninitialized
+# read problems when using glibc.
+random_val="$(@AWK@ 'BEGIN{srand(); print 1+int(255*rand())}' < /dev/null)"
+export MALLOC_PERTURB_=$random_val
+
+# Avoid GNOME keyring stupidity
+export GNOME_KEYRING_CONTROL=
+export GNOME_KEYRING_PID=
+
+# Run the program.
+if [ -z "$timeout_mode" ]; then
+    exec "$@"
+fi
+
+# For tests (./run --test):
+#  - timeout if the test takes too long to run
+
+# Originally 1h, but that is not long enough to run the C API
+# tests on Koji.
+timeout_period=4h
+timeout_kill=30s
+
+# Must use the --foreground option (RHBZ#1025269).
+if timeout --foreground 2 sleep 0 >/dev/null 2>&1; then
+    # Does this version of timeout have the -k option?  (Not on RHEL 6)
+    if timeout -k 10s 10s true >/dev/null 2>&1; then
+        timeout="timeout --foreground -k $timeout_kill $timeout_period"
+    fi
+fi
+
+$timeout "$@"
+fail=$?
+if [ "$fail" -eq 0 ]; then
+    # Test successful.
+    :
+elif [ "$fail" -eq 77 ]; then
+    # Tests return 77 to mean skipped.
+    :
+elif [ "$fail" -eq 124 ]; then
+    # Timed out.
+    echo "$b/run: command timed out after $timeout_period"
+else
+    # Test failed.
+    echo "$b/run: command failed with exit code $fail"
+fi
+exit $fail
diff --git a/subdir-rules.mk b/subdir-rules.mk
new file mode 100644
index 0000000..ce05874
--- /dev/null
+++ b/subdir-rules.mk
@@ -0,0 +1,60 @@
+# libguestfs
+# 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.
+
+# subdir-rules.mk should be included in every *subdirectory* Makefile.am.
+
+# Editor backup files
+CLEANFILES = *~ *.bak
+
+# Patch original and reject files.
+CLEANFILES += *.orig *.rej
+
+# Manual pages - these are all generated from *.pod, so the
+# pages themselves should all be removed by 'make clean'.
+CLEANFILES += *.1 *.3 *.5 *.8
+
+# Stamp files used when generating man pages.
+CLEANFILES += stamp-*.pod
+
+# Files that should be universally removed by 'make distclean'.
+DISTCLEANFILES = stamp-*
+
+# custom silent rules
+guestfs_am_v_podwrapper = $(guestfs_am_v_podwrapper_ at AM_V@)
+guestfs_am_v_podwrapper_ = $(guestfs_am_v_podwrapper_ at AM_DEFAULT_V@)
+guestfs_am_v_podwrapper_0 = @echo "  POD     " $@;
+
+# Test shell scripts should use '$TEST_FUNCTIONS' to get a predefined
+# set of helper functions for running tests (see
+# tests/test-functions.sh).
+#
+# Notes:
+#
+# (1) This is in fact a single command all on one line.  The variables
+# are evaluated in test-functions.sh.
+#
+# (2) We use absolute paths here and in test-functions.sh so that the
+# test can change directory freely.  But we also include the
+# non-absolute values so they can be used by the test script itself.
+export TEST_FUNCTIONS := \
+	source $(abs_top_srcdir)/test-functions.sh \
+	abs_srcdir="$(abs_srcdir)" \
+	abs_builddir="$(abs_builddir)" \
+	top_srcdir="$(top_srcdir)" \
+	top_builddir="$(top_builddir)" \
+	abs_top_srcdir="$(abs_top_srcdir)" \
+	abs_top_builddir="$(abs_top_builddir)"
diff --git a/test-functions.sh b/test-functions.sh
new file mode 100755
index 0000000..609b356
--- /dev/null
+++ b/test-functions.sh
@@ -0,0 +1,120 @@
+#!/bin/bash -
+# libguestfs
+# Copyright (C) 2014-2019 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.
+
+# Most of the tests written in shell script source this file for
+# useful functions.
+#
+# To include this file, the test must do:
+#
+#   $TEST_FUNCTIONS
+#
+# (this macro is defined in subdir-rules.mk).
+
+# Clean up the environment in every test script.
+unset CDPATH
+export LANG=C
+
+# When test-functions.sh is invoked, a list of variables is passed as
+# parameters, so we eval those to define the variables.
+while [ $# -ge 1 ]; do eval "$1"; shift; done
+
+# Skip if $SKIP_<script_name> environment variable is set.
+# Every test should call this function first.
+skip_if_skipped ()
+{
+    local v
+    if [ -n "$1" ]; then
+        v="SKIP_$(basename $1 | tr a-z.- A-Z__)"
+    else
+        v="SKIP_$(basename $0 | tr a-z.- A-Z__)"
+    fi
+    if [ -n "${!v}" ]; then
+        echo "$(basename $0): test skipped because \$$v is set"
+        exit 77
+    fi
+    echo "$(basename $0): info: you can skip this test by setting $v=1"
+}
+
+# Skip if the current libguestfs backend is $1.
+# eg. skip_if_backend uml
+skip_if_backend ()
+{
+    local b="$(guestfish get-backend)"
+    case "$1" in
+        # Some magic happens for $1 == libvirt.
+        libvirt)
+            if [ "$b" = "libvirt" ] || [[ "$b" =~ ^libvirt: ]]; then
+                echo "$(basename $0): test skipped because the current backend is $b"
+                exit 77
+            fi
+            ;;
+        *)
+            if [ "$b" = "$1" ]; then
+                echo "$(basename $0): test skipped because the current backend is $b"
+                exit 77
+            fi
+            ;;
+    esac
+}
+
+# Skip if the current arch != $1.
+skip_unless_arch ()
+{
+    local m="$(uname -m)"
+    case "$1" in
+        # Some magic happens for some architectures.
+        arm)
+            if [[ ! "$m" =~ ^arm ]]; then
+                echo "$(basename $0): test skipped because the current architecture ($m) is not arm (32 bit)"
+                exit 77
+            fi
+            ;;
+        i?86)
+            if [[ ! "$m" =~ ^i?86 ]]; then
+                echo "$(basename $0): test skipped because the current architecture ($m) is not $1"
+                exit 77
+            fi
+            ;;
+        *)
+            if [ "$m" != "$1" ]; then
+                echo "$(basename $0): test skipped because the current architecture ($m) is not $1"
+                exit 77
+            fi
+            ;;
+    esac
+}
+
+# Run an external command and skip if the command fails.  This can be
+# used to test if a command exists.  Normally you should use
+# `cmd --help' or `cmd --version' or similar.
+skip_unless ()
+{
+    if ! "$@"; then
+        echo "$(basename $0): test skipped because $1 is not available"
+        exit 77
+    fi
+}
+
+# Slow tests should always call this function.  (See guestfs-hacking(1)).
+slow_test ()
+{
+    if [ -z "$SLOW" ]; then
+        echo "$(basename $0): use 'make check-slow' to run this test"
+        exit 77
+    fi
+}
-- 
2.21.0




More information about the Libguestfs mailing list