[libguestfs/f20] Backport virt-builder features from upstream at (multiple) users' request.
Richard W.M. Jones
rjones at fedoraproject.org
Tue Nov 5 20:15:10 UTC 2013
commit 384b531c5067698a978e7cd6e9a7c2e4b3922fd9
Author: Richard W.M. Jones <rjones at redhat.com>
Date: Tue Nov 5 19:19:39 2013 +0000
Backport virt-builder features from upstream at (multiple) users' request.
- Use git to manage patches, add copy-patches.sh script.
...-Don-t-run-virt-resize-when-not-necessary.patch | 150 ++
...e-xzcat-binary-configurable-and-use-AC_PA.patch | 73 +
...-pxzcat-optionally-to-speed-up-xzcat-step.patch | 74 +
...-Add-no-sync-option-to-avoid-sync-on-exit.patch | 101 +
...er-Add-mkdir-option-to-create-directories.patch | 137 ++
0006-builder-Allow-upload-to-a-directory.patch | 79 +
...-Add-write-option-to-write-a-literal-file.patch | 135 ++
...ument-how-to-boot-VMs-directly-in-qemu-or.patch | 39 +
...end-the-output-to-the-console-as-well-as-.patch | 62 +
...dd-a-section-on-performance-to-the-manual.patch | 69 +
...dd-m-memsize-and-smp-command-line-options.patch | 153 ++
...low-multiple-source-paths-to-be-specified.patch | 450 +++++
...-t-use-git-tree-libguestfs.git-to-refer-t.patch | 39 +
...Add-a-real-scanner-parser-for-index-files.patch | 1232 ++++++++++++
...-check-valgrind-so-it-does-something-in-t.patch | 41 +
0016-builder-Fix-missing-files-in-EXTRA_DIST.patch | 35 +
...d-an-extra-Makefile.am-to-builder-website.patch | 141 ++
...-website-Add-index-validation-test-script.patch | 57 +
...ernal-implementation-of-parallel-xzcat-px.patch | 942 +++++++++
...lace-fedora-NN-shell-kickstart-with-a-sin.patch | 493 +++++
...eplace-ubuntu-NN-.sh-with-a-single-script.patch | 2081 ++++++++++++++++++++
...eplace-debian-NN-.sh-with-a-single-script.patch | 1578 +++++++++++++++
...-Replace-centos-6.sh-with-a-single-script.patch | 343 ++++
...site-Add-validate.sh-test-script-to-EXTRA.patch | 27 +
0025-builder-Add-missing-dependency.patch | 33 +
...er-Add-some-generated-files-to-CLEANFILES.patch | 29 +
...-dependency-from-index-parse.h-to-index-v.patch | 30 +
...x-centos-script-output-filename-was-wrong.patch | 28 +
...-dependencies-which-automake-doesn-t-gene.patch | 51 +
copy-patches.sh | 53 +
libguestfs.spec | 67 +-
31 files changed, 8821 insertions(+), 1 deletions(-)
---
diff --git a/0001-builder-Don-t-run-virt-resize-when-not-necessary.patch b/0001-builder-Don-t-run-virt-resize-when-not-necessary.patch
new file mode 100644
index 0000000..883bd09
--- /dev/null
+++ b/0001-builder-Don-t-run-virt-resize-when-not-necessary.patch
@@ -0,0 +1,150 @@
+From 1e5b73563918c762542d5251a2fc79ec609a4547 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 22 Oct 2013 13:52:25 +0100
+Subject: [PATCH] builder: Don't run virt-resize when not necessary.
+
+If:
+ - the output is a regular file
+ - the output format is raw
+ - the user didn't specify the --size option
+then we don't need to run virt-resize. Simply uncompress
+the template directly to the output file.
+
+(cherry picked from commit 2f3a3e308af8012501437f723471a66537ecbf64)
+---
+ builder/builder.ml | 65 ++++++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 48 insertions(+), 17 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index 286fd7d..6750deb 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -232,7 +232,12 @@ let main () =
+
+ Sigchecker.verify_detached sigchecker template sigfile in
+
+- let output, size, format, delete_output_file, resize_sparse =
++ (* Plan how to create the output. This depends on:
++ * - did the user specify --output?
++ * - is the output a block device?
++ * - did the user specify --size?
++ *)
++ let output, size, format, delete_output_file, do_resize, resize_sparse =
+ let is_block_device file =
+ try (stat file).st_kind = S_BLK
+ with Unix_error _ -> false
+@@ -259,22 +264,22 @@ let main () =
+ (* Dummy: The output file is never deleted in this case. *)
+ let delete_output_file = ref false in
+
+- output, None, format, delete_output_file, false
++ output, None, format, delete_output_file, true, false
+
+ (* Regular file output. Note the file gets deleted. *)
+ | _ ->
+ (* Check the --size option. *)
+- let size =
++ let size, do_resize =
+ let { Index_parser.size = default_size } = entry in
+ match size with
+- | None -> default_size +^ headroom
++ | None -> default_size, false
+ | Some size ->
+ if size < default_size +^ headroom then (
+ eprintf (f_"%s: --size is too small for this disk image, minimum size is %s\n")
+ prog (human_size default_size);
+ exit 1
+ );
+- size in
++ size, true in
+
+ (* Create the output file. *)
+ let output, format =
+@@ -285,6 +290,14 @@ let main () =
+ | Some output, None -> output, "raw"
+ | Some output, Some format -> output, format in
+
++ (* If the input format != output format then we must run virt-resize. *)
++ let do_resize =
++ let input_format =
++ match entry with
++ | { Index_parser.format = Some format } -> format
++ | { Index_parser.format = None } -> "raw" in
++ if input_format <> format then true else do_resize in
++
+ msg (f_"Creating disk image: %s") output;
+ let cmd =
+ sprintf "qemu-img create -f %s%s %s %Ld%s"
+@@ -308,25 +321,42 @@ let main () =
+ in
+ at_exit delete_file;
+
+- output, Some size, format, delete_output_file, true in
++ output, Some size, format, delete_output_file, do_resize, true in
+
+- let source =
+- (* Uncompress it to a temporary file. *)
++ if not do_resize then (
++ (* If the user did not specify --size and the output is a regular
++ * file and the format is raw, then we just uncompress the template
++ * directly to the output file. This is fast but less flexible.
++ *)
+ let { Index_parser.file_uri = file_uri } = entry in
+- let tmpfile = Filename.temp_file "vbsrc" ".img" in
+- let cmd = sprintf "xzcat %s > %s" (quote template) (quote tmpfile) in
++ let cmd = sprintf "xzcat %s > %s" (quote template) (quote output) in
+ if debug then eprintf "%s\n%!" cmd;
+ msg (f_"Uncompressing: %s") file_uri;
+ let r = Sys.command cmd in
+ if r <> 0 then (
+ eprintf (f_"%s: error: failed to uncompress template\n") prog;
+ exit 1
+- );
+- unlink_on_exit tmpfile;
+- tmpfile in
++ )
++ ) else (
++ (* If none of the above apply, uncompress to a temporary file and
++ * run virt-resize on the result.
++ *)
++ let tmpfile =
++ (* Uncompress it to a temporary file. *)
++ let { Index_parser.file_uri = file_uri } = entry in
++ let tmpfile = Filename.temp_file "vbsrc" ".img" in
++ let cmd = sprintf "xzcat %s > %s" (quote template) (quote tmpfile) in
++ if debug then eprintf "%s\n%!" cmd;
++ msg (f_"Uncompressing: %s") file_uri;
++ let r = Sys.command cmd in
++ if r <> 0 then (
++ eprintf (f_"%s: error: failed to uncompress template\n") prog;
++ exit 1
++ );
++ unlink_on_exit tmpfile;
++ tmpfile in
+
+- (* Resize the source to the output file. *)
+- let () =
++ (* Resize the source to the output file. *)
+ (match size with
+ | None ->
+ msg (f_"Running virt-resize to expand the disk")
+@@ -351,13 +381,14 @@ let main () =
+ (match lvexpand with
+ | None -> ""
+ | Some lvexpand -> sprintf " --lv-expand %s" (quote lvexpand))
+- (quote source) (quote output) in
++ (quote tmpfile) (quote output) in
+ if debug then eprintf "%s\n%!" cmd;
+ let r = Sys.command cmd in
+ if r <> 0 then (
+ eprintf (f_"%s: error: virt-resize failed\n") prog;
+ exit 1
+- ) in
++ )
++ );
+
+ (* Now mount the output disk so we can make changes. *)
+ msg (f_"Opening the new disk");
+--
+1.8.3.1
+
diff --git a/0002-builder-Make-xzcat-binary-configurable-and-use-AC_PA.patch b/0002-builder-Make-xzcat-binary-configurable-and-use-AC_PA.patch
new file mode 100644
index 0000000..daf5ed0
--- /dev/null
+++ b/0002-builder-Make-xzcat-binary-configurable-and-use-AC_PA.patch
@@ -0,0 +1,73 @@
+From 6c92d98723e72d3e47066c53ea9fae0e95e4e7b1 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 22 Oct 2013 14:09:20 +0100
+Subject: [PATCH] builder: Make xzcat binary configurable and use AC_PATH_PROG.
+
+(cherry picked from commit 0e18bccb648f8c96366ae53746d83bd009f924f7)
+---
+ builder/builder.ml | 9 +++++++--
+ configure.ac | 4 ++++
+ mllib/config.ml.in | 2 ++
+ 3 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index 6750deb..ae642d0 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -323,13 +323,18 @@ let main () =
+
+ output, Some size, format, delete_output_file, do_resize, true in
+
++ (* Create xzcat command to uncompress from input to output. *)
++ let xzcat_command input output =
++ sprintf "%s %s > %s" Config.xzcat input output
++ in
++
+ if not do_resize then (
+ (* If the user did not specify --size and the output is a regular
+ * file and the format is raw, then we just uncompress the template
+ * directly to the output file. This is fast but less flexible.
+ *)
+ let { Index_parser.file_uri = file_uri } = entry in
+- let cmd = sprintf "xzcat %s > %s" (quote template) (quote output) in
++ let cmd = xzcat_command template output in
+ if debug then eprintf "%s\n%!" cmd;
+ msg (f_"Uncompressing: %s") file_uri;
+ let r = Sys.command cmd in
+@@ -345,7 +350,7 @@ let main () =
+ (* Uncompress it to a temporary file. *)
+ let { Index_parser.file_uri = file_uri } = entry in
+ let tmpfile = Filename.temp_file "vbsrc" ".img" in
+- let cmd = sprintf "xzcat %s > %s" (quote template) (quote tmpfile) in
++ let cmd = xzcat_command template tmpfile in
+ if debug then eprintf "%s\n%!" cmd;
+ msg (f_"Uncompressing: %s") file_uri;
+ let r = Sys.command cmd in
+diff --git a/configure.ac b/configure.ac
+index 8dc4e7f..b31abbc 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -698,6 +698,10 @@ if test "x$WRESTOOL" != "xno"; then
+ AC_DEFINE_UNQUOTED([WRESTOOL],["$WRESTOOL"],[Name of wrestool program.])
+ fi
+
++dnl Check for xzcat (required).
++AC_PATH_PROGS([XZCAT],[xzcat],[no])
++test "x$XZCAT" = "xno" && AC_MSG_ERROR([xzcat must be installed])
++
+ dnl Check for QEMU for running binaries on this $host_cpu, fall
+ dnl back to basic 'qemu'. Allow the user to override it.
+ qemu_system="$(
+diff --git a/mllib/config.ml.in b/mllib/config.ml.in
+index d18bf7b..129741d 100644
+--- a/mllib/config.ml.in
++++ b/mllib/config.ml.in
+@@ -18,3 +18,5 @@
+
+ let package_name = "@PACKAGE_NAME@"
+ let package_version = "@PACKAGE_VERSION@"
++
++let xzcat = "@XZCAT@"
+--
+1.8.3.1
+
diff --git a/0003-builder-Use-pxzcat-optionally-to-speed-up-xzcat-step.patch b/0003-builder-Use-pxzcat-optionally-to-speed-up-xzcat-step.patch
new file mode 100644
index 0000000..771bcb3
--- /dev/null
+++ b/0003-builder-Use-pxzcat-optionally-to-speed-up-xzcat-step.patch
@@ -0,0 +1,74 @@
+From 6ae9a5c40b4c19869e4843317c8884977cdd16b3 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 22 Oct 2013 14:22:46 +0100
+Subject: [PATCH] builder: Use pxzcat (optionally) to speed up xzcat step.
+
+(cherry picked from commit d4450c6590744ab96c7e0c3b21325d1eff666f29)
+---
+ README | 3 +++
+ builder/builder.ml | 6 ++++--
+ configure.ac | 3 +++
+ mllib/config.ml.in | 4 ++++
+ 4 files changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/README b/README
+index 676bb2f..cdf492e 100644
+--- a/README
++++ b/README
+@@ -170,6 +170,9 @@ The full requirements are described below.
+ | gpg | | O | Used by virt-builder for digital |
+ | | | | signatures |
+ +--------------+-------------+---+-----------------------------------------+
++| pxzcat | | O | Can be used by virt-builder for fast |
++| | | | uncompression of templates. |
+++--------------+-------------+---+-----------------------------------------+
+ | findlib | | O | For the OCaml bindings. |
+ +--------------+-------------+---+-----------------------------------------+
+ | ocaml-gettext| | O | For localizing OCaml virt-* tools. |
+diff --git a/builder/builder.ml b/builder/builder.ml
+index ae642d0..477fc3e 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -323,9 +323,11 @@ let main () =
+
+ output, Some size, format, delete_output_file, do_resize, true in
+
+- (* Create xzcat command to uncompress from input to output. *)
++ (* Create xzcat/pxzcat command to uncompress from input to output. *)
+ let xzcat_command input output =
+- sprintf "%s %s > %s" Config.xzcat input output
++ match Config.pxzcat with
++ | None -> sprintf "%s %s > %s" Config.xzcat input output
++ | Some pxzcat -> sprintf "%s %s -o %s" pxzcat input output
+ in
+
+ if not do_resize then (
+diff --git a/configure.ac b/configure.ac
+index b31abbc..00cb151 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -702,6 +702,9 @@ dnl Check for xzcat (required).
+ AC_PATH_PROGS([XZCAT],[xzcat],[no])
+ test "x$XZCAT" = "xno" && AC_MSG_ERROR([xzcat must be installed])
+
++dnl Check for pxzcat (optional).
++AC_PATH_PROGS([PXZCAT],[pxzcat],[no])
++
+ dnl Check for QEMU for running binaries on this $host_cpu, fall
+ dnl back to basic 'qemu'. Allow the user to override it.
+ qemu_system="$(
+diff --git a/mllib/config.ml.in b/mllib/config.ml.in
+index 129741d..5586c5c 100644
+--- a/mllib/config.ml.in
++++ b/mllib/config.ml.in
+@@ -20,3 +20,7 @@ let package_name = "@PACKAGE_NAME@"
+ let package_version = "@PACKAGE_VERSION@"
+
+ let xzcat = "@XZCAT@"
++let pxzcat =
++ match "@PXZCAT@" with
++ | "no" -> None
++ | path -> Some path
+--
+1.8.3.1
+
diff --git a/0004-builder-Add-no-sync-option-to-avoid-sync-on-exit.patch b/0004-builder-Add-no-sync-option-to-avoid-sync-on-exit.patch
new file mode 100644
index 0000000..827236d
--- /dev/null
+++ b/0004-builder-Add-no-sync-option-to-avoid-sync-on-exit.patch
@@ -0,0 +1,101 @@
+From 5cfe8a0e678468318d8af403c197367979ba62a0 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 22 Oct 2013 22:28:27 +0100
+Subject: [PATCH] builder: Add --no-sync option to avoid sync on exit.
+
+(cherry picked from commit 3f46a92ed5737bb8d75630a39729f95bc96417f6)
+---
+ builder/builder.ml | 5 +++--
+ builder/cmdline.ml | 6 +++++-
+ builder/virt-builder.pod | 17 +++++++++++++++++
+ 3 files changed, 25 insertions(+), 3 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index 477fc3e..7a46174 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -38,7 +38,7 @@ let main () =
+ attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
+ firstboot, run, format, gpg, hostname, install, list_long, network, output,
+ password_crypto, quiet, root_password, scrub, scrub_logfile, size, source,
+- upload =
++ sync, upload =
+ parse_cmdline () in
+
+ (* Timestamped messages in ordinary, non-debug non-quiet mode. *)
+@@ -727,7 +727,8 @@ exec >>%s 2>&1
+ * and therefore bypasses the host cache). In general you should not
+ * use cache=none.
+ *)
+- Fsync.file output;
++ if sync then
++ Fsync.file output;
+
+ (* Now that we've finished the build, don't delete the output file on
+ * exit.
+diff --git a/builder/cmdline.ml b/builder/cmdline.ml
+index 780e171..41d2a64 100644
+--- a/builder/cmdline.ml
++++ b/builder/cmdline.ml
+@@ -161,6 +161,8 @@ let parse_cmdline () =
+ with Not_found -> "http://libguestfs.org/download/builder/index.asc" in
+ let source = ref source in
+
++ let sync = ref true in
++
+ let upload = ref [] in
+ let add_upload arg =
+ let i =
+@@ -232,6 +234,7 @@ let parse_cmdline () =
+ "--scrub", Arg.String add_scrub, "name" ^ " " ^ s_"Scrub a file";
+ "--size", Arg.String set_size, "size" ^ " " ^ s_"Set output disk size";
+ "--source", Arg.Set_string source, "URL" ^ " " ^ s_"Set source URL";
++ "--no-sync", Arg.Clear sync, " " ^ s_"Do not fsync output file on exit";
+ "--upload", Arg.String add_upload, "file:dest" ^ " " ^ s_"Upload file to dest";
+ "-v", Arg.Set debug, " " ^ s_"Enable debugging messages";
+ "--verbose", Arg.Set debug, ditto;
+@@ -287,6 +290,7 @@ read the man page virt-builder(1).
+ let scrub_logfile = !scrub_logfile in
+ let size = !size in
+ let source = !source in
++ let sync = !sync in
+ let upload = List.rev !upload in
+
+ (* Check options. *)
+@@ -343,4 +347,4 @@ read the man page virt-builder(1).
+ attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
+ firstboot, run, format, gpg, hostname, install, list_long, network, output,
+ password_crypto, quiet, root_password, scrub, scrub_logfile, size, source,
+- upload
++ sync, upload
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 094b327..c3ea581 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -410,6 +410,23 @@ You don't have a host network (eg. in secure/restricted environments).
+
+ =back
+
++=item B<--no-sync>
++
++Do not sync the output file on exit.
++
++Virt-builder fsync's the output file or disk image when it exits.
++
++The reason is that qemu/KVM's default caching mode is C<none> or
++C<directsync>, both of which bypass the host page cache. Therefore
++these would not work correctly if you immediately started the guest
++after running virt-builder - they would not see the complete output
++file. (Note that you should not use these caching modes - they are
++fundamentally broken for this and other reasons.)
++
++If you are not using these broken caching modes, you can use
++I<--no-sync> to avoid this unnecessary sync and gain considerable
++extra performance.
++
+ =item B<--notes> os-version
+
+ List any notes associated with this guest, then exit (this does not do
+--
+1.8.3.1
+
diff --git a/0005-builder-Add-mkdir-option-to-create-directories.patch b/0005-builder-Add-mkdir-option-to-create-directories.patch
new file mode 100644
index 0000000..690d672
--- /dev/null
+++ b/0005-builder-Add-mkdir-option-to-create-directories.patch
@@ -0,0 +1,137 @@
+From f29f1c655df5fe7beee82ae663ede60440d28d06 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Fri, 25 Oct 2013 13:35:51 +0100
+Subject: [PATCH] builder: Add --mkdir option to create directories.
+
+(cherry picked from commit 99840550d5508b228ee4b2533ad94da517873f76)
+---
+ builder/builder.ml | 13 ++++++++++---
+ builder/cmdline.ml | 12 +++++++++---
+ builder/test-virt-builder.sh | 1 +
+ builder/virt-builder.pod | 12 ++++++++++++
+ 4 files changed, 32 insertions(+), 6 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index 7a46174..f4f0951 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -36,9 +36,9 @@ let main () =
+ (* Command line argument parsing - see cmdline.ml. *)
+ let mode, arg,
+ attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
+- firstboot, run, format, gpg, hostname, install, list_long, network, output,
+- password_crypto, quiet, root_password, scrub, scrub_logfile, size, source,
+- sync, upload =
++ firstboot, run, format, gpg, hostname, install, list_long, mkdirs,
++ network, output, password_crypto, quiet, root_password, scrub,
++ scrub_logfile, size, source, sync, upload =
+ parse_cmdline () in
+
+ (* Timestamped messages in ordinary, non-debug non-quiet mode. *)
+@@ -582,6 +582,13 @@ exec >>%s 2>&1
+ do_run ~display:cmd cmd
+ );
+
++ (* Make directories. *)
++ List.iter (
++ fun dir ->
++ msg (f_"Making directory: %s") dir;
++ g#mkdir_p dir
++ ) mkdirs;
++
+ (* Upload files. *)
+ List.iter (
+ fun (file, dest) ->
+diff --git a/builder/cmdline.ml b/builder/cmdline.ml
+index 41d2a64..dbf49f2 100644
+--- a/builder/cmdline.ml
++++ b/builder/cmdline.ml
+@@ -119,6 +119,10 @@ let parse_cmdline () =
+ in
+
+ let list_long = ref false in
++
++ let mkdirs = ref [] in
++ let add_mkdir arg = mkdirs := arg :: !mkdirs in
++
+ let network = ref true in
+ let output = ref "" in
+
+@@ -217,6 +221,7 @@ let parse_cmdline () =
+ "--long", Arg.Set list_long, ditto;
+ "--no-logfile", Arg.Set scrub_logfile, " " ^ s_"Scrub build log file";
+ "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options";
++ "--mkdir", Arg.String add_mkdir, "dir" ^ " " ^ s_"Create directory";
+ "--network", Arg.Set network, " " ^ s_"Enable appliance network (default)";
+ "--no-network", Arg.Clear network, " " ^ s_"Disable appliance network";
+ "--notes", Arg.Unit notes_mode, " " ^ s_"Display installation notes";
+@@ -281,6 +286,7 @@ read the man page virt-builder(1).
+ let hostname = !hostname in
+ let install = !install in
+ let list_long = !list_long in
++ let mkdirs = List.rev !mkdirs in
+ let network = !network in
+ let output = match !output with "" -> None | s -> Some s in
+ let password_crypto = !password_crypto in
+@@ -345,6 +351,6 @@ read the man page virt-builder(1).
+
+ mode, arg,
+ attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
+- firstboot, run, format, gpg, hostname, install, list_long, network, output,
+- password_crypto, quiet, root_password, scrub, scrub_logfile, size, source,
+- sync, upload
++ firstboot, run, format, gpg, hostname, install, list_long, mkdirs,
++ network, output, password_crypto, quiet, root_password, scrub,
++ scrub_logfile, size, source, sync, upload
+diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh
+index fbc52a0..a5df027 100755
+--- a/builder/test-virt-builder.sh
++++ b/builder/test-virt-builder.sh
+@@ -54,6 +54,7 @@ rm -f $output
+ -o $output --size 2G --format $format \
+ --hostname test.example.com \
+ --root-password password:123456 \
++ --mkdir /etc/foo/bar/baz \
+ --upload Makefile:/Makefile \
+ --delete /Makefile \
+ --firstboot Makefile --firstboot-command 'echo "hello"' \
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index c3ea581..42d0d8a 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -18,6 +18,7 @@ virt-builder - Build virtual machine images quickly
+ [--root-password ...]
+ [--hostname HOSTNAME]
+ [--install PKG,[PKG...]]
++ [--mkdir DIR]
+ [--upload FILE:DEST]
+ [--edit FILE:EXPR]
+ [--delete FILE] [--scrub FILE]
+@@ -364,6 +365,13 @@ the image was built, use this option.
+
+ See also: L</LOG FILE>.
+
++=item B<--mkdir> DIR
++
++Create a directory in the guest.
++
++This uses S<C<mkdir -p>> so any intermediate directories are created,
++and it also works if the directory already exists.
++
+ =item B<--network>
+
+ =item B<--no-network>
+@@ -749,6 +757,10 @@ Packages are installed (I<--install>).
+
+ =item *
+
++Directories are created (I<--mkdir>).
++
++=item *
++
+ Files are uploaded (I<--upload>).
+
+ =item *
+--
+1.8.3.1
+
diff --git a/0006-builder-Allow-upload-to-a-directory.patch b/0006-builder-Allow-upload-to-a-directory.patch
new file mode 100644
index 0000000..fd50106
--- /dev/null
+++ b/0006-builder-Allow-upload-to-a-directory.patch
@@ -0,0 +1,79 @@
+From ddf6681c75d3ca2a6e94a051a3d3650ac9f79d97 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Sat, 26 Oct 2013 11:27:06 +0100
+Subject: [PATCH] builder: Allow --upload to a directory.
+
+Also set the owner and permissions on the destination file correctly.
+
+(cherry picked from commit 10c849ed1cb4375c5ef811197fa0a3206d365b86)
+---
+ builder/builder.ml | 19 +++++++++++++++++--
+ builder/test-virt-builder.sh | 1 +
+ builder/virt-builder.pod | 9 ++++++++-
+ 3 files changed, 26 insertions(+), 3 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index f4f0951..dab8b41 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -592,8 +592,23 @@ exec >>%s 2>&1
+ (* Upload files. *)
+ List.iter (
+ fun (file, dest) ->
+- msg (f_"Uploading: %s") dest;
+- g#upload file dest
++ msg (f_"Uploading: %s to %s") file dest;
++ let dest =
++ if g#is_dir dest then
++ dest ^ "/" ^ Filename.basename file
++ else
++ dest in
++ (* Do the file upload. *)
++ g#upload file dest;
++
++ (* Copy (some of) the permissions from the local file to the
++ * uploaded file.
++ *)
++ let statbuf = stat file in
++ let perms = statbuf.st_perm land 0o7777 (* sticky & set*id *) in
++ g#chmod perms dest;
++ let uid, gid = statbuf.st_uid, statbuf.st_gid in
++ g#chown uid gid dest
+ ) upload;
+
+ (* Edit files. *)
+diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh
+index a5df027..b39bc3f 100755
+--- a/builder/test-virt-builder.sh
++++ b/builder/test-virt-builder.sh
+@@ -56,6 +56,7 @@ rm -f $output
+ --root-password password:123456 \
+ --mkdir /etc/foo/bar/baz \
+ --upload Makefile:/Makefile \
++ --upload Makefile:/etc/foo/bar/baz \
+ --delete /Makefile \
+ --firstboot Makefile --firstboot-command 'echo "hello"' \
+ --firstboot-install "minicom,inkscape"
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 42d0d8a..810cee7 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -559,7 +559,14 @@ Upload local file C<FILE> to destination C<DEST> in the disk image.
+ File owner and permissions from the original are preserved, so you
+ should set them to what you want them to be in the disk image.
+
+-See also: I<--delete>, I<--scrub>.
++C<DEST> could be the final filename. This can be used to rename
++the file on upload.
++
++If C<DEST> is a directory name (which must already exist in the guest)
++then the file is uploaded into that directory, and it keeps the same
++name as on the local filesystem.
++
++See also: I<--mkdir>, I<--delete>, I<--scrub>.
+
+ =item B<-v>
+
+--
+1.8.3.1
+
diff --git a/0007-builder-Add-write-option-to-write-a-literal-file.patch b/0007-builder-Add-write-option-to-write-a-literal-file.patch
new file mode 100644
index 0000000..0859ad0
--- /dev/null
+++ b/0007-builder-Add-write-option-to-write-a-literal-file.patch
@@ -0,0 +1,135 @@
+From 3c0dacb066a7aff4b55747862898e418f31dce9c Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Sat, 26 Oct 2013 11:40:48 +0100
+Subject: [PATCH] builder: Add --write option to write a literal file.
+
+(cherry picked from commit 0520aa3c42fbb174be37ef75b19390855d225897)
+---
+ builder/builder.ml | 9 ++++++++-
+ builder/cmdline.ml | 17 ++++++++++++++++-
+ builder/test-virt-builder.sh | 1 +
+ builder/virt-builder.pod | 9 +++++++++
+ 4 files changed, 34 insertions(+), 2 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index dab8b41..803de0c 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -38,7 +38,7 @@ let main () =
+ attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
+ firstboot, run, format, gpg, hostname, install, list_long, mkdirs,
+ network, output, password_crypto, quiet, root_password, scrub,
+- scrub_logfile, size, source, sync, upload =
++ scrub_logfile, size, source, sync, upload, writes =
+ parse_cmdline () in
+
+ (* Timestamped messages in ordinary, non-debug non-quiet mode. *)
+@@ -589,6 +589,13 @@ exec >>%s 2>&1
+ g#mkdir_p dir
+ ) mkdirs;
+
++ (* Write files. *)
++ List.iter (
++ fun (file, content) ->
++ msg (f_"Writing: %s") file;
++ g#write file content
++ ) writes;
++
+ (* Upload files. *)
+ List.iter (
+ fun (file, dest) ->
+diff --git a/builder/cmdline.ml b/builder/cmdline.ml
+index dbf49f2..d92fcb9 100644
+--- a/builder/cmdline.ml
++++ b/builder/cmdline.ml
+@@ -184,6 +184,19 @@ let parse_cmdline () =
+ upload := (file, dest) :: !upload
+ in
+
++ let writes = ref [] in
++ let add_write arg =
++ let i =
++ try String.index arg ':'
++ with Not_found ->
++ eprintf (f_"%s: invalid --write format, see the man page.\n") prog;
++ exit 1 in
++ let len = String.length arg in
++ let file = String.sub arg 0 i in
++ let content = String.sub arg (i+1) (len-(i+1)) in
++ writes := (file, content) :: !writes
++ in
++
+ let ditto = " -\"-" in
+ let argspec = Arg.align [
+ "--attach", Arg.String attach_disk, "iso" ^ " " ^ s_"Attach data disk/ISO during install";
+@@ -245,6 +258,7 @@ let parse_cmdline () =
+ "--verbose", Arg.Set debug, ditto;
+ "-V", Arg.Unit display_version, " " ^ s_"Display version and exit";
+ "--version", Arg.Unit display_version, ditto;
++ "--write", Arg.String add_write, "file:content" ^ " " ^ s_"Write file";
+ ] in
+ long_options := argspec;
+
+@@ -298,6 +312,7 @@ read the man page virt-builder(1).
+ let source = !source in
+ let sync = !sync in
+ let upload = List.rev !upload in
++ let writes = List.rev !writes in
+
+ (* Check options. *)
+ let arg =
+@@ -353,4 +368,4 @@ read the man page virt-builder(1).
+ attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
+ firstboot, run, format, gpg, hostname, install, list_long, mkdirs,
+ network, output, password_crypto, quiet, root_password, scrub,
+- scrub_logfile, size, source, sync, upload
++ scrub_logfile, size, source, sync, upload, writes
+diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh
+index b39bc3f..159f013 100755
+--- a/builder/test-virt-builder.sh
++++ b/builder/test-virt-builder.sh
+@@ -55,6 +55,7 @@ rm -f $output
+ --hostname test.example.com \
+ --root-password password:123456 \
+ --mkdir /etc/foo/bar/baz \
++ --write '/etc/foo/bar/baz/foo:Hello World' \
+ --upload Makefile:/Makefile \
+ --upload Makefile:/etc/foo/bar/baz \
+ --delete /Makefile \
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 810cee7..13d342d 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -19,6 +19,7 @@ virt-builder - Build virtual machine images quickly
+ [--hostname HOSTNAME]
+ [--install PKG,[PKG...]]
+ [--mkdir DIR]
++ [--write FILE:CONTENT]
+ [--upload FILE:DEST]
+ [--edit FILE:EXPR]
+ [--delete FILE] [--scrub FILE]
+@@ -583,6 +584,10 @@ your bug report.
+
+ Display version number and exit.
+
++=item B<--write> FILE:CONTENT
++
++Write C<CONTENT> to C<FILE>.
++
+ =back
+
+ =head1 REFERENCE
+@@ -768,6 +773,10 @@ Directories are created (I<--mkdir>).
+
+ =item *
+
++Files are written (I<--write>).
++
++=item *
++
+ Files are uploaded (I<--upload>).
+
+ =item *
+--
+1.8.3.1
+
diff --git a/0008-builder-Document-how-to-boot-VMs-directly-in-qemu-or.patch b/0008-builder-Document-how-to-boot-VMs-directly-in-qemu-or.patch
new file mode 100644
index 0000000..fd3d322
--- /dev/null
+++ b/0008-builder-Document-how-to-boot-VMs-directly-in-qemu-or.patch
@@ -0,0 +1,39 @@
+From a80de72193e4a3fc379628b56035748436e2bcca Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Sat, 26 Oct 2013 14:45:30 +0100
+Subject: [PATCH] builder: Document how to boot VMs directly in qemu or KVM.
+
+(cherry picked from commit 8b34855684fb660823a2801a4a5e8be32a6cc40f)
+---
+ builder/virt-builder.pod | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 13d342d..770d359 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -841,6 +841,21 @@ XXX
+
+ =end comment
+
++=head3 Booting directly using qemu or KVM
++
++The qemu command line is not very stable or easy to use, hence libvirt
++should be used if possible. However a command line similar to the
++following could be used to boot the virtual machine:
++
++ qemu-system-x86_64 \
++ -machine accel=kvm:tcg \
++ -cpu host \
++ -m 2048 \
++ -drive file=disk.img,format=raw,if=virtio
++
++As with libvirt, it is very important that the correct format is
++chosen. It will be C<raw> unless the I<--format> option was used.
++
+ =head2 DEBUGGING BUILDS
+
+ If virt-builder fails with an error, then enable debugging (I<-v>) and
+--
+1.8.3.1
+
diff --git a/0009-firstboot-Send-the-output-to-the-console-as-well-as-.patch b/0009-firstboot-Send-the-output-to-the-console-as-well-as-.patch
new file mode 100644
index 0000000..d8aad17
--- /dev/null
+++ b/0009-firstboot-Send-the-output-to-the-console-as-well-as-.patch
@@ -0,0 +1,62 @@
+From 044198313cda55e0f002d44459c7a09c3b3afdc5 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Sat, 26 Oct 2013 17:09:06 +0100
+Subject: [PATCH] firstboot: Send the output to the console as well as to the
+ log file.
+
+For systemd:
+Currently stdout+stderr go to the journal (these are effectively
+empty unless there are gross errors). The output of the commands
+goes to the log file.
+
+With this change, the output goes to the journal, the console and
+the log file.
+
+For SysV-init:
+Currently stdout+stderr go to the console (but these are effectively
+empty). The output of the commands goes to the log file.
+
+With this change, the output goes to the console and the log file.
+
+(cherry picked from commit f114e28cc80eabdcf47c97e7e3895065cdfe4886)
+---
+ mllib/firstboot.ml | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/mllib/firstboot.ml b/mllib/firstboot.ml
+index 0207cc1..9e4c7b6 100644
+--- a/mllib/firstboot.ml
++++ b/mllib/firstboot.ml
+@@ -45,16 +45,16 @@ let firstboot_sh = sprintf "\
+ d=%s/scripts
+ logfile=~root/virt-sysprep-firstboot.log
+
+-echo \"$0\" \"$@\" >>$logfile
+-echo \"Scripts dir: $d\" >>$logfile
++echo \"$0\" \"$@\" 2>&1 | tee $logfile
++echo \"Scripts dir: $d\" 2>&1 | tee $logfile
+
+ if test \"$1\" = \"start\"
+ then
+ for f in $d/* ; do
+ if test -x \"$f\"
+ then
+- echo '=== Running' $f '===' >>$logfile
+- $f >>$logfile 2>&1
++ echo '=== Running' $f '===' 2>&1 | tee $logfile
++ $f 2>&1 | tee $logfile
+ rm -f $f
+ fi
+ done
+@@ -71,6 +71,8 @@ Before=prefdm.service
+ Type=oneshot
+ ExecStart=%s/firstboot.sh start
+ RemainAfterExit=yes
++StandardOutput=journal+console
++StandardError=inherit
+
+ [Install]
+ WantedBy=default.target
+--
+1.8.3.1
+
diff --git a/0010-builder-Add-a-section-on-performance-to-the-manual.patch b/0010-builder-Add-a-section-on-performance-to-the-manual.patch
new file mode 100644
index 0000000..bc581c2
--- /dev/null
+++ b/0010-builder-Add-a-section-on-performance-to-the-manual.patch
@@ -0,0 +1,69 @@
+From bf28209da7771951de0f113a5b9175fd75e27439 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Sun, 27 Oct 2013 14:59:39 +0000
+Subject: [PATCH] builder: Add a section on performance to the manual.
+
+(cherry picked from commit 2937c035958f84986e84c47df49f79d19c4b5b59)
+---
+ builder/virt-builder.pod | 45 ++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 44 insertions(+), 1 deletion(-)
+
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 770d359..442bbec 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -1290,7 +1290,50 @@ etc are truly random when the guest boots.
+
+ You should check digital signatures and not ignore any signing errors.
+
+-=head2 USER MODE LINUX
++=head2 PERFORMANCE
++
++The most important aspect of getting good performance is caching.
++Templates gets downloaded into the cache the first time they are used,
++or if you use the I<--cache-all-templates> option. See L</CACHING>
++above for further information.
++
++Packages required for the I<--install> option are downloaded using the
++host network connection. Setting the C<http_proxy>, C<https_proxy>
++and C<ftp_proxy> environment variables to point to a local web cache
++may ensure they only need to be downloaded once. You can also try
++using a local package repository, although this can be complex to set
++up and varies according to which Linux distro you are trying to
++install.
++
++=head3 Skipping virt-resize
++
++Virt-builder can skip the virt-resize step under certain conditions.
++This makes virt-builder much faster. The conditions are:
++
++=over 4
++
++=item *
++
++the output must be a regular file (not a block device), B<and>
++
++=item *
++
++the user did B<not> use the I<--size> option, B<and>
++
++=item *
++
++the output format is the same as the template format (usually raw).
++
++=back
++
++=head3 pxzcat
++
++Virt-builder can use C<pxzcat> (parallel xzcat) if available to
++uncompress the templates. The default is to use regular C<xzcat>
++which is single-threaded. Currently this has to be compiled in,
++ie. virt-builder will probably need to be recompiled to use pxzcat.
++
++=head3 User-Mode Linux
+
+ You can use virt-builder with the User-Mode Linux (UML) backend. This
+ may be faster when running virt-builder inside a virtual machine
+--
+1.8.3.1
+
diff --git a/0011-builder-Add-m-memsize-and-smp-command-line-options.patch b/0011-builder-Add-m-memsize-and-smp-command-line-options.patch
new file mode 100644
index 0000000..4d3ec5a
--- /dev/null
+++ b/0011-builder-Add-m-memsize-and-smp-command-line-options.patch
@@ -0,0 +1,153 @@
+From 8a98e37fde47ad310e8cee3c041f401d8d9739a8 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 29 Oct 2013 19:23:33 +0000
+Subject: [PATCH] builder: Add -m/--memsize and --smp command line options.
+
+(cherry picked from commit 42e445f98692c6344baafaab1da10e821288ac0a)
+---
+ builder/builder.ml | 6 ++++--
+ builder/cmdline.ml | 15 +++++++++++++--
+ builder/virt-builder.pod | 22 ++++++++++++++++------
+ 3 files changed, 33 insertions(+), 10 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index 803de0c..c9fd291 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -36,9 +36,9 @@ let main () =
+ (* Command line argument parsing - see cmdline.ml. *)
+ let mode, arg,
+ attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
+- firstboot, run, format, gpg, hostname, install, list_long, mkdirs,
++ firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs,
+ network, output, password_crypto, quiet, root_password, scrub,
+- scrub_logfile, size, source, sync, upload, writes =
++ scrub_logfile, size, smp, source, sync, upload, writes =
+ parse_cmdline () in
+
+ (* Timestamped messages in ordinary, non-debug non-quiet mode. *)
+@@ -403,6 +403,8 @@ let main () =
+ let g = new G.guestfs () in
+ if debug then g#set_trace true;
+
++ (match memsize with None -> () | Some memsize -> g#set_memsize memsize);
++ (match smp with None -> () | Some smp -> g#set_smp smp);
+ g#set_network network;
+
+ (* The output disk is being created, so use cache=unsafe here. *)
+diff --git a/builder/cmdline.ml b/builder/cmdline.ml
+index d92fcb9..f8e604e 100644
+--- a/builder/cmdline.ml
++++ b/builder/cmdline.ml
+@@ -120,6 +120,9 @@ let parse_cmdline () =
+
+ let list_long = ref false in
+
++ let memsize = ref None in
++ let set_memsize arg = memsize := Some arg in
++
+ let mkdirs = ref [] in
+ let add_mkdir arg = mkdirs := arg :: !mkdirs in
+
+@@ -160,6 +163,9 @@ let parse_cmdline () =
+ let size = ref None in
+ let set_size arg = size := Some (parse_size ~prog arg) in
+
++ let smp = ref None in
++ let set_smp arg = smp := Some arg in
++
+ let source =
+ try Sys.getenv "VIRT_BUILDER_SOURCE"
+ with Not_found -> "http://libguestfs.org/download/builder/index.asc" in
+@@ -234,6 +240,8 @@ let parse_cmdline () =
+ "--long", Arg.Set list_long, ditto;
+ "--no-logfile", Arg.Set scrub_logfile, " " ^ s_"Scrub build log file";
+ "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options";
++ "-m", Arg.Int set_memsize, "mb" ^ " " ^ s_"Set memory size";
++ "--memsize", Arg.Int set_memsize, "mb" ^ ditto;
+ "--mkdir", Arg.String add_mkdir, "dir" ^ " " ^ s_"Create directory";
+ "--network", Arg.Set network, " " ^ s_"Enable appliance network (default)";
+ "--no-network", Arg.Clear network, " " ^ s_"Disable appliance network";
+@@ -251,6 +259,7 @@ let parse_cmdline () =
+ "--run-command", Arg.String add_run_cmd, "cmd+args" ^ " " ^ s_"Run command in disk image";
+ "--scrub", Arg.String add_scrub, "name" ^ " " ^ s_"Scrub a file";
+ "--size", Arg.String set_size, "size" ^ " " ^ s_"Set output disk size";
++ "--smp", Arg.Int set_smp, "vcpus" ^ " " ^ s_"Set number of vCPUs";
+ "--source", Arg.Set_string source, "URL" ^ " " ^ s_"Set source URL";
+ "--no-sync", Arg.Clear sync, " " ^ s_"Do not fsync output file on exit";
+ "--upload", Arg.String add_upload, "file:dest" ^ " " ^ s_"Upload file to dest";
+@@ -300,6 +309,7 @@ read the man page virt-builder(1).
+ let hostname = !hostname in
+ let install = !install in
+ let list_long = !list_long in
++ let memsize = !memsize in
+ let mkdirs = List.rev !mkdirs in
+ let network = !network in
+ let output = match !output with "" -> None | s -> Some s in
+@@ -309,6 +319,7 @@ read the man page virt-builder(1).
+ let scrub = List.rev !scrub in
+ let scrub_logfile = !scrub_logfile in
+ let size = !size in
++ let smp = !smp in
+ let source = !source in
+ let sync = !sync in
+ let upload = List.rev !upload in
+@@ -366,6 +377,6 @@ read the man page virt-builder(1).
+
+ mode, arg,
+ attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
+- firstboot, run, format, gpg, hostname, install, list_long, mkdirs,
++ firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs,
+ network, output, password_crypto, quiet, root_password, scrub,
+- scrub_logfile, size, source, sync, upload, writes
++ scrub_logfile, size, smp, source, sync, upload, writes
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 442bbec..70e19c3 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -366,6 +366,18 @@ the image was built, use this option.
+
+ See also: L</LOG FILE>.
+
++=item B<-m> MB
++
++=item B<--memsize> MB
++
++Change the amount of memory allocated to I<--run> scripts. Increase
++this if you find that I<--run> scripts or the I<--install> option are
++running out of memory.
++
++The default can be found with this command:
++
++ guestfish get-memsize
++
+ =item B<--mkdir> DIR
+
+ Create a directory in the guest.
+@@ -541,6 +553,10 @@ output is a file, then the size is the same as the template. If the
+ output is a device, partition, etc then the size of that device is
+ used.
+
++=item B<--smp> N
++
++Enable N E<ge> 2 virtual CPUs for I<--run> scripts to use.
++
+ =item B<--source> URL
+
+ Set the source URL to look for templates. If not specified it
+@@ -1368,12 +1384,6 @@ are actually interpreted by L<curl(1)>, not virt-builder.
+
+ Used to determine the location of the template cache. See L</CACHING>.
+
+-=item C<LIBGUESTFS_MEMSIZE>
+-
+-The size (in megabytes) of the appliance. The default can be found
+-using the command S<C<guestfish get-memsize>>. Increase this if you
+-find that I<--run> scripts are running out of memory.
+-
+ =item C<VIRT_BUILDER_FINGERPRINT>
+
+ Set the default value for the GPG signature fingerprint (see
+--
+1.8.3.1
+
diff --git a/0012-builder-Allow-multiple-source-paths-to-be-specified.patch b/0012-builder-Allow-multiple-source-paths-to-be-specified.patch
new file mode 100644
index 0000000..be5152c
--- /dev/null
+++ b/0012-builder-Allow-multiple-source-paths-to-be-specified.patch
@@ -0,0 +1,450 @@
+From 2c081f7d45a250220860a3a21938a3f2d7d39a9b Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Fri, 1 Nov 2013 14:16:34 +0000
+Subject: [PATCH] builder: Allow multiple source paths to be specified.
+
+Users can now specify multiple source paths, eg:
+
+ virt-builder --source http://example.com/foo \
+ --source http://example.com/bar
+
+to get templates from multiple places.
+
+There is still only one built-in path, but we can add more later.
+
+(cherry picked from commit bb4e882d61b49045aabd35912ae7e3a18cd6028b)
+---
+ builder/builder.ml | 32 +++++++++++-------
+ builder/cmdline.ml | 69 ++++++++++++++++++++++++++++++---------
+ builder/index_parser.ml | 5 ++-
+ builder/index_parser.mli | 2 ++
+ builder/list_entries.ml | 10 ++++--
+ builder/list_entries.mli | 2 +-
+ builder/sigchecker.ml | 7 ++--
+ builder/sigchecker.mli | 4 ++-
+ builder/test-virt-builder-list.sh | 1 +
+ builder/virt-builder.pod | 57 ++++++++++++++++++++++++++------
+ 10 files changed, 143 insertions(+), 46 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index c9fd291..fc6078c 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -35,22 +35,27 @@ let prog = Filename.basename Sys.executable_name
+ let main () =
+ (* Command line argument parsing - see cmdline.ml. *)
+ let mode, arg,
+- attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
++ attach, cache, check_signature, curl, debug, delete, edit,
+ firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs,
+ network, output, password_crypto, quiet, root_password, scrub,
+- scrub_logfile, size, smp, source, sync, upload, writes =
++ scrub_logfile, size, smp, sources, sync, upload, writes =
+ parse_cmdline () in
+
+ (* Timestamped messages in ordinary, non-debug non-quiet mode. *)
+ let msg fs = make_message_function ~quiet fs in
+
+- (* If debugging, echo the command line arguments. *)
++ (* If debugging, echo the command line arguments and the sources. *)
+ if debug then (
+ eprintf "command line:";
+ List.iter (eprintf " %s") (Array.to_list Sys.argv);
+- prerr_newline ()
++ prerr_newline ();
++ List.iteri (
++ fun i (source, fingerprint) ->
++ eprintf "source[%d] = (%S, %S)\n" i source fingerprint
++ ) sources
+ );
+
++
+ (* Handle some modes here, some later on. *)
+ let mode =
+ match mode with
+@@ -125,19 +130,23 @@ let main () =
+ )
+ in
+
+- (* Make the downloader and signature checker abstract data types. *)
++ (* Download the sources. *)
+ let downloader = Downloader.create ~debug ~curl ~cache in
+- let sigchecker =
+- Sigchecker.create ~debug ~gpg ?fingerprint ~check_signature in
+-
+- (* Download the source (index) file. *)
+- let index = Index_parser.get_index ~debug ~downloader ~sigchecker source in
++ let index : Index_parser.index =
++ List.concat (
++ List.map (
++ fun (source, fingerprint) ->
++ let sigchecker =
++ Sigchecker.create ~debug ~gpg ~fingerprint ~check_signature in
++ Index_parser.get_index ~debug ~downloader ~sigchecker source
++ ) sources
++ ) in
+
+ (* Now handle the remaining modes. *)
+ let mode =
+ match mode with
+ | `List -> (* --list *)
+- List_entries.list_entries ~list_long ~source index;
++ List_entries.list_entries ~list_long ~sources index;
+ exit 0
+
+ | `Print_cache -> (* --print-cache *)
+@@ -184,6 +193,7 @@ let main () =
+ eprintf (f_"%s: cannot find os-version '%s'.\nUse --list to list available guest types.\n")
+ prog arg;
+ exit 1 in
++ let sigchecker = entry.Index_parser.sigchecker in
+
+ (match mode with
+ | `Notes -> (* --notes *)
+diff --git a/builder/cmdline.ml b/builder/cmdline.ml
+index f8e604e..5256390 100644
+--- a/builder/cmdline.ml
++++ b/builder/cmdline.ml
+@@ -37,6 +37,8 @@ let default_cachedir =
+ with Not_found ->
+ None (* no cache directory *)
+
++let default_source = "http://libguestfs.org/download/builder/index.asc"
++
+ let parse_cmdline () =
+ let display_version () =
+ printf "virt-builder %s\n" Config.package_version;
+@@ -83,11 +85,8 @@ let parse_cmdline () =
+ edit := (file, expr) :: !edit
+ in
+
+- let fingerprint =
+- try Some (Sys.getenv "VIRT_BUILDER_FINGERPRINT")
+- with Not_found -> None in
+- let fingerprint = ref fingerprint in
+- let set_fingerprint fp = fingerprint := Some fp in
++ let fingerprints = ref [] in
++ let add_fingerprint arg = fingerprints := arg :: !fingerprints in
+
+ let firstboot = ref [] in
+ let add_firstboot s =
+@@ -166,10 +165,8 @@ let parse_cmdline () =
+ let smp = ref None in
+ let set_smp arg = smp := Some arg in
+
+- let source =
+- try Sys.getenv "VIRT_BUILDER_SOURCE"
+- with Not_found -> "http://libguestfs.org/download/builder/index.asc" in
+- let source = ref source in
++ let sources = ref [] in
++ let add_source arg = sources := arg :: !sources in
+
+ let sync = ref true in
+
+@@ -223,7 +220,7 @@ let parse_cmdline () =
+ "--delete-cache", Arg.Unit delete_cache_mode,
+ " " ^ s_"Delete the template cache";
+ "--edit", Arg.String add_edit, "file:expr" ^ " " ^ s_"Edit file with Perl expr";
+- "--fingerprint", Arg.String set_fingerprint,
++ "--fingerprint", Arg.String add_fingerprint,
+ "AAAA.." ^ " " ^ s_"Fingerprint of valid signing key";
+ "--firstboot", Arg.String add_firstboot, "script" ^ " " ^ s_"Run script at first guest boot";
+ "--firstboot-command", Arg.String add_firstboot_cmd, "cmd+args" ^ " " ^ s_"Run command at first guest boot";
+@@ -260,7 +257,7 @@ let parse_cmdline () =
+ "--scrub", Arg.String add_scrub, "name" ^ " " ^ s_"Scrub a file";
+ "--size", Arg.String set_size, "size" ^ " " ^ s_"Set output disk size";
+ "--smp", Arg.Int set_smp, "vcpus" ^ " " ^ s_"Set number of vCPUs";
+- "--source", Arg.Set_string source, "URL" ^ " " ^ s_"Set source URL";
++ "--source", Arg.String add_source, "URL" ^ " " ^ s_"Set source URL";
+ "--no-sync", Arg.Clear sync, " " ^ s_"Do not fsync output file on exit";
+ "--upload", Arg.String add_upload, "file:dest" ^ " " ^ s_"Upload file to dest";
+ "-v", Arg.Set debug, " " ^ s_"Enable debugging messages";
+@@ -301,7 +298,7 @@ read the man page virt-builder(1).
+ let debug = !debug in
+ let delete = List.rev !delete in
+ let edit = List.rev !edit in
+- let fingerprint = !fingerprint in
++ let fingerprints = List.rev !fingerprints in
+ let firstboot = List.rev !firstboot in
+ let run = List.rev !run in
+ let format = match !format with "" -> None | s -> Some s in
+@@ -320,7 +317,7 @@ read the man page virt-builder(1).
+ let scrub_logfile = !scrub_logfile in
+ let size = !size in
+ let smp = !smp in
+- let source = !source in
++ let sources = List.rev !sources in
+ let sync = !sync in
+ let upload = List.rev !upload in
+ let writes = List.rev !writes in
+@@ -375,8 +372,50 @@ read the man page virt-builder(1).
+ exit 1
+ ) in
+
++ (* Check source(s) and fingerprint(s), or use environment or default. *)
++ let sources =
++ let list_split = function "" -> [] | str -> string_nsplit "," str in
++ let rec repeat x = function
++ | 0 -> [] | 1 -> [x]
++ | n -> x :: repeat x (n-1)
++ in
++
++ let sources =
++ if sources <> [] then sources
++ else (
++ try list_split (Sys.getenv "VIRT_BUILDER_SOURCE")
++ with Not_found -> [ default_source ]
++ ) in
++ let fingerprints =
++ if fingerprints <> [] then fingerprints
++ else (
++ try list_split (Sys.getenv "VIRT_BUILDER_FINGERPRINT")
++ with Not_found -> [ Sigchecker.default_fingerprint ]
++ ) in
++
++ let nr_sources = List.length sources in
++ let fingerprints =
++ match fingerprints with
++ | [fingerprint] ->
++ (* You're allowed to have multiple sources and one fingerprint: it
++ * means that the same fingerprint is used for all sources.
++ *)
++ repeat fingerprint nr_sources
++ | xs -> xs in
++
++ if List.length fingerprints <> nr_sources then (
++ eprintf (f_"%s: source and fingerprint lists are not the same length\n")
++ prog;
++ exit 1
++ );
++
++ assert (nr_sources > 0);
++
++ (* Combine the sources and fingerprints into a single list of pairs. *)
++ List.combine sources fingerprints in
++
+ mode, arg,
+- attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
++ attach, cache, check_signature, curl, debug, delete, edit,
+ firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs,
+ network, output, password_crypto, quiet, root_password, scrub,
+- scrub_logfile, size, smp, source, sync, upload, writes
++ scrub_logfile, size, smp, sources, sync, upload, writes
+diff --git a/builder/index_parser.ml b/builder/index_parser.ml
+index b5a0cf0..dc039fe 100644
+--- a/builder/index_parser.ml
++++ b/builder/index_parser.ml
+@@ -37,6 +37,8 @@ and entry = {
+ lvexpand : string option;
+ notes : string option;
+ hidden : bool;
++
++ sigchecker : Sigchecker.t;
+ }
+
+ let print_entry chan (name, { printable_name = printable_name;
+@@ -348,7 +350,8 @@ let get_index ~debug ~downloader ~sigchecker source =
+ expand = expand;
+ lvexpand = lvexpand;
+ notes = notes;
+- hidden = hidden } in
++ hidden = hidden;
++ sigchecker = sigchecker } in
+ n, entry
+ ) sections in
+
+diff --git a/builder/index_parser.mli b/builder/index_parser.mli
+index 79df5ef..0b6317d 100644
+--- a/builder/index_parser.mli
++++ b/builder/index_parser.mli
+@@ -31,6 +31,8 @@ and entry = {
+ lvexpand : string option;
+ notes : string option;
+ hidden : bool;
++
++ sigchecker : Sigchecker.t;
+ }
+
+ val get_index : debug:bool -> downloader:Downloader.t -> sigchecker:Sigchecker.t -> string -> index
+diff --git a/builder/list_entries.ml b/builder/list_entries.ml
+index b233f0e..04a65ca 100644
+--- a/builder/list_entries.ml
++++ b/builder/list_entries.ml
+@@ -21,10 +21,14 @@ open Common_utils
+
+ open Printf
+
+-let list_entries ?(list_long = false) ~source index =
++let list_entries ?(list_long = false) ~sources index =
+ if list_long then (
+- printf (f_"Source URI: %s\n") source;
+- printf "\n"
++ List.iter (
++ fun (source, fingerprint) ->
++ printf (f_"Source URI: %s\n") source;
++ printf (f_"Fingerprint: %s\n") fingerprint;
++ printf "\n"
++ ) sources
+ );
+
+ List.iter (
+diff --git a/builder/list_entries.mli b/builder/list_entries.mli
+index e1d5c06..d9486b0 100644
+--- a/builder/list_entries.mli
++++ b/builder/list_entries.mli
+@@ -16,4 +16,4 @@
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+-val list_entries : ?list_long:bool -> source:string -> Index_parser.index -> unit
++val list_entries : ?list_long:bool -> sources:(string * string) list -> Index_parser.index -> unit
+diff --git a/builder/sigchecker.ml b/builder/sigchecker.ml
+index 2bd3c11..b20a186 100644
+--- a/builder/sigchecker.ml
++++ b/builder/sigchecker.ml
+@@ -104,7 +104,7 @@ type t = {
+ check_signature : bool;
+ }
+
+-let create ~debug ~gpg ?(fingerprint = default_fingerprint) ~check_signature =
++let create ~debug ~gpg ~fingerprint ~check_signature =
+ {
+ debug = debug;
+ gpg = gpg;
+@@ -188,10 +188,9 @@ and do_verify t args =
+ exit 1
+ )
+
+-(* Import the default public key, if it's the default fingerprint. *)
++(* Import the default public key. *)
+ and import_key t =
+- if not !key_imported && equal_fingerprints t.fingerprint default_fingerprint
+- then (
++ if not !key_imported then (
+ let filename, chan = Filename.open_temp_file "vbpubkey" ".asc" in
+ unlink_on_exit filename;
+ output_string chan default_pubkey;
+diff --git a/builder/sigchecker.mli b/builder/sigchecker.mli
+index 4d89129..cdd800e 100644
+--- a/builder/sigchecker.mli
++++ b/builder/sigchecker.mli
+@@ -16,9 +16,11 @@
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
++val default_fingerprint : string
++
+ type t
+
+-val create : debug:bool -> gpg:string -> ?fingerprint:string -> check_signature:bool -> t
++val create : debug:bool -> gpg:string -> fingerprint:string -> check_signature:bool -> t
+
+ val verify : t -> string -> unit
+ (** Verify the file is signed (if check_signature is true). *)
+diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh
+index 01e4d1b..823f774 100755
+--- a/builder/test-virt-builder-list.sh
++++ b/builder/test-virt-builder-list.sh
+@@ -39,6 +39,7 @@ fi
+ long_list=$(./virt-builder --no-check-signature --no-cache --list --long)
+
+ if [ "$long_list" != "Source URI: $VIRT_BUILDER_SOURCE
++Fingerprint: F777 4FB1 AD07 4A7E 8C87 67EA 9173 8F73 E1B7 68A0
+
+ os-version: phony-debian
+ Full name: Phony Debian
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 70e19c3..4e33bc8 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -264,10 +264,14 @@ Check that the index and templates are signed by the key with the
+ given fingerprint. (The fingerprint is a long string, usually written
+ as 10 groups of 4 hexadecimal digits).
+
+-If signature checking is enabled and the I<--fingerprint> option is
+-not given, then this checks the download was signed by
+-S<F777 4FB1 AD07 4A7E 8C87 67EA 9173 8F73 E1B7 68A0> (which is
+-S<Richard W.M. Jones's> key).
++You can give this option multiple times. If you have multiple source
++URLs, then you can have either no fingerprint, one fingerprint or
++multiple fingerprints. If you have multiple, then each must
++correspond 1-1 with a source URL.
++
++The default fingerprint (if none are supplied) is
++S<F777 4FB1 AD07 4A7E 8C87 67EA 9173 8F73 E1B7 68A0>
++(which is S<Richard W.M. Jones's> key).
+
+ You can also set the C<VIRT_BUILDER_FINGERPRINT> environment variable.
+
+@@ -559,8 +563,11 @@ Enable N E<ge> 2 virtual CPUs for I<--run> scripts to use.
+
+ =item B<--source> URL
+
+-Set the source URL to look for templates. If not specified it
+-defaults to L<http://libguestfs.org/download/builder/index.asc>
++Set the source URL to look for indexes.
++
++You can give this option multiple times to specify multiple sources.
++If not specified it defaults to
++L<http://libguestfs.org/download/builder/index.asc>
+
+ See also L</CREATING YOUR OWN TEMPLATES> below.
+
+@@ -1202,6 +1209,36 @@ Now run virt-builder commands as normal, eg:
+
+ To debug problems, add the C<-v> option to these commands.
+
++=head3 Running virt-builder against multiple sources
++
++It is possible to use multiple sources with virt-builder. Use either
++multiple I<--source> and/or I<--fingerprint> options, or a
++comma-separated list in the C<VIRT_BUILDER_SOURCE> /
++C<VIRT_BUILDER_FINGERPRINT> environment variables:
++
++ virt-builder \
++ --source http://example.com/s1/index.asc \
++ --source http://example.com/s2/index.asc
++
++or equivalently:
++
++ export VIRT_BUILDER_SOURCE=http://example.com/s1/index.asc,http://example.com/s2/index.asc
++ virt-builder [...]
++
++You can provide N, 1 or 0 fingerprints. In the case where you
++provide N fingerprints, N = number of sources and there is a 1-1
++correspondence between each source and each fingerprint:
++
++ virt-builder \
++ --source http://example.com/s1/index.asc --fingerprint '0123 ...' \
++ --source http://example.com/s2/index.asc --fingerprint '9876 ...'
++
++In the case where you provide 1 fingerprint, the same fingerprint
++is used for all sources.
++
++In the case where you provide no fingerprints, the default fingerprint
++built into virt-builder is used for all sources.
++
+ =head3 Licensing of templates
+
+ You should be aware of the licensing of images that you distribute.
+@@ -1386,13 +1423,13 @@ Used to determine the location of the template cache. See L</CACHING>.
+
+ =item C<VIRT_BUILDER_FINGERPRINT>
+
+-Set the default value for the GPG signature fingerprint (see
+-I<--fingerprint> option).
++Set the default value for the GPG signature fingerprint or
++comma-separated list of fingerprints (see I<--fingerprint> option).
+
+ =item C<VIRT_BUILDER_SOURCE>
+
+-Set the default value for the source URL for the template repository
+-(see I<--source> option).
++Set the default value for the source URL (or comma-separated list of
++URLs) for the template repository (see I<--source> option).
+
+ =item C<XDG_CACHE_HOME>
+
+--
+1.8.3.1
+
diff --git a/0013-builder-Don-t-use-git-tree-libguestfs.git-to-refer-t.patch b/0013-builder-Don-t-use-git-tree-libguestfs.git-to-refer-t.patch
new file mode 100644
index 0000000..4ee60bd
--- /dev/null
+++ b/0013-builder-Don-t-use-git-tree-libguestfs.git-to-refer-t.patch
@@ -0,0 +1,39 @@
+From f1a283dc21a295d31dfb7d37ed67b1359841070c Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Mon, 4 Nov 2013 21:35:48 +0000
+Subject: [PATCH] builder: Don't use git tree / libguestfs.git to refer to the
+ source.
+
+git is just a VCS.
+
+(cherry picked from commit 3ffdddbedf176fa5f12172fb2e3c6bd4b2690f9e)
+---
+ builder/virt-builder.pod | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 4e33bc8..5eba666 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -949,7 +949,7 @@ out the information in this index file.
+
+ The templates hosted on libguestfs.org were created using shell
+ scripts, kickstart files and preseed files which can be found in the
+-libguestfs source tree, in C<libguestfs.git/builder/website>.
++libguestfs source tree, in C<builder/website>.
+
+ =head3 Setting up the repository
+
+@@ -994,8 +994,7 @@ Also find the fingerprint of your key:
+ There are many ways to create the templates. For example you could
+ clone existing guests (see L<virt-sysprep(1)>), or you could install a
+ guest by hand (L<virt-install(1)>). To see how the templates were
+-created for virt-builder, look at the scripts in
+-C<libguestfs.git/builder/website>
++created for virt-builder, look at the scripts in C<builder/website>
+
+ For best results when compressing the templates, use the following xz
+ options (see L<nbdkit-xz-plugin(1)> for further explanation):
+--
+1.8.3.1
+
diff --git a/0014-builder-Add-a-real-scanner-parser-for-index-files.patch b/0014-builder-Add-a-real-scanner-parser-for-index-files.patch
new file mode 100644
index 0000000..74852a7
--- /dev/null
+++ b/0014-builder-Add-a-real-scanner-parser-for-index-files.patch
@@ -0,0 +1,1232 @@
+From 4785b527ce69d0aa1c7983f81a70f30d9837ee88 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Mon, 4 Nov 2013 14:53:41 +0000
+Subject: [PATCH] builder: Add a real scanner/parser for index files.
+
+This adds a tool called virt-index-validate to validate index files.
+
+(cherry picked from commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633)
+---
+ .gitignore | 7 ++
+ README | 4 +
+ builder/Makefile.am | 56 +++++++++----
+ builder/index-parse.y | 123 +++++++++++++++++++++++++++++
+ builder/index-parser-c.c | 105 +++++++++++++++++++++++++
+ builder/index-scan.l | 103 ++++++++++++++++++++++++
+ builder/index-struct.c | 58 ++++++++++++++
+ builder/index-struct.h | 48 ++++++++++++
+ builder/index-validate.c | 161 ++++++++++++++++++++++++++++++++++++++
+ builder/index_parser.ml | 143 ++++-----------------------------
+ builder/list_entries.ml | 2 +-
+ builder/test-virt-builder-list.sh | 12 ++-
+ builder/virt-builder.pod | 17 ++++
+ builder/virt-index-validate.pod | 92 ++++++++++++++++++++++
+ configure.ac | 4 +
+ po-docs/ja/Makefile.am | 1 +
+ po-docs/podfiles | 1 +
+ po-docs/uk/Makefile.am | 1 +
+ po/POTFILES | 5 ++
+ 19 files changed, 793 insertions(+), 150 deletions(-)
+ create mode 100644 builder/index-parse.y
+ create mode 100644 builder/index-parser-c.c
+ create mode 100644 builder/index-scan.l
+ create mode 100644 builder/index-struct.c
+ create mode 100644 builder/index-struct.h
+ create mode 100644 builder/index-validate.c
+ create mode 100644 builder/virt-index-validate.pod
+
+diff --git a/.gitignore b/.gitignore
+index 8a1ffef..e2ea9ce 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -58,10 +58,16 @@ Makefile.in
+ /bash/virt-sparsify
+ /build-aux
+ /builder/.depend
++/builder/index-parse.c
++/builder/index-parse.h
++/builder/index-scan.c
+ /builder/stamp-virt-builder.pod
++/builder/stamp-virt-index-validate.pod
+ /builder/test-index
+ /builder/virt-builder
+ /builder/virt-builder.1
++/builder/virt-index-validate
++/builder/virt-index-validate.1
+ /builder/*.xz
+ /cat/stamp-virt-*.pod
+ /cat/virt-cat
+@@ -224,6 +230,7 @@ Makefile.in
+ /html/virt-edit.1.html
+ /html/virt-filesystems.1.html
+ /html/virt-format.1.html
++/html/virt-index-validate.1.html
+ /html/virt-inspector.1.html
+ /html/virt-list-filesystems.1.html
+ /html/virt-list-partitions.1.html
+diff --git a/README b/README
+index cdf492e..461915d 100644
+--- a/README
++++ b/README
+@@ -94,6 +94,10 @@ The full requirements are described below.
+ +--------------+-------------+---+-----------------------------------------+
+ | gperf | | R | |
+ +--------------+-------------+---+-----------------------------------------+
++| flex | | R | flex & bison are required for virt- |
+++--------------+-------------+---| builder. We could make these |
++| bison | | R | optional but automakes makes it hard. |
+++--------------+-------------+---+-----------------------------------------+
+ | PCRE | | R | Perl-compatible Regular Expression lib. |
+ +--------------+-------------+---+-----------------------------------------+
+ | genisoimage | | R | mkisofs may work. |
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index b995c90..cb490e1 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -17,6 +17,12 @@
+
+ include $(top_srcdir)/subdir-rules.mk
+
++AM_YFLAGS = -d
++AM_CFLAGS = \
++ -I$(shell $(OCAMLC) -where) \
++ -I$(top_srcdir)/src \
++ -I$(top_srcdir)/fish
++
+ EXTRA_DIST = \
+ $(SOURCES) \
+ virt-builder.pod \
+@@ -71,6 +77,9 @@ SOURCES = \
+ sigchecker.mli \
+ sigchecker.ml
+
++man_MANS =
++noinst_DATA =
++
+ if HAVE_OCAML
+
+ # Note this list must be in dependency order.
+@@ -87,6 +96,10 @@ OBJECTS = \
+ $(top_builddir)/mllib/fsync.cmx \
+ $(top_builddir)/mllib/password.cmx \
+ $(top_builddir)/mllib/config.cmx \
++ index-scan.o \
++ index-struct.o \
++ index-parse.o \
++ index-parser-c.o \
+ get_kernel.cmx \
+ downloader.cmx \
+ sigchecker.cmx \
+@@ -127,24 +140,10 @@ virt-builder: $(OBJECTS)
+ .ml.cmx:
+ $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) -c $< -o $@
+
+-# automake will decide we don't need C support in this file. Really
+-# we do, so we have to provide it ourselves.
+-
+-DEFAULT_INCLUDES = \
+- -I. \
+- -I$(top_builddir) \
+- -I$(shell $(OCAMLC) -where) \
+- -I$(top_srcdir)/src \
+- -I$(top_srcdir)/fish
+-
+-.c.o:
+- $(CC) $(CFLAGS) $(PROF_CFLAGS) $(DEFAULT_INCLUDES) -c $< -o $@
+-
+ # Manual pages and HTML files for the website.
+
+-man_MANS = virt-builder.1
+-
+-noinst_DATA = $(top_builddir)/html/virt-builder.1.html
++man_MANS += virt-builder.1
++noinst_DATA += $(top_builddir)/html/virt-builder.1.html
+
+ virt-builder.1 $(top_builddir)/html/virt-builder.1.html: stamp-virt-builder.pod
+
+@@ -200,3 +199,28 @@ endif
+ DISTCLEANFILES = .depend
+
+ .PHONY: depend docs
++
++# Build a small C index validator program.
++bin_PROGRAMS = virt-index-validate
++
++virt_index_validate_SOURCES = \
++ index-parse.y \
++ index-scan.l \
++ index-struct.h \
++ index-struct.c \
++ index-validate.c
++
++man_MANS += virt-index-validate.1
++noinst_DATA += $(top_builddir)/html/virt-index-validate.1.html
++
++virt-index-validate.1 $(top_builddir)/html/virt-index-validate.1.html: stamp-virt-index-validate.pod
++
++stamp-virt-index-validate.pod: virt-index-validate.pod
++ $(PODWRAPPER) \
++ --man virt-index-validate.1 \
++ --html $(top_builddir)/html/virt-index-validate.1.html \
++ --license GPLv2+ \
++ $<
++ touch $@
++
++CLEANFILES += stamp-virt-index-validate.pod
+diff --git a/builder/index-parse.y b/builder/index-parse.y
+new file mode 100644
+index 0000000..f5e551b
+--- /dev/null
++++ b/builder/index-parse.y
+@@ -0,0 +1,123 @@
++/* libguestfs virt-builder tool -*- fundamental -*-
++ * 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.
++ */
++
++%{
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include "index-struct.h"
++
++extern void yyerror (const char *);
++extern int yylex (void);
++
++/* Join two strings with \n */
++static char *
++concat_newline (const char *str1, const char *str2)
++{
++ size_t len1, len2, len;
++ char *ret;
++
++ if (str2 == NULL)
++ return strdup (str1);
++
++ len1 = strlen (str1);
++ len2 = strlen (str2);
++ len = len1 + 1 /* \n */ + len2 + 1 /* \0 */;
++ ret = malloc (len);
++ memcpy (ret, str1, len1);
++ ret[len1] = '\n';
++ memcpy (ret + len1 + 1, str2, len2);
++ ret[len-1] = '\0';
++
++ return ret;
++}
++
++%}
++
++%locations
++
++%union {
++ struct section *section;
++ struct field *field;
++ char *str;
++}
++
++%token <str> SECTION_HEADER
++%token <field> FIELD
++%token <str> VALUE_CONT
++%token EMPTY_LINE
++%token PGP_PROLOGUE
++%token PGP_EPILOGUE
++
++%type <section> sections section
++%type <field> fields field
++%type <str> continuations
++
++%%
++
++index:
++ sections
++ { parsed_index = $1; }
++ | PGP_PROLOGUE sections PGP_EPILOGUE
++ { parsed_index = $2; }
++
++sections:
++ section
++ { $$ = $1; }
++ | section EMPTY_LINE sections
++ { $$ = $1; $$->next = $3; }
++
++section:
++ SECTION_HEADER fields
++ { $$ = malloc (sizeof (struct section));
++ $$->next = NULL;
++ $$->name = $1;
++ $$->fields = $2; }
++
++fields:
++ /* empty */
++ { $$ = NULL; }
++ | field fields
++ { $$ = $1; $$->next = $2; }
++
++field: FIELD continuations
++ { $$ = $1;
++ char *old_value = $$->value;
++ $$->value = concat_newline (old_value, $2);
++ free (old_value);
++ free ($2); }
++
++continuations:
++ /* empty */
++ { $$ = NULL; }
++ | VALUE_CONT continuations
++ { $$ = concat_newline ($1, $2);
++ free ($1);
++ free ($2); }
++
++%%
++
++void
++yyerror (const char *msg)
++{
++ fprintf (stderr, "syntax error at line %d: %s\n",
++ yylloc.first_line, msg);
++}
+diff --git a/builder/index-parser-c.c b/builder/index-parser-c.c
+new file mode 100644
+index 0000000..17e680b
+--- /dev/null
++++ b/builder/index-parser-c.c
+@@ -0,0 +1,105 @@
++/* virt-builder
++ * Copyright (C) 2013 Red Hat Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++/* This file handles the interface between the C/lex/yacc index file
++ * parser, and the OCaml world. See index_parser.ml for the OCaml
++ * type definition.
++ */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <unistd.h>
++
++#include <caml/alloc.h>
++#include <caml/fail.h>
++#include <caml/memory.h>
++#include <caml/mlvalues.h>
++
++#ifdef HAVE_CAML_UNIXSUPPORT_H
++#include <caml/unixsupport.h>
++#else
++#define Nothing ((value) 0)
++extern void unix_error (int errcode, char * cmdname, value arg) Noreturn;
++#endif
++
++#include "index-struct.h"
++#include "index-parse.h"
++
++extern FILE *yyin;
++
++value
++virt_builder_parse_index (value filenamev)
++{
++ CAMLparam1 (filenamev);
++ CAMLlocal4 (rv, v, sv, fv);
++ struct section *sections;
++ size_t i, nr_sections;
++
++ yyin = fopen (String_val (filenamev), "r");
++ if (yyin == NULL)
++ unix_error (errno, (char *) "fopen", filenamev);
++
++ if (yyparse () != 0) {
++ fclose (yyin);
++ caml_invalid_argument ("parse error");
++ }
++
++ if (fclose (yyin) == EOF)
++ unix_error (errno, (char *) "fclose", filenamev);
++
++ /* Convert the parsed data to OCaml structures. */
++ nr_sections = 0;
++ for (sections = parsed_index; sections != NULL; sections = sections->next)
++ nr_sections++;
++ rv = caml_alloc (nr_sections, 0);
++
++ for (i = 0, sections = parsed_index; sections != NULL;
++ i++, sections = sections->next) {
++ struct field *fields;
++ size_t j, nr_fields;
++
++ nr_fields = 0;
++ for (fields = sections->fields; fields != NULL; fields = fields->next)
++ nr_fields++;
++ fv = caml_alloc (nr_fields, 0);
++
++ for (j = 0, fields = sections->fields; fields != NULL;
++ j++, fields = fields->next) {
++ v = caml_alloc_tuple (2);
++ sv = caml_copy_string (fields->key);
++ Store_field (v, 0, sv); /* (key, value) */
++ sv = caml_copy_string (fields->value);
++ Store_field (v, 1, sv);
++ Store_field (fv, j, v); /* assign to return array of fields */
++ }
++
++ v = caml_alloc_tuple (2);
++ sv = caml_copy_string (sections->name);
++ Store_field (v, 0, sv); /* (name, fields) */
++ Store_field (v, 1, fv);
++ Store_field (rv, i, v); /* assign to return array of sections */
++ }
++
++ /* Free parsed global data. */
++ free_index ();
++
++ CAMLreturn (rv);
++}
+diff --git a/builder/index-scan.l b/builder/index-scan.l
+new file mode 100644
+index 0000000..9a6a0e3
+--- /dev/null
++++ b/builder/index-scan.l
+@@ -0,0 +1,103 @@
++/* libguestfs virt-builder tool -*- fundamental -*-
++ * 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.
++ */
++
++%{
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include "index-parse.h"
++#include "index-struct.h"
++
++#define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno;
++
++extern void yyerror (const char *);
++
++%}
++
++%option noyywrap
++%option yylineno
++
++%%
++
++ /* Apart from the PGP prologue/epilogue which is a hack, the
++ * scanning strategy is to deal with the file strictly line by
++ * line, and pass those lines up to the parser which deals with
++ * whether they appear in the right order to be meaningful.
++ * Note that flex does longest-match.
++ */
++
++ /* Ignore comments - '#' MUST appear at the start of a line. */
++^"#".*\n { seen_comments++; }
++
++ /* An empty line is significant. */
++^\n { return EMPTY_LINE; }
++
++ /* [...] marks beginning of a section. */
++^"["[-A-Za-z0-9.]+"]"\n {
++ yylval.str = strndup (yytext+1, yyleng-3);
++ return SECTION_HEADER;
++ }
++
++ /* field=value or field[subfield]=value */
++^[A-Za-z0-9_.]+("["[A-Za-z0-9_,.]+"]")?"=".*\n {
++ size_t i = strcspn (yytext, "=");
++ yylval.field = malloc (sizeof (struct field));
++ yylval.field->next = NULL;
++ yylval.field->key = strndup (yytext, i);
++ /* Note we chop the final \n off here. */
++ yylval.field->value = strndup (yytext+i+1, yyleng-(i+2));
++ return FIELD;
++ }
++
++ /* Continuation line for multi-line values. */
++^[[:blank:]].*\n {
++ yylval.str = strndup (yytext+1, yyleng-2);
++ return VALUE_CONT;
++ }
++
++ /* Hack to eat the PGP prologue. */
++^"-----BEGIN PGP SIGNED MESSAGE-----\n" {
++ int c, prevnl = 0;
++
++ /* Eat everything to the first blank line. */
++ while ((c = input ()) != EOF) {
++ if (c == '\n' && prevnl)
++ break;
++ prevnl = c == '\n';
++ }
++
++ return PGP_PROLOGUE;
++}
++
++ /* Hack to eat the PGP epilogue. */
++^"-----BEGIN PGP SIGNATURE-----\n" {
++ /* Eat everything to the end of the file. */
++ while (input () != EOF)
++ ;
++
++ return PGP_EPILOGUE;
++}
++
++ /* anything else is an error */
++. {
++ yyerror ("unexpected character in input");
++ exit (EXIT_FAILURE);
++}
+diff --git a/builder/index-struct.c b/builder/index-struct.c
+new file mode 100644
+index 0000000..26bed24
+--- /dev/null
++++ b/builder/index-struct.c
+@@ -0,0 +1,58 @@
++/* libguestfs virt-builder tool
++ * 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.
++ */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++
++#include "index-struct.h"
++
++struct section *parsed_index = NULL;
++int seen_comments = 0;
++
++static void free_section (struct section *section);
++static void free_field (struct field *field);
++
++void
++free_index (void)
++{
++ free_section (parsed_index);
++}
++
++static void
++free_section (struct section *section)
++{
++ if (section) {
++ free_section (section->next);
++ free (section->name);
++ free_field (section->fields);
++ free (section);
++ }
++}
++
++static void
++free_field (struct field *field)
++{
++ if (field) {
++ free_field (field->next);
++ free (field->key);
++ free (field->value);
++ free (field);
++ }
++}
+diff --git a/builder/index-struct.h b/builder/index-struct.h
+new file mode 100644
+index 0000000..ac8a3dd
+--- /dev/null
++++ b/builder/index-struct.h
+@@ -0,0 +1,48 @@
++/* libguestfs virt-builder tool
++ * 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.
++ */
++
++/* The data structures produced when parsing the index file. */
++
++#ifndef INDEX_STRUCT_H
++#define INDEX_STRUCT_H
++
++/* A section or list of sections. */
++struct section {
++ struct section *next;
++ char *name;
++ struct field *fields;
++};
++
++/* A field or list of fields. */
++struct field {
++ struct field *next;
++ char *key;
++ char *value;
++};
++
++/* The parser (yyparse) stores the result here. */
++extern struct section *parsed_index;
++
++/* yyparse sets this if any comments were seen. Required for checking
++ * compatibility with virt-builder 1.24.
++ */
++extern int seen_comments;
++
++extern void free_index (void);
++
++#endif /* INDEX_STRUCT_H */
+diff --git a/builder/index-validate.c b/builder/index-validate.c
+new file mode 100644
+index 0000000..d156c43
+--- /dev/null
++++ b/builder/index-validate.c
+@@ -0,0 +1,161 @@
++/* libguestfs virt-builder tool
++ * 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.
++ */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <limits.h>
++#include <getopt.h>
++#include <errno.h>
++#include <libintl.h>
++
++#include <guestfs.h>
++
++#include "guestfs-internal-frontend.h"
++
++#include "index-struct.h"
++#include "index-parse.h"
++
++extern FILE *yyin;
++
++static void
++usage (int exit_status)
++{
++ printf ("%s index\n", program_name);
++ exit (exit_status);
++}
++
++int
++main (int argc, char *argv[])
++{
++ enum { HELP_OPTION = CHAR_MAX + 1 };
++ static const char *options = "V";
++ static const struct option long_options[] = {
++ { "help", 0, 0, HELP_OPTION },
++ { "compat-1.24.0", 0, 0, 0 },
++ { "compat-1.24.1", 0, 0, 0 },
++ { "version", 0, 0, 'V' },
++ { 0, 0, 0, 0 }
++ };
++ int c;
++ int option_index;
++ int compat_1_24_0 = 0;
++ int compat_1_24_1 = 0;
++ const char *input;
++ struct section *sections;
++
++ for (;;) {
++ c = getopt_long (argc, argv, options, long_options, &option_index);
++ if (c == -1) break;
++
++ switch (c) {
++ case 0: /* options which are long only */
++ if (STREQ (long_options[option_index].name, "compat-1.24.0"))
++ compat_1_24_0 = compat_1_24_1 = 1;
++ else if (STREQ (long_options[option_index].name, "compat-1.24.1"))
++ compat_1_24_1 = 1;
++ else {
++ fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
++ program_name, long_options[option_index].name, option_index);
++ exit (EXIT_FAILURE);
++ }
++ break;
++
++ case 'V':
++ printf ("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
++ exit (EXIT_SUCCESS);
++
++ case HELP_OPTION:
++ usage (EXIT_SUCCESS);
++
++ default:
++ usage (EXIT_FAILURE);
++ }
++ }
++
++ if (optind != argc-1)
++ usage (EXIT_FAILURE);
++
++ input = argv[optind++];
++
++ yyin = fopen (input, "r");
++ if (yyin == NULL) {
++ perror (input);
++ exit (EXIT_FAILURE);
++ }
++
++ if (yyparse () != 0) {
++ fprintf (stderr, _("%s: '%s' could not be validated, see errors above\n"),
++ program_name, input);
++ exit (EXIT_FAILURE);
++ }
++
++ if (fclose (yyin) == EOF) {
++ fprintf (stderr, _("%s: %s: error reading input file: %m\n"),
++ program_name, input);
++ exit (EXIT_FAILURE);
++ }
++
++ if (compat_1_24_1 && seen_comments) {
++ fprintf (stderr, _("%s: %s contains comments which will not work with virt-builder 1.24.1\n"),
++ program_name, input);
++ exit (EXIT_FAILURE);
++ }
++
++ /* Iterate over the parsed sections, semantically validating it. */
++ for (sections = parsed_index; sections != NULL; sections = sections->next) {
++ int seen_sig = 0;
++ struct field *fields;
++
++ for (fields = sections->fields; fields != NULL; fields = fields->next) {
++ if (compat_1_24_0) {
++ if (strchr (fields->key, '[') ||
++ strchr (fields->key, ']')) {
++ fprintf (stderr, _("%s: %s: section [%s], field '%s' has invalid characters which will not work with virt-builder 1.24.0\n"),
++ program_name, input, sections->name, fields->key);
++ exit (EXIT_FAILURE);
++ }
++ }
++ if (compat_1_24_1) {
++ if (strchr (fields->key, '.') ||
++ strchr (fields->key, ',')) {
++ fprintf (stderr, _("%s: %s: section [%s], field '%s' has invalid characters which will not work with virt-builder 1.24.1\n"),
++ program_name, input, sections->name, fields->key);
++ exit (EXIT_FAILURE);
++ }
++ }
++ if (STREQ (fields->key, "sig"))
++ seen_sig = 1;
++ }
++
++ if (compat_1_24_0 && !seen_sig) {
++ fprintf (stderr, _("%s: %s: section [%s] is missing a 'sig' field which will not work with virt-builder 1.24.0\n"),
++ program_name, input, sections->name);
++ exit (EXIT_FAILURE);
++ }
++ }
++
++ /* Free the parsed data. */
++ free_index ();
++
++ printf ("%s validated OK\n", input);
++
++ exit (EXIT_SUCCESS);
++}
+diff --git a/builder/index_parser.ml b/builder/index_parser.ml
+index dc039fe..fb47e50 100644
+--- a/builder/index_parser.ml
++++ b/builder/index_parser.ml
+@@ -97,14 +97,17 @@ let print_entry chan (name, { printable_name = printable_name;
+ );
+ if hidden then fp "hidden=true\n"
+
+-let fieldname_rex = Str.regexp "^\\([][a-z0-9_]+\\)=\\(.*\\)$"
++(* Types returned by the C index parser. *)
++type sections = section array
++and section = string * fields (* [name] + fields *)
++and fields = field array
++and field = string * string (* key + value *)
++
++(* Calls yyparse in the C code. *)
++external parse_index : string -> sections = "virt_builder_parse_index"
+
+ let get_index ~debug ~downloader ~sigchecker source =
+- let rec corrupt_line line =
+- eprintf (f_"virt-builder: error parsing index near this line:\n\n%s\n")
+- line;
+- corrupt_file ()
+- and corrupt_file () =
++ let corrupt_file () =
+ eprintf (f_"\nThe index file downloaded from '%s' is corrupt.\nYou need to ask the supplier of this file to fix it and upload a fixed version.\n")
+ source;
+ exit 1
+@@ -119,133 +122,15 @@ let get_index ~debug ~downloader ~sigchecker source =
+ *)
+ Sigchecker.verify sigchecker tmpfile;
+
+- (* Check the index page is not too huge. *)
+- let st = stat tmpfile in
+- if st.st_size > 1_000_000 then (
+- eprintf (f_"virt-builder: index page '%s' is too large (size %d bytes)\n")
+- source st.st_size;
+- exit 1
+- );
+-
+- (* Load the file into memory. *)
+- let index = read_whole_file tmpfile in
++ (* Try parsing the file. *)
++ let sections = parse_index tmpfile in
+ if delete_tmpfile then
+ (try Unix.unlink tmpfile with _ -> ());
+
+- (* Split file into lines. *)
+- let index = string_nsplit "\n" index in
+-
+- (* If there is a signature (checked above) then remove it. *)
+- let index =
+- match index with
+- | "-----BEGIN PGP SIGNED MESSAGE-----" :: lines ->
+- (* Ignore all lines until we get to first blank. *)
+- let lines = dropwhile ((<>) "") lines in
+- (* Ignore the blank line too. *)
+- let lines = List.tl lines in
+- (* Take lines until we get to the end signature. *)
+- let lines = takewhile ((<>) "-----BEGIN PGP SIGNATURE-----") lines in
+- lines
+- | _ -> index in
+-
+- (* Split into sections around each /^[/ *)
+- let rec loop = function
+- | [] -> []
+- | x :: xs when String.length x >= 1 && x.[0] = '[' ->
+- let lines = takewhile ((<>) "") xs in
+- let rest = dropwhile ((<>) "") xs in
+- if rest = [] then
+- [x, lines]
+- else (
+- let rest = List.tl rest in
+- let rest = loop rest in
+- (x, lines) :: rest
+- )
+- | x :: _ -> corrupt_line x
+- in
+- let sections = loop index in
+-
+- (* Parse the fields in each section. *)
+- let isspace = function ' ' | '\t' -> true | _ -> false in
+- let starts_space str = String.length str >= 1 && isspace str.[0] in
+- let rec loop = function
+- | [] -> []
+- | x :: xs when not (starts_space x) && String.contains x '=' ->
+- let xs' = takewhile starts_space xs in
+- let ys = dropwhile starts_space xs in
+- (x :: xs') :: loop ys
+- | x :: _ -> corrupt_line x
+- in
+- let sections = List.map (fun (n, lines) -> n, loop lines) sections in
+-
+- if debug then (
+- eprintf "index file (%s) after splitting:\n" source;
+- List.iter (
+- fun (n, fields) ->
+- eprintf " os-version: %s\n" n;
+- let i = ref 0 in
+- List.iter (
+- fun field ->
+- eprintf " %d: " !i;
+- List.iter prerr_endline field;
+- incr i
+- ) fields
+- ) sections
+- );
+-
+- (* Now we've parsed the file into the correct sections, we
+- * interpret the meaning of the fields.
+- *)
++ let sections = Array.to_list sections in
+ let sections = List.map (
+ fun (n, fields) ->
+- let len = String.length n in
+- if len < 3 || n.[0] <> '[' || n.[len-1] <> ']' then
+- corrupt_line n;
+- let n = String.sub n 1 (len-2) in
+-
+- let fields = List.map (
+- function
+- | [] -> assert false (* can never happen, I think? *)
+- | x :: xs when Str.string_match fieldname_rex x 0 ->
+- let field = Str.matched_group 1 x in
+- let rest_of_line = Str.matched_group 2 x in
+- let allow_multiline =
+- match field with
+- | "name" -> false
+- | "osinfo" -> false
+- | "file" -> false
+- | "sig" -> false
+- | "checksum" | "checksum[sha512]" -> false
+- | "revision" -> false
+- | "format" -> false
+- | "size" -> false
+- | "compressed_size" -> false
+- | "expand" -> false
+- | "lvexpand" -> false
+- | "notes" -> true
+- | "hidden" -> false
+- | _ ->
+- if debug then
+- eprintf "warning: unknown field '%s' in index (ignored)\n%!"
+- field;
+- true in
+- let value =
+- if not allow_multiline then (
+- if xs <> [] then (
+- eprintf (f_"virt-builder: field '%s' cannot span multiple lines\n")
+- field;
+- corrupt_line (List.hd xs)
+- );
+- rest_of_line
+- ) else (
+- String.concat "\n" (rest_of_line :: xs)
+- ) in
+- field, value
+- | x :: _ ->
+- corrupt_line x
+- ) fields in
+-
+- (n, fields)
++ n, Array.to_list fields
+ ) sections in
+
+ (* Check for repeated os-version names. *)
+@@ -356,7 +241,7 @@ let get_index ~debug ~downloader ~sigchecker source =
+ ) sections in
+
+ if debug then (
+- eprintf "index file (%s) after parsing:\n" source;
++ eprintf "index file (%s) after parsing (C parser):\n" source;
+ List.iter (print_entry Pervasives.stderr) entries
+ );
+
+diff --git a/builder/list_entries.ml b/builder/list_entries.ml
+index 04a65ca..8c24fe2 100644
+--- a/builder/list_entries.ml
++++ b/builder/list_entries.ml
+@@ -62,7 +62,7 @@ let list_entries ?(list_long = false) ~sources index =
+ | None -> ()
+ | Some notes ->
+ printf "\n";
+- printf "Notes:\n %s\n" notes
++ printf "Notes:\n\n%s\n" notes
+ );
+ printf "\n"
+ )
+diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh
+index 823f774..0a7c0d4 100755
+--- a/builder/test-virt-builder-list.sh
++++ b/builder/test-virt-builder-list.sh
+@@ -46,28 +46,32 @@ Full name: Phony Debian
+ Minimum/default size: 512.0M
+
+ Notes:
+- Phony Debian look-alike used for testing.
++
++Phony Debian look-alike used for testing.
+
+ os-version: phony-fedora
+ Full name: Phony Fedora
+ Minimum/default size: 1.0G
+
+ Notes:
+- Phony Fedora look-alike used for testing.
++
++Phony Fedora look-alike used for testing.
+
+ os-version: phony-ubuntu
+ Full name: Phony Ubuntu
+ Minimum/default size: 512.0M
+
+ Notes:
+- Phony Ubuntu look-alike used for testing.
++
++Phony Ubuntu look-alike used for testing.
+
+ os-version: phony-windows
+ Full name: Phony Windows
+ Minimum/default size: 512.0M
+
+ Notes:
+- Phony Windows look-alike used for testing." ]; then
++
++Phony Windows look-alike used for testing." ]; then
+ echo "$0: unexpected --list --long output:"
+ echo "$long_list"
+ exit 1
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 5eba666..6497c0a 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -1245,6 +1245,23 @@ For open source guests, provide a link to the source code in the
+ C<notes> field and comply with other requirements (eg. around
+ trademarks).
+
++=head3 Formal specification of the index file
++
++The index file format has a formal specification defined by the flex
++scanner and bison parser used to parse the file. This can be found in
++the following files in the libguestfs source tree:
++
++ builder/index-scan.l
++ builder/index-parse.y
++
++A tool called L<virt-index-validate(1)> is available to validate the
++index file to ensure it is correct.
++
++Note that the parser and tool can work on either the signed or
++unsigned index file (ie. C<index> or C<index.asc>).
++
++The index is always encoded in UTF-8.
++
+ =head2 CACHING
+
+ Since the templates are usually very large, downloaded templates are
+diff --git a/builder/virt-index-validate.pod b/builder/virt-index-validate.pod
+new file mode 100644
+index 0000000..6b03703
+--- /dev/null
++++ b/builder/virt-index-validate.pod
+@@ -0,0 +1,92 @@
++=encoding utf8
++
++=head1 NAME
++
++virt-index-validate - Validate virt-builder index file
++
++=head1 SYNOPSIS
++
++ virt-index-validate index
++
++=head1 DESCRIPTION
++
++L<virt-builder(1)> uses an index file to store metadata about templates
++that it knows how to use. This index file has a specific format which
++virt-index-validate knows how to validate.
++
++Note that virt-index-validate can validate either the signed or
++unsigned index file (ie. either C<index> or C<index.asc>). It can
++only validate a local file, not a URL.
++
++=head1 OPTIONS
++
++=over 4
++
++=item B<--compat-1.24.0>
++
++Check for compatibility with virt-builder 1.24.0. (Using this option
++implies I<--compat-1.24.1>, so you don't need to use both.)
++
++In particular:
++
++=over 4
++
++=item *
++
++This version of virt-builder could not handle C<[...]>
++(square brackets) in field names (eg. C<checksum[sha512]=...>).
++
++=item *
++
++It required detached signatures (C<sig=...>).
++
++=back
++
++=item B<--compat-1.24.1>
++
++Check for compatibility with virt-builder E<ge> 1.24.1.
++
++In particular:
++
++=over 4
++
++=item *
++
++This version of virt-builder could not handle C<.> (period) in field
++names or C<,> (comma) in subfield names.
++
++=item *
++
++It could not handle comments appearing in the file.
++
++=back
++
++=item B<--help>
++
++Display help.
++
++=item B<-V>
++
++=item B<--version>
++
++Display version number and exit.
++
++=back
++
++=head1 EXIT STATUS
++
++This program returns 0 if the index file validates, or non-zero if
++there was an error.
++
++=head1 SEE ALSO
++
++L<virt-builder(1)>,
++L<http://libguestfs.org/>.
++
++=head1 AUTHOR
++
++Richard W.M. Jones L<http://people.redhat.com/~rjones/>
++
++=head1 COPYRIGHT
++
++Copyright (C) 2013 Red Hat Inc.
+diff --git a/configure.ac b/configure.ac
+index 00cb151..30040e0 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -705,6 +705,10 @@ test "x$XZCAT" = "xno" && AC_MSG_ERROR([xzcat must be installed])
+ dnl Check for pxzcat (optional).
+ AC_PATH_PROGS([PXZCAT],[pxzcat],[no])
+
++dnl (f)lex and bison are required for virt-builder.
++AC_PROG_LEX
++AC_PROG_YACC
++
+ dnl Check for QEMU for running binaries on this $host_cpu, fall
+ dnl back to basic 'qemu'. Allow the user to override it.
+ qemu_system="$(
+diff --git a/po-docs/ja/Makefile.am b/po-docs/ja/Makefile.am
+index b053be0..f74ee42 100644
+--- a/po-docs/ja/Makefile.am
++++ b/po-docs/ja/Makefile.am
+@@ -60,6 +60,7 @@ MANPAGES = \
+ virt-edit.1 \
+ virt-filesystems.1 \
+ virt-format.1 \
++ virt-index-validate.1 \
+ virt-inspector.1 \
+ virt-list-filesystems.1 \
+ virt-list-partitions.1 \
+diff --git a/po-docs/podfiles b/po-docs/podfiles
+index 5ff9447..dd2898c 100644
+--- a/po-docs/podfiles
++++ b/po-docs/podfiles
+@@ -1,6 +1,7 @@
+ ../align/virt-alignment-scan.pod
+ ../appliance/libguestfs-make-fixed-appliance.pod
+ ../builder/virt-builder.pod
++../builder/virt-index-validate.pod
+ ../cat/virt-cat.pod
+ ../cat/virt-filesystems.pod
+ ../cat/virt-ls.pod
+diff --git a/po-docs/uk/Makefile.am b/po-docs/uk/Makefile.am
+index b053be0..f74ee42 100644
+--- a/po-docs/uk/Makefile.am
++++ b/po-docs/uk/Makefile.am
+@@ -60,6 +60,7 @@ MANPAGES = \
+ virt-edit.1 \
+ virt-filesystems.1 \
+ virt-format.1 \
++ virt-index-validate.1 \
+ virt-inspector.1 \
+ virt-list-filesystems.1 \
+ virt-list-partitions.1 \
+diff --git a/po/POTFILES b/po/POTFILES
+index a766f64..aa52b75 100644
+--- a/po/POTFILES
++++ b/po/POTFILES
+@@ -1,4 +1,9 @@
+ align/scan.c
++builder/index-parse.c
++builder/index-parser-c.c
++builder/index-scan.c
++builder/index-struct.c
++builder/index-validate.c
+ cat/cat.c
+ cat/filesystems.c
+ cat/ls.c
+--
+1.8.3.1
+
diff --git a/0015-builder-Fix-check-valgrind-so-it-does-something-in-t.patch b/0015-builder-Fix-check-valgrind-so-it-does-something-in-t.patch
new file mode 100644
index 0000000..78259cc
--- /dev/null
+++ b/0015-builder-Fix-check-valgrind-so-it-does-something-in-t.patch
@@ -0,0 +1,41 @@
+From a6f859302b6d7781ccb698ee8592bd16a4a28857 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Mon, 4 Nov 2013 22:13:23 +0000
+Subject: [PATCH] builder: Fix 'check-valgrind' so it does something in this
+ directory.
+
+(cherry picked from commit 2dca9d719434f6783e11976699e45a98128ca913)
+---
+ builder/test-virt-builder-list.sh | 2 +-
+ builder/test-virt-builder.sh | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh
+index 0a7c0d4..11305a9 100755
+--- a/builder/test-virt-builder-list.sh
++++ b/builder/test-virt-builder-list.sh
+@@ -25,7 +25,7 @@ abs_srcdir=$(cd $srcdir && pwd)
+
+ export VIRT_BUILDER_SOURCE=file://$abs_srcdir/test-index
+
+-short_list=$(./virt-builder --no-check-signature --no-cache --list)
++short_list=$($VG ./virt-builder --no-check-signature --no-cache --list)
+
+ if [ "$short_list" != "phony-debian Phony Debian
+ phony-fedora Phony Fedora
+diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh
+index 159f013..6296d16 100755
+--- a/builder/test-virt-builder.sh
++++ b/builder/test-virt-builder.sh
+@@ -49,7 +49,7 @@ rm -f $output
+ # Note we cannot test --install, --run since the phony Fedora doesn't
+ # have a real OS inside just some configuration files. Just about
+ # every other option is fair game.
+-./virt-builder phony-fedora \
++$VG ./virt-builder phony-fedora \
+ -v --no-cache --no-check-signature $no_network \
+ -o $output --size 2G --format $format \
+ --hostname test.example.com \
+--
+1.8.3.1
+
diff --git a/0016-builder-Fix-missing-files-in-EXTRA_DIST.patch b/0016-builder-Fix-missing-files-in-EXTRA_DIST.patch
new file mode 100644
index 0000000..88cf641
--- /dev/null
+++ b/0016-builder-Fix-missing-files-in-EXTRA_DIST.patch
@@ -0,0 +1,35 @@
+From 736e8d289efb5a1e749dc9961fcc4fd519fa8b4c Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 07:15:19 +0000
+Subject: [PATCH] builder: Fix missing files in EXTRA_DIST.
+
+This fixes commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633.
+
+(cherry picked from commit 2035a75d66676c5fb2cc047a36c174dd953cd1b9)
+---
+ builder/Makefile.am | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index cb490e1..9dbe51e 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -26,6 +26,7 @@ AM_CFLAGS = \
+ EXTRA_DIST = \
+ $(SOURCES) \
+ virt-builder.pod \
++ virt-index-validate.pod \
+ test-virt-builder.sh \
+ test-virt-builder-list.sh \
+ website/.gitignore \
+@@ -70,6 +71,7 @@ SOURCES = \
+ get_kernel.ml \
+ index_parser.mli \
+ index_parser.ml \
++ index-parser-c.c \
+ list_entries.mli \
+ list_entries.ml \
+ perl_edit.ml \
+--
+1.8.3.1
+
diff --git a/0017-builder-Add-an-extra-Makefile.am-to-builder-website.patch b/0017-builder-Add-an-extra-Makefile.am-to-builder-website.patch
new file mode 100644
index 0000000..b238cf2
--- /dev/null
+++ b/0017-builder-Add-an-extra-Makefile.am-to-builder-website.patch
@@ -0,0 +1,141 @@
+From e02dc7c0e4f017b2e7b53b7f70e80deef1ba5377 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 07:20:37 +0000
+Subject: [PATCH] builder: Add an extra Makefile.am to builder/website.
+
+(cherry picked from commit cd10f6f4db32689b2552b52a4875795be8b35694)
+---
+ Makefile.am | 2 +-
+ builder/Makefile.am | 31 +--------------------------
+ builder/website/Makefile.am | 51 +++++++++++++++++++++++++++++++++++++++++++++
+ configure.ac | 1 +
+ 4 files changed, 54 insertions(+), 31 deletions(-)
+ create mode 100644 builder/website/Makefile.am
+
+diff --git a/Makefile.am b/Makefile.am
+index 3014f6d..8aab678 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -118,7 +118,7 @@ SUBDIRS += csharp
+ # OCaml tools. Note 'mllib' contains random shared code used by
+ # all of the OCaml tools.
+ if HAVE_OCAML
+-SUBDIRS += mllib builder resize sparsify sysprep
++SUBDIRS += mllib builder builder/website resize sparsify sysprep
+ endif
+
+ # Perl tools.
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index 9dbe51e..c3719d1 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -28,36 +28,7 @@ EXTRA_DIST = \
+ virt-builder.pod \
+ virt-index-validate.pod \
+ test-virt-builder.sh \
+- test-virt-builder-list.sh \
+- website/.gitignore \
+- website/test-guest.sh \
+- website/README \
+- website/index \
+- website/index.asc \
+- website/centos-6.ks \
+- website/centos-6.sh \
+- website/centos-6.xz.sig \
+- website/debian-6.preseed \
+- website/debian-6.sh \
+- website/debian-6.xz.sig \
+- website/debian-7.preseed \
+- website/debian-7.sh \
+- website/debian-7.xz.sig \
+- website/fedora-18.ks \
+- website/fedora-18.sh \
+- website/fedora-18.xz.sig \
+- website/fedora-19.ks \
+- website/fedora-19.sh \
+- website/fedora-19.xz.sig \
+- website/ubuntu-10.04.preseed \
+- website/ubuntu-10.04.sh \
+- website/ubuntu-10.04.xz.sig \
+- website/ubuntu-12.04.preseed \
+- website/ubuntu-12.04.sh \
+- website/ubuntu-12.04.xz.sig \
+- website/ubuntu-13.10.preseed \
+- website/ubuntu-13.10.sh \
+- website/ubuntu-13.10.xz.sig
++ test-virt-builder-list.sh
+
+ CLEANFILES = *~ *.cmi *.cmo *.cmx *.cmxa *.o virt-builder
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+new file mode 100644
+index 0000000..ba74485
+--- /dev/null
++++ b/builder/website/Makefile.am
+@@ -0,0 +1,51 @@
++# libguestfs virt-builder tool
++# 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.
++
++include $(top_srcdir)/subdir-rules.mk
++
++EXTRA_DIST = \
++ .gitignore \
++ test-guest.sh \
++ README \
++ index \
++ index.asc \
++ centos-6.ks \
++ centos-6.sh \
++ centos-6.xz.sig \
++ debian-6.preseed \
++ debian-6.sh \
++ debian-6.xz.sig \
++ debian-7.preseed \
++ debian-7.sh \
++ debian-7.xz.sig \
++ fedora-18.ks \
++ fedora-18.sh \
++ fedora-18.xz.sig \
++ fedora-19.ks \
++ fedora-19.sh \
++ fedora-19.xz.sig \
++ ubuntu-10.04.preseed \
++ ubuntu-10.04.sh \
++ ubuntu-10.04.xz.sig \
++ ubuntu-12.04.preseed \
++ ubuntu-12.04.sh \
++ ubuntu-12.04.xz.sig \
++ ubuntu-13.10.preseed \
++ ubuntu-13.10.sh \
++ ubuntu-13.10.xz.sig
++
++CLEANFILES = *~
+diff --git a/configure.ac b/configure.ac
+index 30040e0..d797187 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1658,6 +1658,7 @@ AC_CONFIG_FILES([Makefile
+ bash/Makefile
+ builder/Makefile
+ builder/test-index
++ builder/website/Makefile
+ cat/Makefile
+ csharp/Makefile
+ daemon/Makefile
+--
+1.8.3.1
+
diff --git a/0018-builder-website-Add-index-validation-test-script.patch b/0018-builder-website-Add-index-validation-test-script.patch
new file mode 100644
index 0000000..8647d1b
--- /dev/null
+++ b/0018-builder-website-Add-index-validation-test-script.patch
@@ -0,0 +1,57 @@
+From 919c22ead98cce4368425259f882ba7ed47c98fa Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 07:25:46 +0000
+Subject: [PATCH] builder/website: Add index validation test script.
+
+(cherry picked from commit 154bfb7dd46e7998eed1d40ead95923590763739)
+---
+ builder/website/Makefile.am | 4 ++++
+ builder/website/validate.sh | 24 ++++++++++++++++++++++++
+ 2 files changed, 28 insertions(+)
+ create mode 100755 builder/website/validate.sh
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+index ba74485..2a3bbe6 100644
+--- a/builder/website/Makefile.am
++++ b/builder/website/Makefile.am
+@@ -49,3 +49,7 @@ EXTRA_DIST = \
+ ubuntu-13.10.xz.sig
+
+ CLEANFILES = *~
++
++# Validates the index file.
++TESTS_ENVIRONMENT = $(top_builddir)/run --test
++TESTS = validate.sh
+diff --git a/builder/website/validate.sh b/builder/website/validate.sh
+new file mode 100755
+index 0000000..f09e30c
+--- /dev/null
++++ b/builder/website/validate.sh
+@@ -0,0 +1,24 @@
++#!/bin/bash -
++# libguestfs virt-builder validate index
++# 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.
++
++export LANG=C
++set -e
++
++../virt-index-validate index
++../virt-index-validate index.asc
++
+--
+1.8.3.1
+
diff --git a/0019-builder-Internal-implementation-of-parallel-xzcat-px.patch b/0019-builder-Internal-implementation-of-parallel-xzcat-px.patch
new file mode 100644
index 0000000..35fbc48
--- /dev/null
+++ b/0019-builder-Internal-implementation-of-parallel-xzcat-px.patch
@@ -0,0 +1,942 @@
+From e20aea882e564c537b7ce8f7db6c618e5b4ffaee Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 10:21:32 +0000
+Subject: [PATCH] builder: Internal implementation of parallel xzcat (pxzcat).
+
+Instead of calling out to the pxzcat program, use an internal
+implementation. This requires liblzma to be available at build time.
+If it's not available, fall back to using regular xzcat.
+
+It is intended that eventually this code will go away when regular
+xzcat / unxz is able to use threads.
+
+(cherry picked from commit 681c88ef5d69b1dec4b929ff3451c45968023e5a)
+---
+ README | 2 +-
+ builder/Makefile.am | 11 +-
+ builder/builder.ml | 24 +-
+ builder/pxzcat-c.c | 650 +++++++++++++++++++++++++++++++++++++++++++++++
+ builder/pxzcat.ml | 19 ++
+ builder/pxzcat.mli | 31 +++
+ builder/virt-builder.pod | 7 +-
+ configure.ac | 10 +-
+ mllib/config.ml.in | 6 -
+ po/POTFILES | 1 +
+ po/POTFILES-ml | 1 +
+ 11 files changed, 726 insertions(+), 36 deletions(-)
+ create mode 100644 builder/pxzcat-c.c
+ create mode 100644 builder/pxzcat.ml
+ create mode 100644 builder/pxzcat.mli
+
+diff --git a/README b/README
+index 461915d..baf4de4 100644
+--- a/README
++++ b/README
+@@ -174,7 +174,7 @@ The full requirements are described below.
+ | gpg | | O | Used by virt-builder for digital |
+ | | | | signatures |
+ +--------------+-------------+---+-----------------------------------------+
+-| pxzcat | | O | Can be used by virt-builder for fast |
++| liblzma | | O | Can be used by virt-builder for fast |
+ | | | | uncompression of templates. |
+ +--------------+-------------+---+-----------------------------------------+
+ | findlib | | O | For the OCaml bindings. |
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index c3719d1..2027203 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -21,7 +21,9 @@ AM_YFLAGS = -d
+ AM_CFLAGS = \
+ -I$(shell $(OCAMLC) -where) \
+ -I$(top_srcdir)/src \
+- -I$(top_srcdir)/fish
++ -I$(top_srcdir)/fish \
++ -pthread \
++ $(LIBLZMA_CFLAGS)
+
+ EXTRA_DIST = \
+ $(SOURCES) \
+@@ -47,6 +49,9 @@ SOURCES = \
+ list_entries.ml \
+ perl_edit.ml \
+ perl_edit.mli \
++ pxzcat.ml \
++ pxzcat.mli \
++ pxzcat-c.c \
+ sigchecker.mli \
+ sigchecker.ml
+
+@@ -73,6 +78,8 @@ OBJECTS = \
+ index-struct.o \
+ index-parse.o \
+ index-parser-c.o \
++ pxzcat-c.o \
++ pxzcat.cmx \
+ get_kernel.cmx \
+ downloader.cmx \
+ sigchecker.cmx \
+@@ -102,7 +109,7 @@ OCAMLOPTFLAGS = $(OCAMLCFLAGS)
+ virt-builder: $(OBJECTS)
+ $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \
+ mlguestfs.cmxa -linkpkg $^ \
+- -cclib '-lncurses -lcrypt' \
++ -cclib '-pthread $(LIBLZMA_LIBS) -lncurses -lcrypt -lpthread' \
+ $(OCAML_GCOV_LDFLAGS) \
+ -o $@
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index fc6078c..a5a4dfe 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -24,6 +24,7 @@ open Common_utils
+ open Password
+
+ open Cmdline
++open Pxzcat
+
+ open Unix
+ open Printf
+@@ -333,27 +334,14 @@ let main () =
+
+ output, Some size, format, delete_output_file, do_resize, true in
+
+- (* Create xzcat/pxzcat command to uncompress from input to output. *)
+- let xzcat_command input output =
+- match Config.pxzcat with
+- | None -> sprintf "%s %s > %s" Config.xzcat input output
+- | Some pxzcat -> sprintf "%s %s -o %s" pxzcat input output
+- in
+-
+ if not do_resize then (
+ (* If the user did not specify --size and the output is a regular
+ * file and the format is raw, then we just uncompress the template
+ * directly to the output file. This is fast but less flexible.
+ *)
+ let { Index_parser.file_uri = file_uri } = entry in
+- let cmd = xzcat_command template output in
+- if debug then eprintf "%s\n%!" cmd;
+ msg (f_"Uncompressing: %s") file_uri;
+- let r = Sys.command cmd in
+- if r <> 0 then (
+- eprintf (f_"%s: error: failed to uncompress template\n") prog;
+- exit 1
+- )
++ pxzcat template output
+ ) else (
+ (* If none of the above apply, uncompress to a temporary file and
+ * run virt-resize on the result.
+@@ -362,14 +350,8 @@ let main () =
+ (* Uncompress it to a temporary file. *)
+ let { Index_parser.file_uri = file_uri } = entry in
+ let tmpfile = Filename.temp_file "vbsrc" ".img" in
+- let cmd = xzcat_command template tmpfile in
+- if debug then eprintf "%s\n%!" cmd;
+ msg (f_"Uncompressing: %s") file_uri;
+- let r = Sys.command cmd in
+- if r <> 0 then (
+- eprintf (f_"%s: error: failed to uncompress template\n") prog;
+- exit 1
+- );
++ pxzcat template tmpfile;
+ unlink_on_exit tmpfile;
+ tmpfile in
+
+diff --git a/builder/pxzcat-c.c b/builder/pxzcat-c.c
+new file mode 100644
+index 0000000..5ffc9d9
+--- /dev/null
++++ b/builder/pxzcat-c.c
+@@ -0,0 +1,650 @@
++/* virt-builder
++ * Copyright (C) 2013 Red Hat Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++
++#include <pthread.h>
++
++#include <caml/alloc.h>
++#include <caml/fail.h>
++#include <caml/memory.h>
++#include <caml/mlvalues.h>
++
++#ifdef HAVE_CAML_UNIXSUPPORT_H
++#include <caml/unixsupport.h>
++#else
++#define Nothing ((value) 0)
++extern void unix_error (int errcode, char * cmdname, value arg) Noreturn;
++#endif
++
++#ifdef HAVE_LIBLZMA
++#include <lzma.h>
++
++static void pxzcat (value filenamev, value outputfilev, unsigned nr_threads);
++#endif
++
++value
++virt_builder_pxzcat (value inputfilev, value outputfilev)
++{
++ CAMLparam2 (inputfilev, outputfilev);
++
++#ifdef HAVE_LIBLZMA
++
++ /* Parallel implementation of xzcat (pxzcat). */
++ /* XXX Make number of threads configurable? */
++ long i;
++ unsigned nr_threads;
++
++ i = sysconf (_SC_NPROCESSORS_ONLN);
++ if (i <= 0) {
++ perror ("could not get number of cores");
++ i = 1;
++ }
++ nr_threads = (unsigned) i;
++
++ /* NB: This might throw an exception if something fails. If it
++ * does, this function won't return as a regular C function.
++ */
++ pxzcat (inputfilev, outputfilev, nr_threads);
++
++#else
++
++ /* Fallback: use regular xzcat. */
++ int fd;
++ pid_t pid;
++ int status;
++
++ fd = open (String_val (outputfilev), O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666);
++ if (fd == -1)
++ unix_error (errno, "open", outputfilev);
++
++ pid = fork ();
++ if (pid == -1) {
++ int err = errno;
++ close (fd);
++ unix_error (err, "fork", Nothing);
++ }
++
++ if (pid == 0) { /* child - run xzcat */
++ dup2 (fd, 1);
++ execlp (XZCAT, XZCAT, String_val (inputfilev), NULL);
++ perror (XZCAT);
++ _exit (EXIT_FAILURE);
++ }
++
++ close (fd);
++
++ if (waitpid (pid, &status, 0) == -1)
++ unix_error (errno, "waitpid", Nothing);
++ if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
++ caml_failwith (XZCAT " program failed, see earlier error messages");
++
++#endif
++
++ CAMLreturn (Val_unit);
++}
++
++#ifdef HAVE_LIBLZMA
++
++#define DEBUG 0
++
++#if DEBUG
++#define debug(fs,...) fprintf (stderr, "pxzcat: debug: " fs "\n", ## __VA_ARGS__)
++#else
++#define debug(fs,...) /* nothing */
++#endif
++
++/* Size of buffers used in decompression loop. */
++#define BUFFER_SIZE (64*1024)
++
++#define XZ_HEADER_MAGIC "\xfd" "7zXZ\0"
++#define XZ_HEADER_MAGIC_LEN 6
++#define XZ_FOOTER_MAGIC "YZ"
++#define XZ_FOOTER_MAGIC_LEN 2
++
++static int check_header_magic (int fd);
++static lzma_index *parse_indexes (value filenamev, int fd);
++static void iter_blocks (lzma_index *idx, unsigned nr_threads, value filenamev, int fd, value outputfilev, int ofd);
++
++static void
++pxzcat (value filenamev, value outputfilev, unsigned nr_threads)
++{
++ int fd, ofd;
++ uint64_t size;
++ lzma_index *idx;
++
++ /* Open the file. */
++ fd = open (String_val (filenamev), O_RDONLY);
++ if (fd == -1)
++ unix_error (errno, "open", filenamev);
++
++ /* Check file magic. */
++ if (!check_header_magic (fd)) {
++ close (fd);
++ caml_invalid_argument ("input file is not an xz file");
++ }
++
++ /* Read and parse the indexes. */
++ idx = parse_indexes (filenamev, fd);
++
++ /* Get the file uncompressed size, create the output file. */
++ size = lzma_index_uncompressed_size (idx);
++ debug ("uncompressed size = %" PRIu64 " bytes", size);
++
++ /* Avoid annoying ext4 auto_da_alloc which causes a flush on close
++ * unless we are very careful about not truncating a regular file
++ * from non-zero size to zero size. (Thanks Eric Sandeen)
++ */
++ ofd = open (String_val (outputfilev), O_WRONLY|O_CREAT|O_NOCTTY, 0644);
++ if (ofd == -1) {
++ int err = errno;
++ close (fd);
++ unix_error (err, "open", outputfilev);
++ }
++
++ if (ftruncate (ofd, 1) == -1) {
++ int err = errno;
++ close (fd);
++ unix_error (err, "ftruncate", outputfilev);
++ }
++
++ if (lseek (ofd, 0, SEEK_SET) == -1) {
++ int err = errno;
++ close (fd);
++ unix_error (err, "lseek", outputfilev);
++ }
++
++ if (write (ofd, "\0", 1) == -1) {
++ int err = errno;
++ close (fd);
++ unix_error (err, "write", outputfilev);
++ }
++
++ if (ftruncate (ofd, size) == -1) {
++ int err = errno;
++ close (fd);
++ unix_error (err, "ftruncate", outputfilev);
++ }
++
++ /* Tell the kernel we won't read the output file. */
++ posix_fadvise (fd, 0, 0, POSIX_FADV_RANDOM|POSIX_FADV_DONTNEED);
++
++ /* Iterate over blocks. */
++ iter_blocks (idx, nr_threads, filenamev, fd, outputfilev, ofd);
++
++ lzma_index_end (idx, NULL);
++
++ if (close (fd) == -1)
++ unix_error (errno, "close", filenamev);
++}
++
++static int
++check_header_magic (int fd)
++{
++ char buf[XZ_HEADER_MAGIC_LEN];
++
++ if (lseek (fd, 0, SEEK_SET) == -1)
++ return 0;
++ if (read (fd, buf, XZ_HEADER_MAGIC_LEN) != XZ_HEADER_MAGIC_LEN)
++ return 0;
++ if (memcmp (buf, XZ_HEADER_MAGIC, XZ_HEADER_MAGIC_LEN) != 0)
++ return 0;
++ return 1;
++}
++
++/* For explanation of this function, see src/xz/list.c:parse_indexes
++ * in the xz sources.
++ */
++static lzma_index *
++parse_indexes (value filenamev, int fd)
++{
++ lzma_ret r;
++ off_t pos, index_size;
++ uint8_t footer[LZMA_STREAM_HEADER_SIZE];
++ uint8_t header[LZMA_STREAM_HEADER_SIZE];
++ lzma_stream_flags footer_flags;
++ lzma_stream_flags header_flags;
++ lzma_stream strm = LZMA_STREAM_INIT;
++ ssize_t n;
++ lzma_index *combined_index = NULL;
++ lzma_index *this_index = NULL;
++ lzma_vli stream_padding = 0;
++ size_t nr_streams = 0;
++
++ /* Check file size is a multiple of 4 bytes. */
++ pos = lseek (fd, 0, SEEK_END);
++ if (pos == (off_t) -1)
++ unix_error (errno, "lseek", filenamev);
++
++ if ((pos & 3) != 0)
++ caml_invalid_argument ("input not an xz file: size is not a multiple of 4 bytes");
++
++ /* Jump backwards through the file identifying each stream. */
++ while (pos > 0) {
++ debug ("looping through streams: pos = %" PRIu64, (uint64_t) pos);
++
++ if (pos < LZMA_STREAM_HEADER_SIZE)
++ caml_invalid_argument ("corrupted xz file");
++
++ if (lseek (fd, -LZMA_STREAM_HEADER_SIZE, SEEK_CUR) == -1)
++ unix_error (errno, "lseek", filenamev);
++
++ if (read (fd, footer, LZMA_STREAM_HEADER_SIZE) != LZMA_STREAM_HEADER_SIZE)
++ unix_error (errno, "read", filenamev);
++
++ /* Skip stream padding. */
++ if (footer[8] == 0 && footer[9] == 0 &&
++ footer[10] == 0 && footer[11] == 0) {
++ stream_padding += 4;
++ pos -= 4;
++ continue;
++ }
++
++ pos -= LZMA_STREAM_HEADER_SIZE;
++ nr_streams++;
++
++ debug ("decode stream footer at pos = %" PRIu64, (uint64_t) pos);
++
++ /* Does the stream footer look reasonable? */
++ r = lzma_stream_footer_decode (&footer_flags, footer);
++ if (r != LZMA_OK) {
++ fprintf (stderr, "invalid stream footer - error %d\n", r);
++ caml_invalid_argument ("invalid stream footer");
++ }
++
++ debug ("backward_size = %" PRIu64, (uint64_t) footer_flags.backward_size);
++ index_size = footer_flags.backward_size;
++ if (pos < index_size + LZMA_STREAM_HEADER_SIZE)
++ caml_invalid_argument ("invalid stream footer");
++
++ pos -= index_size;
++ debug ("decode index at pos = %" PRIu64, (uint64_t) pos);
++
++ /* Seek backwards to the index of this stream. */
++ if (lseek (fd, pos, SEEK_SET) == -1)
++ unix_error (errno, "lseek", filenamev);
++
++ /* Decode the index. */
++ r = lzma_index_decoder (&strm, &this_index, UINT64_MAX);
++ if (r != LZMA_OK) {
++ fprintf (stderr, "invalid stream index - error %d\n", r);
++ caml_invalid_argument ("invalid stream index");
++ }
++
++ do {
++ uint8_t buf[BUFSIZ];
++
++ strm.avail_in = index_size;
++ if (strm.avail_in > BUFSIZ)
++ strm.avail_in = BUFSIZ;
++
++ n = read (fd, &buf, strm.avail_in);
++ if (n == -1)
++ unix_error (errno, "read", filenamev);
++
++ index_size -= strm.avail_in;
++
++ strm.next_in = buf;
++ r = lzma_code (&strm, LZMA_RUN);
++ } while (r == LZMA_OK);
++
++ if (r != LZMA_STREAM_END) {
++ fprintf (stderr, "could not parse index - error %d\n", r);
++ caml_invalid_argument ("could not parse index");
++ }
++
++ pos -= lzma_index_total_size (this_index) + LZMA_STREAM_HEADER_SIZE;
++
++ debug ("decode stream header at pos = %" PRIu64, (uint64_t) pos);
++
++ /* Read and decode the stream header. */
++ if (lseek (fd, pos, SEEK_SET) == -1)
++ unix_error (errno, "lseek", filenamev);
++
++ if (read (fd, header, LZMA_STREAM_HEADER_SIZE) != LZMA_STREAM_HEADER_SIZE)
++ unix_error (errno, "read stream header", filenamev);
++
++ r = lzma_stream_header_decode (&header_flags, header);
++ if (r != LZMA_OK) {
++ fprintf (stderr, "invalid stream header - error %d\n", r);
++ caml_invalid_argument ("invalid stream header");
++ }
++
++ /* Header and footer of the stream should be equal. */
++ r = lzma_stream_flags_compare (&header_flags, &footer_flags);
++ if (r != LZMA_OK) {
++ fprintf (stderr, "header and footer of stream are not equal - error %d\n",
++ r);
++ caml_invalid_argument ("header and footer of stream are not equal");
++ }
++
++ /* Store the decoded stream flags in this_index. */
++ r = lzma_index_stream_flags (this_index, &footer_flags);
++ if (r != LZMA_OK) {
++ fprintf (stderr, "cannot read stream_flags from index - error %d\n", r);
++ caml_invalid_argument ("cannot read stream_flags from index");
++ }
++
++ /* Store the amount of stream padding so far. Needed to calculate
++ * compressed offsets correctly in multi-stream files.
++ */
++ r = lzma_index_stream_padding (this_index, stream_padding);
++ if (r != LZMA_OK) {
++ fprintf (stderr, "cannot set stream_padding in index - error %d\n", r);
++ caml_invalid_argument ("cannot set stream_padding in index");
++ }
++
++ if (combined_index != NULL) {
++ r = lzma_index_cat (this_index, combined_index, NULL);
++ if (r != LZMA_OK) {
++ fprintf (stderr, "cannot combine indexes - error %d\n", r);
++ caml_invalid_argument ("cannot combine indexes");
++ }
++ }
++
++ combined_index = this_index;
++ this_index = NULL;
++ }
++
++ lzma_end (&strm);
++
++ return combined_index;
++}
++
++/* Return true iff the buffer is all zero bytes.
++ *
++ * Note that gcc is smart enough to optimize this properly:
++ * http://stackoverflow.com/questions/1493936/faster-means-of-checking-for-an-empty-buffer-in-c/1493989#1493989
++ */
++static inline int
++is_zero (const char *buffer, size_t size)
++{
++ size_t i;
++
++ for (i = 0; i < size; ++i) {
++ if (buffer[i] != 0)
++ return 0;
++ }
++
++ return 1;
++}
++
++struct global_state {
++ /* Current iterator. Threads update this, but it is protected by a
++ * mutex, and each thread takes a copy of it when working on it.
++ */
++ lzma_index_iter iter;
++ lzma_bool iter_finished;
++ pthread_mutex_t iter_mutex;
++
++ /* Note that all threads are accessing these fds, so you have
++ * to use pread/pwrite instead of lseek!
++ */
++
++ /* Input file. */
++ const char *filename;
++ int fd;
++
++ /* Output file. */
++ const char *outputfile;
++ int ofd;
++};
++
++struct per_thread_state {
++ unsigned thread_num;
++ struct global_state *global;
++ int status;
++};
++
++/* Create threads to iterate over the blocks and uncompress. */
++static void *worker_thread (void *vp);
++
++static void
++iter_blocks (lzma_index *idx, unsigned nr_threads,
++ value filenamev, int fd, value outputfilev, int ofd)
++{
++ struct global_state global;
++ struct per_thread_state per_thread[nr_threads];
++ pthread_t thread[nr_threads];
++ unsigned u, nr_errors;
++ int err;
++ void *status;
++
++ lzma_index_iter_init (&global.iter, idx);
++ global.iter_finished = 0;
++ err = pthread_mutex_init (&global.iter_mutex, NULL);
++ if (err != 0)
++ unix_error (err, "pthread_mutex_init", Nothing);
++
++ global.filename = String_val (filenamev);
++ global.fd = fd;
++ global.outputfile = String_val (outputfilev);
++ global.ofd = ofd;
++
++ for (u = 0; u < nr_threads; ++u) {
++ per_thread[u].thread_num = u;
++ per_thread[u].global = &global;
++ }
++
++ /* Start the threads. */
++ for (u = 0; u < nr_threads; ++u) {
++ err = pthread_create (&thread[u], NULL, worker_thread, &per_thread[u]);
++ if (err != 0)
++ unix_error (err, "pthread_create", Nothing);
++ }
++
++ /* Wait for the threads to exit. */
++ nr_errors = 0;
++ for (u = 0; u < nr_threads; ++u) {
++ err = pthread_join (thread[u], &status);
++ if (err != 0) {
++ fprintf (stderr, "pthread_join (%u): %s\n", u, strerror (err));
++ nr_errors++;
++ }
++ if (*(int *)status == -1)
++ nr_errors++;
++ }
++
++ if (nr_errors > 0)
++ caml_invalid_argument ("some threads failed, see earlier errors");
++}
++
++/* Iterate over the blocks and uncompress. */
++static void *
++worker_thread (void *vp)
++{
++ struct per_thread_state *state = vp;
++ struct global_state *global = state->global;
++ lzma_index_iter iter;
++ int err;
++ off_t position, oposition;
++ uint8_t header[LZMA_BLOCK_HEADER_SIZE_MAX];
++ ssize_t n;
++ lzma_block block;
++ lzma_filter filters[LZMA_FILTERS_MAX + 1];
++ lzma_ret r;
++ lzma_stream strm = LZMA_STREAM_INIT;
++ uint8_t buf[BUFFER_SIZE];
++ char outbuf[BUFFER_SIZE];
++ size_t i;
++ lzma_bool iter_finished;
++
++ state->status = -1;
++
++ for (;;) {
++ /* Get the next block. */
++ err = pthread_mutex_lock (&global->iter_mutex);
++ if (err != 0) abort ();
++ iter_finished = global->iter_finished;
++ if (!iter_finished) {
++ iter_finished = global->iter_finished =
++ lzma_index_iter_next (&global->iter, LZMA_INDEX_ITER_NONEMPTY_BLOCK);
++ if (!iter_finished)
++ /* Take a local copy of this iterator since another thread will
++ * update the global version.
++ */
++ iter = global->iter;
++ }
++ err = pthread_mutex_unlock (&global->iter_mutex);
++ if (err != 0) abort ();
++ if (iter_finished)
++ break;
++
++ /* Read the block header. Start by reading a single byte which
++ * tell us how big the block header is.
++ */
++ position = iter.block.compressed_file_offset;
++ n = pread (global->fd, header, 1, position);
++ if (n == 0) {
++ fprintf (stderr,
++ "%s: read: unexpected end of file reading block header byte\n",
++ global->filename);
++ return &state->status;
++ }
++ if (n == -1) {
++ perror (String_val (global->filename));
++ return &state->status;
++ }
++ position++;
++
++ if (header[0] == '\0') {
++ fprintf (stderr,
++ "%s: read: unexpected invalid block in file, header[0] = 0\n",
++ global->filename);
++ return &state->status;
++ }
++
++ block.version = 0;
++ block.check = iter.stream.flags->check;
++ block.filters = filters;
++ block.header_size = lzma_block_header_size_decode (header[0]);
++
++ /* Now read and decode the block header. */
++ n = pread (global->fd, &header[1], block.header_size-1, position);
++ if (n >= 0 && n != block.header_size-1) {
++ fprintf (stderr,
++ "%s: read: unexpected end of file reading block header\n",
++ global->filename);
++ return &state->status;
++ }
++ if (n == -1) {
++ perror (global->filename);
++ return &state->status;
++ }
++ position += n;
++
++ r = lzma_block_header_decode (&block, NULL, header);
++ if (r != LZMA_OK) {
++ fprintf (stderr, "%s: invalid block header (error %d)\n",
++ global->filename, r);
++ return &state->status;
++ }
++
++ /* What this actually does is it checks that the block header
++ * matches the index.
++ */
++ r = lzma_block_compressed_size (&block, iter.block.unpadded_size);
++ if (r != LZMA_OK) {
++ fprintf (stderr,
++ "%s: cannot calculate compressed size (error %d)\n",
++ global->filename, r);
++ return &state->status;
++ }
++
++ /* Where we will start writing to. */
++ oposition = iter.block.uncompressed_file_offset;
++
++ /* Read the block data and uncompress it. */
++ r = lzma_block_decoder (&strm, &block);
++ if (r != LZMA_OK) {
++ fprintf (stderr, "%s: invalid block (error %d)\n", global->filename, r);
++ return &state->status;
++ }
++
++ strm.next_in = NULL;
++ strm.avail_in = 0;
++ strm.next_out = outbuf;
++ strm.avail_out = sizeof outbuf;
++
++ for (;;) {
++ lzma_action action = LZMA_RUN;
++
++ if (strm.avail_in == 0) {
++ strm.next_in = buf;
++ n = pread (global->fd, buf, sizeof buf, position);
++ if (n == -1) {
++ perror (global->filename);
++ return &state->status;
++ }
++ position += n;
++ strm.avail_in = n;
++ if (n == 0)
++ action = LZMA_FINISH;
++ }
++
++ r = lzma_code (&strm, action);
++
++ if (strm.avail_out == 0 || r == LZMA_STREAM_END) {
++ size_t wsz = sizeof outbuf - strm.avail_out;
++
++ /* Don't write if the block is all zero, to preserve output file
++ * sparseness. However we have to update oposition.
++ */
++ if (!is_zero (outbuf, wsz)) {
++ if (pwrite (global->ofd, outbuf, wsz, oposition) != wsz) {
++ /* XXX Handle short writes. */
++ perror (global->filename);
++ return &state->status;
++ }
++ }
++ oposition += wsz;
++
++ strm.next_out = outbuf;
++ strm.avail_out = sizeof outbuf;
++ }
++
++ if (r == LZMA_STREAM_END)
++ break;
++ if (r != LZMA_OK) {
++ fprintf (stderr,
++ "%s: could not parse block data (error %d)\n",
++ global->filename, r);
++ return &state->status;
++ }
++ }
++
++ lzma_end (&strm);
++
++ for (i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i)
++ free (filters[i].options);
++ }
++
++ state->status = 0;
++ return &state->status;
++}
++
++#endif /* HAVE_LIBLZMA */
+diff --git a/builder/pxzcat.ml b/builder/pxzcat.ml
+new file mode 100644
+index 0000000..5645370
+--- /dev/null
++++ b/builder/pxzcat.ml
+@@ -0,0 +1,19 @@
++(* virt-builder
++ * Copyright (C) 2013 Red Hat Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ *)
++
++external pxzcat : string -> string -> unit = "virt_builder_pxzcat"
+diff --git a/builder/pxzcat.mli b/builder/pxzcat.mli
+new file mode 100644
+index 0000000..a2830f0
+--- /dev/null
++++ b/builder/pxzcat.mli
+@@ -0,0 +1,31 @@
++(* virt-builder
++ * Copyright (C) 2013 Red Hat Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ *)
++
++(** {1 Parallel xzcat (or fall back to regular xzcat).}
++
++ Eventually regular xzcat will be able to work in parallel and this
++ code can go away.
++*)
++
++val pxzcat : string -> string -> unit
++ (** [pxzcat input output] uncompresses the file [input] to the file
++ [output]. The input and output must both be seekable.
++
++ If liblzma was found at compile time, this uses an internal
++ implementation of parallel xzcat. Otherwise regular xzcat is
++ used. *)
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 6497c0a..bad59c1 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -1397,10 +1397,9 @@ the output format is the same as the template format (usually raw).
+
+ =head3 pxzcat
+
+-Virt-builder can use C<pxzcat> (parallel xzcat) if available to
+-uncompress the templates. The default is to use regular C<xzcat>
+-which is single-threaded. Currently this has to be compiled in,
+-ie. virt-builder will probably need to be recompiled to use pxzcat.
++Virt-builder uses an internal implementation of pxzcat (parallel
++xzcat) if liblzma was found at build time. If liblzma was not found
++at build time, regular C<xzcat> is used which is single-threaded.
+
+ =head3 User-Mode Linux
+
+diff --git a/configure.ac b/configure.ac
+index d797187..7a18b8e 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -701,9 +701,15 @@ fi
+ dnl Check for xzcat (required).
+ AC_PATH_PROGS([XZCAT],[xzcat],[no])
+ test "x$XZCAT" = "xno" && AC_MSG_ERROR([xzcat must be installed])
++AC_DEFINE_UNQUOTED([XZCAT],["$XZCAT"],[Name of xzcat program.])
+
+-dnl Check for pxzcat (optional).
+-AC_PATH_PROGS([PXZCAT],[pxzcat],[no])
++dnl liblzma can be used by virt-builder (optional).
++PKG_CHECK_MODULES([LIBLZMA], [liblzma],[
++ AC_SUBST([LIBLZMA_CFLAGS])
++ AC_SUBST([LIBLZMA_LIBS])
++ AC_DEFINE([HAVE_LIBLZMA],[1],[liblzma found at compile time.])
++],
++[AC_MSG_WARN([liblzma not found, virt-builder will be slower])])
+
+ dnl (f)lex and bison are required for virt-builder.
+ AC_PROG_LEX
+diff --git a/mllib/config.ml.in b/mllib/config.ml.in
+index 5586c5c..d18bf7b 100644
+--- a/mllib/config.ml.in
++++ b/mllib/config.ml.in
+@@ -18,9 +18,3 @@
+
+ let package_name = "@PACKAGE_NAME@"
+ let package_version = "@PACKAGE_VERSION@"
+-
+-let xzcat = "@XZCAT@"
+-let pxzcat =
+- match "@PXZCAT@" with
+- | "no" -> None
+- | path -> Some path
+diff --git a/po/POTFILES b/po/POTFILES
+index aa52b75..4bf805f 100644
+--- a/po/POTFILES
++++ b/po/POTFILES
+@@ -4,6 +4,7 @@ builder/index-parser-c.c
+ builder/index-scan.c
+ builder/index-struct.c
+ builder/index-validate.c
++builder/pxzcat-c.c
+ cat/cat.c
+ cat/filesystems.c
+ cat/ls.c
+diff --git a/po/POTFILES-ml b/po/POTFILES-ml
+index 185f87b..39ca2a0 100644
+--- a/po/POTFILES-ml
++++ b/po/POTFILES-ml
+@@ -5,6 +5,7 @@ builder/get_kernel.ml
+ builder/index_parser.ml
+ builder/list_entries.ml
+ builder/perl_edit.ml
++builder/pxzcat.ml
+ builder/sigchecker.ml
+ mllib/common_gettext.ml
+ mllib/common_utils.ml
+--
+1.8.3.1
+
diff --git a/0020-builder-Replace-fedora-NN-shell-kickstart-with-a-sin.patch b/0020-builder-Replace-fedora-NN-shell-kickstart-with-a-sin.patch
new file mode 100644
index 0000000..ef5ce5c
--- /dev/null
+++ b/0020-builder-Replace-fedora-NN-shell-kickstart-with-a-sin.patch
@@ -0,0 +1,493 @@
+From 7d81c64a1f96ef72c3ad84ce05d182bda3b30faa Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 13:59:55 +0000
+Subject: [PATCH] builder: Replace fedora-<NN> shell & kickstart with a single
+ script.
+
+Just use:
+
+ ./fedora.sh 18
+
+Note that you don't need to be root.
+
+(cherry picked from commit ade0f1a97d6371f5d5a538da9d41263146cc58d6)
+---
+ builder/website/Makefile.am | 5 +--
+ builder/website/fedora-18.ks | 38 -----------------
+ builder/website/fedora-18.sh | 75 ---------------------------------
+ builder/website/fedora-19.ks | 38 -----------------
+ builder/website/fedora-19.sh | 75 ---------------------------------
+ builder/website/fedora.sh | 99 ++++++++++++++++++++++++++++++++++++++++++++
+ builder/website/index | 12 +++---
+ builder/website/index.asc | 36 ++++++++--------
+ 8 files changed, 124 insertions(+), 254 deletions(-)
+ delete mode 100644 builder/website/fedora-18.ks
+ delete mode 100755 builder/website/fedora-18.sh
+ delete mode 100644 builder/website/fedora-19.ks
+ delete mode 100755 builder/website/fedora-19.sh
+ create mode 100755 builder/website/fedora.sh
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+index 2a3bbe6..4188439 100644
+--- a/builder/website/Makefile.am
++++ b/builder/website/Makefile.am
+@@ -32,11 +32,8 @@ EXTRA_DIST = \
+ debian-7.preseed \
+ debian-7.sh \
+ debian-7.xz.sig \
+- fedora-18.ks \
+- fedora-18.sh \
++ fedora.sh \
+ fedora-18.xz.sig \
+- fedora-19.ks \
+- fedora-19.sh \
+ fedora-19.xz.sig \
+ ubuntu-10.04.preseed \
+ ubuntu-10.04.sh \
+diff --git a/builder/website/fedora-18.ks b/builder/website/fedora-18.ks
+deleted file mode 100644
+index 5e6fe24..0000000
+--- a/builder/website/fedora-18.ks
++++ /dev/null
+@@ -1,38 +0,0 @@
+-# virt-builder
+-# Copyright (C) 2013 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-
+-install
+-text
+-reboot
+-lang en_US.UTF-8
+-keyboard us
+-network --bootproto dhcp
+-rootpw builder
+-firewall --enabled --ssh
+-selinux --enforcing
+-timezone --utc America/New_York
+-bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"
+-zerombr
+-clearpart --all --initlabel
+-autopart --type=plain
+-
+-# Halt the system once configuration has finished.
+-poweroff
+-
+-%packages
+- at core
+-%end
+diff --git a/builder/website/fedora-18.sh b/builder/website/fedora-18.sh
+deleted file mode 100755
+index 6fd6214..0000000
+--- a/builder/website/fedora-18.sh
++++ /dev/null
+@@ -1,75 +0,0 @@
+-#!/bin/bash -
+-# virt-builder
+-# Copyright (C) 2013 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-export http_proxy=http://cache.home.annexia.org:3128
+-export https_proxy=$http_proxy
+-export ftp_proxy=$http_proxy
+-tree=http://mirror.bytemark.co.uk/fedora/linux/releases/18/Fedora/x86_64/os/
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+- echo "You have to run this script as root."
+- exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f fedora-18.ks ]; then
+- echo "You are running this script from the wrong directory."
+- exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-virsh undefine tmpf18 ||:
+-rm -f fedora-18 fedora-18.old
+-
+-virt-install \
+- --name=tmpf18 \
+- --ram 2048 \
+- --cpu=host --vcpus=2 \
+- --os-type=linux --os-variant=fedora18 \
+- --initrd-inject=$pwd/fedora-18.ks \
+- --extra-args="ks=file:/fedora-18.ks console=tty0 console=ttyS0,115200 proxy=$http_proxy" \
+- --disk $pwd/fedora-18,size=6 \
+- --location=$tree \
+- --nographics \
+- --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine tmpf18
+-
+-# Sysprep (removes logfiles and so on).
+-# Note this also touches /.autorelabel so the further installation
+-# changes that we make will be labelled properly at first boot.
+-virt-sysprep -a fedora-18
+-
+-# Sparsify.
+-mv fedora-18 fedora-18.old
+-virt-sparsify fedora-18.old fedora-18
+-rm fedora-18.old
+-
+-# Compress.
+-rm -f fedora-18.xz
+-xz --best --block-size=16777216 fedora-18
+-
+-# Result:
+-ls -lh fedora-18.xz
+diff --git a/builder/website/fedora-19.ks b/builder/website/fedora-19.ks
+deleted file mode 100644
+index 5e6fe24..0000000
+--- a/builder/website/fedora-19.ks
++++ /dev/null
+@@ -1,38 +0,0 @@
+-# virt-builder
+-# Copyright (C) 2013 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-
+-install
+-text
+-reboot
+-lang en_US.UTF-8
+-keyboard us
+-network --bootproto dhcp
+-rootpw builder
+-firewall --enabled --ssh
+-selinux --enforcing
+-timezone --utc America/New_York
+-bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"
+-zerombr
+-clearpart --all --initlabel
+-autopart --type=plain
+-
+-# Halt the system once configuration has finished.
+-poweroff
+-
+-%packages
+- at core
+-%end
+diff --git a/builder/website/fedora-19.sh b/builder/website/fedora-19.sh
+deleted file mode 100755
+index d175cdf..0000000
+--- a/builder/website/fedora-19.sh
++++ /dev/null
+@@ -1,75 +0,0 @@
+-#!/bin/bash -
+-# virt-builder
+-# Copyright (C) 2013 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-export http_proxy=http://cache.home.annexia.org:3128
+-export https_proxy=$http_proxy
+-export ftp_proxy=$http_proxy
+-tree=http://mirror.bytemark.co.uk/fedora/linux/releases/19/Fedora/x86_64/os/
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+- echo "You have to run this script as root."
+- exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f fedora-19.ks ]; then
+- echo "You are running this script from the wrong directory."
+- exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-virsh undefine tmpf19 ||:
+-rm -f fedora-19 fedora-19.old
+-
+-virt-install \
+- --name=tmpf19 \
+- --ram 2048 \
+- --cpu=host --vcpus=2 \
+- --os-type=linux --os-variant=fedora19 \
+- --initrd-inject=$pwd/fedora-19.ks \
+- --extra-args="ks=file:/fedora-19.ks console=tty0 console=ttyS0,115200 proxy=$http_proxy" \
+- --disk $pwd/fedora-19,size=4 \
+- --location=$tree \
+- --nographics \
+- --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine tmpf19
+-
+-# Sysprep (removes logfiles and so on).
+-# Note this also touches /.autorelabel so the further installation
+-# changes that we make will be labelled properly at first boot.
+-virt-sysprep -a fedora-19
+-
+-# Sparsify.
+-mv fedora-19 fedora-19.old
+-virt-sparsify fedora-19.old fedora-19
+-rm fedora-19.old
+-
+-# Compress.
+-rm -f fedora-19.xz
+-xz --best --block-size=16777216 fedora-19
+-
+-# Result:
+-ls -lh fedora-19.xz
+diff --git a/builder/website/fedora.sh b/builder/website/fedora.sh
+new file mode 100755
+index 0000000..bb164d8
+--- /dev/null
++++ b/builder/website/fedora.sh
+@@ -0,0 +1,99 @@
++#!/bin/bash -
++# virt-builder
++# Copyright (C) 2013 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++
++# This script was used to create the Fedora templates used by
++# virt-builder.
++
++unset CDPATH
++export LANG=C
++set -e
++set -x
++
++if [ $# -ne 1 ]; then
++ echo "$0 VERSION"
++ exit 1
++fi
++
++version=$1
++tree=http://mirror.bytemark.co.uk/fedora/linux/releases/$version/Fedora/x86_64/os/
++output=fedora-$version
++tmpname=tmp-$(tr -cd 'a-f0-9' < /dev/urandom | head -c 8)
++
++rm -f $output $output.old $output.xz
++
++# Generate the kickstart to a temporary file.
++ks=$(mktemp)
++cat > $ks <<'EOF'
++install
++text
++reboot
++lang en_US.UTF-8
++keyboard us
++network --bootproto dhcp
++rootpw builder
++firewall --enabled --ssh
++selinux --enforcing
++timezone --utc America/New_York
++bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"
++zerombr
++clearpart --all --initlabel
++autopart --type=plain
++
++# Halt the system once configuration has finished.
++poweroff
++
++%packages
++ at core
++%end
++EOF
++
++# Clean up function.
++cleanup ()
++{
++ rm -f $ks
++ virsh undefine $tmpname ||:
++}
++trap cleanup INT QUIT TERM EXIT ERR
++
++virt-install \
++ --name=$tmpname \
++ --ram=2048 \
++ --cpu=host --vcpus=2 \
++ --os-type=linux --os-variant=fedora18 \
++ --initrd-inject=$ks \
++ --extra-args="ks=file:/`basename $ks` console=tty0 console=ttyS0,115200 proxy=$http_proxy" \
++ --disk $(pwd)/$output,size=6 \
++ --location=$tree \
++ --nographics \
++ --noreboot
++
++# Sysprep (removes logfiles and so on).
++# Note this also touches /.autorelabel so the further installation
++# changes that we make will be labelled properly at first boot.
++virt-sysprep -a $output
++
++# Sparsify.
++mv $output $output.old
++virt-sparsify $output.old $output
++rm $output.old
++
++# Compress.
++xz --best --block-size=16777216 $output
++
++# Result:
++ls -lh $output.xz
+diff --git a/builder/website/index b/builder/website/index
+index 6165f28..bea11ce 100644
+--- a/builder/website/index
++++ b/builder/website/index
+@@ -96,9 +96,9 @@ notes=Fedora 18.
+ This Fedora image contains only unmodified @Core group packages.
+
+ It is thus very minimal. The kickstart and install script can be
+- found in the libguestfs git tree:
+- libguestfs.git/builder/website/fedora-18.ks
+- libguestfs.git/builder/website/fedora-18.sh
++ found in the libguestfs source tree:
++
++ builder/website/fedora.sh
+
+ Fedora and the Infinity design logo are trademarks of Red Hat, Inc.
+ Source and further information is available from http://fedoraproject.org/
+@@ -118,9 +118,9 @@ notes=Fedora 19.
+ This Fedora image contains only unmodified @Core group packages.
+
+ It is thus very minimal. The kickstart and install script can be
+- found in the libguestfs git tree:
+- libguestfs.git/builder/website/fedora-19.ks
+- libguestfs.git/builder/website/fedora-19.sh
++ found in the libguestfs source tree:
++
++ builder/website/fedora.sh
+
+ Fedora and the Infinity design logo are trademarks of Red Hat, Inc.
+ Source and further information is available from http://fedoraproject.org/
+diff --git a/builder/website/index.asc b/builder/website/index.asc
+index 087ebeb..c04cf1d 100644
+--- a/builder/website/index.asc
++++ b/builder/website/index.asc
+@@ -99,9 +99,9 @@ notes=Fedora 18.
+ This Fedora image contains only unmodified @Core group packages.
+
+ It is thus very minimal. The kickstart and install script can be
+- found in the libguestfs git tree:
+- libguestfs.git/builder/website/fedora-18.ks
+- libguestfs.git/builder/website/fedora-18.sh
++ found in the libguestfs source tree:
++
++ builder/website/fedora.sh
+
+ Fedora and the Infinity design logo are trademarks of Red Hat, Inc.
+ Source and further information is available from http://fedoraproject.org/
+@@ -122,8 +122,8 @@ notes=Fedora 19.
+
+ It is thus very minimal. The kickstart and install script can be
+ found in the libguestfs git tree:
+- libguestfs.git/builder/website/fedora-19.ks
+- libguestfs.git/builder/website/fedora-19.sh
++
++ builder/website/fedora.sh
+
+ Fedora and the Infinity design logo are trademarks of Red Hat, Inc.
+ Source and further information is available from http://fedoraproject.org/
+@@ -202,17 +202,17 @@ notes=Ubuntu 13.10 (Saucy).
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.14 (GNU/Linux)
+
+-iQIcBAEBAgAGBQJSc9qSAAoJEJFzj3Pht2igkYkQAKoYhPycj0ydM5Gk3nbaSOuU
+-Rsz1LsujBsYTM+E51UjBm4bcCJw4HwHYRUMT/t5cdMSX/NjSNGHjeLRBQvOGJMHx
+-DV6quFv/mwSCjvncWPuT3iCRNIIAq0ECr5YvfKhJ6HtoD/cQM7WUivYdZUJERC89
+-H1d5bjDiU25qLrhl68fEMyQzzpKIq3CbsIsczlCxxuHefXNhhp7XmqGtrNwpd7im
+-FtbKaIPeUDreoDCNNZzeUwdJ3TR6ybPB1Iy5Pl3kaBcM3VKqV5qXdQdmCbLyVtzg
+-rg4cSxTRiMJGstMVIiDJzsS+DGfUngpXZnxndDpzaX6BVgMqFjSPcjjif2f+wWsK
+-t1eXAhyoUYK+mepsNmYsOzBLFgnQKnmRO4cy6DgKq+twrx4v7snDpQ8J+HZkGHM6
+-sdliAQ7QEBmcLVArlzsq61RP3XlWrSIwmRG7BBGFptom4p+m7JeIPCH9EKZ9QIDK
+-tWOq8LqEAsNvaJrw+HTcGaryEYOf6YmJFd0iHgqDOnrsvsPK9Ex8hhC05jYe/Lkp
+-HzZiRjHFpHbm8lBVFcrajyGumdIieg2EUh7iygxaRFQa+7UA7fkYuGhYXKcsbgyT
+-Q3/c5TUAAM9qpj70rtTHV0LCmXL21aPqsMRPD/Oawe9N2iYe0HfNuZ1bBauPJEGy
+-pixuD1Mt3Xl/2Hl0GVcY
+-=x34e
++iQIcBAEBAgAGBQJSePm7AAoJEJFzj3Pht2ig+fYP/RODYX3Y6Rfqgn5YcgOVbkEN
++5RNxNvE/cFba5w6eZzI2q/kdjH9JzHMqmevHwANNq8i37tmgrkFkGgZK7QD92xWS
++GF9QeaNh9usLi3gB9WRxsT5p017IUsns4lFhlPs6nXnuIqb3+7B/qYPQFqgW9QbO
++c3WYWhnHvxAAGvARnVirGs7ucyajjoqJA+P5yfnnxl8BPEk+1nuXowEH423czYq3
++E3dX5AUFy3mjfzK2DH12ladUYvxbur1p7eGKx7VkD1ZaqWtt+pss0+M7WO+tAt+w
++JkggdkBqY30T2zxchF8bRiObAFCXEpC7UmA50UPxXiVK94rXSr1jvAVHsh8nSjXA
++QfRcFA4JjnYRBqCiCu4Tp08MmfMKHFkCn/VtjUhugJHClkeR1GYkhUJ9pnu1goK/
++N3yNyW/kORgSgZFfmLvUcdAQIIyWTqvgXFkEe16FnWNmH1Aq8JbAH5l/Iw8Nk+bU
++gB9+kKdVyAH7j5+fasIuiw4N0dgiq4k3xktOgUMIt4I1mqpWEVJBGUWgcH/qx+FP
++nUoHXTDBLY6MZXAmtuV4TpvRPX85O5nSe6NnGsivaYVa7Dsqk5TUZhUpU46F2Sqv
++HsvhXO295LT7hPj2Cd++NAy1R+WV+eeldPwP+Ff9adOvB8uShHW+hVpSUVmeeIku
++LLd8N3ZnefviQj+p61It
++=qKVc
+ -----END PGP SIGNATURE-----
+--
+1.8.3.1
+
diff --git a/0021-builder-Replace-ubuntu-NN-.sh-with-a-single-script.patch b/0021-builder-Replace-ubuntu-NN-.sh-with-a-single-script.patch
new file mode 100644
index 0000000..7988148
--- /dev/null
+++ b/0021-builder-Replace-ubuntu-NN-.sh-with-a-single-script.patch
@@ -0,0 +1,2081 @@
+From da7e551daadfe32b0f386ffed41efc18a2150e3d Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 14:08:01 +0000
+Subject: [PATCH] builder: Replace ubuntu-<NN>.sh with a single script.
+
+Just use:
+
+ ./ubuntu.sh 10.04 lucid
+
+Note that you don't need to be root.
+
+(cherry picked from commit 91b5e7fb37751719304573882c521071aa811e36)
+---
+ builder/website/Makefile.am | 8 +-
+ builder/website/index | 21 +-
+ builder/website/index.asc | 49 ++---
+ builder/website/ubuntu-10.04.preseed | 376 -----------------------------------
+ builder/website/ubuntu-10.04.sh | 85 --------
+ builder/website/ubuntu-12.04.preseed | 376 -----------------------------------
+ builder/website/ubuntu-12.04.sh | 85 --------
+ builder/website/ubuntu-13.10.preseed | 376 -----------------------------------
+ builder/website/ubuntu-13.10.sh | 85 --------
+ builder/website/ubuntu.preseed | 376 +++++++++++++++++++++++++++++++++++
+ builder/website/ubuntu.sh | 84 ++++++++
+ 11 files changed, 500 insertions(+), 1421 deletions(-)
+ delete mode 100644 builder/website/ubuntu-10.04.preseed
+ delete mode 100755 builder/website/ubuntu-10.04.sh
+ delete mode 100644 builder/website/ubuntu-12.04.preseed
+ delete mode 100755 builder/website/ubuntu-12.04.sh
+ delete mode 100644 builder/website/ubuntu-13.10.preseed
+ delete mode 100755 builder/website/ubuntu-13.10.sh
+ create mode 100644 builder/website/ubuntu.preseed
+ create mode 100755 builder/website/ubuntu.sh
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+index 4188439..dfcb494 100644
+--- a/builder/website/Makefile.am
++++ b/builder/website/Makefile.am
+@@ -35,14 +35,10 @@ EXTRA_DIST = \
+ fedora.sh \
+ fedora-18.xz.sig \
+ fedora-19.xz.sig \
+- ubuntu-10.04.preseed \
+- ubuntu-10.04.sh \
++ ubuntu.preseed \
++ ubuntu.sh \
+ ubuntu-10.04.xz.sig \
+- ubuntu-12.04.preseed \
+- ubuntu-12.04.sh \
+ ubuntu-12.04.xz.sig \
+- ubuntu-13.10.preseed \
+- ubuntu-13.10.sh \
+ ubuntu-13.10.xz.sig
+
+ CLEANFILES = *~
+diff --git a/builder/website/index b/builder/website/index
+index bea11ce..4e6a867 100644
+--- a/builder/website/index
++++ b/builder/website/index
+@@ -141,9 +141,10 @@ notes=Ubuntu 10.04 (Lucid).
+
+ Only the openssh-server package is selected in tasksel.
+ The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/ubuntu-10.04.preseed
+- libguestfs.git/builder/website/ubuntu-10.04.sh
++ can be found in the libguestfs source tree:
++
++ builder/website/ubuntu.preseed
++ builder/website/ubuntu.sh
+
+ This image does not contain SSH host keys. To regenerate them use:
+
+@@ -165,9 +166,10 @@ notes=Ubuntu 12.04 (Precise).
+
+ Only the openssh-server package is selected in tasksel.
+ The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/ubuntu-12.04.preseed
+- libguestfs.git/builder/website/ubuntu-12.04.sh
++ can be found in the libguestfs source tree:
++
++ builder/website/ubuntu.preseed
++ builder/website/ubuntu.sh
+
+ This image does not contain SSH host keys. To regenerate them use:
+
+@@ -189,9 +191,10 @@ notes=Ubuntu 13.10 (Saucy).
+
+ Only the openssh-server package is selected in tasksel.
+ The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/ubuntu-13.10.preseed
+- libguestfs.git/builder/website/ubuntu-13.10.sh
++ can be found in the libguestfs source tree:
++
++ builder/website/ubuntu.preseed
++ builder/website/ubuntu.sh
+
+ This image does not contain SSH host keys. To regenerate them use:
+
+diff --git a/builder/website/index.asc b/builder/website/index.asc
+index c04cf1d..35e103c 100644
+--- a/builder/website/index.asc
++++ b/builder/website/index.asc
+@@ -121,7 +121,7 @@ notes=Fedora 19.
+ This Fedora image contains only unmodified @Core group packages.
+
+ It is thus very minimal. The kickstart and install script can be
+- found in the libguestfs git tree:
++ found in the libguestfs source tree:
+
+ builder/website/fedora.sh
+
+@@ -144,9 +144,10 @@ notes=Ubuntu 10.04 (Lucid).
+
+ Only the openssh-server package is selected in tasksel.
+ The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/ubuntu-10.04.preseed
+- libguestfs.git/builder/website/ubuntu-10.04.sh
++ can be found in the libguestfs source tree:
++
++ builder/website/ubuntu.preseed
++ builder/website/ubuntu.sh
+
+ This image does not contain SSH host keys. To regenerate them use:
+
+@@ -168,9 +169,10 @@ notes=Ubuntu 12.04 (Precise).
+
+ Only the openssh-server package is selected in tasksel.
+ The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/ubuntu-12.04.preseed
+- libguestfs.git/builder/website/ubuntu-12.04.sh
++ can be found in the libguestfs source tree:
++
++ builder/website/ubuntu.preseed
++ builder/website/ubuntu.sh
+
+ This image does not contain SSH host keys. To regenerate them use:
+
+@@ -192,9 +194,10 @@ notes=Ubuntu 13.10 (Saucy).
+
+ Only the openssh-server package is selected in tasksel.
+ The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/ubuntu-13.10.preseed
+- libguestfs.git/builder/website/ubuntu-13.10.sh
++ can be found in the libguestfs source tree:
++
++ builder/website/ubuntu.preseed
++ builder/website/ubuntu.sh
+
+ This image does not contain SSH host keys. To regenerate them use:
+
+@@ -202,17 +205,17 @@ notes=Ubuntu 13.10 (Saucy).
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.14 (GNU/Linux)
+
+-iQIcBAEBAgAGBQJSePm7AAoJEJFzj3Pht2ig+fYP/RODYX3Y6Rfqgn5YcgOVbkEN
+-5RNxNvE/cFba5w6eZzI2q/kdjH9JzHMqmevHwANNq8i37tmgrkFkGgZK7QD92xWS
+-GF9QeaNh9usLi3gB9WRxsT5p017IUsns4lFhlPs6nXnuIqb3+7B/qYPQFqgW9QbO
+-c3WYWhnHvxAAGvARnVirGs7ucyajjoqJA+P5yfnnxl8BPEk+1nuXowEH423czYq3
+-E3dX5AUFy3mjfzK2DH12ladUYvxbur1p7eGKx7VkD1ZaqWtt+pss0+M7WO+tAt+w
+-JkggdkBqY30T2zxchF8bRiObAFCXEpC7UmA50UPxXiVK94rXSr1jvAVHsh8nSjXA
+-QfRcFA4JjnYRBqCiCu4Tp08MmfMKHFkCn/VtjUhugJHClkeR1GYkhUJ9pnu1goK/
+-N3yNyW/kORgSgZFfmLvUcdAQIIyWTqvgXFkEe16FnWNmH1Aq8JbAH5l/Iw8Nk+bU
+-gB9+kKdVyAH7j5+fasIuiw4N0dgiq4k3xktOgUMIt4I1mqpWEVJBGUWgcH/qx+FP
+-nUoHXTDBLY6MZXAmtuV4TpvRPX85O5nSe6NnGsivaYVa7Dsqk5TUZhUpU46F2Sqv
+-HsvhXO295LT7hPj2Cd++NAy1R+WV+eeldPwP+Ff9adOvB8uShHW+hVpSUVmeeIku
+-LLd8N3ZnefviQj+p61It
+-=qKVc
++iQIcBAEBAgAGBQJSePzzAAoJEJFzj3Pht2igrqQP/j/P4lsPU5HjBKNcNLNxKtHV
++9VJkn5/pfJGp0ovVoZqVJMknTwMQV850TDkbzMteWGgJEYFf5a6g8VHjmAkCunkl
++f1Das08tUjJcOow/pR8Dkwd2mGU4EDzwzun3BXnGgpnLcOURhLD28xp2SlLTmzfh
++tP5EWqgEBTT6Z8h6Rtth27lKveEk14w+QzJfwTgecySN+hTQY12NUIayNKmPrBE1
++SrbAGnw1KkpXAI7JQ1ofORsPKKSwZuHvhJY094315UwmB76EDwGzkMrRzZsYgMwN
++fESGh0YzyDdpl68G7QSOLUsDdZLXSB/dHi9FK4f6FsoUVf3kxelkZM4EXChL1ZMm
++NCMWhiYlmX5Z7KgPZqmKVToDXwQ0AAo0a+wNvJo4frtvDHMIGjBe/f+h4k67yOoc
++WGXqYGQG3cRrqVLanA5dFFmX+GGL/TG2cinvi+x5kJ902KeM17uyzk1uuMAUh/Rl
++RVSsLg9QH4sLE8wEPpaUzz2ei1Bf4P26hHtVOdK7YAueDUhfSfn9KIV/n5Fz4pRg
++G8FlpPnL1sfzbj8qpLqXHDnJ3rXGnYkSBalNJ7WVBBNlqaewuK/bcmLp9ffVeaN9
++CcDsWbv2UaeXXu8N9pcW2kEo1cBjKTR9NPT8ueZY0g0InNrPaz/cFMOf5K9MBfuC
++lRwdaDejqzKc5gYRKFnH
++=tYWz
+ -----END PGP SIGNATURE-----
+diff --git a/builder/website/ubuntu-10.04.preseed b/builder/website/ubuntu-10.04.preseed
+deleted file mode 100644
+index 236e174..0000000
+--- a/builder/website/ubuntu-10.04.preseed
++++ /dev/null
+@@ -1,376 +0,0 @@
+-#### Contents of the preconfiguration file (for &releasename;)
+-### Localization
+-# Locale sets language and country.
+-d-i debian-installer/locale string en_US
+-
+-# Keyboard selection.
+-# Disable automatic (interactive) keymap detection.
+-d-i console-setup/ask_detect boolean false
+-#d-i console-setup/modelcode string pc105
+-d-i console-setup/layoutcode string us
+-# To select a variant of the selected layout (if you leave this out, the
+-# basic form of the layout will be used):
+-#d-i console-setup/variantcode string dvorak
+-
+-### Network configuration
+-# netcfg will choose an interface that has link if possible. This makes it
+-# skip displaying a list if there is more than one interface.
+-d-i netcfg/choose_interface select auto
+-
+-# To pick a particular interface instead:
+-#d-i netcfg/choose_interface select eth1
+-
+-# If you have a slow dhcp server and the installer times out waiting for
+-# it, this might be useful.
+-#d-i netcfg/dhcp_timeout string 60
+-
+-# If you prefer to configure the network manually, uncomment this line and
+-# the static network configuration below.
+-#d-i netcfg/disable_dhcp boolean true
+-
+-# If you want the preconfiguration file to work on systems both with and
+-# without a dhcp server, uncomment these lines and the static network
+-# configuration below.
+-#d-i netcfg/dhcp_failed note
+-#d-i netcfg/dhcp_options select Configure network manually
+-
+-# Static network configuration.
+-#d-i netcfg/get_nameservers string 192.168.1.1
+-#d-i netcfg/get_ipaddress string 192.168.1.42
+-#d-i netcfg/get_netmask string 255.255.255.0
+-#d-i netcfg/get_gateway string 192.168.1.1
+-#d-i netcfg/confirm_static boolean true
+-
+-# Any hostname and domain names assigned from dhcp take precedence over
+-# values set here. However, setting the values still prevents the questions
+-# from being shown, even if values come from dhcp.
+-d-i netcfg/get_hostname string unassigned-hostname
+-d-i netcfg/get_domain string unassigned-domain
+-
+-# Disable that annoying WEP key dialog.
+-d-i netcfg/wireless_wep string
+-# The wacky dhcp hostname that some ISPs use as a password of sorts.
+-#d-i netcfg/dhcp_hostname string radish
+-
+-# If non-free firmware is needed for the network or other hardware, you can
+-# configure the installer to always try to load it, without prompting. Or
+-# change to false to disable asking.
+-#d-i hw-detect/load_firmware boolean true
+-
+-### Mirror settings
+-# If you select ftp, the mirror/country string does not need to be set.
+-#d-i mirror/protocol string ftp
+-#d-i mirror/country string manual
+-#d-i mirror/http/hostname string http.us.debian.org
+-#d-i mirror/http/directory string /ubuntu
+-#d-i mirror/http/proxy string
+-
+-# Alternatively: by default, the installer uses CC.archive.ubuntu.com where
+-# CC is the ISO-3166-2 code for the selected country. You can preseed this
+-# so that it does so without asking.
+-d-i mirror/http/mirror select uk.archive.ubuntu.com
+-
+-# Suite to install.
+-#d-i mirror/suite string &releasename;
+-# Suite to use for loading installer components (optional).
+-#d-i mirror/udeb/suite string &releasename;
+-# Components to use for loading installer components (optional).
+-#d-i mirror/udeb/components multiselect main, restricted
+-
+-### Clock and time zone setup
+-# Controls whether or not the hardware clock is set to UTC.
+-d-i clock-setup/utc boolean true
+-
+-# You may set this to any valid setting for $TZ; see the contents of
+-# /usr/share/zoneinfo/ for valid values.
+-d-i time/zone string US/Eastern
+-
+-# Controls whether to use NTP to set the clock during the install
+-d-i clock-setup/ntp boolean true
+-# NTP server to use. The default is almost always fine here.
+-#d-i clock-setup/ntp-server string ntp.example.com
+-
+-### Partitioning
+-# If the system has free space you can choose to only partition that space.
+-# Alternatives: custom, some_device, some_device_crypto, some_device_lvm.
+-#d-i partman-auto/init_automatically_partition select biggest_free
+-
+-# Alternatively, you can specify a disk to partition. The device name must
+-# be given in traditional non-devfs format.
+-# Note: A disk must be specified, unless the system has only one disk.
+-# For example, to use the first SCSI/SATA hard disk:
+-#d-i partman-auto/disk string /dev/sda
+-# In addition, you'll need to specify the method to use.
+-# The presently available methods are: "regular", "lvm" and "crypto"
+-d-i partman-auto/method string regular
+-
+-# If one of the disks that are going to be automatically partitioned
+-# contains an old LVM configuration, the user will normally receive a
+-# warning. This can be preseeded away...
+-d-i partman-lvm/device_remove_lvm boolean true
+-# The same applies to pre-existing software RAID array:
+-d-i partman-md/device_remove_md boolean true
+-# And the same goes for the confirmation to write the lvm partitions.
+-d-i partman-lvm/confirm boolean true
+-
+-# For LVM partitioning, you can select how much of the volume group to use
+-# for logical volumes.
+-#d-i partman-auto-lvm/guided_size string max
+-#d-i partman-auto-lvm/guided_size string 10GB
+-#d-i partman-auto-lvm/guided_size string 50%
+-
+-# You can choose one of the three predefined partitioning recipes:
+-# - atomic: all files in one partition
+-# - home: separate /home partition
+-# - multi: separate /home, /usr, /var, and /tmp partitions
+-d-i partman-auto/choose_recipe select atomic
+-
+-# Or provide a recipe of your own...
+-# The recipe format is documented in the file devel/partman-auto-recipe.txt.
+-# If you have a way to get a recipe file into the d-i environment, you can
+-# just point at it.
+-#d-i partman-auto/expert_recipe_file string /hd-media/recipe
+-
+-# If not, you can put an entire recipe into the preconfiguration file in one
+-# (logical) line. This example creates a small /boot partition, suitable
+-# swap, and uses the rest of the space for the root partition:
+-#d-i partman-auto/expert_recipe string \
+-# boot-root :: \
+-# 40 50 100 ext3 \
+-# $primary{ } $bootable{ } \
+-# method{ format } format{ } \
+-# use_filesystem{ } filesystem{ ext3 } \
+-# mountpoint{ /boot } \
+-# . \
+-# 500 10000 1000000000 ext3 \
+-# method{ format } format{ } \
+-# use_filesystem{ } filesystem{ ext3 } \
+-# mountpoint{ / } \
+-# . \
+-# 64 512 300% linux-swap \
+-# method{ swap } format{ } \
+-# .
+-
+-# If you just want to change the default filesystem from ext3 to something
+-# else, you can do that without providing a full recipe.
+-#d-i partman/default_filesystem string ext4
+-
+-# This makes partman automatically partition without confirmation, provided
+-# that you told it what to do using one of the methods above.
+-d-i partman/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-### Controlling how partitions are mounted
+-# The default is to mount by UUID, but you can also choose "traditional" to
+-# use traditional device names, or "label" to try filesystem labels before
+-# falling back to UUIDs.
+-#d-i partman/mount_style select uuid
+-
+-### Base system installation
+-# The kernel image (meta) package to be installed; "none" can be used if no
+-# kernel is to be installed.
+-#d-i base-installer/kernel/image string linux-generic
+-
+-### Account setup
+-# Skip creation of a root account (normal user account will be able to
+-# use sudo). The default is false; preseed this to true if you want to set
+-# a root password.
+-#d-i passwd/root-login boolean false
+-# Alternatively, to skip creation of a normal user account.
+-d-i passwd/make-user boolean false
+-
+-# Root password, either in clear text
+-d-i passwd/root-password password builder
+-d-i passwd/root-password-again password builder
+-# or encrypted using an MD5 hash.
+-#d-i passwd/root-password-crypted password [MD5 hash]
+-
+-# To create a normal user account.
+-#d-i passwd/user-fullname string Ubuntu User
+-#d-i passwd/username string ubuntu
+-# Normal user's password, either in clear text
+-#d-i passwd/user-password password insecure
+-#d-i passwd/user-password-again password insecure
+-# or encrypted using an MD5 hash.
+-#d-i passwd/user-password-crypted password [MD5 hash]
+-# Create the first user with the specified UID instead of the default.
+-#d-i passwd/user-uid string 1010
+-# The installer will warn about weak passwords. If you are sure you know
+-# what you're doing and want to override it, uncomment this.
+-#d-i user-setup/allow-password-weak boolean true
+-
+-# The user account will be added to some standard initial groups. To
+-# override that, use this.
+-#d-i passwd/user-default-groups string audio cdrom video
+-
+-# Set to true if you want to encrypt the first user's home directory.
+-d-i user-setup/encrypt-home boolean false
+-
+-### Apt setup
+-# You can choose to install restricted and universe software, or to install
+-# software from the backports repository.
+-#d-i apt-setup/restricted boolean true
+-#d-i apt-setup/universe boolean true
+-#d-i apt-setup/backports boolean true
+-# Uncomment this if you don't want to use a network mirror.
+-#d-i apt-setup/use_mirror boolean false
+-# Select which update services to use; define the mirrors to be used.
+-# Values shown below are the normal defaults.
+-#d-i apt-setup/services-select multiselect security
+-#d-i apt-setup/security_host string security.ubuntu.com
+-#d-i apt-setup/security_path string /ubuntu
+-
+-# Additional repositories, local[0-9] available
+-#d-i apt-setup/local0/repository string \
+-# http://local.server/ubuntu &releasename; main
+-#d-i apt-setup/local0/comment string local server
+-# Enable deb-src lines
+-#d-i apt-setup/local0/source boolean true
+-# URL to the public key of the local repository; you must provide a key or
+-# apt will complain about the unauthenticated repository and so the
+-# sources.list line will be left commented out
+-#d-i apt-setup/local0/key string http://local.server/key
+-
+-# By default the installer requires that repositories be authenticated
+-# using a known gpg key. This setting can be used to disable that
+-# authentication. Warning: Insecure, not recommended.
+-#d-i debian-installer/allow_unauthenticated string true
+-
+-### Package selection
+-#tasksel tasksel/first multiselect ubuntu-desktop
+-#tasksel tasksel/first multiselect lamp-server, print-server
+-#tasksel tasksel/first multiselect kubuntu-desktop
+-tasksel tasksel/first multiselect openssh-server
+-
+-# Individual additional packages to install
+-#d-i pkgsel/include string openssh-server build-essential
+-# Whether to upgrade packages after debootstrap.
+-# Allowed values: none, safe-upgrade, full-upgrade
+-#d-i pkgsel/upgrade select none
+-
+-# Language pack selection
+-#d-i pkgsel/language-packs multiselect de, en, zh
+-
+-# Policy for applying updates. May be "none" (no automatic updates),
+-# "unattended-upgrades" (install security updates automatically), or
+-# "landscape" (manage system with Landscape).
+-#d-i pkgsel/update-policy select none
+-
+-# Some versions of the installer can report back on what software you have
+-# installed, and what software you use. The default is not to report back,
+-# but sending reports helps the project determine what software is most
+-# popular and include it on CDs.
+-#popularity-contest popularity-contest/participate boolean false
+-
+-# By default, the system's locate database will be updated after the
+-# installer has finished installing most packages. This may take a while, so
+-# if you don't want it, you can set this to "false" to turn it off.
+-#d-i pkgsel/updatedb boolean true
+-
+-### Boot loader installation
+-# Grub is the default boot loader (for x86). If you want lilo installed
+-# instead, uncomment this:
+-#d-i grub-installer/skip boolean true
+-# To also skip installing lilo, and install no bootloader, uncomment this
+-# too:
+-#d-i lilo-installer/skip boolean true
+-
+-# This is fairly safe to set, it makes grub install automatically to the MBR
+-# if no other operating system is detected on the machine.
+-d-i grub-installer/only_debian boolean true
+-
+-# This one makes grub-installer install to the MBR if it also finds some other
+-# OS, which is less safe as it might not be able to boot that other OS.
+-d-i grub-installer/with_other_os boolean true
+-
+-# Alternatively, if you want to install to a location other than the mbr,
+-# uncomment and edit these lines:
+-#d-i grub-installer/only_debian boolean false
+-#d-i grub-installer/with_other_os boolean false
+-#d-i grub-installer/bootdev string (hd0,0)
+-# To install grub to multiple disks:
+-#d-i grub-installer/bootdev string (hd0,0) (hd1,0) (hd2,0)
+-
+-# Optional password for grub, either in clear text
+-#d-i grub-installer/password password r00tme
+-#d-i grub-installer/password-again password r00tme
+-# or encrypted using an MD5 hash, see grub-md5-crypt(8).
+-#d-i grub-installer/password-crypted password [MD5 hash]
+-
+-### Finishing up the installation
+-# During installations from serial console, the regular virtual consoles
+-# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
+-# line to prevent this.
+-#d-i finish-install/keep-consoles boolean true
+-
+-# Avoid that last message about the install being complete.
+-d-i finish-install/reboot_in_progress note
+-
+-# This will prevent the installer from ejecting the CD during the reboot,
+-# which is useful in some situations.
+-#d-i cdrom-detect/eject boolean false
+-
+-# This is how to make the installer shutdown when finished, but not
+-# reboot into the installed system.
+-#d-i debian-installer/exit/halt boolean true
+-# This will power off the machine instead of just halting it.
+-#d-i debian-installer/exit/poweroff boolean true
+-
+-### X configuration
+-# X can detect the right driver for some cards, but if you're preseeding,
+-# you override whatever it chooses. Still, vesa will work most places.
+-#xserver-xorg xserver-xorg/config/device/driver select vesa
+-
+-# A caveat with mouse autodetection is that if it fails, X will retry it
+-# over and over. So if it's preseeded to be done, there is a possibility of
+-# an infinite loop if the mouse is not autodetected.
+-#xserver-xorg xserver-xorg/autodetect_mouse boolean true
+-
+-# Monitor autodetection is recommended.
+-xserver-xorg xserver-xorg/autodetect_monitor boolean true
+-# Uncomment if you have an LCD display.
+-#xserver-xorg xserver-xorg/config/monitor/lcd boolean true
+-# X has three configuration paths for the monitor. Here's how to preseed
+-# the "medium" path, which is always available. The "simple" path may not
+-# be available, and the "advanced" path asks too many questions.
+-xserver-xorg xserver-xorg/config/monitor/selection-method \
+- select medium
+-xserver-xorg xserver-xorg/config/monitor/mode-list \
+- select 1024x768 @ 60 Hz
+-
+-### Preseeding other packages
+-# Depending on what software you choose to install, or if things go wrong
+-# during the installation process, it's possible that other questions may
+-# be asked. You can preseed those too, of course. To get a list of every
+-# possible question that could be asked during an install, do an
+-# installation, and then run these commands:
+-# debconf-get-selections --installer > file
+-# debconf-get-selections >> file
+-
+-
+-#### Advanced options
+-### Running custom commands during the installation
+-# d-i preseeding is inherently not secure. Nothing in the installer checks
+-# for attempts at buffer overflows or other exploits of the values of a
+-# preconfiguration file like this one. Only use preconfiguration files from
+-# trusted locations! To drive that home, and because it's generally useful,
+-# here's a way to run any shell command you'd like inside the installer,
+-# automatically.
+-
+-# This first command is run as early as possible, just after
+-# preseeding is read.
+-#d-i preseed/early_command string anna-install some-udeb
+-
+-# This command is run immediately before the partitioner starts. It may be
+-# useful to apply dynamic partitioner preseeding that depends on the state
+-# of the disks (which may not be visible when preseed/early_command runs).
+-#d-i partman/early_command string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
+-
+-# This command is run just before the install finishes, but when there is
+-# still a usable /target directory. You can chroot to /target and use it
+-# directly, or use the apt-install and in-target commands to easily install
+-# packages and run commands in the target system.
+-#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+-
+diff --git a/builder/website/ubuntu-10.04.sh b/builder/website/ubuntu-10.04.sh
+deleted file mode 100755
+index 943a96a..0000000
+--- a/builder/website/ubuntu-10.04.sh
++++ /dev/null
+@@ -1,85 +0,0 @@
+-#!/bin/bash -
+-# 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.
+-
+-# The basic plan comes from:
+-# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
+-# https://wiki.debian.org/DebianInstaller/Preseed
+-# https://help.ubuntu.com/10.04/installation-guide/i386/preseed-using.html
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-#export http_proxy=http://squid.corp.redhat.com:3128
+-#export https_proxy=$http_proxy
+-#export ftp_proxy=$http_proxy
+-location=http://archive.ubuntu.net/ubuntu/dists/lucid/main/installer-amd64
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+- echo "You have to run this script as root."
+- exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f ubuntu-10.04.preseed ]; then
+- echo "You are running this script from the wrong directory."
+- exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-# Note that the injected file must be called "/preseed.cfg" in order
+-# for d-i to pick it up.
+-sed -e "s, at CACHE@,$http_proxy,g" < ubuntu-10.04.preseed > preseed.cfg
+-
+-name=tmplucid
+-
+-virsh undefine $name ||:
+-rm -f ubuntu-10.04 ubuntu-10.04.old
+-
+-virt-install \
+- --name $name \
+- --ram=1024 \
+- --os-type=linux --os-variant=ubuntulucid \
+- --initrd-inject=$pwd/preseed.cfg \
+- --extra-args="auto console=tty0 console=ttyS0,115200" \
+- --disk=$pwd/ubuntu-10.04,size=4 \
+- --location=$location \
+- --nographics \
+- --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine $name
+-
+-rm preseed.cfg
+-
+-# Sysprep (removes logfiles and so on).
+-virt-sysprep -a ubuntu-10.04
+-
+-# Sparsify.
+-mv ubuntu-10.04 ubuntu-10.04.old
+-virt-sparsify ubuntu-10.04.old ubuntu-10.04
+-rm ubuntu-10.04.old
+-
+-# Compress.
+-rm -f ubuntu-10.04.xz
+-xz --best --block-size=16777216 ubuntu-10.04
+-
+-# Result:
+-ls -lh ubuntu-10.04.xz
+diff --git a/builder/website/ubuntu-12.04.preseed b/builder/website/ubuntu-12.04.preseed
+deleted file mode 100644
+index 236e174..0000000
+--- a/builder/website/ubuntu-12.04.preseed
++++ /dev/null
+@@ -1,376 +0,0 @@
+-#### Contents of the preconfiguration file (for &releasename;)
+-### Localization
+-# Locale sets language and country.
+-d-i debian-installer/locale string en_US
+-
+-# Keyboard selection.
+-# Disable automatic (interactive) keymap detection.
+-d-i console-setup/ask_detect boolean false
+-#d-i console-setup/modelcode string pc105
+-d-i console-setup/layoutcode string us
+-# To select a variant of the selected layout (if you leave this out, the
+-# basic form of the layout will be used):
+-#d-i console-setup/variantcode string dvorak
+-
+-### Network configuration
+-# netcfg will choose an interface that has link if possible. This makes it
+-# skip displaying a list if there is more than one interface.
+-d-i netcfg/choose_interface select auto
+-
+-# To pick a particular interface instead:
+-#d-i netcfg/choose_interface select eth1
+-
+-# If you have a slow dhcp server and the installer times out waiting for
+-# it, this might be useful.
+-#d-i netcfg/dhcp_timeout string 60
+-
+-# If you prefer to configure the network manually, uncomment this line and
+-# the static network configuration below.
+-#d-i netcfg/disable_dhcp boolean true
+-
+-# If you want the preconfiguration file to work on systems both with and
+-# without a dhcp server, uncomment these lines and the static network
+-# configuration below.
+-#d-i netcfg/dhcp_failed note
+-#d-i netcfg/dhcp_options select Configure network manually
+-
+-# Static network configuration.
+-#d-i netcfg/get_nameservers string 192.168.1.1
+-#d-i netcfg/get_ipaddress string 192.168.1.42
+-#d-i netcfg/get_netmask string 255.255.255.0
+-#d-i netcfg/get_gateway string 192.168.1.1
+-#d-i netcfg/confirm_static boolean true
+-
+-# Any hostname and domain names assigned from dhcp take precedence over
+-# values set here. However, setting the values still prevents the questions
+-# from being shown, even if values come from dhcp.
+-d-i netcfg/get_hostname string unassigned-hostname
+-d-i netcfg/get_domain string unassigned-domain
+-
+-# Disable that annoying WEP key dialog.
+-d-i netcfg/wireless_wep string
+-# The wacky dhcp hostname that some ISPs use as a password of sorts.
+-#d-i netcfg/dhcp_hostname string radish
+-
+-# If non-free firmware is needed for the network or other hardware, you can
+-# configure the installer to always try to load it, without prompting. Or
+-# change to false to disable asking.
+-#d-i hw-detect/load_firmware boolean true
+-
+-### Mirror settings
+-# If you select ftp, the mirror/country string does not need to be set.
+-#d-i mirror/protocol string ftp
+-#d-i mirror/country string manual
+-#d-i mirror/http/hostname string http.us.debian.org
+-#d-i mirror/http/directory string /ubuntu
+-#d-i mirror/http/proxy string
+-
+-# Alternatively: by default, the installer uses CC.archive.ubuntu.com where
+-# CC is the ISO-3166-2 code for the selected country. You can preseed this
+-# so that it does so without asking.
+-d-i mirror/http/mirror select uk.archive.ubuntu.com
+-
+-# Suite to install.
+-#d-i mirror/suite string &releasename;
+-# Suite to use for loading installer components (optional).
+-#d-i mirror/udeb/suite string &releasename;
+-# Components to use for loading installer components (optional).
+-#d-i mirror/udeb/components multiselect main, restricted
+-
+-### Clock and time zone setup
+-# Controls whether or not the hardware clock is set to UTC.
+-d-i clock-setup/utc boolean true
+-
+-# You may set this to any valid setting for $TZ; see the contents of
+-# /usr/share/zoneinfo/ for valid values.
+-d-i time/zone string US/Eastern
+-
+-# Controls whether to use NTP to set the clock during the install
+-d-i clock-setup/ntp boolean true
+-# NTP server to use. The default is almost always fine here.
+-#d-i clock-setup/ntp-server string ntp.example.com
+-
+-### Partitioning
+-# If the system has free space you can choose to only partition that space.
+-# Alternatives: custom, some_device, some_device_crypto, some_device_lvm.
+-#d-i partman-auto/init_automatically_partition select biggest_free
+-
+-# Alternatively, you can specify a disk to partition. The device name must
+-# be given in traditional non-devfs format.
+-# Note: A disk must be specified, unless the system has only one disk.
+-# For example, to use the first SCSI/SATA hard disk:
+-#d-i partman-auto/disk string /dev/sda
+-# In addition, you'll need to specify the method to use.
+-# The presently available methods are: "regular", "lvm" and "crypto"
+-d-i partman-auto/method string regular
+-
+-# If one of the disks that are going to be automatically partitioned
+-# contains an old LVM configuration, the user will normally receive a
+-# warning. This can be preseeded away...
+-d-i partman-lvm/device_remove_lvm boolean true
+-# The same applies to pre-existing software RAID array:
+-d-i partman-md/device_remove_md boolean true
+-# And the same goes for the confirmation to write the lvm partitions.
+-d-i partman-lvm/confirm boolean true
+-
+-# For LVM partitioning, you can select how much of the volume group to use
+-# for logical volumes.
+-#d-i partman-auto-lvm/guided_size string max
+-#d-i partman-auto-lvm/guided_size string 10GB
+-#d-i partman-auto-lvm/guided_size string 50%
+-
+-# You can choose one of the three predefined partitioning recipes:
+-# - atomic: all files in one partition
+-# - home: separate /home partition
+-# - multi: separate /home, /usr, /var, and /tmp partitions
+-d-i partman-auto/choose_recipe select atomic
+-
+-# Or provide a recipe of your own...
+-# The recipe format is documented in the file devel/partman-auto-recipe.txt.
+-# If you have a way to get a recipe file into the d-i environment, you can
+-# just point at it.
+-#d-i partman-auto/expert_recipe_file string /hd-media/recipe
+-
+-# If not, you can put an entire recipe into the preconfiguration file in one
+-# (logical) line. This example creates a small /boot partition, suitable
+-# swap, and uses the rest of the space for the root partition:
+-#d-i partman-auto/expert_recipe string \
+-# boot-root :: \
+-# 40 50 100 ext3 \
+-# $primary{ } $bootable{ } \
+-# method{ format } format{ } \
+-# use_filesystem{ } filesystem{ ext3 } \
+-# mountpoint{ /boot } \
+-# . \
+-# 500 10000 1000000000 ext3 \
+-# method{ format } format{ } \
+-# use_filesystem{ } filesystem{ ext3 } \
+-# mountpoint{ / } \
+-# . \
+-# 64 512 300% linux-swap \
+-# method{ swap } format{ } \
+-# .
+-
+-# If you just want to change the default filesystem from ext3 to something
+-# else, you can do that without providing a full recipe.
+-#d-i partman/default_filesystem string ext4
+-
+-# This makes partman automatically partition without confirmation, provided
+-# that you told it what to do using one of the methods above.
+-d-i partman/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-### Controlling how partitions are mounted
+-# The default is to mount by UUID, but you can also choose "traditional" to
+-# use traditional device names, or "label" to try filesystem labels before
+-# falling back to UUIDs.
+-#d-i partman/mount_style select uuid
+-
+-### Base system installation
+-# The kernel image (meta) package to be installed; "none" can be used if no
+-# kernel is to be installed.
+-#d-i base-installer/kernel/image string linux-generic
+-
+-### Account setup
+-# Skip creation of a root account (normal user account will be able to
+-# use sudo). The default is false; preseed this to true if you want to set
+-# a root password.
+-#d-i passwd/root-login boolean false
+-# Alternatively, to skip creation of a normal user account.
+-d-i passwd/make-user boolean false
+-
+-# Root password, either in clear text
+-d-i passwd/root-password password builder
+-d-i passwd/root-password-again password builder
+-# or encrypted using an MD5 hash.
+-#d-i passwd/root-password-crypted password [MD5 hash]
+-
+-# To create a normal user account.
+-#d-i passwd/user-fullname string Ubuntu User
+-#d-i passwd/username string ubuntu
+-# Normal user's password, either in clear text
+-#d-i passwd/user-password password insecure
+-#d-i passwd/user-password-again password insecure
+-# or encrypted using an MD5 hash.
+-#d-i passwd/user-password-crypted password [MD5 hash]
+-# Create the first user with the specified UID instead of the default.
+-#d-i passwd/user-uid string 1010
+-# The installer will warn about weak passwords. If you are sure you know
+-# what you're doing and want to override it, uncomment this.
+-#d-i user-setup/allow-password-weak boolean true
+-
+-# The user account will be added to some standard initial groups. To
+-# override that, use this.
+-#d-i passwd/user-default-groups string audio cdrom video
+-
+-# Set to true if you want to encrypt the first user's home directory.
+-d-i user-setup/encrypt-home boolean false
+-
+-### Apt setup
+-# You can choose to install restricted and universe software, or to install
+-# software from the backports repository.
+-#d-i apt-setup/restricted boolean true
+-#d-i apt-setup/universe boolean true
+-#d-i apt-setup/backports boolean true
+-# Uncomment this if you don't want to use a network mirror.
+-#d-i apt-setup/use_mirror boolean false
+-# Select which update services to use; define the mirrors to be used.
+-# Values shown below are the normal defaults.
+-#d-i apt-setup/services-select multiselect security
+-#d-i apt-setup/security_host string security.ubuntu.com
+-#d-i apt-setup/security_path string /ubuntu
+-
+-# Additional repositories, local[0-9] available
+-#d-i apt-setup/local0/repository string \
+-# http://local.server/ubuntu &releasename; main
+-#d-i apt-setup/local0/comment string local server
+-# Enable deb-src lines
+-#d-i apt-setup/local0/source boolean true
+-# URL to the public key of the local repository; you must provide a key or
+-# apt will complain about the unauthenticated repository and so the
+-# sources.list line will be left commented out
+-#d-i apt-setup/local0/key string http://local.server/key
+-
+-# By default the installer requires that repositories be authenticated
+-# using a known gpg key. This setting can be used to disable that
+-# authentication. Warning: Insecure, not recommended.
+-#d-i debian-installer/allow_unauthenticated string true
+-
+-### Package selection
+-#tasksel tasksel/first multiselect ubuntu-desktop
+-#tasksel tasksel/first multiselect lamp-server, print-server
+-#tasksel tasksel/first multiselect kubuntu-desktop
+-tasksel tasksel/first multiselect openssh-server
+-
+-# Individual additional packages to install
+-#d-i pkgsel/include string openssh-server build-essential
+-# Whether to upgrade packages after debootstrap.
+-# Allowed values: none, safe-upgrade, full-upgrade
+-#d-i pkgsel/upgrade select none
+-
+-# Language pack selection
+-#d-i pkgsel/language-packs multiselect de, en, zh
+-
+-# Policy for applying updates. May be "none" (no automatic updates),
+-# "unattended-upgrades" (install security updates automatically), or
+-# "landscape" (manage system with Landscape).
+-#d-i pkgsel/update-policy select none
+-
+-# Some versions of the installer can report back on what software you have
+-# installed, and what software you use. The default is not to report back,
+-# but sending reports helps the project determine what software is most
+-# popular and include it on CDs.
+-#popularity-contest popularity-contest/participate boolean false
+-
+-# By default, the system's locate database will be updated after the
+-# installer has finished installing most packages. This may take a while, so
+-# if you don't want it, you can set this to "false" to turn it off.
+-#d-i pkgsel/updatedb boolean true
+-
+-### Boot loader installation
+-# Grub is the default boot loader (for x86). If you want lilo installed
+-# instead, uncomment this:
+-#d-i grub-installer/skip boolean true
+-# To also skip installing lilo, and install no bootloader, uncomment this
+-# too:
+-#d-i lilo-installer/skip boolean true
+-
+-# This is fairly safe to set, it makes grub install automatically to the MBR
+-# if no other operating system is detected on the machine.
+-d-i grub-installer/only_debian boolean true
+-
+-# This one makes grub-installer install to the MBR if it also finds some other
+-# OS, which is less safe as it might not be able to boot that other OS.
+-d-i grub-installer/with_other_os boolean true
+-
+-# Alternatively, if you want to install to a location other than the mbr,
+-# uncomment and edit these lines:
+-#d-i grub-installer/only_debian boolean false
+-#d-i grub-installer/with_other_os boolean false
+-#d-i grub-installer/bootdev string (hd0,0)
+-# To install grub to multiple disks:
+-#d-i grub-installer/bootdev string (hd0,0) (hd1,0) (hd2,0)
+-
+-# Optional password for grub, either in clear text
+-#d-i grub-installer/password password r00tme
+-#d-i grub-installer/password-again password r00tme
+-# or encrypted using an MD5 hash, see grub-md5-crypt(8).
+-#d-i grub-installer/password-crypted password [MD5 hash]
+-
+-### Finishing up the installation
+-# During installations from serial console, the regular virtual consoles
+-# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
+-# line to prevent this.
+-#d-i finish-install/keep-consoles boolean true
+-
+-# Avoid that last message about the install being complete.
+-d-i finish-install/reboot_in_progress note
+-
+-# This will prevent the installer from ejecting the CD during the reboot,
+-# which is useful in some situations.
+-#d-i cdrom-detect/eject boolean false
+-
+-# This is how to make the installer shutdown when finished, but not
+-# reboot into the installed system.
+-#d-i debian-installer/exit/halt boolean true
+-# This will power off the machine instead of just halting it.
+-#d-i debian-installer/exit/poweroff boolean true
+-
+-### X configuration
+-# X can detect the right driver for some cards, but if you're preseeding,
+-# you override whatever it chooses. Still, vesa will work most places.
+-#xserver-xorg xserver-xorg/config/device/driver select vesa
+-
+-# A caveat with mouse autodetection is that if it fails, X will retry it
+-# over and over. So if it's preseeded to be done, there is a possibility of
+-# an infinite loop if the mouse is not autodetected.
+-#xserver-xorg xserver-xorg/autodetect_mouse boolean true
+-
+-# Monitor autodetection is recommended.
+-xserver-xorg xserver-xorg/autodetect_monitor boolean true
+-# Uncomment if you have an LCD display.
+-#xserver-xorg xserver-xorg/config/monitor/lcd boolean true
+-# X has three configuration paths for the monitor. Here's how to preseed
+-# the "medium" path, which is always available. The "simple" path may not
+-# be available, and the "advanced" path asks too many questions.
+-xserver-xorg xserver-xorg/config/monitor/selection-method \
+- select medium
+-xserver-xorg xserver-xorg/config/monitor/mode-list \
+- select 1024x768 @ 60 Hz
+-
+-### Preseeding other packages
+-# Depending on what software you choose to install, or if things go wrong
+-# during the installation process, it's possible that other questions may
+-# be asked. You can preseed those too, of course. To get a list of every
+-# possible question that could be asked during an install, do an
+-# installation, and then run these commands:
+-# debconf-get-selections --installer > file
+-# debconf-get-selections >> file
+-
+-
+-#### Advanced options
+-### Running custom commands during the installation
+-# d-i preseeding is inherently not secure. Nothing in the installer checks
+-# for attempts at buffer overflows or other exploits of the values of a
+-# preconfiguration file like this one. Only use preconfiguration files from
+-# trusted locations! To drive that home, and because it's generally useful,
+-# here's a way to run any shell command you'd like inside the installer,
+-# automatically.
+-
+-# This first command is run as early as possible, just after
+-# preseeding is read.
+-#d-i preseed/early_command string anna-install some-udeb
+-
+-# This command is run immediately before the partitioner starts. It may be
+-# useful to apply dynamic partitioner preseeding that depends on the state
+-# of the disks (which may not be visible when preseed/early_command runs).
+-#d-i partman/early_command string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
+-
+-# This command is run just before the install finishes, but when there is
+-# still a usable /target directory. You can chroot to /target and use it
+-# directly, or use the apt-install and in-target commands to easily install
+-# packages and run commands in the target system.
+-#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+-
+diff --git a/builder/website/ubuntu-12.04.sh b/builder/website/ubuntu-12.04.sh
+deleted file mode 100755
+index 6134b1d..0000000
+--- a/builder/website/ubuntu-12.04.sh
++++ /dev/null
+@@ -1,85 +0,0 @@
+-#!/bin/bash -
+-# 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.
+-
+-# The basic plan comes from:
+-# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
+-# https://wiki.debian.org/DebianInstaller/Preseed
+-# https://help.ubuntu.com/10.04/installation-guide/i386/preseed-using.html
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-#export http_proxy=http://squid.corp.redhat.com:3128
+-#export https_proxy=$http_proxy
+-#export ftp_proxy=$http_proxy
+-location=http://archive.ubuntu.net/ubuntu/dists/precise/main/installer-amd64
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+- echo "You have to run this script as root."
+- exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f ubuntu-12.04.preseed ]; then
+- echo "You are running this script from the wrong directory."
+- exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-# Note that the injected file must be called "/preseed.cfg" in order
+-# for d-i to pick it up.
+-sed -e "s, at CACHE@,$http_proxy,g" < ubuntu-12.04.preseed > preseed.cfg
+-
+-name=tmpprecise
+-
+-virsh undefine $name ||:
+-rm -f ubuntu-12.04 ubuntu-12.04.old
+-
+-virt-install \
+- --name $name \
+- --ram=1024 \
+- --os-type=linux --os-variant=ubuntuprecise \
+- --initrd-inject=$pwd/preseed.cfg \
+- --extra-args="auto console=tty0 console=ttyS0,115200" \
+- --disk=$pwd/ubuntu-12.04,size=4 \
+- --location=$location \
+- --nographics \
+- --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine $name
+-
+-rm preseed.cfg
+-
+-# Sysprep (removes logfiles and so on).
+-virt-sysprep -a ubuntu-12.04
+-
+-# Sparsify.
+-mv ubuntu-12.04 ubuntu-12.04.old
+-virt-sparsify ubuntu-12.04.old ubuntu-12.04
+-rm ubuntu-12.04.old
+-
+-# Compress.
+-rm -f ubuntu-12.04.xz
+-xz --best --block-size=16777216 ubuntu-12.04
+-
+-# Result:
+-ls -lh ubuntu-12.04.xz
+diff --git a/builder/website/ubuntu-13.10.preseed b/builder/website/ubuntu-13.10.preseed
+deleted file mode 100644
+index 236e174..0000000
+--- a/builder/website/ubuntu-13.10.preseed
++++ /dev/null
+@@ -1,376 +0,0 @@
+-#### Contents of the preconfiguration file (for &releasename;)
+-### Localization
+-# Locale sets language and country.
+-d-i debian-installer/locale string en_US
+-
+-# Keyboard selection.
+-# Disable automatic (interactive) keymap detection.
+-d-i console-setup/ask_detect boolean false
+-#d-i console-setup/modelcode string pc105
+-d-i console-setup/layoutcode string us
+-# To select a variant of the selected layout (if you leave this out, the
+-# basic form of the layout will be used):
+-#d-i console-setup/variantcode string dvorak
+-
+-### Network configuration
+-# netcfg will choose an interface that has link if possible. This makes it
+-# skip displaying a list if there is more than one interface.
+-d-i netcfg/choose_interface select auto
+-
+-# To pick a particular interface instead:
+-#d-i netcfg/choose_interface select eth1
+-
+-# If you have a slow dhcp server and the installer times out waiting for
+-# it, this might be useful.
+-#d-i netcfg/dhcp_timeout string 60
+-
+-# If you prefer to configure the network manually, uncomment this line and
+-# the static network configuration below.
+-#d-i netcfg/disable_dhcp boolean true
+-
+-# If you want the preconfiguration file to work on systems both with and
+-# without a dhcp server, uncomment these lines and the static network
+-# configuration below.
+-#d-i netcfg/dhcp_failed note
+-#d-i netcfg/dhcp_options select Configure network manually
+-
+-# Static network configuration.
+-#d-i netcfg/get_nameservers string 192.168.1.1
+-#d-i netcfg/get_ipaddress string 192.168.1.42
+-#d-i netcfg/get_netmask string 255.255.255.0
+-#d-i netcfg/get_gateway string 192.168.1.1
+-#d-i netcfg/confirm_static boolean true
+-
+-# Any hostname and domain names assigned from dhcp take precedence over
+-# values set here. However, setting the values still prevents the questions
+-# from being shown, even if values come from dhcp.
+-d-i netcfg/get_hostname string unassigned-hostname
+-d-i netcfg/get_domain string unassigned-domain
+-
+-# Disable that annoying WEP key dialog.
+-d-i netcfg/wireless_wep string
+-# The wacky dhcp hostname that some ISPs use as a password of sorts.
+-#d-i netcfg/dhcp_hostname string radish
+-
+-# If non-free firmware is needed for the network or other hardware, you can
+-# configure the installer to always try to load it, without prompting. Or
+-# change to false to disable asking.
+-#d-i hw-detect/load_firmware boolean true
+-
+-### Mirror settings
+-# If you select ftp, the mirror/country string does not need to be set.
+-#d-i mirror/protocol string ftp
+-#d-i mirror/country string manual
+-#d-i mirror/http/hostname string http.us.debian.org
+-#d-i mirror/http/directory string /ubuntu
+-#d-i mirror/http/proxy string
+-
+-# Alternatively: by default, the installer uses CC.archive.ubuntu.com where
+-# CC is the ISO-3166-2 code for the selected country. You can preseed this
+-# so that it does so without asking.
+-d-i mirror/http/mirror select uk.archive.ubuntu.com
+-
+-# Suite to install.
+-#d-i mirror/suite string &releasename;
+-# Suite to use for loading installer components (optional).
+-#d-i mirror/udeb/suite string &releasename;
+-# Components to use for loading installer components (optional).
+-#d-i mirror/udeb/components multiselect main, restricted
+-
+-### Clock and time zone setup
+-# Controls whether or not the hardware clock is set to UTC.
+-d-i clock-setup/utc boolean true
+-
+-# You may set this to any valid setting for $TZ; see the contents of
+-# /usr/share/zoneinfo/ for valid values.
+-d-i time/zone string US/Eastern
+-
+-# Controls whether to use NTP to set the clock during the install
+-d-i clock-setup/ntp boolean true
+-# NTP server to use. The default is almost always fine here.
+-#d-i clock-setup/ntp-server string ntp.example.com
+-
+-### Partitioning
+-# If the system has free space you can choose to only partition that space.
+-# Alternatives: custom, some_device, some_device_crypto, some_device_lvm.
+-#d-i partman-auto/init_automatically_partition select biggest_free
+-
+-# Alternatively, you can specify a disk to partition. The device name must
+-# be given in traditional non-devfs format.
+-# Note: A disk must be specified, unless the system has only one disk.
+-# For example, to use the first SCSI/SATA hard disk:
+-#d-i partman-auto/disk string /dev/sda
+-# In addition, you'll need to specify the method to use.
+-# The presently available methods are: "regular", "lvm" and "crypto"
+-d-i partman-auto/method string regular
+-
+-# If one of the disks that are going to be automatically partitioned
+-# contains an old LVM configuration, the user will normally receive a
+-# warning. This can be preseeded away...
+-d-i partman-lvm/device_remove_lvm boolean true
+-# The same applies to pre-existing software RAID array:
+-d-i partman-md/device_remove_md boolean true
+-# And the same goes for the confirmation to write the lvm partitions.
+-d-i partman-lvm/confirm boolean true
+-
+-# For LVM partitioning, you can select how much of the volume group to use
+-# for logical volumes.
+-#d-i partman-auto-lvm/guided_size string max
+-#d-i partman-auto-lvm/guided_size string 10GB
+-#d-i partman-auto-lvm/guided_size string 50%
+-
+-# You can choose one of the three predefined partitioning recipes:
+-# - atomic: all files in one partition
+-# - home: separate /home partition
+-# - multi: separate /home, /usr, /var, and /tmp partitions
+-d-i partman-auto/choose_recipe select atomic
+-
+-# Or provide a recipe of your own...
+-# The recipe format is documented in the file devel/partman-auto-recipe.txt.
+-# If you have a way to get a recipe file into the d-i environment, you can
+-# just point at it.
+-#d-i partman-auto/expert_recipe_file string /hd-media/recipe
+-
+-# If not, you can put an entire recipe into the preconfiguration file in one
+-# (logical) line. This example creates a small /boot partition, suitable
+-# swap, and uses the rest of the space for the root partition:
+-#d-i partman-auto/expert_recipe string \
+-# boot-root :: \
+-# 40 50 100 ext3 \
+-# $primary{ } $bootable{ } \
+-# method{ format } format{ } \
+-# use_filesystem{ } filesystem{ ext3 } \
+-# mountpoint{ /boot } \
+-# . \
+-# 500 10000 1000000000 ext3 \
+-# method{ format } format{ } \
+-# use_filesystem{ } filesystem{ ext3 } \
+-# mountpoint{ / } \
+-# . \
+-# 64 512 300% linux-swap \
+-# method{ swap } format{ } \
+-# .
+-
+-# If you just want to change the default filesystem from ext3 to something
+-# else, you can do that without providing a full recipe.
+-#d-i partman/default_filesystem string ext4
+-
+-# This makes partman automatically partition without confirmation, provided
+-# that you told it what to do using one of the methods above.
+-d-i partman/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-### Controlling how partitions are mounted
+-# The default is to mount by UUID, but you can also choose "traditional" to
+-# use traditional device names, or "label" to try filesystem labels before
+-# falling back to UUIDs.
+-#d-i partman/mount_style select uuid
+-
+-### Base system installation
+-# The kernel image (meta) package to be installed; "none" can be used if no
+-# kernel is to be installed.
+-#d-i base-installer/kernel/image string linux-generic
+-
+-### Account setup
+-# Skip creation of a root account (normal user account will be able to
+-# use sudo). The default is false; preseed this to true if you want to set
+-# a root password.
+-#d-i passwd/root-login boolean false
+-# Alternatively, to skip creation of a normal user account.
+-d-i passwd/make-user boolean false
+-
+-# Root password, either in clear text
+-d-i passwd/root-password password builder
+-d-i passwd/root-password-again password builder
+-# or encrypted using an MD5 hash.
+-#d-i passwd/root-password-crypted password [MD5 hash]
+-
+-# To create a normal user account.
+-#d-i passwd/user-fullname string Ubuntu User
+-#d-i passwd/username string ubuntu
+-# Normal user's password, either in clear text
+-#d-i passwd/user-password password insecure
+-#d-i passwd/user-password-again password insecure
+-# or encrypted using an MD5 hash.
+-#d-i passwd/user-password-crypted password [MD5 hash]
+-# Create the first user with the specified UID instead of the default.
+-#d-i passwd/user-uid string 1010
+-# The installer will warn about weak passwords. If you are sure you know
+-# what you're doing and want to override it, uncomment this.
+-#d-i user-setup/allow-password-weak boolean true
+-
+-# The user account will be added to some standard initial groups. To
+-# override that, use this.
+-#d-i passwd/user-default-groups string audio cdrom video
+-
+-# Set to true if you want to encrypt the first user's home directory.
+-d-i user-setup/encrypt-home boolean false
+-
+-### Apt setup
+-# You can choose to install restricted and universe software, or to install
+-# software from the backports repository.
+-#d-i apt-setup/restricted boolean true
+-#d-i apt-setup/universe boolean true
+-#d-i apt-setup/backports boolean true
+-# Uncomment this if you don't want to use a network mirror.
+-#d-i apt-setup/use_mirror boolean false
+-# Select which update services to use; define the mirrors to be used.
+-# Values shown below are the normal defaults.
+-#d-i apt-setup/services-select multiselect security
+-#d-i apt-setup/security_host string security.ubuntu.com
+-#d-i apt-setup/security_path string /ubuntu
+-
+-# Additional repositories, local[0-9] available
+-#d-i apt-setup/local0/repository string \
+-# http://local.server/ubuntu &releasename; main
+-#d-i apt-setup/local0/comment string local server
+-# Enable deb-src lines
+-#d-i apt-setup/local0/source boolean true
+-# URL to the public key of the local repository; you must provide a key or
+-# apt will complain about the unauthenticated repository and so the
+-# sources.list line will be left commented out
+-#d-i apt-setup/local0/key string http://local.server/key
+-
+-# By default the installer requires that repositories be authenticated
+-# using a known gpg key. This setting can be used to disable that
+-# authentication. Warning: Insecure, not recommended.
+-#d-i debian-installer/allow_unauthenticated string true
+-
+-### Package selection
+-#tasksel tasksel/first multiselect ubuntu-desktop
+-#tasksel tasksel/first multiselect lamp-server, print-server
+-#tasksel tasksel/first multiselect kubuntu-desktop
+-tasksel tasksel/first multiselect openssh-server
+-
+-# Individual additional packages to install
+-#d-i pkgsel/include string openssh-server build-essential
+-# Whether to upgrade packages after debootstrap.
+-# Allowed values: none, safe-upgrade, full-upgrade
+-#d-i pkgsel/upgrade select none
+-
+-# Language pack selection
+-#d-i pkgsel/language-packs multiselect de, en, zh
+-
+-# Policy for applying updates. May be "none" (no automatic updates),
+-# "unattended-upgrades" (install security updates automatically), or
+-# "landscape" (manage system with Landscape).
+-#d-i pkgsel/update-policy select none
+-
+-# Some versions of the installer can report back on what software you have
+-# installed, and what software you use. The default is not to report back,
+-# but sending reports helps the project determine what software is most
+-# popular and include it on CDs.
+-#popularity-contest popularity-contest/participate boolean false
+-
+-# By default, the system's locate database will be updated after the
+-# installer has finished installing most packages. This may take a while, so
+-# if you don't want it, you can set this to "false" to turn it off.
+-#d-i pkgsel/updatedb boolean true
+-
+-### Boot loader installation
+-# Grub is the default boot loader (for x86). If you want lilo installed
+-# instead, uncomment this:
+-#d-i grub-installer/skip boolean true
+-# To also skip installing lilo, and install no bootloader, uncomment this
+-# too:
+-#d-i lilo-installer/skip boolean true
+-
+-# This is fairly safe to set, it makes grub install automatically to the MBR
+-# if no other operating system is detected on the machine.
+-d-i grub-installer/only_debian boolean true
+-
+-# This one makes grub-installer install to the MBR if it also finds some other
+-# OS, which is less safe as it might not be able to boot that other OS.
+-d-i grub-installer/with_other_os boolean true
+-
+-# Alternatively, if you want to install to a location other than the mbr,
+-# uncomment and edit these lines:
+-#d-i grub-installer/only_debian boolean false
+-#d-i grub-installer/with_other_os boolean false
+-#d-i grub-installer/bootdev string (hd0,0)
+-# To install grub to multiple disks:
+-#d-i grub-installer/bootdev string (hd0,0) (hd1,0) (hd2,0)
+-
+-# Optional password for grub, either in clear text
+-#d-i grub-installer/password password r00tme
+-#d-i grub-installer/password-again password r00tme
+-# or encrypted using an MD5 hash, see grub-md5-crypt(8).
+-#d-i grub-installer/password-crypted password [MD5 hash]
+-
+-### Finishing up the installation
+-# During installations from serial console, the regular virtual consoles
+-# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
+-# line to prevent this.
+-#d-i finish-install/keep-consoles boolean true
+-
+-# Avoid that last message about the install being complete.
+-d-i finish-install/reboot_in_progress note
+-
+-# This will prevent the installer from ejecting the CD during the reboot,
+-# which is useful in some situations.
+-#d-i cdrom-detect/eject boolean false
+-
+-# This is how to make the installer shutdown when finished, but not
+-# reboot into the installed system.
+-#d-i debian-installer/exit/halt boolean true
+-# This will power off the machine instead of just halting it.
+-#d-i debian-installer/exit/poweroff boolean true
+-
+-### X configuration
+-# X can detect the right driver for some cards, but if you're preseeding,
+-# you override whatever it chooses. Still, vesa will work most places.
+-#xserver-xorg xserver-xorg/config/device/driver select vesa
+-
+-# A caveat with mouse autodetection is that if it fails, X will retry it
+-# over and over. So if it's preseeded to be done, there is a possibility of
+-# an infinite loop if the mouse is not autodetected.
+-#xserver-xorg xserver-xorg/autodetect_mouse boolean true
+-
+-# Monitor autodetection is recommended.
+-xserver-xorg xserver-xorg/autodetect_monitor boolean true
+-# Uncomment if you have an LCD display.
+-#xserver-xorg xserver-xorg/config/monitor/lcd boolean true
+-# X has three configuration paths for the monitor. Here's how to preseed
+-# the "medium" path, which is always available. The "simple" path may not
+-# be available, and the "advanced" path asks too many questions.
+-xserver-xorg xserver-xorg/config/monitor/selection-method \
+- select medium
+-xserver-xorg xserver-xorg/config/monitor/mode-list \
+- select 1024x768 @ 60 Hz
+-
+-### Preseeding other packages
+-# Depending on what software you choose to install, or if things go wrong
+-# during the installation process, it's possible that other questions may
+-# be asked. You can preseed those too, of course. To get a list of every
+-# possible question that could be asked during an install, do an
+-# installation, and then run these commands:
+-# debconf-get-selections --installer > file
+-# debconf-get-selections >> file
+-
+-
+-#### Advanced options
+-### Running custom commands during the installation
+-# d-i preseeding is inherently not secure. Nothing in the installer checks
+-# for attempts at buffer overflows or other exploits of the values of a
+-# preconfiguration file like this one. Only use preconfiguration files from
+-# trusted locations! To drive that home, and because it's generally useful,
+-# here's a way to run any shell command you'd like inside the installer,
+-# automatically.
+-
+-# This first command is run as early as possible, just after
+-# preseeding is read.
+-#d-i preseed/early_command string anna-install some-udeb
+-
+-# This command is run immediately before the partitioner starts. It may be
+-# useful to apply dynamic partitioner preseeding that depends on the state
+-# of the disks (which may not be visible when preseed/early_command runs).
+-#d-i partman/early_command string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
+-
+-# This command is run just before the install finishes, but when there is
+-# still a usable /target directory. You can chroot to /target and use it
+-# directly, or use the apt-install and in-target commands to easily install
+-# packages and run commands in the target system.
+-#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+-
+diff --git a/builder/website/ubuntu-13.10.sh b/builder/website/ubuntu-13.10.sh
+deleted file mode 100755
+index 7373176..0000000
+--- a/builder/website/ubuntu-13.10.sh
++++ /dev/null
+@@ -1,85 +0,0 @@
+-#!/bin/bash -
+-# 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.
+-
+-# The basic plan comes from:
+-# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
+-# https://wiki.debian.org/DebianInstaller/Preseed
+-# https://help.ubuntu.com/10.04/installation-guide/i386/preseed-using.html
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-#export http_proxy=http://squid.corp.redhat.com:3128
+-#export https_proxy=$http_proxy
+-#export ftp_proxy=$http_proxy
+-location=http://archive.ubuntu.net/ubuntu/dists/saucy/main/installer-amd64
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+- echo "You have to run this script as root."
+- exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f ubuntu-13.10.preseed ]; then
+- echo "You are running this script from the wrong directory."
+- exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-# Note that the injected file must be called "/preseed.cfg" in order
+-# for d-i to pick it up.
+-sed -e "s, at CACHE@,$http_proxy,g" < ubuntu-13.10.preseed > preseed.cfg
+-
+-name=tmpsaucy
+-
+-virsh undefine $name ||:
+-rm -f ubuntu-13.10 ubuntu-13.10.old
+-
+-virt-install \
+- --name $name \
+- --ram=1024 \
+- --os-type=linux --os-variant=ubuntusaucy \
+- --initrd-inject=$pwd/preseed.cfg \
+- --extra-args="auto console=tty0 console=ttyS0,115200" \
+- --disk=$pwd/ubuntu-13.10,size=4 \
+- --location=$location \
+- --nographics \
+- --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine $name
+-
+-rm preseed.cfg
+-
+-# Sysprep (removes logfiles and so on).
+-virt-sysprep -a ubuntu-13.10
+-
+-# Sparsify.
+-mv ubuntu-13.10 ubuntu-13.10.old
+-virt-sparsify ubuntu-13.10.old ubuntu-13.10
+-rm ubuntu-13.10.old
+-
+-# Compress.
+-rm -f ubuntu-13.10.xz
+-xz --best --block-size=16777216 ubuntu-13.10
+-
+-# Result:
+-ls -lh ubuntu-13.10.xz
+diff --git a/builder/website/ubuntu.preseed b/builder/website/ubuntu.preseed
+new file mode 100644
+index 0000000..236e174
+--- /dev/null
++++ b/builder/website/ubuntu.preseed
+@@ -0,0 +1,376 @@
++#### Contents of the preconfiguration file (for &releasename;)
++### Localization
++# Locale sets language and country.
++d-i debian-installer/locale string en_US
++
++# Keyboard selection.
++# Disable automatic (interactive) keymap detection.
++d-i console-setup/ask_detect boolean false
++#d-i console-setup/modelcode string pc105
++d-i console-setup/layoutcode string us
++# To select a variant of the selected layout (if you leave this out, the
++# basic form of the layout will be used):
++#d-i console-setup/variantcode string dvorak
++
++### Network configuration
++# netcfg will choose an interface that has link if possible. This makes it
++# skip displaying a list if there is more than one interface.
++d-i netcfg/choose_interface select auto
++
++# To pick a particular interface instead:
++#d-i netcfg/choose_interface select eth1
++
++# If you have a slow dhcp server and the installer times out waiting for
++# it, this might be useful.
++#d-i netcfg/dhcp_timeout string 60
++
++# If you prefer to configure the network manually, uncomment this line and
++# the static network configuration below.
++#d-i netcfg/disable_dhcp boolean true
++
++# If you want the preconfiguration file to work on systems both with and
++# without a dhcp server, uncomment these lines and the static network
++# configuration below.
++#d-i netcfg/dhcp_failed note
++#d-i netcfg/dhcp_options select Configure network manually
++
++# Static network configuration.
++#d-i netcfg/get_nameservers string 192.168.1.1
++#d-i netcfg/get_ipaddress string 192.168.1.42
++#d-i netcfg/get_netmask string 255.255.255.0
++#d-i netcfg/get_gateway string 192.168.1.1
++#d-i netcfg/confirm_static boolean true
++
++# Any hostname and domain names assigned from dhcp take precedence over
++# values set here. However, setting the values still prevents the questions
++# from being shown, even if values come from dhcp.
++d-i netcfg/get_hostname string unassigned-hostname
++d-i netcfg/get_domain string unassigned-domain
++
++# Disable that annoying WEP key dialog.
++d-i netcfg/wireless_wep string
++# The wacky dhcp hostname that some ISPs use as a password of sorts.
++#d-i netcfg/dhcp_hostname string radish
++
++# If non-free firmware is needed for the network or other hardware, you can
++# configure the installer to always try to load it, without prompting. Or
++# change to false to disable asking.
++#d-i hw-detect/load_firmware boolean true
++
++### Mirror settings
++# If you select ftp, the mirror/country string does not need to be set.
++#d-i mirror/protocol string ftp
++#d-i mirror/country string manual
++#d-i mirror/http/hostname string http.us.debian.org
++#d-i mirror/http/directory string /ubuntu
++#d-i mirror/http/proxy string
++
++# Alternatively: by default, the installer uses CC.archive.ubuntu.com where
++# CC is the ISO-3166-2 code for the selected country. You can preseed this
++# so that it does so without asking.
++d-i mirror/http/mirror select uk.archive.ubuntu.com
++
++# Suite to install.
++#d-i mirror/suite string &releasename;
++# Suite to use for loading installer components (optional).
++#d-i mirror/udeb/suite string &releasename;
++# Components to use for loading installer components (optional).
++#d-i mirror/udeb/components multiselect main, restricted
++
++### Clock and time zone setup
++# Controls whether or not the hardware clock is set to UTC.
++d-i clock-setup/utc boolean true
++
++# You may set this to any valid setting for $TZ; see the contents of
++# /usr/share/zoneinfo/ for valid values.
++d-i time/zone string US/Eastern
++
++# Controls whether to use NTP to set the clock during the install
++d-i clock-setup/ntp boolean true
++# NTP server to use. The default is almost always fine here.
++#d-i clock-setup/ntp-server string ntp.example.com
++
++### Partitioning
++# If the system has free space you can choose to only partition that space.
++# Alternatives: custom, some_device, some_device_crypto, some_device_lvm.
++#d-i partman-auto/init_automatically_partition select biggest_free
++
++# Alternatively, you can specify a disk to partition. The device name must
++# be given in traditional non-devfs format.
++# Note: A disk must be specified, unless the system has only one disk.
++# For example, to use the first SCSI/SATA hard disk:
++#d-i partman-auto/disk string /dev/sda
++# In addition, you'll need to specify the method to use.
++# The presently available methods are: "regular", "lvm" and "crypto"
++d-i partman-auto/method string regular
++
++# If one of the disks that are going to be automatically partitioned
++# contains an old LVM configuration, the user will normally receive a
++# warning. This can be preseeded away...
++d-i partman-lvm/device_remove_lvm boolean true
++# The same applies to pre-existing software RAID array:
++d-i partman-md/device_remove_md boolean true
++# And the same goes for the confirmation to write the lvm partitions.
++d-i partman-lvm/confirm boolean true
++
++# For LVM partitioning, you can select how much of the volume group to use
++# for logical volumes.
++#d-i partman-auto-lvm/guided_size string max
++#d-i partman-auto-lvm/guided_size string 10GB
++#d-i partman-auto-lvm/guided_size string 50%
++
++# You can choose one of the three predefined partitioning recipes:
++# - atomic: all files in one partition
++# - home: separate /home partition
++# - multi: separate /home, /usr, /var, and /tmp partitions
++d-i partman-auto/choose_recipe select atomic
++
++# Or provide a recipe of your own...
++# The recipe format is documented in the file devel/partman-auto-recipe.txt.
++# If you have a way to get a recipe file into the d-i environment, you can
++# just point at it.
++#d-i partman-auto/expert_recipe_file string /hd-media/recipe
++
++# If not, you can put an entire recipe into the preconfiguration file in one
++# (logical) line. This example creates a small /boot partition, suitable
++# swap, and uses the rest of the space for the root partition:
++#d-i partman-auto/expert_recipe string \
++# boot-root :: \
++# 40 50 100 ext3 \
++# $primary{ } $bootable{ } \
++# method{ format } format{ } \
++# use_filesystem{ } filesystem{ ext3 } \
++# mountpoint{ /boot } \
++# . \
++# 500 10000 1000000000 ext3 \
++# method{ format } format{ } \
++# use_filesystem{ } filesystem{ ext3 } \
++# mountpoint{ / } \
++# . \
++# 64 512 300% linux-swap \
++# method{ swap } format{ } \
++# .
++
++# If you just want to change the default filesystem from ext3 to something
++# else, you can do that without providing a full recipe.
++#d-i partman/default_filesystem string ext4
++
++# This makes partman automatically partition without confirmation, provided
++# that you told it what to do using one of the methods above.
++d-i partman/confirm_write_new_label boolean true
++d-i partman/choose_partition select finish
++d-i partman/confirm boolean true
++d-i partman/confirm_nooverwrite boolean true
++
++### Controlling how partitions are mounted
++# The default is to mount by UUID, but you can also choose "traditional" to
++# use traditional device names, or "label" to try filesystem labels before
++# falling back to UUIDs.
++#d-i partman/mount_style select uuid
++
++### Base system installation
++# The kernel image (meta) package to be installed; "none" can be used if no
++# kernel is to be installed.
++#d-i base-installer/kernel/image string linux-generic
++
++### Account setup
++# Skip creation of a root account (normal user account will be able to
++# use sudo). The default is false; preseed this to true if you want to set
++# a root password.
++#d-i passwd/root-login boolean false
++# Alternatively, to skip creation of a normal user account.
++d-i passwd/make-user boolean false
++
++# Root password, either in clear text
++d-i passwd/root-password password builder
++d-i passwd/root-password-again password builder
++# or encrypted using an MD5 hash.
++#d-i passwd/root-password-crypted password [MD5 hash]
++
++# To create a normal user account.
++#d-i passwd/user-fullname string Ubuntu User
++#d-i passwd/username string ubuntu
++# Normal user's password, either in clear text
++#d-i passwd/user-password password insecure
++#d-i passwd/user-password-again password insecure
++# or encrypted using an MD5 hash.
++#d-i passwd/user-password-crypted password [MD5 hash]
++# Create the first user with the specified UID instead of the default.
++#d-i passwd/user-uid string 1010
++# The installer will warn about weak passwords. If you are sure you know
++# what you're doing and want to override it, uncomment this.
++#d-i user-setup/allow-password-weak boolean true
++
++# The user account will be added to some standard initial groups. To
++# override that, use this.
++#d-i passwd/user-default-groups string audio cdrom video
++
++# Set to true if you want to encrypt the first user's home directory.
++d-i user-setup/encrypt-home boolean false
++
++### Apt setup
++# You can choose to install restricted and universe software, or to install
++# software from the backports repository.
++#d-i apt-setup/restricted boolean true
++#d-i apt-setup/universe boolean true
++#d-i apt-setup/backports boolean true
++# Uncomment this if you don't want to use a network mirror.
++#d-i apt-setup/use_mirror boolean false
++# Select which update services to use; define the mirrors to be used.
++# Values shown below are the normal defaults.
++#d-i apt-setup/services-select multiselect security
++#d-i apt-setup/security_host string security.ubuntu.com
++#d-i apt-setup/security_path string /ubuntu
++
++# Additional repositories, local[0-9] available
++#d-i apt-setup/local0/repository string \
++# http://local.server/ubuntu &releasename; main
++#d-i apt-setup/local0/comment string local server
++# Enable deb-src lines
++#d-i apt-setup/local0/source boolean true
++# URL to the public key of the local repository; you must provide a key or
++# apt will complain about the unauthenticated repository and so the
++# sources.list line will be left commented out
++#d-i apt-setup/local0/key string http://local.server/key
++
++# By default the installer requires that repositories be authenticated
++# using a known gpg key. This setting can be used to disable that
++# authentication. Warning: Insecure, not recommended.
++#d-i debian-installer/allow_unauthenticated string true
++
++### Package selection
++#tasksel tasksel/first multiselect ubuntu-desktop
++#tasksel tasksel/first multiselect lamp-server, print-server
++#tasksel tasksel/first multiselect kubuntu-desktop
++tasksel tasksel/first multiselect openssh-server
++
++# Individual additional packages to install
++#d-i pkgsel/include string openssh-server build-essential
++# Whether to upgrade packages after debootstrap.
++# Allowed values: none, safe-upgrade, full-upgrade
++#d-i pkgsel/upgrade select none
++
++# Language pack selection
++#d-i pkgsel/language-packs multiselect de, en, zh
++
++# Policy for applying updates. May be "none" (no automatic updates),
++# "unattended-upgrades" (install security updates automatically), or
++# "landscape" (manage system with Landscape).
++#d-i pkgsel/update-policy select none
++
++# Some versions of the installer can report back on what software you have
++# installed, and what software you use. The default is not to report back,
++# but sending reports helps the project determine what software is most
++# popular and include it on CDs.
++#popularity-contest popularity-contest/participate boolean false
++
++# By default, the system's locate database will be updated after the
++# installer has finished installing most packages. This may take a while, so
++# if you don't want it, you can set this to "false" to turn it off.
++#d-i pkgsel/updatedb boolean true
++
++### Boot loader installation
++# Grub is the default boot loader (for x86). If you want lilo installed
++# instead, uncomment this:
++#d-i grub-installer/skip boolean true
++# To also skip installing lilo, and install no bootloader, uncomment this
++# too:
++#d-i lilo-installer/skip boolean true
++
++# This is fairly safe to set, it makes grub install automatically to the MBR
++# if no other operating system is detected on the machine.
++d-i grub-installer/only_debian boolean true
++
++# This one makes grub-installer install to the MBR if it also finds some other
++# OS, which is less safe as it might not be able to boot that other OS.
++d-i grub-installer/with_other_os boolean true
++
++# Alternatively, if you want to install to a location other than the mbr,
++# uncomment and edit these lines:
++#d-i grub-installer/only_debian boolean false
++#d-i grub-installer/with_other_os boolean false
++#d-i grub-installer/bootdev string (hd0,0)
++# To install grub to multiple disks:
++#d-i grub-installer/bootdev string (hd0,0) (hd1,0) (hd2,0)
++
++# Optional password for grub, either in clear text
++#d-i grub-installer/password password r00tme
++#d-i grub-installer/password-again password r00tme
++# or encrypted using an MD5 hash, see grub-md5-crypt(8).
++#d-i grub-installer/password-crypted password [MD5 hash]
++
++### Finishing up the installation
++# During installations from serial console, the regular virtual consoles
++# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
++# line to prevent this.
++#d-i finish-install/keep-consoles boolean true
++
++# Avoid that last message about the install being complete.
++d-i finish-install/reboot_in_progress note
++
++# This will prevent the installer from ejecting the CD during the reboot,
++# which is useful in some situations.
++#d-i cdrom-detect/eject boolean false
++
++# This is how to make the installer shutdown when finished, but not
++# reboot into the installed system.
++#d-i debian-installer/exit/halt boolean true
++# This will power off the machine instead of just halting it.
++#d-i debian-installer/exit/poweroff boolean true
++
++### X configuration
++# X can detect the right driver for some cards, but if you're preseeding,
++# you override whatever it chooses. Still, vesa will work most places.
++#xserver-xorg xserver-xorg/config/device/driver select vesa
++
++# A caveat with mouse autodetection is that if it fails, X will retry it
++# over and over. So if it's preseeded to be done, there is a possibility of
++# an infinite loop if the mouse is not autodetected.
++#xserver-xorg xserver-xorg/autodetect_mouse boolean true
++
++# Monitor autodetection is recommended.
++xserver-xorg xserver-xorg/autodetect_monitor boolean true
++# Uncomment if you have an LCD display.
++#xserver-xorg xserver-xorg/config/monitor/lcd boolean true
++# X has three configuration paths for the monitor. Here's how to preseed
++# the "medium" path, which is always available. The "simple" path may not
++# be available, and the "advanced" path asks too many questions.
++xserver-xorg xserver-xorg/config/monitor/selection-method \
++ select medium
++xserver-xorg xserver-xorg/config/monitor/mode-list \
++ select 1024x768 @ 60 Hz
++
++### Preseeding other packages
++# Depending on what software you choose to install, or if things go wrong
++# during the installation process, it's possible that other questions may
++# be asked. You can preseed those too, of course. To get a list of every
++# possible question that could be asked during an install, do an
++# installation, and then run these commands:
++# debconf-get-selections --installer > file
++# debconf-get-selections >> file
++
++
++#### Advanced options
++### Running custom commands during the installation
++# d-i preseeding is inherently not secure. Nothing in the installer checks
++# for attempts at buffer overflows or other exploits of the values of a
++# preconfiguration file like this one. Only use preconfiguration files from
++# trusted locations! To drive that home, and because it's generally useful,
++# here's a way to run any shell command you'd like inside the installer,
++# automatically.
++
++# This first command is run as early as possible, just after
++# preseeding is read.
++#d-i preseed/early_command string anna-install some-udeb
++
++# This command is run immediately before the partitioner starts. It may be
++# useful to apply dynamic partitioner preseeding that depends on the state
++# of the disks (which may not be visible when preseed/early_command runs).
++#d-i partman/early_command string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
++
++# This command is run just before the install finishes, but when there is
++# still a usable /target directory. You can chroot to /target and use it
++# directly, or use the apt-install and in-target commands to easily install
++# packages and run commands in the target system.
++#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
++
+diff --git a/builder/website/ubuntu.sh b/builder/website/ubuntu.sh
+new file mode 100755
+index 0000000..edafd69
+--- /dev/null
++++ b/builder/website/ubuntu.sh
+@@ -0,0 +1,84 @@
++#!/bin/bash -
++# 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.
++
++# The basic plan comes from:
++# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
++# https://wiki.debian.org/DebianInstaller/Preseed
++# https://help.ubuntu.com/10.04/installation-guide/i386/preseed-using.html
++
++unset CDPATH
++export LANG=C
++set -e
++set -x
++
++if [ $# -ne 2 ]; then
++ echo "$0 VERSION DIST"
++ exit 1
++fi
++
++# Some configuration.
++version=$1
++dist=$2
++location=http://archive.ubuntu.net/ubuntu/dists/$dist/main/installer-amd64
++output=ubuntu-$version
++tmpname=tmp-$(tr -cd 'a-f0-9' < /dev/urandom | head -c 8)
++
++rm -f $output $output.old $output.xz
++
++# Make sure it's being run from the correct directory.
++if [ ! -f ubuntu.preseed ]; then
++ echo "You are running this script from the wrong directory."
++ exit 1
++fi
++
++# Note that the injected file must be called "/preseed.cfg" in order
++# for d-i to pick it up.
++sed -e "s, at CACHE@,$http_proxy,g" < ubuntu.preseed > preseed.cfg
++
++# Clean up function.
++cleanup ()
++{
++ rm -f preseed.cfg
++ virsh undefine $tmpname ||:
++}
++trap cleanup INT QUIT TERM EXIT ERR
++
++virt-install \
++ --name=$tmpname \
++ --ram=1024 \
++ --os-type=linux --os-variant=ubuntu$dist \
++ --initrd-inject=$(pwd)/preseed.cfg \
++ --extra-args="auto console=tty0 console=ttyS0,115200" \
++ --disk=$(pwd)/$output,size=4 \
++ --location=$location \
++ --nographics \
++ --noreboot
++
++# Sysprep (removes logfiles and so on).
++virt-sysprep -a $output
++
++# Sparsify.
++mv $output $output.old
++virt-sparsify $output.old $output
++rm $output.old
++
++# Compress.
++xz --best --block-size=16777216 $output
++
++# Result:
++ls -lh $output.xz
+--
+1.8.3.1
+
diff --git a/0022-builder-Replace-debian-NN-.sh-with-a-single-script.patch b/0022-builder-Replace-debian-NN-.sh-with-a-single-script.patch
new file mode 100644
index 0000000..aeaf7bf
--- /dev/null
+++ b/0022-builder-Replace-debian-NN-.sh-with-a-single-script.patch
@@ -0,0 +1,1578 @@
+From 181b928c9e821fd8888966ba422120474b938f2e Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 14:08:01 +0000
+Subject: [PATCH] builder: Replace debian-<NN>.sh with a single script.
+
+Just use:
+
+ ./debian.sh 6 squeeze
+
+Note that you don't need to be root.
+
+(cherry picked from commit af9e9299bf0f422d7e07ccfe9a59e664b49c2dfe)
+---
+ builder/website/Makefile.am | 6 +-
+ builder/website/debian-6.preseed | 385 ---------------------------------------
+ builder/website/debian-6.sh | 76 --------
+ builder/website/debian-7.preseed | 385 ---------------------------------------
+ builder/website/debian-7.sh | 82 ---------
+ builder/website/debian.preseed | 385 +++++++++++++++++++++++++++++++++++++++
+ builder/website/debian.sh | 83 +++++++++
+ builder/website/index | 14 +-
+ builder/website/index.asc | 40 ++--
+ 9 files changed, 499 insertions(+), 957 deletions(-)
+ delete mode 100644 builder/website/debian-6.preseed
+ delete mode 100755 builder/website/debian-6.sh
+ delete mode 100644 builder/website/debian-7.preseed
+ delete mode 100755 builder/website/debian-7.sh
+ create mode 100644 builder/website/debian.preseed
+ create mode 100755 builder/website/debian.sh
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+index dfcb494..a662176 100644
+--- a/builder/website/Makefile.am
++++ b/builder/website/Makefile.am
+@@ -26,11 +26,9 @@ EXTRA_DIST = \
+ centos-6.ks \
+ centos-6.sh \
+ centos-6.xz.sig \
+- debian-6.preseed \
+- debian-6.sh \
++ debian.preseed \
++ debian.sh \
+ debian-6.xz.sig \
+- debian-7.preseed \
+- debian-7.sh \
+ debian-7.xz.sig \
+ fedora.sh \
+ fedora-18.xz.sig \
+diff --git a/builder/website/debian-6.preseed b/builder/website/debian-6.preseed
+deleted file mode 100644
+index faa4430..0000000
+--- a/builder/website/debian-6.preseed
++++ /dev/null
+@@ -1,385 +0,0 @@
+-#### Contents of the preconfiguration file (for wheezy)
+-### Localization
+-# Preseeding only locale sets language, country and locale.
+-d-i debian-installer/locale string en_US
+-
+-# The values can also be preseeded individually for greater flexibility.
+-#d-i debian-installer/language string en
+-#d-i debian-installer/country string NL
+-#d-i debian-installer/locale string en_GB.UTF-8
+-# Optionally specify additional locales to be generated.
+-#d-i localechooser/supported-locales multiselect en_US.UTF-8, nl_NL.UTF-8
+-
+-# Keyboard selection.
+-# keymap is an alias for keyboard-configuration/xkb-keymap
+-d-i keymap select us
+-# d-i keyboard-configuration/toggle select No toggling
+-
+-### Network configuration
+-# Disable network configuration entirely. This is useful for cdrom
+-# installations on non-networked devices where the network questions,
+-# warning and long timeouts are a nuisance.
+-d-i netcfg/enable boolean true
+-
+-# netcfg will choose an interface that has link if possible. This makes it
+-# skip displaying a list if there is more than one interface.
+-d-i netcfg/choose_interface select auto
+-
+-# To pick a particular interface instead:
+-#d-i netcfg/choose_interface select eth1
+-
+-# To set a different link detection timeout (default is 3 seconds).
+-# Values are interpreted as seconds.
+-#d-i netcfg/link_detection_timeout string 10
+-
+-# If you have a slow dhcp server and the installer times out waiting for
+-# it, this might be useful.
+-#d-i netcfg/dhcp_timeout string 60
+-#d-i netcfg/dhcpv6_timeout string 60
+-
+-# If you prefer to configure the network manually, uncomment this line and
+-# the static network configuration below.
+-#d-i netcfg/disable_autoconfig boolean true
+-
+-# If you want the preconfiguration file to work on systems both with and
+-# without a dhcp server, uncomment these lines and the static network
+-# configuration below.
+-#d-i netcfg/dhcp_failed note
+-#d-i netcfg/dhcp_options select Configure network manually
+-
+-# Static network configuration.
+-#
+-# IPv4 example
+-#d-i netcfg/get_ipaddress string 192.168.1.42
+-#d-i netcfg/get_netmask string 255.255.255.0
+-#d-i netcfg/get_gateway string 192.168.1.1
+-#d-i netcfg/get_nameservers string 192.168.1.1
+-#d-i netcfg/confirm_static boolean true
+-#
+-# IPv6 example
+-#d-i netcfg/get_ipaddress string fc00::2
+-#d-i netcfg/get_netmask string ffff:ffff:ffff:ffff::
+-#d-i netcfg/get_gateway string fc00::1
+-#d-i netcfg/get_nameservers string fc00::1
+-#d-i netcfg/confirm_static boolean true
+-
+-# Any hostname and domain names assigned from dhcp take precedence over
+-# values set here. However, setting the values still prevents the questions
+-# from being shown, even if values come from dhcp.
+-d-i netcfg/get_hostname string unassigned-hostname
+-d-i netcfg/get_domain string unassigned-domain
+-
+-# If you want to force a hostname, regardless of what either the DHCP
+-# server returns or what the reverse DNS entry for the IP is, uncomment
+-# and adjust the following line.
+-#d-i netcfg/hostname string somehost
+-
+-# Disable that annoying WEP key dialog.
+-d-i netcfg/wireless_wep string
+-# The wacky dhcp hostname that some ISPs use as a password of sorts.
+-#d-i netcfg/dhcp_hostname string radish
+-
+-# If non-free firmware is needed for the network or other hardware, you can
+-# configure the installer to always try to load it, without prompting. Or
+-# change to false to disable asking.
+-#d-i hw-detect/load_firmware boolean true
+-
+-### Network console
+-# Use the following settings if you wish to make use of the network-console
+-# component for remote installation over SSH. This only makes sense if you
+-# intend to perform the remainder of the installation manually.
+-#d-i anna/choose_modules string network-console
+-#d-i network-console/authorized_keys_url string http://10.0.0.1/openssh-key
+-#d-i network-console/password password r00tme
+-#d-i network-console/password-again password r00tme
+-
+-### Mirror settings
+-# If you select ftp, the mirror/country string does not need to be set.
+-#d-i mirror/protocol string ftp
+-d-i mirror/country string manual
+-d-i mirror/http/hostname string ftp.uk.debian.org
+-d-i mirror/http/directory string /debian
+-d-i mirror/http/proxy string @CACHE@
+-
+-# Suite to install.
+-#d-i mirror/suite string testing
+-# Suite to use for loading installer components (optional).
+-#d-i mirror/udeb/suite string testing
+-
+-### Account setup
+-# Skip creation of a root account (normal user account will be able to
+-# use sudo).
+-#d-i passwd/root-login boolean false
+-# Alternatively, to skip creation of a normal user account.
+-d-i passwd/make-user boolean false
+-
+-# Root password, either in clear text
+-d-i passwd/root-password password builder
+-d-i passwd/root-password-again password builder
+-# or encrypted using an MD5 hash.
+-#d-i passwd/root-password-crypted password [MD5 hash]
+-
+-# To create a normal user account.
+-#d-i passwd/user-fullname string Debian User
+-#d-i passwd/username string debian
+-# Normal user's password, either in clear text
+-#d-i passwd/user-password password insecure
+-#d-i passwd/user-password-again password insecure
+-# or encrypted using an MD5 hash.
+-#d-i passwd/user-password-crypted password [MD5 hash]
+-# Create the first user with the specified UID instead of the default.
+-#d-i passwd/user-uid string 1010
+-
+-# The user account will be added to some standard initial groups. To
+-# override that, use this.
+-#d-i passwd/user-default-groups string audio cdrom video
+-
+-### Clock and time zone setup
+-# Controls whether or not the hardware clock is set to UTC.
+-d-i clock-setup/utc boolean true
+-
+-# You may set this to any valid setting for $TZ; see the contents of
+-# /usr/share/zoneinfo/ for valid values.
+-d-i time/zone string US/Eastern
+-
+-# Controls whether to use NTP to set the clock during the install
+-d-i clock-setup/ntp boolean true
+-# NTP server to use. The default is almost always fine here.
+-#d-i clock-setup/ntp-server string ntp.example.com
+-
+-### Partitioning
+-## Partitioning example
+-# If the system has free space you can choose to only partition that space.
+-# This is only honoured if partman-auto/method (below) is not set.
+-#d-i partman-auto/init_automatically_partition select biggest_free
+-
+-# Alternatively, you may specify a disk to partition. If the system has only
+-# one disk the installer will default to using that, but otherwise the device
+-# name must be given in traditional, non-devfs format (so e.g. /dev/hda or
+-# /dev/sda, and not e.g. /dev/discs/disc0/disc).
+-# For example, to use the first SCSI/SATA hard disk:
+-#d-i partman-auto/disk string /dev/sda
+-# In addition, you'll need to specify the method to use.
+-# The presently available methods are:
+-# - regular: use the usual partition types for your architecture
+-# - lvm: use LVM to partition the disk
+-# - crypto: use LVM within an encrypted partition
+-d-i partman-auto/method string regular
+-
+-# If one of the disks that are going to be automatically partitioned
+-# contains an old LVM configuration, the user will normally receive a
+-# warning. This can be preseeded away...
+-d-i partman-lvm/device_remove_lvm boolean true
+-# The same applies to pre-existing software RAID array:
+-d-i partman-md/device_remove_md boolean true
+-# And the same goes for the confirmation to write the lvm partitions.
+-d-i partman-lvm/confirm boolean true
+-d-i partman-lvm/confirm_nooverwrite boolean true
+-
+-# You can choose one of the three predefined partitioning recipes:
+-# - atomic: all files in one partition
+-# - home: separate /home partition
+-# - multi: separate /home, /usr, /var, and /tmp partitions
+-d-i partman-auto/choose_recipe select atomic
+-
+-# Or provide a recipe of your own...
+-# If you have a way to get a recipe file into the d-i environment, you can
+-# just point at it.
+-#d-i partman-auto/expert_recipe_file string /hd-media/recipe
+-
+-# If not, you can put an entire recipe into the preconfiguration file in one
+-# (logical) line. This example creates a small /boot partition, suitable
+-# swap, and uses the rest of the space for the root partition:
+-#d-i partman-auto/expert_recipe string \
+-# boot-root :: \
+-# 40 50 100 ext3 \
+-# $primary{ } $bootable{ } \
+-# method{ format } format{ } \
+-# use_filesystem{ } filesystem{ ext3 } \
+-# mountpoint{ /boot } \
+-# . \
+-# 500 10000 1000000000 ext3 \
+-# method{ format } format{ } \
+-# use_filesystem{ } filesystem{ ext3 } \
+-# mountpoint{ / } \
+-# . \
+-# 64 512 300% linux-swap \
+-# method{ swap } format{ } \
+-# .
+-
+-# The full recipe format is documented in the file partman-auto-recipe.txt
+-# included in the 'debian-installer' package or available from D-I source
+-# repository. This also documents how to specify settings such as file
+-# system labels, volume group names and which physical devices to include
+-# in a volume group.
+-
+-# This makes partman automatically partition without confirmation, provided
+-# that you told it what to do using one of the methods above.
+-d-i partman-partitioning/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-## Partitioning using RAID
+-# The method should be set to "raid".
+-#d-i partman-auto/method string raid
+-# Specify the disks to be partitioned. They will all get the same layout,
+-# so this will only work if the disks are the same size.
+-#d-i partman-auto/disk string /dev/sda /dev/sdb
+-
+-# Next you need to specify the physical partitions that will be used.
+-#d-i partman-auto/expert_recipe string \
+-# multiraid :: \
+-# 1000 5000 4000 raid \
+-# $primary{ } method{ raid } \
+-# . \
+-# 64 512 300% raid \
+-# method{ raid } \
+-# . \
+-# 500 10000 1000000000 raid \
+-# method{ raid } \
+-# .
+-
+-# Last you need to specify how the previously defined partitions will be
+-# used in the RAID setup. Remember to use the correct partition numbers
+-# for logical partitions. RAID levels 0, 1, 5, 6 and 10 are supported;
+-# devices are separated using "#".
+-# Parameters are:
+-# <raidtype> <devcount> <sparecount> <fstype> <mountpoint> \
+-# <devices> <sparedevices>
+-
+-#d-i partman-auto-raid/recipe string \
+-# 1 2 0 ext3 / \
+-# /dev/sda1#/dev/sdb1 \
+-# . \
+-# 1 2 0 swap - \
+-# /dev/sda5#/dev/sdb5 \
+-# . \
+-# 0 2 0 ext3 /home \
+-# /dev/sda6#/dev/sdb6 \
+-# .
+-
+-# For additional information see the file partman-auto-raid-recipe.txt
+-# included in the 'debian-installer' package or available from D-I source
+-# repository.
+-
+-# This makes partman automatically partition without confirmation.
+-d-i partman-md/confirm boolean true
+-d-i partman-partitioning/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-## Controlling how partitions are mounted
+-# The default is to mount by UUID, but you can also choose "traditional" to
+-# use traditional device names, or "label" to try filesystem labels before
+-# falling back to UUIDs.
+-#d-i partman/mount_style select uuid
+-
+-### Base system installation
+-# Configure APT to not install recommended packages by default. Use of this
+-# option can result in an incomplete system and should only be used by very
+-# experienced users.
+-#d-i base-installer/install-recommends boolean false
+-
+-# The kernel image (meta) package to be installed; "none" can be used if no
+-# kernel is to be installed.
+-#d-i base-installer/kernel/image string linux-image-486
+-
+-### Apt setup
+-# You can choose to install non-free and contrib software.
+-#d-i apt-setup/non-free boolean true
+-#d-i apt-setup/contrib boolean true
+-# Uncomment this if you don't want to use a network mirror.
+-#d-i apt-setup/use_mirror boolean false
+-# Select which update services to use; define the mirrors to be used.
+-# Values shown below are the normal defaults.
+-#d-i apt-setup/services-select multiselect security, volatile
+-#d-i apt-setup/security_host string security.debian.org
+-#d-i apt-setup/volatile_host string volatile.debian.org
+-
+-# Additional repositories, local[0-9] available
+-#d-i apt-setup/local0/repository string \
+-# http://local.server/debian stable main
+-#d-i apt-setup/local0/comment string local server
+-# Enable deb-src lines
+-#d-i apt-setup/local0/source boolean true
+-# URL to the public key of the local repository; you must provide a key or
+-# apt will complain about the unauthenticated repository and so the
+-# sources.list line will be left commented out
+-#d-i apt-setup/local0/key string http://local.server/key
+-
+-# By default the installer requires that repositories be authenticated
+-# using a known gpg key. This setting can be used to disable that
+-# authentication. Warning: Insecure, not recommended.
+-#d-i debian-installer/allow_unauthenticated boolean true
+-
+-### Package selection
+-#tasksel tasksel/first multiselect standard, web-server
+-# If the desktop task is selected, install the kde and xfce desktops
+-# instead of the default gnome desktop.
+-#tasksel tasksel/desktop multiselect kde, xfce
+-
+-# Individual additional packages to install
+-#d-i pkgsel/include string openssh-server build-essential
+-# Whether to upgrade packages after debootstrap.
+-# Allowed values: none, safe-upgrade, full-upgrade
+-#d-i pkgsel/upgrade select none
+-
+-# Some versions of the installer can report back on what software you have
+-# installed, and what software you use. The default is not to report back,
+-# but sending reports helps the project determine what software is most
+-# popular and include it on CDs.
+-popularity-contest popularity-contest/participate boolean false
+-
+-### Finishing up the installation
+-# During installations from serial console, the regular virtual consoles
+-# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
+-# line to prevent this.
+-#d-i finish-install/keep-consoles boolean true
+-
+-# Avoid that last message about the install being complete.
+-d-i finish-install/reboot_in_progress note
+-
+-# This will prevent the installer from ejecting the CD during the reboot,
+-# which is useful in some situations.
+-#d-i cdrom-detect/eject boolean false
+-
+-# This is how to make the installer shutdown when finished, but not
+-# reboot into the installed system.
+-#d-i debian-installer/exit/halt boolean true
+-# This will power off the machine instead of just halting it.
+-#d-i debian-installer/exit/poweroff boolean true
+-
+-### Preseeding other packages
+-# Depending on what software you choose to install, or if things go wrong
+-# during the installation process, it's possible that other questions may
+-# be asked. You can preseed those too, of course. To get a list of every
+-# possible question that could be asked during an install, do an
+-# installation, and then run these commands:
+-# debconf-get-selections --installer > file
+-# debconf-get-selections >> file
+-
+-
+-#### Advanced options
+-### Running custom commands during the installation
+-# d-i preseeding is inherently not secure. Nothing in the installer checks
+-# for attempts at buffer overflows or other exploits of the values of a
+-# preconfiguration file like this one. Only use preconfiguration files from
+-# trusted locations! To drive that home, and because it's generally useful,
+-# here's a way to run any shell command you'd like inside the installer,
+-# automatically.
+-
+-# This first command is run as early as possible, just after
+-# preseeding is read.
+-#d-i preseed/early_command string anna-install some-udeb
+-# This command is run immediately before the partitioner starts. It may be
+-# useful to apply dynamic partitioner preseeding that depends on the state
+-# of the disks (which may not be visible when preseed/early_command runs).
+-#d-i partman/early_command \
+-# string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
+-# This command is run just before the install finishes, but when there is
+-# still a usable /target directory. You can chroot to /target and use it
+-# directly, or use the apt-install and in-target commands to easily install
+-# packages and run commands in the target system.
+-#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+diff --git a/builder/website/debian-6.sh b/builder/website/debian-6.sh
+deleted file mode 100755
+index 7976c9c..0000000
+--- a/builder/website/debian-6.sh
++++ /dev/null
+@@ -1,76 +0,0 @@
+-#!/bin/bash -
+-# 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.
+-
+-# The basic plan comes from:
+-# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
+-# https://wiki.debian.org/DebianInstaller/Preseed
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-export http_proxy=http://cache.home.annexia.org:3128
+-export https_proxy=$http_proxy
+-export ftp_proxy=$http_proxy
+-location=http://ftp.uk.debian.org/debian/dists/squeeze/main/installer-amd64
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f debian-6.preseed ]; then
+- echo "You are running this script from the wrong directory."
+- exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-# Note that the injected file must be called "/preseed.cfg" in order
+-# for d-i to pick it up.
+-sed -e "s, at CACHE@,$http_proxy,g" < debian-6.preseed > preseed.cfg
+-
+-virsh undefine tmpd6 ||:
+-rm -f debian-6 debian-6.old
+-
+-virt-install \
+- --name tmpd6 \
+- --ram=1024 \
+- --os-type=linux --os-variant=debiansqueeze \
+- --initrd-inject=$pwd/preseed.cfg \
+- --extra-args="auto console=tty0 console=ttyS0,115200" \
+- --disk=$pwd/debian-6,size=4 \
+- --location=$location \
+- --nographics \
+- --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine tmpd6
+-
+-rm preseed.cfg
+-
+-# Sysprep (removes logfiles and so on).
+-virt-sysprep -a debian-6
+-
+-# Sparsify.
+-mv debian-6 debian-6.old
+-virt-sparsify debian-6.old debian-6
+-rm debian-6.old
+-
+-# Compress.
+-rm -f debian-6.xz
+-xz --best --block-size=$((16*1024*1024)) debian-6
+-
+-# Result:
+-ls -lh debian-6.xz
+diff --git a/builder/website/debian-7.preseed b/builder/website/debian-7.preseed
+deleted file mode 100644
+index faa4430..0000000
+--- a/builder/website/debian-7.preseed
++++ /dev/null
+@@ -1,385 +0,0 @@
+-#### Contents of the preconfiguration file (for wheezy)
+-### Localization
+-# Preseeding only locale sets language, country and locale.
+-d-i debian-installer/locale string en_US
+-
+-# The values can also be preseeded individually for greater flexibility.
+-#d-i debian-installer/language string en
+-#d-i debian-installer/country string NL
+-#d-i debian-installer/locale string en_GB.UTF-8
+-# Optionally specify additional locales to be generated.
+-#d-i localechooser/supported-locales multiselect en_US.UTF-8, nl_NL.UTF-8
+-
+-# Keyboard selection.
+-# keymap is an alias for keyboard-configuration/xkb-keymap
+-d-i keymap select us
+-# d-i keyboard-configuration/toggle select No toggling
+-
+-### Network configuration
+-# Disable network configuration entirely. This is useful for cdrom
+-# installations on non-networked devices where the network questions,
+-# warning and long timeouts are a nuisance.
+-d-i netcfg/enable boolean true
+-
+-# netcfg will choose an interface that has link if possible. This makes it
+-# skip displaying a list if there is more than one interface.
+-d-i netcfg/choose_interface select auto
+-
+-# To pick a particular interface instead:
+-#d-i netcfg/choose_interface select eth1
+-
+-# To set a different link detection timeout (default is 3 seconds).
+-# Values are interpreted as seconds.
+-#d-i netcfg/link_detection_timeout string 10
+-
+-# If you have a slow dhcp server and the installer times out waiting for
+-# it, this might be useful.
+-#d-i netcfg/dhcp_timeout string 60
+-#d-i netcfg/dhcpv6_timeout string 60
+-
+-# If you prefer to configure the network manually, uncomment this line and
+-# the static network configuration below.
+-#d-i netcfg/disable_autoconfig boolean true
+-
+-# If you want the preconfiguration file to work on systems both with and
+-# without a dhcp server, uncomment these lines and the static network
+-# configuration below.
+-#d-i netcfg/dhcp_failed note
+-#d-i netcfg/dhcp_options select Configure network manually
+-
+-# Static network configuration.
+-#
+-# IPv4 example
+-#d-i netcfg/get_ipaddress string 192.168.1.42
+-#d-i netcfg/get_netmask string 255.255.255.0
+-#d-i netcfg/get_gateway string 192.168.1.1
+-#d-i netcfg/get_nameservers string 192.168.1.1
+-#d-i netcfg/confirm_static boolean true
+-#
+-# IPv6 example
+-#d-i netcfg/get_ipaddress string fc00::2
+-#d-i netcfg/get_netmask string ffff:ffff:ffff:ffff::
+-#d-i netcfg/get_gateway string fc00::1
+-#d-i netcfg/get_nameservers string fc00::1
+-#d-i netcfg/confirm_static boolean true
+-
+-# Any hostname and domain names assigned from dhcp take precedence over
+-# values set here. However, setting the values still prevents the questions
+-# from being shown, even if values come from dhcp.
+-d-i netcfg/get_hostname string unassigned-hostname
+-d-i netcfg/get_domain string unassigned-domain
+-
+-# If you want to force a hostname, regardless of what either the DHCP
+-# server returns or what the reverse DNS entry for the IP is, uncomment
+-# and adjust the following line.
+-#d-i netcfg/hostname string somehost
+-
+-# Disable that annoying WEP key dialog.
+-d-i netcfg/wireless_wep string
+-# The wacky dhcp hostname that some ISPs use as a password of sorts.
+-#d-i netcfg/dhcp_hostname string radish
+-
+-# If non-free firmware is needed for the network or other hardware, you can
+-# configure the installer to always try to load it, without prompting. Or
+-# change to false to disable asking.
+-#d-i hw-detect/load_firmware boolean true
+-
+-### Network console
+-# Use the following settings if you wish to make use of the network-console
+-# component for remote installation over SSH. This only makes sense if you
+-# intend to perform the remainder of the installation manually.
+-#d-i anna/choose_modules string network-console
+-#d-i network-console/authorized_keys_url string http://10.0.0.1/openssh-key
+-#d-i network-console/password password r00tme
+-#d-i network-console/password-again password r00tme
+-
+-### Mirror settings
+-# If you select ftp, the mirror/country string does not need to be set.
+-#d-i mirror/protocol string ftp
+-d-i mirror/country string manual
+-d-i mirror/http/hostname string ftp.uk.debian.org
+-d-i mirror/http/directory string /debian
+-d-i mirror/http/proxy string @CACHE@
+-
+-# Suite to install.
+-#d-i mirror/suite string testing
+-# Suite to use for loading installer components (optional).
+-#d-i mirror/udeb/suite string testing
+-
+-### Account setup
+-# Skip creation of a root account (normal user account will be able to
+-# use sudo).
+-#d-i passwd/root-login boolean false
+-# Alternatively, to skip creation of a normal user account.
+-d-i passwd/make-user boolean false
+-
+-# Root password, either in clear text
+-d-i passwd/root-password password builder
+-d-i passwd/root-password-again password builder
+-# or encrypted using an MD5 hash.
+-#d-i passwd/root-password-crypted password [MD5 hash]
+-
+-# To create a normal user account.
+-#d-i passwd/user-fullname string Debian User
+-#d-i passwd/username string debian
+-# Normal user's password, either in clear text
+-#d-i passwd/user-password password insecure
+-#d-i passwd/user-password-again password insecure
+-# or encrypted using an MD5 hash.
+-#d-i passwd/user-password-crypted password [MD5 hash]
+-# Create the first user with the specified UID instead of the default.
+-#d-i passwd/user-uid string 1010
+-
+-# The user account will be added to some standard initial groups. To
+-# override that, use this.
+-#d-i passwd/user-default-groups string audio cdrom video
+-
+-### Clock and time zone setup
+-# Controls whether or not the hardware clock is set to UTC.
+-d-i clock-setup/utc boolean true
+-
+-# You may set this to any valid setting for $TZ; see the contents of
+-# /usr/share/zoneinfo/ for valid values.
+-d-i time/zone string US/Eastern
+-
+-# Controls whether to use NTP to set the clock during the install
+-d-i clock-setup/ntp boolean true
+-# NTP server to use. The default is almost always fine here.
+-#d-i clock-setup/ntp-server string ntp.example.com
+-
+-### Partitioning
+-## Partitioning example
+-# If the system has free space you can choose to only partition that space.
+-# This is only honoured if partman-auto/method (below) is not set.
+-#d-i partman-auto/init_automatically_partition select biggest_free
+-
+-# Alternatively, you may specify a disk to partition. If the system has only
+-# one disk the installer will default to using that, but otherwise the device
+-# name must be given in traditional, non-devfs format (so e.g. /dev/hda or
+-# /dev/sda, and not e.g. /dev/discs/disc0/disc).
+-# For example, to use the first SCSI/SATA hard disk:
+-#d-i partman-auto/disk string /dev/sda
+-# In addition, you'll need to specify the method to use.
+-# The presently available methods are:
+-# - regular: use the usual partition types for your architecture
+-# - lvm: use LVM to partition the disk
+-# - crypto: use LVM within an encrypted partition
+-d-i partman-auto/method string regular
+-
+-# If one of the disks that are going to be automatically partitioned
+-# contains an old LVM configuration, the user will normally receive a
+-# warning. This can be preseeded away...
+-d-i partman-lvm/device_remove_lvm boolean true
+-# The same applies to pre-existing software RAID array:
+-d-i partman-md/device_remove_md boolean true
+-# And the same goes for the confirmation to write the lvm partitions.
+-d-i partman-lvm/confirm boolean true
+-d-i partman-lvm/confirm_nooverwrite boolean true
+-
+-# You can choose one of the three predefined partitioning recipes:
+-# - atomic: all files in one partition
+-# - home: separate /home partition
+-# - multi: separate /home, /usr, /var, and /tmp partitions
+-d-i partman-auto/choose_recipe select atomic
+-
+-# Or provide a recipe of your own...
+-# If you have a way to get a recipe file into the d-i environment, you can
+-# just point at it.
+-#d-i partman-auto/expert_recipe_file string /hd-media/recipe
+-
+-# If not, you can put an entire recipe into the preconfiguration file in one
+-# (logical) line. This example creates a small /boot partition, suitable
+-# swap, and uses the rest of the space for the root partition:
+-#d-i partman-auto/expert_recipe string \
+-# boot-root :: \
+-# 40 50 100 ext3 \
+-# $primary{ } $bootable{ } \
+-# method{ format } format{ } \
+-# use_filesystem{ } filesystem{ ext3 } \
+-# mountpoint{ /boot } \
+-# . \
+-# 500 10000 1000000000 ext3 \
+-# method{ format } format{ } \
+-# use_filesystem{ } filesystem{ ext3 } \
+-# mountpoint{ / } \
+-# . \
+-# 64 512 300% linux-swap \
+-# method{ swap } format{ } \
+-# .
+-
+-# The full recipe format is documented in the file partman-auto-recipe.txt
+-# included in the 'debian-installer' package or available from D-I source
+-# repository. This also documents how to specify settings such as file
+-# system labels, volume group names and which physical devices to include
+-# in a volume group.
+-
+-# This makes partman automatically partition without confirmation, provided
+-# that you told it what to do using one of the methods above.
+-d-i partman-partitioning/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-## Partitioning using RAID
+-# The method should be set to "raid".
+-#d-i partman-auto/method string raid
+-# Specify the disks to be partitioned. They will all get the same layout,
+-# so this will only work if the disks are the same size.
+-#d-i partman-auto/disk string /dev/sda /dev/sdb
+-
+-# Next you need to specify the physical partitions that will be used.
+-#d-i partman-auto/expert_recipe string \
+-# multiraid :: \
+-# 1000 5000 4000 raid \
+-# $primary{ } method{ raid } \
+-# . \
+-# 64 512 300% raid \
+-# method{ raid } \
+-# . \
+-# 500 10000 1000000000 raid \
+-# method{ raid } \
+-# .
+-
+-# Last you need to specify how the previously defined partitions will be
+-# used in the RAID setup. Remember to use the correct partition numbers
+-# for logical partitions. RAID levels 0, 1, 5, 6 and 10 are supported;
+-# devices are separated using "#".
+-# Parameters are:
+-# <raidtype> <devcount> <sparecount> <fstype> <mountpoint> \
+-# <devices> <sparedevices>
+-
+-#d-i partman-auto-raid/recipe string \
+-# 1 2 0 ext3 / \
+-# /dev/sda1#/dev/sdb1 \
+-# . \
+-# 1 2 0 swap - \
+-# /dev/sda5#/dev/sdb5 \
+-# . \
+-# 0 2 0 ext3 /home \
+-# /dev/sda6#/dev/sdb6 \
+-# .
+-
+-# For additional information see the file partman-auto-raid-recipe.txt
+-# included in the 'debian-installer' package or available from D-I source
+-# repository.
+-
+-# This makes partman automatically partition without confirmation.
+-d-i partman-md/confirm boolean true
+-d-i partman-partitioning/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-## Controlling how partitions are mounted
+-# The default is to mount by UUID, but you can also choose "traditional" to
+-# use traditional device names, or "label" to try filesystem labels before
+-# falling back to UUIDs.
+-#d-i partman/mount_style select uuid
+-
+-### Base system installation
+-# Configure APT to not install recommended packages by default. Use of this
+-# option can result in an incomplete system and should only be used by very
+-# experienced users.
+-#d-i base-installer/install-recommends boolean false
+-
+-# The kernel image (meta) package to be installed; "none" can be used if no
+-# kernel is to be installed.
+-#d-i base-installer/kernel/image string linux-image-486
+-
+-### Apt setup
+-# You can choose to install non-free and contrib software.
+-#d-i apt-setup/non-free boolean true
+-#d-i apt-setup/contrib boolean true
+-# Uncomment this if you don't want to use a network mirror.
+-#d-i apt-setup/use_mirror boolean false
+-# Select which update services to use; define the mirrors to be used.
+-# Values shown below are the normal defaults.
+-#d-i apt-setup/services-select multiselect security, volatile
+-#d-i apt-setup/security_host string security.debian.org
+-#d-i apt-setup/volatile_host string volatile.debian.org
+-
+-# Additional repositories, local[0-9] available
+-#d-i apt-setup/local0/repository string \
+-# http://local.server/debian stable main
+-#d-i apt-setup/local0/comment string local server
+-# Enable deb-src lines
+-#d-i apt-setup/local0/source boolean true
+-# URL to the public key of the local repository; you must provide a key or
+-# apt will complain about the unauthenticated repository and so the
+-# sources.list line will be left commented out
+-#d-i apt-setup/local0/key string http://local.server/key
+-
+-# By default the installer requires that repositories be authenticated
+-# using a known gpg key. This setting can be used to disable that
+-# authentication. Warning: Insecure, not recommended.
+-#d-i debian-installer/allow_unauthenticated boolean true
+-
+-### Package selection
+-#tasksel tasksel/first multiselect standard, web-server
+-# If the desktop task is selected, install the kde and xfce desktops
+-# instead of the default gnome desktop.
+-#tasksel tasksel/desktop multiselect kde, xfce
+-
+-# Individual additional packages to install
+-#d-i pkgsel/include string openssh-server build-essential
+-# Whether to upgrade packages after debootstrap.
+-# Allowed values: none, safe-upgrade, full-upgrade
+-#d-i pkgsel/upgrade select none
+-
+-# Some versions of the installer can report back on what software you have
+-# installed, and what software you use. The default is not to report back,
+-# but sending reports helps the project determine what software is most
+-# popular and include it on CDs.
+-popularity-contest popularity-contest/participate boolean false
+-
+-### Finishing up the installation
+-# During installations from serial console, the regular virtual consoles
+-# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
+-# line to prevent this.
+-#d-i finish-install/keep-consoles boolean true
+-
+-# Avoid that last message about the install being complete.
+-d-i finish-install/reboot_in_progress note
+-
+-# This will prevent the installer from ejecting the CD during the reboot,
+-# which is useful in some situations.
+-#d-i cdrom-detect/eject boolean false
+-
+-# This is how to make the installer shutdown when finished, but not
+-# reboot into the installed system.
+-#d-i debian-installer/exit/halt boolean true
+-# This will power off the machine instead of just halting it.
+-#d-i debian-installer/exit/poweroff boolean true
+-
+-### Preseeding other packages
+-# Depending on what software you choose to install, or if things go wrong
+-# during the installation process, it's possible that other questions may
+-# be asked. You can preseed those too, of course. To get a list of every
+-# possible question that could be asked during an install, do an
+-# installation, and then run these commands:
+-# debconf-get-selections --installer > file
+-# debconf-get-selections >> file
+-
+-
+-#### Advanced options
+-### Running custom commands during the installation
+-# d-i preseeding is inherently not secure. Nothing in the installer checks
+-# for attempts at buffer overflows or other exploits of the values of a
+-# preconfiguration file like this one. Only use preconfiguration files from
+-# trusted locations! To drive that home, and because it's generally useful,
+-# here's a way to run any shell command you'd like inside the installer,
+-# automatically.
+-
+-# This first command is run as early as possible, just after
+-# preseeding is read.
+-#d-i preseed/early_command string anna-install some-udeb
+-# This command is run immediately before the partitioner starts. It may be
+-# useful to apply dynamic partitioner preseeding that depends on the state
+-# of the disks (which may not be visible when preseed/early_command runs).
+-#d-i partman/early_command \
+-# string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
+-# This command is run just before the install finishes, but when there is
+-# still a usable /target directory. You can chroot to /target and use it
+-# directly, or use the apt-install and in-target commands to easily install
+-# packages and run commands in the target system.
+-#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+diff --git a/builder/website/debian-7.sh b/builder/website/debian-7.sh
+deleted file mode 100755
+index b294b65..0000000
+--- a/builder/website/debian-7.sh
++++ /dev/null
+@@ -1,82 +0,0 @@
+-#!/bin/bash -
+-# 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.
+-
+-# The basic plan comes from:
+-# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
+-# https://wiki.debian.org/DebianInstaller/Preseed
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-export http_proxy=http://cache.home.annexia.org:3128
+-export https_proxy=$http_proxy
+-export ftp_proxy=$http_proxy
+-location=http://ftp.uk.debian.org/debian/dists/stable/main/installer-amd64
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+- echo "You have to run this script as root."
+- exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f debian-7.preseed ]; then
+- echo "You are running this script from the wrong directory."
+- exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-# Note that the injected file must be called "/preseed.cfg" in order
+-# for d-i to pick it up.
+-sed -e "s, at CACHE@,$http_proxy,g" < debian-7.preseed > preseed.cfg
+-
+-virsh undefine tmpd7 ||:
+-rm -f debian-7 debian-7.old
+-
+-virt-install \
+- --name tmpd7 \
+- --ram=1024 \
+- --os-type=linux --os-variant=debianwheezy \
+- --initrd-inject=$pwd/preseed.cfg \
+- --extra-args="auto console=tty0 console=ttyS0,115200" \
+- --disk=$pwd/debian-7,size=4 \
+- --location=$location \
+- --nographics \
+- --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine tmpd7
+-
+-rm preseed.cfg
+-
+-# Sysprep (removes logfiles and so on).
+-virt-sysprep -a debian-7
+-
+-# Sparsify.
+-mv debian-7 debian-7.old
+-virt-sparsify debian-7.old debian-7
+-rm debian-7.old
+-
+-# Compress.
+-rm -f debian-7.xz
+-xz --best --block-size=16777216 debian-7
+-
+-# Result:
+-ls -lh debian-7.xz
+diff --git a/builder/website/debian.preseed b/builder/website/debian.preseed
+new file mode 100644
+index 0000000..faa4430
+--- /dev/null
++++ b/builder/website/debian.preseed
+@@ -0,0 +1,385 @@
++#### Contents of the preconfiguration file (for wheezy)
++### Localization
++# Preseeding only locale sets language, country and locale.
++d-i debian-installer/locale string en_US
++
++# The values can also be preseeded individually for greater flexibility.
++#d-i debian-installer/language string en
++#d-i debian-installer/country string NL
++#d-i debian-installer/locale string en_GB.UTF-8
++# Optionally specify additional locales to be generated.
++#d-i localechooser/supported-locales multiselect en_US.UTF-8, nl_NL.UTF-8
++
++# Keyboard selection.
++# keymap is an alias for keyboard-configuration/xkb-keymap
++d-i keymap select us
++# d-i keyboard-configuration/toggle select No toggling
++
++### Network configuration
++# Disable network configuration entirely. This is useful for cdrom
++# installations on non-networked devices where the network questions,
++# warning and long timeouts are a nuisance.
++d-i netcfg/enable boolean true
++
++# netcfg will choose an interface that has link if possible. This makes it
++# skip displaying a list if there is more than one interface.
++d-i netcfg/choose_interface select auto
++
++# To pick a particular interface instead:
++#d-i netcfg/choose_interface select eth1
++
++# To set a different link detection timeout (default is 3 seconds).
++# Values are interpreted as seconds.
++#d-i netcfg/link_detection_timeout string 10
++
++# If you have a slow dhcp server and the installer times out waiting for
++# it, this might be useful.
++#d-i netcfg/dhcp_timeout string 60
++#d-i netcfg/dhcpv6_timeout string 60
++
++# If you prefer to configure the network manually, uncomment this line and
++# the static network configuration below.
++#d-i netcfg/disable_autoconfig boolean true
++
++# If you want the preconfiguration file to work on systems both with and
++# without a dhcp server, uncomment these lines and the static network
++# configuration below.
++#d-i netcfg/dhcp_failed note
++#d-i netcfg/dhcp_options select Configure network manually
++
++# Static network configuration.
++#
++# IPv4 example
++#d-i netcfg/get_ipaddress string 192.168.1.42
++#d-i netcfg/get_netmask string 255.255.255.0
++#d-i netcfg/get_gateway string 192.168.1.1
++#d-i netcfg/get_nameservers string 192.168.1.1
++#d-i netcfg/confirm_static boolean true
++#
++# IPv6 example
++#d-i netcfg/get_ipaddress string fc00::2
++#d-i netcfg/get_netmask string ffff:ffff:ffff:ffff::
++#d-i netcfg/get_gateway string fc00::1
++#d-i netcfg/get_nameservers string fc00::1
++#d-i netcfg/confirm_static boolean true
++
++# Any hostname and domain names assigned from dhcp take precedence over
++# values set here. However, setting the values still prevents the questions
++# from being shown, even if values come from dhcp.
++d-i netcfg/get_hostname string unassigned-hostname
++d-i netcfg/get_domain string unassigned-domain
++
++# If you want to force a hostname, regardless of what either the DHCP
++# server returns or what the reverse DNS entry for the IP is, uncomment
++# and adjust the following line.
++#d-i netcfg/hostname string somehost
++
++# Disable that annoying WEP key dialog.
++d-i netcfg/wireless_wep string
++# The wacky dhcp hostname that some ISPs use as a password of sorts.
++#d-i netcfg/dhcp_hostname string radish
++
++# If non-free firmware is needed for the network or other hardware, you can
++# configure the installer to always try to load it, without prompting. Or
++# change to false to disable asking.
++#d-i hw-detect/load_firmware boolean true
++
++### Network console
++# Use the following settings if you wish to make use of the network-console
++# component for remote installation over SSH. This only makes sense if you
++# intend to perform the remainder of the installation manually.
++#d-i anna/choose_modules string network-console
++#d-i network-console/authorized_keys_url string http://10.0.0.1/openssh-key
++#d-i network-console/password password r00tme
++#d-i network-console/password-again password r00tme
++
++### Mirror settings
++# If you select ftp, the mirror/country string does not need to be set.
++#d-i mirror/protocol string ftp
++d-i mirror/country string manual
++d-i mirror/http/hostname string ftp.uk.debian.org
++d-i mirror/http/directory string /debian
++d-i mirror/http/proxy string @CACHE@
++
++# Suite to install.
++#d-i mirror/suite string testing
++# Suite to use for loading installer components (optional).
++#d-i mirror/udeb/suite string testing
++
++### Account setup
++# Skip creation of a root account (normal user account will be able to
++# use sudo).
++#d-i passwd/root-login boolean false
++# Alternatively, to skip creation of a normal user account.
++d-i passwd/make-user boolean false
++
++# Root password, either in clear text
++d-i passwd/root-password password builder
++d-i passwd/root-password-again password builder
++# or encrypted using an MD5 hash.
++#d-i passwd/root-password-crypted password [MD5 hash]
++
++# To create a normal user account.
++#d-i passwd/user-fullname string Debian User
++#d-i passwd/username string debian
++# Normal user's password, either in clear text
++#d-i passwd/user-password password insecure
++#d-i passwd/user-password-again password insecure
++# or encrypted using an MD5 hash.
++#d-i passwd/user-password-crypted password [MD5 hash]
++# Create the first user with the specified UID instead of the default.
++#d-i passwd/user-uid string 1010
++
++# The user account will be added to some standard initial groups. To
++# override that, use this.
++#d-i passwd/user-default-groups string audio cdrom video
++
++### Clock and time zone setup
++# Controls whether or not the hardware clock is set to UTC.
++d-i clock-setup/utc boolean true
++
++# You may set this to any valid setting for $TZ; see the contents of
++# /usr/share/zoneinfo/ for valid values.
++d-i time/zone string US/Eastern
++
++# Controls whether to use NTP to set the clock during the install
++d-i clock-setup/ntp boolean true
++# NTP server to use. The default is almost always fine here.
++#d-i clock-setup/ntp-server string ntp.example.com
++
++### Partitioning
++## Partitioning example
++# If the system has free space you can choose to only partition that space.
++# This is only honoured if partman-auto/method (below) is not set.
++#d-i partman-auto/init_automatically_partition select biggest_free
++
++# Alternatively, you may specify a disk to partition. If the system has only
++# one disk the installer will default to using that, but otherwise the device
++# name must be given in traditional, non-devfs format (so e.g. /dev/hda or
++# /dev/sda, and not e.g. /dev/discs/disc0/disc).
++# For example, to use the first SCSI/SATA hard disk:
++#d-i partman-auto/disk string /dev/sda
++# In addition, you'll need to specify the method to use.
++# The presently available methods are:
++# - regular: use the usual partition types for your architecture
++# - lvm: use LVM to partition the disk
++# - crypto: use LVM within an encrypted partition
++d-i partman-auto/method string regular
++
++# If one of the disks that are going to be automatically partitioned
++# contains an old LVM configuration, the user will normally receive a
++# warning. This can be preseeded away...
++d-i partman-lvm/device_remove_lvm boolean true
++# The same applies to pre-existing software RAID array:
++d-i partman-md/device_remove_md boolean true
++# And the same goes for the confirmation to write the lvm partitions.
++d-i partman-lvm/confirm boolean true
++d-i partman-lvm/confirm_nooverwrite boolean true
++
++# You can choose one of the three predefined partitioning recipes:
++# - atomic: all files in one partition
++# - home: separate /home partition
++# - multi: separate /home, /usr, /var, and /tmp partitions
++d-i partman-auto/choose_recipe select atomic
++
++# Or provide a recipe of your own...
++# If you have a way to get a recipe file into the d-i environment, you can
++# just point at it.
++#d-i partman-auto/expert_recipe_file string /hd-media/recipe
++
++# If not, you can put an entire recipe into the preconfiguration file in one
++# (logical) line. This example creates a small /boot partition, suitable
++# swap, and uses the rest of the space for the root partition:
++#d-i partman-auto/expert_recipe string \
++# boot-root :: \
++# 40 50 100 ext3 \
++# $primary{ } $bootable{ } \
++# method{ format } format{ } \
++# use_filesystem{ } filesystem{ ext3 } \
++# mountpoint{ /boot } \
++# . \
++# 500 10000 1000000000 ext3 \
++# method{ format } format{ } \
++# use_filesystem{ } filesystem{ ext3 } \
++# mountpoint{ / } \
++# . \
++# 64 512 300% linux-swap \
++# method{ swap } format{ } \
++# .
++
++# The full recipe format is documented in the file partman-auto-recipe.txt
++# included in the 'debian-installer' package or available from D-I source
++# repository. This also documents how to specify settings such as file
++# system labels, volume group names and which physical devices to include
++# in a volume group.
++
++# This makes partman automatically partition without confirmation, provided
++# that you told it what to do using one of the methods above.
++d-i partman-partitioning/confirm_write_new_label boolean true
++d-i partman/choose_partition select finish
++d-i partman/confirm boolean true
++d-i partman/confirm_nooverwrite boolean true
++
++## Partitioning using RAID
++# The method should be set to "raid".
++#d-i partman-auto/method string raid
++# Specify the disks to be partitioned. They will all get the same layout,
++# so this will only work if the disks are the same size.
++#d-i partman-auto/disk string /dev/sda /dev/sdb
++
++# Next you need to specify the physical partitions that will be used.
++#d-i partman-auto/expert_recipe string \
++# multiraid :: \
++# 1000 5000 4000 raid \
++# $primary{ } method{ raid } \
++# . \
++# 64 512 300% raid \
++# method{ raid } \
++# . \
++# 500 10000 1000000000 raid \
++# method{ raid } \
++# .
++
++# Last you need to specify how the previously defined partitions will be
++# used in the RAID setup. Remember to use the correct partition numbers
++# for logical partitions. RAID levels 0, 1, 5, 6 and 10 are supported;
++# devices are separated using "#".
++# Parameters are:
++# <raidtype> <devcount> <sparecount> <fstype> <mountpoint> \
++# <devices> <sparedevices>
++
++#d-i partman-auto-raid/recipe string \
++# 1 2 0 ext3 / \
++# /dev/sda1#/dev/sdb1 \
++# . \
++# 1 2 0 swap - \
++# /dev/sda5#/dev/sdb5 \
++# . \
++# 0 2 0 ext3 /home \
++# /dev/sda6#/dev/sdb6 \
++# .
++
++# For additional information see the file partman-auto-raid-recipe.txt
++# included in the 'debian-installer' package or available from D-I source
++# repository.
++
++# This makes partman automatically partition without confirmation.
++d-i partman-md/confirm boolean true
++d-i partman-partitioning/confirm_write_new_label boolean true
++d-i partman/choose_partition select finish
++d-i partman/confirm boolean true
++d-i partman/confirm_nooverwrite boolean true
++
++## Controlling how partitions are mounted
++# The default is to mount by UUID, but you can also choose "traditional" to
++# use traditional device names, or "label" to try filesystem labels before
++# falling back to UUIDs.
++#d-i partman/mount_style select uuid
++
++### Base system installation
++# Configure APT to not install recommended packages by default. Use of this
++# option can result in an incomplete system and should only be used by very
++# experienced users.
++#d-i base-installer/install-recommends boolean false
++
++# The kernel image (meta) package to be installed; "none" can be used if no
++# kernel is to be installed.
++#d-i base-installer/kernel/image string linux-image-486
++
++### Apt setup
++# You can choose to install non-free and contrib software.
++#d-i apt-setup/non-free boolean true
++#d-i apt-setup/contrib boolean true
++# Uncomment this if you don't want to use a network mirror.
++#d-i apt-setup/use_mirror boolean false
++# Select which update services to use; define the mirrors to be used.
++# Values shown below are the normal defaults.
++#d-i apt-setup/services-select multiselect security, volatile
++#d-i apt-setup/security_host string security.debian.org
++#d-i apt-setup/volatile_host string volatile.debian.org
++
++# Additional repositories, local[0-9] available
++#d-i apt-setup/local0/repository string \
++# http://local.server/debian stable main
++#d-i apt-setup/local0/comment string local server
++# Enable deb-src lines
++#d-i apt-setup/local0/source boolean true
++# URL to the public key of the local repository; you must provide a key or
++# apt will complain about the unauthenticated repository and so the
++# sources.list line will be left commented out
++#d-i apt-setup/local0/key string http://local.server/key
++
++# By default the installer requires that repositories be authenticated
++# using a known gpg key. This setting can be used to disable that
++# authentication. Warning: Insecure, not recommended.
++#d-i debian-installer/allow_unauthenticated boolean true
++
++### Package selection
++#tasksel tasksel/first multiselect standard, web-server
++# If the desktop task is selected, install the kde and xfce desktops
++# instead of the default gnome desktop.
++#tasksel tasksel/desktop multiselect kde, xfce
++
++# Individual additional packages to install
++#d-i pkgsel/include string openssh-server build-essential
++# Whether to upgrade packages after debootstrap.
++# Allowed values: none, safe-upgrade, full-upgrade
++#d-i pkgsel/upgrade select none
++
++# Some versions of the installer can report back on what software you have
++# installed, and what software you use. The default is not to report back,
++# but sending reports helps the project determine what software is most
++# popular and include it on CDs.
++popularity-contest popularity-contest/participate boolean false
++
++### Finishing up the installation
++# During installations from serial console, the regular virtual consoles
++# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
++# line to prevent this.
++#d-i finish-install/keep-consoles boolean true
++
++# Avoid that last message about the install being complete.
++d-i finish-install/reboot_in_progress note
++
++# This will prevent the installer from ejecting the CD during the reboot,
++# which is useful in some situations.
++#d-i cdrom-detect/eject boolean false
++
++# This is how to make the installer shutdown when finished, but not
++# reboot into the installed system.
++#d-i debian-installer/exit/halt boolean true
++# This will power off the machine instead of just halting it.
++#d-i debian-installer/exit/poweroff boolean true
++
++### Preseeding other packages
++# Depending on what software you choose to install, or if things go wrong
++# during the installation process, it's possible that other questions may
++# be asked. You can preseed those too, of course. To get a list of every
++# possible question that could be asked during an install, do an
++# installation, and then run these commands:
++# debconf-get-selections --installer > file
++# debconf-get-selections >> file
++
++
++#### Advanced options
++### Running custom commands during the installation
++# d-i preseeding is inherently not secure. Nothing in the installer checks
++# for attempts at buffer overflows or other exploits of the values of a
++# preconfiguration file like this one. Only use preconfiguration files from
++# trusted locations! To drive that home, and because it's generally useful,
++# here's a way to run any shell command you'd like inside the installer,
++# automatically.
++
++# This first command is run as early as possible, just after
++# preseeding is read.
++#d-i preseed/early_command string anna-install some-udeb
++# This command is run immediately before the partitioner starts. It may be
++# useful to apply dynamic partitioner preseeding that depends on the state
++# of the disks (which may not be visible when preseed/early_command runs).
++#d-i partman/early_command \
++# string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
++# This command is run just before the install finishes, but when there is
++# still a usable /target directory. You can chroot to /target and use it
++# directly, or use the apt-install and in-target commands to easily install
++# packages and run commands in the target system.
++#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+diff --git a/builder/website/debian.sh b/builder/website/debian.sh
+new file mode 100755
+index 0000000..ae0ff75
+--- /dev/null
++++ b/builder/website/debian.sh
+@@ -0,0 +1,83 @@
++#!/bin/bash -
++# 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.
++
++# The basic plan comes from:
++# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
++# https://wiki.debian.org/DebianInstaller/Preseed
++
++unset CDPATH
++export LANG=C
++set -e
++set -x
++
++if [ $# -ne 2 ]; then
++ echo "$0 VERSION DIST"
++ exit 1
++fi
++
++# Some configuration.
++version=$1
++dist=$2
++location=http://ftp.uk.debian.org/debian/dists/$dist/main/installer-amd64
++output=debian-$version
++tmpname=tmp-$(tr -cd 'a-f0-9' < /dev/urandom | head -c 8)
++
++rm -f $output $output.old $output.xz
++
++# Make sure it's being run from the correct directory.
++if [ ! -f debian.preseed ]; then
++ echo "You are running this script from the wrong directory."
++ exit 1
++fi
++
++# Note that the injected file must be called "/preseed.cfg" in order
++# for d-i to pick it up.
++sed -e "s, at CACHE@,$http_proxy,g" < debian.preseed > preseed.cfg
++
++# Clean up function.
++cleanup ()
++{
++ rm -f preseed.cfg
++ virsh undefine $tmpname ||:
++}
++trap cleanup INT QUIT TERM EXIT ERR
++
++virt-install \
++ --name=$tmpname \
++ --ram=1024 \
++ --os-type=linux --os-variant=debian$dist \
++ --initrd-inject=$(pwd)/preseed.cfg \
++ --extra-args="auto console=tty0 console=ttyS0,115200" \
++ --disk=$(pwd)/$output,size=4 \
++ --location=$location \
++ --nographics \
++ --noreboot
++
++# Sysprep (removes logfiles and so on).
++virt-sysprep -a $output
++
++# Sparsify.
++mv $output $output.old
++virt-sparsify $output.old $output
++rm $output.old
++
++# Compress.
++xz --best --block-size=16777216 $output
++
++# Result:
++ls -lh $output.xz
+diff --git a/builder/website/index b/builder/website/index
+index 4e6a867..494c177 100644
+--- a/builder/website/index
++++ b/builder/website/index
+@@ -36,9 +36,10 @@ notes=Debian 6 (Squeeze).
+ This is a default Debian install.
+
+ The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/debian-6.preseed
+- libguestfs.git/builder/website/debian-6.sh
++ can be found in the libguestfs source tree:
++
++ builder/website/debian.preseed
++ builder/website/debian.sh
+
+ This image is so very minimal that it only includes an ssh
+ server and no virtual consoles. To enable virtual consoles
+@@ -66,9 +67,10 @@ notes=Debian 7 (Wheezy).
+ This is a default Debian install.
+
+ The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/debian-7.preseed
+- libguestfs.git/builder/website/debian-7.sh
++ can be found in the libguestfs source tree:
++
++ builder/website/debian.preseed
++ builder/website/debian.sh
+
+ This image is so very minimal that it only includes an ssh
+ server and no virtual consoles. To enable virtual consoles
+diff --git a/builder/website/index.asc b/builder/website/index.asc
+index 35e103c..35f6281 100644
+--- a/builder/website/index.asc
++++ b/builder/website/index.asc
+@@ -39,9 +39,10 @@ notes=Debian 6 (Squeeze).
+ This is a default Debian install.
+
+ The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/debian-6.preseed
+- libguestfs.git/builder/website/debian-6.sh
++ can be found in the libguestfs source tree:
++
++ builder/website/debian.preseed
++ builder/website/debian.sh
+
+ This image is so very minimal that it only includes an ssh
+ server and no virtual consoles. To enable virtual consoles
+@@ -69,9 +70,10 @@ notes=Debian 7 (Wheezy).
+ This is a default Debian install.
+
+ The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/debian-7.preseed
+- libguestfs.git/builder/website/debian-7.sh
++ can be found in the libguestfs source tree:
++
++ builder/website/debian.preseed
++ builder/website/debian.sh
+
+ This image is so very minimal that it only includes an ssh
+ server and no virtual consoles. To enable virtual consoles
+@@ -205,17 +207,17 @@ notes=Ubuntu 13.10 (Saucy).
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.14 (GNU/Linux)
+
+-iQIcBAEBAgAGBQJSePzzAAoJEJFzj3Pht2igrqQP/j/P4lsPU5HjBKNcNLNxKtHV
+-9VJkn5/pfJGp0ovVoZqVJMknTwMQV850TDkbzMteWGgJEYFf5a6g8VHjmAkCunkl
+-f1Das08tUjJcOow/pR8Dkwd2mGU4EDzwzun3BXnGgpnLcOURhLD28xp2SlLTmzfh
+-tP5EWqgEBTT6Z8h6Rtth27lKveEk14w+QzJfwTgecySN+hTQY12NUIayNKmPrBE1
+-SrbAGnw1KkpXAI7JQ1ofORsPKKSwZuHvhJY094315UwmB76EDwGzkMrRzZsYgMwN
+-fESGh0YzyDdpl68G7QSOLUsDdZLXSB/dHi9FK4f6FsoUVf3kxelkZM4EXChL1ZMm
+-NCMWhiYlmX5Z7KgPZqmKVToDXwQ0AAo0a+wNvJo4frtvDHMIGjBe/f+h4k67yOoc
+-WGXqYGQG3cRrqVLanA5dFFmX+GGL/TG2cinvi+x5kJ902KeM17uyzk1uuMAUh/Rl
+-RVSsLg9QH4sLE8wEPpaUzz2ei1Bf4P26hHtVOdK7YAueDUhfSfn9KIV/n5Fz4pRg
+-G8FlpPnL1sfzbj8qpLqXHDnJ3rXGnYkSBalNJ7WVBBNlqaewuK/bcmLp9ffVeaN9
+-CcDsWbv2UaeXXu8N9pcW2kEo1cBjKTR9NPT8ueZY0g0InNrPaz/cFMOf5K9MBfuC
+-lRwdaDejqzKc5gYRKFnH
+-=tYWz
++iQIcBAEBAgAGBQJSeP5LAAoJEJFzj3Pht2igO5QP/2jjVb8W15AWxvuATDc/kOXE
++8Dvg4hFbvvBnv/U9QQ1/2BNQDykATcVIE/lWg7VzpF2HLuEwbVdwAgEO73xKpeRT
++U6zGNxkTi0mfr3aKT4rfQtqNlMkc1IMVCQSBJEIHLd1hjh2gozBCM9KM4f5YHK2P
++i/6GX8j7AeWzVkOb60PKKQrGk1ycXm0UbZuS0MPBqnc9v56fzEyaWVvvrCQEOq7a
++zTJULgOcfCBHQLF8re2upQV5NbYwruplaCYpsTcvNHvQ/vsoUIf0dNbqvarpwFUQ
++FHDesMZQBW6OWzsIBkeMYfIJ4GXO0A0ZlVuzBW07eHbmr0ev1b4c37npHrsuytbI
++TF6SUF7wyIxZlKbyf4W+RaX1hAsMOKXU8ptsMBmBPn7UnWrLbCDAPpS27ruZOA4q
++oPGeuKLUGPnimjNEatkJH8rmWlg71hsCy1hMGAOTXAUpCgPXHv/WHa0n4GTbtJ1y
++VzUElr0wAGPOqrClJse6po1h7f6XEdB4mLZ8OYHKNDjJl57QirUcmnmYmRMsctN4
++tKYgnEcv+PhNMEV/GIQXLrtCYX/Ty81AV4hwlfzL3fjqdxX9f+Fem5PcxeMaS0ik
++xfnpMsRuprkoNyTAhDr6AX9AcY4fEW8NSfG5YUjt+s27IFLIjl7HfWCbRqcqGwv9
++VvLm+Omd+GUA6rd4fuee
++=Gv5k
+ -----END PGP SIGNATURE-----
+--
+1.8.3.1
+
diff --git a/0023-builder-Replace-centos-6.sh-with-a-single-script.patch b/0023-builder-Replace-centos-6.sh-with-a-single-script.patch
new file mode 100644
index 0000000..e70794c
--- /dev/null
+++ b/0023-builder-Replace-centos-6.sh-with-a-single-script.patch
@@ -0,0 +1,343 @@
+From 401de624d1bbd3a2b5bd0a7bad17f6f17c986a5d Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 14:08:01 +0000
+Subject: [PATCH] builder: Replace centos-6.sh with a single script.
+
+Just use:
+
+ ./centos.sh 6
+
+Note that you don't need to be root.
+
+(cherry picked from commit 2f3fb2420e7f2ccc19fdc863ecc7b7ce29dd6aa1)
+---
+ builder/website/Makefile.am | 3 +-
+ builder/website/centos-6.ks | 40 ------------------
+ builder/website/centos-6.sh | 78 ----------------------------------
+ builder/website/centos.sh | 101 ++++++++++++++++++++++++++++++++++++++++++++
+ builder/website/index | 6 +--
+ builder/website/index.asc | 32 +++++++-------
+ 6 files changed, 121 insertions(+), 139 deletions(-)
+ delete mode 100644 builder/website/centos-6.ks
+ delete mode 100755 builder/website/centos-6.sh
+ create mode 100755 builder/website/centos.sh
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+index a662176..cdf263a 100644
+--- a/builder/website/Makefile.am
++++ b/builder/website/Makefile.am
+@@ -23,8 +23,7 @@ EXTRA_DIST = \
+ README \
+ index \
+ index.asc \
+- centos-6.ks \
+- centos-6.sh \
++ centos.sh \
+ centos-6.xz.sig \
+ debian.preseed \
+ debian.sh \
+diff --git a/builder/website/centos-6.ks b/builder/website/centos-6.ks
+deleted file mode 100644
+index 55e2e86..0000000
+--- a/builder/website/centos-6.ks
++++ /dev/null
+@@ -1,40 +0,0 @@
+-# virt-builder
+-# Copyright (C) 2013 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-
+-install
+-text
+-reboot
+-lang en_US.UTF-8
+-keyboard us
+-network --bootproto dhcp
+-rootpw builder
+-firewall --enabled --ssh
+-selinux --enforcing
+-timezone --utc America/New_York
+-bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"
+-zerombr
+-clearpart --all --initlabel
+-part /boot --fstype=ext4 --size=512 --asprimary
+-part swap --size=1024 --asprimary
+-part / --fstype=ext4 --size=1024 --grow --asprimary
+-
+-# Halt the system once configuration has finished.
+-poweroff
+-
+-%packages
+- at core
+-%end
+diff --git a/builder/website/centos-6.sh b/builder/website/centos-6.sh
+deleted file mode 100755
+index 611ba90..0000000
+--- a/builder/website/centos-6.sh
++++ /dev/null
+@@ -1,78 +0,0 @@
+-#!/bin/bash -
+-# virt-builder
+-# Copyright (C) 2013 Red Hat Inc.
+-#
+-# This program is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
+-# (at your option) any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-export http_proxy=http://cache.home.annexia.org:3128
+-export https_proxy=$http_proxy
+-export ftp_proxy=$http_proxy
+-
+-# We rebuild this every time there is a new 6.x release, and bump
+-# the revision in the index.
+-tree=http://mirror.bytemark.co.uk/centos/6.4/os/x86_64/
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+- echo "You have to run this script as root."
+- exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f centos-6.ks ]; then
+- echo "You are running this script from the wrong directory."
+- exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-virsh undefine tmpc6 ||:
+-rm -f centos-6 centos-6.old
+-
+-virt-install \
+- --name=tmpc6 \
+- --ram 2048 \
+- --cpu=host --vcpus=2 \
+- --os-type=linux --os-variant=fedora18 \
+- --initrd-inject=$pwd/centos-6.ks \
+- --extra-args="ks=file:/centos-6.ks console=tty0 console=ttyS0,115200 proxy=$http_proxy" \
+- --disk $pwd/centos-6,size=6 \
+- --location=$tree \
+- --nographics \
+- --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine tmpc6
+-
+-# Sysprep (removes logfiles and so on).
+-# Note this also touches /.autorelabel so the further installation
+-# changes that we make will be labelled properly at first boot.
+-virt-sysprep -a centos-6
+-
+-# Sparsify.
+-mv centos-6 centos-6.old
+-virt-sparsify centos-6.old centos-6
+-rm centos-6.old
+-
+-# Compress.
+-rm -f centos-6.xz
+-xz --best --block-size=16777216 centos-6
+-
+-# Result:
+-ls -lh centos-6.xz
+diff --git a/builder/website/centos.sh b/builder/website/centos.sh
+new file mode 100755
+index 0000000..ce7abb6
+--- /dev/null
++++ b/builder/website/centos.sh
+@@ -0,0 +1,101 @@
++#!/bin/bash -
++# virt-builder
++# Copyright (C) 2013 Red Hat Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++
++unset CDPATH
++export LANG=C
++set -e
++set -x
++
++if [ $# -ne 1 ]; then
++ echo "$0 VERSION"
++ exit 1
++fi
++
++version=$1
++output=fedora-$version
++tmpname=tmp-$(tr -cd 'a-f0-9' < /dev/urandom | head -c 8)
++
++# We rebuild this every time there is a new 6.x release, and bump
++# the revision in the index.
++tree=http://mirror.bytemark.co.uk/centos/$version/os/x86_64/
++
++rm -f $output $output.old $output.xz
++
++# Generate the kickstart to a temporary file.
++ks=$(mktemp)
++cat > $ks <<'EOF'
++install
++text
++reboot
++lang en_US.UTF-8
++keyboard us
++network --bootproto dhcp
++rootpw builder
++firewall --enabled --ssh
++selinux --enforcing
++timezone --utc America/New_York
++bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"
++zerombr
++clearpart --all --initlabel
++part /boot --fstype=ext4 --size=512 --asprimary
++part swap --size=1024 --asprimary
++part / --fstype=ext4 --size=1024 --grow --asprimary
++
++# Halt the system once configuration has finished.
++poweroff
++
++%packages
++ at core
++%end
++EOF
++
++# Clean up function.
++cleanup ()
++{
++ rm -f $ks
++ virsh undefine $tmpname ||:
++}
++trap cleanup INT QUIT TERM EXIT ERR
++
++virt-install \
++ --name=$tmpname \
++ --ram=2048 \
++ --cpu=host --vcpus=2 \
++ --os-type=linux --os-variant=rhel$version \
++ --initrd-inject=$ks \
++ --extra-args="ks=file:/`basename $ks` console=tty0 console=ttyS0,115200 proxy=$http_proxy" \
++ --disk $(pwd)/$output,size=6 \
++ --location=$tree \
++ --nographics \
++ --noreboot
++
++# Sysprep (removes logfiles and so on).
++# Note this also touches /.autorelabel so the further installation
++# changes that we make will be labelled properly at first boot.
++virt-sysprep -a $output
++
++# Sparsify.
++mv $output $output.old
++virt-sparsify $output.old $output
++rm $output.old
++
++# Compress.
++xz --best --block-size=16777216 $output
++
++# Result:
++ls -lh $output.xz
+diff --git a/builder/website/index b/builder/website/index
+index 494c177..49b964c 100644
+--- a/builder/website/index
++++ b/builder/website/index
+@@ -14,9 +14,9 @@ notes=CentOS 6.4
+ This CentOS image contains only unmodified @Core group packages.
+
+ It is thus very minimal. The kickstart and install script can be
+- found in the libguestfs git tree:
+- libguestfs.git/builder/website/centos-6.ks
+- libguestfs.git/builder/website/centos-6.sh
++ found in the libguestfs source tree:
++
++ builder/website/centos.sh
+
+ Note that `virt-builder centos-6' will always install the latest
+ 6.x release.
+diff --git a/builder/website/index.asc b/builder/website/index.asc
+index 35f6281..6711df7 100644
+--- a/builder/website/index.asc
++++ b/builder/website/index.asc
+@@ -17,9 +17,9 @@ notes=CentOS 6.4
+ This CentOS image contains only unmodified @Core group packages.
+
+ It is thus very minimal. The kickstart and install script can be
+- found in the libguestfs git tree:
+- libguestfs.git/builder/website/centos-6.ks
+- libguestfs.git/builder/website/centos-6.sh
++ found in the libguestfs source tree:
++
++ builder/website/centos.sh
+
+ Note that `virt-builder centos-6' will always install the latest
+ 6.x release.
+@@ -207,17 +207,17 @@ notes=Ubuntu 13.10 (Saucy).
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.14 (GNU/Linux)
+
+-iQIcBAEBAgAGBQJSeP5LAAoJEJFzj3Pht2igO5QP/2jjVb8W15AWxvuATDc/kOXE
+-8Dvg4hFbvvBnv/U9QQ1/2BNQDykATcVIE/lWg7VzpF2HLuEwbVdwAgEO73xKpeRT
+-U6zGNxkTi0mfr3aKT4rfQtqNlMkc1IMVCQSBJEIHLd1hjh2gozBCM9KM4f5YHK2P
+-i/6GX8j7AeWzVkOb60PKKQrGk1ycXm0UbZuS0MPBqnc9v56fzEyaWVvvrCQEOq7a
+-zTJULgOcfCBHQLF8re2upQV5NbYwruplaCYpsTcvNHvQ/vsoUIf0dNbqvarpwFUQ
+-FHDesMZQBW6OWzsIBkeMYfIJ4GXO0A0ZlVuzBW07eHbmr0ev1b4c37npHrsuytbI
+-TF6SUF7wyIxZlKbyf4W+RaX1hAsMOKXU8ptsMBmBPn7UnWrLbCDAPpS27ruZOA4q
+-oPGeuKLUGPnimjNEatkJH8rmWlg71hsCy1hMGAOTXAUpCgPXHv/WHa0n4GTbtJ1y
+-VzUElr0wAGPOqrClJse6po1h7f6XEdB4mLZ8OYHKNDjJl57QirUcmnmYmRMsctN4
+-tKYgnEcv+PhNMEV/GIQXLrtCYX/Ty81AV4hwlfzL3fjqdxX9f+Fem5PcxeMaS0ik
+-xfnpMsRuprkoNyTAhDr6AX9AcY4fEW8NSfG5YUjt+s27IFLIjl7HfWCbRqcqGwv9
+-VvLm+Omd+GUA6rd4fuee
+-=Gv5k
++iQIcBAEBAgAGBQJSeP+vAAoJEJFzj3Pht2igQIEQALPlH98SZFjg0JAWWMQyLlfb
++A9CF8z2Y/3E8D1+kAqNIJZwXuaJ2f4KnTh1gU1VYHj97hEI6+GolrfISGF+NZOdG
++cI39bQYPWXPbO78Ftv/Ox92JjzbK6XFgErRhbL9ldqmQJ6e51Kpqc5ItULx6rmHD
++uBrOCiUAP49GjxA/LZWzEVHYNidQz/c3kpMFOVIyavWffVzpeFM8+R7zyYWOxP9K
++HZvNM/8TIRCsIyvKETTxMvq+fqGLZBck0e6jT9GugQ5cH0QrdQQIYZd6K3PkvMH6
++Lao9KFfQcdWa7RNa3JNOKIf8Y19VyhAzybLunbjEBJqeq1Sn/3DNtAto3IV7JuOD
++1ySBFDh4I5xEGLBfwhbNOmgV9ccDaffCIju+vz9P9War04cnAFXP9WrUlzvDz5Jl
++zp8CoasP8TdZE9A1zc57UPsdB946/yU6c5zmVOj1uyNxlW3ED/ZD98c45OKuYlpb
++gXhP6am/6QGJFO7mAGihltjAqUayhTsE3s3O26pxQ5AiysuzppjvoNDc8XAlHkWd
++NbLiS4mXY7BbRvdmIg2g9Q7ohnOqQ13L/7CDgu622BPqj1vfrw2KjNJ+w6DzfXN7
++bDevIRlB/hqHaeRAQobUm4ecnVwtIOjDLIjKtHQWkNFiNpaIVIRHgE35F0GVij/R
++wCAfC7j5yJwXxDx8jMZf
++=EoPi
+ -----END PGP SIGNATURE-----
+--
+1.8.3.1
+
diff --git a/0024-builder-website-Add-validate.sh-test-script-to-EXTRA.patch b/0024-builder-website-Add-validate.sh-test-script-to-EXTRA.patch
new file mode 100644
index 0000000..5f0404c
--- /dev/null
+++ b/0024-builder-website-Add-validate.sh-test-script-to-EXTRA.patch
@@ -0,0 +1,27 @@
+From 6f548264f40339e829c3bb2023f3352b4e69b490 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 15:15:17 +0000
+Subject: [PATCH] builder/website: Add validate.sh test script to EXTRA_DIST.
+
+This fixes commit 154bfb7dd46e7998eed1d40ead95923590763739.
+
+(cherry picked from commit 92206e8d09455b3ec63d44e4b55d5eef415681af)
+---
+ builder/website/Makefile.am | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+index cdf263a..ec1ca65 100644
+--- a/builder/website/Makefile.am
++++ b/builder/website/Makefile.am
+@@ -20,6 +20,7 @@ include $(top_srcdir)/subdir-rules.mk
+ EXTRA_DIST = \
+ .gitignore \
+ test-guest.sh \
++ validate.sh \
+ README \
+ index \
+ index.asc \
+--
+1.8.3.1
+
diff --git a/0025-builder-Add-missing-dependency.patch b/0025-builder-Add-missing-dependency.patch
new file mode 100644
index 0000000..edd4420
--- /dev/null
+++ b/0025-builder-Add-missing-dependency.patch
@@ -0,0 +1,33 @@
+From 7ae728b1a5db0290ca2ed488ae3e67c968d2f477 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 15:42:05 +0000
+Subject: [PATCH] builder: Add missing dependency.
+
+index-parser-c.c depends on index-parse.h being created first.
+However without an explicit dependency, this is not done (and implicit
+deps don't work because automake doesn't sufficiently understand OCaml
+programs).
+
+This fixes commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633.
+
+(cherry picked from commit dfe97b352d6b398c3cb3ddb1c9984767722e514b)
+---
+ builder/Makefile.am | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index 2027203..a44f820 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -120,6 +120,8 @@ virt-builder: $(OBJECTS)
+ .ml.cmx:
+ $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) -c $< -o $@
+
++index-parser-c.o: index-parse.h
++
+ # Manual pages and HTML files for the website.
+
+ man_MANS += virt-builder.1
+--
+1.8.3.1
+
diff --git a/0026-builder-Add-some-generated-files-to-CLEANFILES.patch b/0026-builder-Add-some-generated-files-to-CLEANFILES.patch
new file mode 100644
index 0000000..956efff
--- /dev/null
+++ b/0026-builder-Add-some-generated-files-to-CLEANFILES.patch
@@ -0,0 +1,29 @@
+From 88ffe2a4e415e7502f6749938a621899d2de0251 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 15:43:24 +0000
+Subject: [PATCH] builder: Add some generated files to CLEANFILES.
+
+This updates commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633.
+
+(cherry picked from commit 01551e546293bbbd094d4d4acfdaf421f7758251)
+---
+ builder/Makefile.am | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index a44f820..44384d9 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -205,4 +205,8 @@ stamp-virt-index-validate.pod: virt-index-validate.pod
+ $<
+ touch $@
+
+-CLEANFILES += stamp-virt-index-validate.pod
++CLEANFILES += \
++ index-parse.c \
++ index-parse.h \
++ index-scan.c \
++ stamp-virt-index-validate.pod
+--
+1.8.3.1
+
diff --git a/0027-builder-Add-dependency-from-index-parse.h-to-index-v.patch b/0027-builder-Add-dependency-from-index-parse.h-to-index-v.patch
new file mode 100644
index 0000000..5da91eb
--- /dev/null
+++ b/0027-builder-Add-dependency-from-index-parse.h-to-index-v.patch
@@ -0,0 +1,30 @@
+From 5ab8da71343c6f8c0dd16111480893730db2cc84 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 15:56:34 +0000
+Subject: [PATCH] builder: Add dependency from index-parse.h to index-validate.
+
+For some reason automake doesn't get this dependency right,
+resulting in occasional build failures if yacc races the
+rest of the build.
+
+(cherry picked from commit e3ac293e869a4c69225e3d954b812e9bf21588a1)
+---
+ builder/Makefile.am | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index 44384d9..593e3ef 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -192,6 +192,8 @@ virt_index_validate_SOURCES = \
+ index-struct.c \
+ index-validate.c
+
++index-validate.o: index-parse.h
++
+ man_MANS += virt-index-validate.1
+ noinst_DATA += $(top_builddir)/html/virt-index-validate.1.html
+
+--
+1.8.3.1
+
diff --git a/0028-builder-Fix-centos-script-output-filename-was-wrong.patch b/0028-builder-Fix-centos-script-output-filename-was-wrong.patch
new file mode 100644
index 0000000..c406961
--- /dev/null
+++ b/0028-builder-Fix-centos-script-output-filename-was-wrong.patch
@@ -0,0 +1,28 @@
+From 1f8d51695861b76edc23aca82f39ef816a20061d Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 16:51:08 +0000
+Subject: [PATCH] builder: Fix centos script - output filename was wrong.
+
+This fixes commit 2f3fb2420e7f2ccc19fdc863ecc7b7ce29dd6aa1.
+
+(cherry picked from commit 663012c5ffecc6f89ad164d292fc0f970338f824)
+---
+ builder/website/centos.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/builder/website/centos.sh b/builder/website/centos.sh
+index ce7abb6..d9f2645 100755
+--- a/builder/website/centos.sh
++++ b/builder/website/centos.sh
+@@ -27,7 +27,7 @@ if [ $# -ne 1 ]; then
+ fi
+
+ version=$1
+-output=fedora-$version
++output=centos-$version
+ tmpname=tmp-$(tr -cd 'a-f0-9' < /dev/urandom | head -c 8)
+
+ # We rebuild this every time there is a new 6.x release, and bump
+--
+1.8.3.1
+
diff --git a/0029-builder-Add-dependencies-which-automake-doesn-t-gene.patch b/0029-builder-Add-dependencies-which-automake-doesn-t-gene.patch
new file mode 100644
index 0000000..64e64a9
--- /dev/null
+++ b/0029-builder-Add-dependencies-which-automake-doesn-t-gene.patch
@@ -0,0 +1,51 @@
+From 90b8f20a41798ba4a38e7681783a5a14a13ef541 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 17:40:20 +0000
+Subject: [PATCH] builder: Add dependencies which automake doesn't generate
+ correctly.
+
+This is a further attempt, earlier commits:
+commit e3ac293e869a4c69225e3d954b812e9bf21588a1
+commit dfe97b352d6b398c3cb3ddb1c9984767722e514b
+
+(cherry picked from commit 4339b55d105eab6eba2756bffff42a1c34f9f656)
+---
+ builder/Makefile.am | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index 593e3ef..a828ffd 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -120,8 +120,6 @@ virt-builder: $(OBJECTS)
+ .ml.cmx:
+ $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) -c $< -o $@
+
+-index-parser-c.o: index-parse.h
+-
+ # Manual pages and HTML files for the website.
+
+ man_MANS += virt-builder.1
+@@ -192,8 +190,6 @@ virt_index_validate_SOURCES = \
+ index-struct.c \
+ index-validate.c
+
+-index-validate.o: index-parse.h
+-
+ man_MANS += virt-index-validate.1
+ noinst_DATA += $(top_builddir)/html/virt-index-validate.1.html
+
+@@ -212,3 +208,10 @@ CLEANFILES += \
+ index-parse.h \
+ index-scan.c \
+ stamp-virt-index-validate.pod
++
++# Fix dependencies which automake doesn't generate correctly.
++if HAVE_OCAML
++index-parser-c.o: index-parse.h
++index-scan.o: index-parse.h
++endif
++index-validate.o: index-parse.h
+--
+1.8.3.1
+
diff --git a/copy-patches.sh b/copy-patches.sh
new file mode 100755
index 0000000..e242cd2
--- /dev/null
+++ b/copy-patches.sh
@@ -0,0 +1,53 @@
+#!/bin/bash -
+
+set -e
+
+# Maintainer script to copy patches from the git repo to the current
+# directory. Use it like this:
+# ./copy-patches.sh
+
+# Check we're in the right directory.
+if [ ! -f libguestfs.spec ]; then
+ echo "$0: run this from the directory containing 'libguestfs.spec'"
+ exit 1
+fi
+
+git_checkout=$HOME/d/libguestfs-fedora-20
+if [ ! -d $git_checkout ]; then
+ echo "$0: $git_checkout does not exist"
+ echo "This script is only for use by the maintainer when preparing a"
+ echo "libguestfs release for Fedora 20."
+ exit 1
+fi
+
+# Get the base version of libguestfs.
+version=`grep '^Version:' libguestfs.spec | awk '{print $2}'`
+
+# Remove any existing patches.
+git rm -f [0-9]*.patch ||:
+rm -f [0-9]*.patch
+
+# Get the patches.
+(cd $git_checkout; rm -f [0-9]*.patch; git format-patch -N $version)
+mv $git_checkout/[0-9]*.patch .
+
+# Remove any not to be applied.
+rm -f *NOT-FOR-RPM*.patch
+
+# Add the patches.
+git add [0-9]*.patch
+
+# Print out the patch lines.
+echo
+echo "--- Copy the following text into libguestfs.spec file"
+echo
+
+echo "# Git-managed patches."
+for f in [0-9]*.patch; do
+ n=`echo $f | awk -F- '{print $1}'`
+ echo "Patch$n: $f"
+done
+
+echo "# Add any non-git patches here."
+echo
+echo "--- End of text"
diff --git a/libguestfs.spec b/libguestfs.spec
index f446e06..65c3334 100644
--- a/libguestfs.spec
+++ b/libguestfs.spec
@@ -12,13 +12,56 @@ Summary: Access and modify virtual machine disk images
Name: libguestfs
Epoch: 1
Version: 1.24.1
-Release: 1%{?dist}
+Release: 2%{?dist}
License: LGPLv2+
# Source and patches.
URL: http://libguestfs.org/
Source0: http://libguestfs.org/download/1.23-development/%{name}-%{version}.tar.gz
+# Note we use the fedora-20 branch from the upstream repo which
+# contains only upstream, backported patches, but conveniently manages
+# them in git. In order to update this list, run the
+# 'copy-patches.sh' script.
+
+# Git-managed patches.
+Patch0001: 0001-builder-Don-t-run-virt-resize-when-not-necessary.patch
+Patch0002: 0002-builder-Make-xzcat-binary-configurable-and-use-AC_PA.patch
+Patch0003: 0003-builder-Use-pxzcat-optionally-to-speed-up-xzcat-step.patch
+Patch0004: 0004-builder-Add-no-sync-option-to-avoid-sync-on-exit.patch
+Patch0005: 0005-builder-Add-mkdir-option-to-create-directories.patch
+Patch0006: 0006-builder-Allow-upload-to-a-directory.patch
+Patch0007: 0007-builder-Add-write-option-to-write-a-literal-file.patch
+Patch0008: 0008-builder-Document-how-to-boot-VMs-directly-in-qemu-or.patch
+Patch0009: 0009-firstboot-Send-the-output-to-the-console-as-well-as-.patch
+Patch0010: 0010-builder-Add-a-section-on-performance-to-the-manual.patch
+Patch0011: 0011-builder-Add-m-memsize-and-smp-command-line-options.patch
+Patch0012: 0012-builder-Allow-multiple-source-paths-to-be-specified.patch
+Patch0013: 0013-builder-Don-t-use-git-tree-libguestfs.git-to-refer-t.patch
+Patch0014: 0014-builder-Add-a-real-scanner-parser-for-index-files.patch
+Patch0015: 0015-builder-Fix-check-valgrind-so-it-does-something-in-t.patch
+Patch0016: 0016-builder-Fix-missing-files-in-EXTRA_DIST.patch
+Patch0017: 0017-builder-Add-an-extra-Makefile.am-to-builder-website.patch
+Patch0018: 0018-builder-website-Add-index-validation-test-script.patch
+Patch0019: 0019-builder-Internal-implementation-of-parallel-xzcat-px.patch
+Patch0020: 0020-builder-Replace-fedora-NN-shell-kickstart-with-a-sin.patch
+Patch0021: 0021-builder-Replace-ubuntu-NN-.sh-with-a-single-script.patch
+Patch0022: 0022-builder-Replace-debian-NN-.sh-with-a-single-script.patch
+Patch0023: 0023-builder-Replace-centos-6.sh-with-a-single-script.patch
+Patch0024: 0024-builder-website-Add-validate.sh-test-script-to-EXTRA.patch
+Patch0025: 0025-builder-Add-missing-dependency.patch
+Patch0026: 0026-builder-Add-some-generated-files-to-CLEANFILES.patch
+Patch0027: 0027-builder-Add-dependency-from-index-parse.h-to-index-v.patch
+Patch0028: 0028-builder-Fix-centos-script-output-filename-was-wrong.patch
+Patch0029: 0029-builder-Add-dependencies-which-automake-doesn-t-gene.patch
+# Add any non-git patches here.
+
+# Use git for patch management.
+BuildRequires: git
+
+# Run autotools after applying the patches.
+BuildRequires: autoconf, automake, libtool, gettext-devel
+
# Basic build requirements:
BuildRequires: perl(Pod::Simple)
BuildRequires: perl(Pod::Man)
@@ -147,6 +190,8 @@ Source3: 99-guestfsd.rules
# Replacement README file for Fedora users.
Source4: README-replacement.in
+Source5: copy-patches.sh
+
# https://fedoraproject.org/wiki/Packaging:No_Bundled_Libraries#Packages_granted_exceptions
Provides: bundled(gnulib)
@@ -573,6 +618,19 @@ for %{name}.
%prep
%setup -q
+# Use git to manage patches.
+# http://rwmj.wordpress.com/2011/08/09/nice-rpm-git-patch-management-trick/
+git init
+git config user.email "libguestfs at redhat.com"
+git config user.name "libguestfs"
+git add .
+git commit -a -q -m "%{version} baseline"
+git am %{patches}
+
+# Patches affect Makefile.am and configure.ac, so rerun autotools.
+autoreconf -i
+autoconf
+
if [ "$(getenforce | tr '[A-Z]' '[a-z]')" != "disabled" ]; then
# For sVirt to work, the local temporary directory we use in the
# tests must be labelled the same way as /tmp.
@@ -630,6 +688,9 @@ fi
--enable-install-daemon \
$extra
+# Patches above add man pages, so this is needed.
+make -C po-docs update-po
+
# 'INSTALLDIRS' ensures that Perl and Ruby libs are installed in the
# vendor dir not the site dir.
make V=1 INSTALLDIRS=vendor %{?_smp_mflags}
@@ -980,6 +1041,10 @@ mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/run/libguestfs
%changelog
+* Tue Nov 05 2013 Richard W.M. Jones <rjones at redhat.com> - 1:1.24.1-2
+- Backport virt-builder features from upstream at users [multiple] requests.
+- Use git to manage patches, add copy-patches.sh script.
+
* Fri Nov 01 2013 Richard W.M. Jones <rjones at redhat.com> - 1:1.24.1-1
- New upstream version 1.24.1.
More information about the scm-commits
mailing list