Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 00/67] Proposed patches for libguestfs 1.22.6.
In the kernel and qemu communities it is routine for patches that will be backported to stable branches to be posted for review. I'm proposing we do the same for libguestfs stable branches. All of the attached have been tested with 'make check-release'. Rich.
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 01/67] generator: Fix whitespace.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 559bd48960f795dc59d889e5776f545f2e0d494a) --- generator/xdr.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/xdr.ml b/generator/xdr.ml index e2161cd..60e9dad 100644 --- a/generator/xdr.ml +++ b/generator/xdr.ml @@ -92,7 +92,7 @@ let generate_xdr () pr "/* Function arguments and return values. */\n"; pr "\n"; List.iter ( - fun { name =shortname; style = ret, args, optargs } -> + fun { name = shortname; style = ret, args, optargs } -> let name = "guestfs_" ^ shortname in (* Ordinary arguments and optional arguments are concatenated -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 02/67] generator: Fix the case where a daemon function has one FileIn/FileOut parameter and no other parameters.
From: "Richard W.M. Jones" <rjones@redhat.com> The FileIn/FileOut parameters are not passed through to the daemon. Previously we generated incorrect RPC code (an empty 'struct guestfs_<fn>_args') because we didn't account for these FileIn/FileOut parameters correctly. (cherry picked from commit e31c32ce1bc87d164103e79288effc64bb41181f) --- generator/c.ml | 12 +++++++----- generator/daemon.ml | 26 ++++++++++++++++---------- generator/xdr.ml | 47 +++++++++++++++++++++++++---------------------- 3 files changed, 48 insertions(+), 37 deletions(-) diff --git a/generator/c.ml b/generator/c.ml index 646a173..451c28d 100644 --- a/generator/c.ml +++ b/generator/c.ml @@ -1317,7 +1317,10 @@ and generate_client_actions hash () handle_null_optargs optargs c_name; - (match args with + let args_passed_to_daemon + List.filter (function FileIn _ | FileOut _ -> false | _ -> true) + args in + (match args_passed_to_daemon with | [] -> () | _ -> pr " struct guestfs_%s_args args;\n" name ); @@ -1385,7 +1388,7 @@ and generate_client_actions hash () pr "\n"; (* Send the main header and arguments. *) - if args = [] && optargs = [] then ( + if args_passed_to_daemon = [] && optargs = [] then ( pr " serial = guestfs___send (g, GUESTFS_PROC_%s, progress_hint, 0,\n" (String.uppercase name); pr " NULL, NULL);\n" @@ -1407,7 +1410,6 @@ and generate_client_actions hash () pr " args.%s = %s;\n" n n | Int64 n -> pr " args.%s = %s;\n" n n - | FileIn _ | FileOut _ -> () | BufferIn n -> pr " /* Just catch grossly large sizes. XDR encoding will make this precise. */\n"; pr " if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n; @@ -1418,8 +1420,8 @@ and generate_client_actions hash () pr " }\n"; pr " args.%s.%s_val = (char *) %s;\n" n n n; pr " args.%s.%s_len = %s_size;\n" n n n - | Pointer _ -> assert false - ) args; + | FileIn _ | FileOut _ | Pointer _ -> assert false + ) args_passed_to_daemon; List.iter ( fun argt -> diff --git a/generator/daemon.ml b/generator/daemon.ml index 704deb6..e68622b 100644 --- a/generator/daemon.ml +++ b/generator/daemon.ml @@ -57,7 +57,11 @@ let generate_daemon_actions_h () List.iter ( fun { name = name; style = ret, args, optargs } -> - let style = ret, args @ args_of_optargs optargs, [] in + let args_passed_to_daemon = args @ args_of_optargs optargs in + let args_passed_to_daemon + List.filter (function FileIn _ | FileOut _ -> false | _ -> true) + args_passed_to_daemon in + let style = ret, args_passed_to_daemon, [] in generate_prototype ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_" name style; @@ -108,7 +112,11 @@ and generate_daemon_actions () pr " char *r;\n" ); - if args <> [] || optargs <> [] then ( + let args_passed_to_daemon = args @ args_of_optargs optargs in + let args_passed_to_daemon + List.filter (function FileIn _ | FileOut _ -> false | _ -> true) + args_passed_to_daemon in + if args_passed_to_daemon <> [] then ( pr " struct guestfs_%s_args args;\n" name; List.iter ( function @@ -119,12 +127,11 @@ and generate_daemon_actions () | Bool n -> pr " int %s;\n" n | Int n -> pr " int %s;\n" n | Int64 n -> pr " int64_t %s;\n" n - | FileIn _ | FileOut _ -> () | BufferIn n -> pr " const char *%s;\n" n; pr " size_t %s_size;\n" n - | Pointer _ -> assert false - ) (args @ args_of_optargs optargs) + | FileIn _ | FileOut _ | Pointer _ -> assert false + ) args_passed_to_daemon ); pr "\n"; @@ -174,7 +181,7 @@ and generate_daemon_actions () pr "\n"; (* Decode arguments. *) - if args <> [] || optargs <> [] then ( + if args_passed_to_daemon <> [] then ( pr " memset (&args, 0, sizeof args);\n"; pr "\n"; pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name; @@ -236,12 +243,11 @@ and generate_daemon_actions () | Bool n -> pr " %s = args.%s;\n" n n | Int n -> pr " %s = args.%s;\n" n n | Int64 n -> pr " %s = args.%s;\n" n n - | FileIn _ | FileOut _ -> () | BufferIn n -> pr " %s = args.%s.%s_val;\n" n n n; pr " %s_size = args.%s.%s_len;\n" n n n - | Pointer _ -> assert false - ) (args @ args_of_optargs optargs); + | FileIn _ | FileOut _ | Pointer _ -> assert false + ) args_passed_to_daemon; pr "\n" ); @@ -346,7 +352,7 @@ and generate_daemon_actions () (* Free the args. *) pr "done:\n"; - (match args with + (match args_passed_to_daemon with | [] -> () | _ -> pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n" diff --git a/generator/xdr.ml b/generator/xdr.ml index 60e9dad..0d1b4e3 100644 --- a/generator/xdr.ml +++ b/generator/xdr.ml @@ -98,29 +98,32 @@ let generate_xdr () (* Ordinary arguments and optional arguments are concatenated * together in the XDR args struct. The optargs_bitmask field * in the header controls which optional arguments are - * meaningful. + * meaningful. FileIn/FileOut parameters are ignored here. *) - (match args @ args_of_optargs optargs with - | [] -> () - | args -> - pr "struct %s_args {\n" name; - List.iter ( - function - | Pathname n | Device n | Mountable n | Dev_or_Path n - | Mountable_or_Path n | String n - | Key n -> - pr " string %s<>;\n" n - | OptString n -> pr " guestfs_str *%s;\n" n - | StringList n | DeviceList n -> pr " guestfs_str %s<>;\n" n - | Bool n -> pr " bool %s;\n" n - | Int n -> pr " int %s;\n" n - | Int64 n -> pr " int64_t %s;\n" n - | BufferIn n -> - pr " opaque %s<>;\n" n - | FileIn _ | FileOut _ -> () - | Pointer _ -> assert false - ) args; - pr "};\n\n" + let args_passed_to_daemon = args @ args_of_optargs optargs in + let args_passed_to_daemon + List.filter (function FileIn _ | FileOut _ -> false | _ -> true) + args_passed_to_daemon in + (match args_passed_to_daemon with + | [] -> () + | args -> + pr "struct %s_args {\n" name; + List.iter ( + function + | Pathname n | Device n | Mountable n | Dev_or_Path n + | Mountable_or_Path n | String n + | Key n -> + pr " string %s<>;\n" n + | OptString n -> pr " guestfs_str *%s;\n" n + | StringList n | DeviceList n -> pr " guestfs_str %s<>;\n" n + | Bool n -> pr " bool %s;\n" n + | Int n -> pr " int %s;\n" n + | Int64 n -> pr " int64_t %s;\n" n + | BufferIn n -> + pr " opaque %s<>;\n" n + | FileIn _ | FileOut _ | Pointer _ -> assert false + ) args; + pr "};\n\n" ); (match ret with | RErr -> () -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 03/67] src/file.c: Be sure to call guestfs___lazy_make_tmpdir before using g->tmpdir.
From: "Richard W.M. Jones" <rjones@redhat.com> Although g->tmpdir is always set after launch, and none of these calls should be used before launch, it's always possible that a caller would use one of these APIs before launching the handle. If guestfs___lazy_make_tmpdir is not called, then g->tmpdir is NULL, and the constructed filename would look like "(null)/...". In fact it's possible to observe this error (although it seems to have no especially bad effects): $ strace guestfish ls / |& fgrep '(null)' unlink("(null)/ls1") = -1 ENOENT (No such file or directory) (cherry picked from commit 1937108a4a6070750f0d636f7dcc8725441cc4eb) --- src/file.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/file.c b/src/file.c index 7051936..d21a61d 100644 --- a/src/file.c +++ b/src/file.c @@ -88,6 +88,9 @@ guestfs__read_file (guestfs_h *g, const char *path, size_t *size_r) char *ret = NULL; struct stat statbuf; + if (guestfs___lazy_make_tmpdir (g) == -1) + goto err; + tmpfile = safe_asprintf (g, "%s/cat%d", g->tmpdir, ++g->unique); if (guestfs_download (g, path, tmpfile) == -1) @@ -212,6 +215,9 @@ guestfs__find (guestfs_h *g, const char *directory) char **ret = NULL; size_t i, count, size; + if (guestfs___lazy_make_tmpdir (g) == -1) + goto err; + tmpfile = safe_asprintf (g, "%s/find%d", g->tmpdir, ++g->unique); if (guestfs_find0 (g, directory, tmpfile) == -1) @@ -313,6 +319,9 @@ write_or_append (guestfs_h *g, const char *path, (!append ? guestfs_internal_write : guestfs_internal_write_append) (g, path, content, size); + if (guestfs___lazy_make_tmpdir (g) == -1) + goto err; + /* Write the content out to a temporary file. */ tmpfile = safe_asprintf (g, "%s/write%d", g->tmpdir, ++g->unique); @@ -508,6 +517,9 @@ guestfs__ls (guestfs_h *g, const char *directory) char **ret = NULL; size_t i, count, size; + if (guestfs___lazy_make_tmpdir (g) == -1) + goto err; + tmpfile = safe_asprintf (g, "%s/ls%d", g->tmpdir, ++g->unique); if (guestfs_ls0 (g, directory, tmpfile) == -1) -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 04/67] resize: Link to information about dracut-modules-growroot.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit fb282e677c015de65627790a02aceb6ed264ed80) --- resize/virt-resize.pod | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resize/virt-resize.pod b/resize/virt-resize.pod index 839e4d8..2794b02 100644 --- a/resize/virt-resize.pod +++ b/resize/virt-resize.pod @@ -719,6 +719,10 @@ hand-calculating sector offsets, which is something that virt-resize was designed to avoid. If you want to see the guestfish-equivalent commands that virt-resize runs, use the I<--debug> flag. +L<dracut(8)> includes a module called C<dracut-modules-growroot> which +can be used to grow the root partition when the guest first boots up. +There is documentation for this module in an associated README file. + =head1 SHELL QUOTING Libvirt guest names can contain arbitrary characters, some of which -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 05/67] daemon: cap-get-file: Return empty string if no capability on file (RHBZ#989356).
From: "Richard W.M. Jones" <rjones@redhat.com> Return an empty string (instead of an error) if no capabilities are set on a file, and document that in the API. (cherry picked from commit c663ab3bb9ab02fb3ca6209333c2d5402081c4de) --- daemon/cap.c | 12 ++++++++++++ generator/actions.ml | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/daemon/cap.c b/daemon/cap.c index d1f0398..1d732c5 100644 --- a/daemon/cap.c +++ b/daemon/cap.c @@ -48,6 +48,18 @@ do_cap_get_file (const char *path) CHROOT_OUT; if (cap == NULL) { + /* The getcap utility (part of libcap) ignores ENODATA. It just + * means there is no capability attached to the file (RHBZ#989356). + */ + if (errno == ENODATA) { + ret = strdup (""); + if (ret == NULL) { + reply_with_perror ("strdup"); + return NULL; + } + return ret; + } + reply_with_perror ("%s", path); return NULL; } diff --git a/generator/actions.ml b/generator/actions.ml index 238553d..d30aec8 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -10928,7 +10928,9 @@ attached to directory C<dir>." }; shortdesc = "get the Linux capabilities attached to a file"; longdesc = "\ This function returns the Linux capabilities attached to C<path>. -The capabilities set is returned in text form (see L<cap_to_text(3)>)." }; +The capabilities set is returned in text form (see L<cap_to_text(3)>). + +If no capabilities are attached to a file, an empty string is returned." }; { defaults with name = "cap_set_file"; -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 06/67] resize: Move isatty_stdout function to separate module (TTY.isatty_stdout).
From: "Richard W.M. Jones" <rjones@redhat.com> It was jammed into the Progress module just for convenience. (cherry picked from commit b56990ddf8aa4dc4db3da592783acfe055c05534) --- po/POTFILES | 1 + po/POTFILES-ml | 1 + resize/Makefile.am | 7 ++++++- resize/progress-c.c | 9 --------- resize/progress.ml | 3 +-- resize/tTY.ml | 19 +++++++++++++++++++ resize/tTY.mli | 23 +++++++++++++++++++++++ resize/tty-c.c | 35 +++++++++++++++++++++++++++++++++++ sparsify/Makefile.am | 2 ++ 9 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 resize/tTY.ml create mode 100644 resize/tTY.mli create mode 100644 resize/tty-c.c diff --git a/po/POTFILES b/po/POTFILES index 4aaa7f7..457e129 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -231,6 +231,7 @@ python/guestfs-py.c rescue/test-virt-rescue.pl rescue/virt-rescue.c resize/progress-c.c +resize/tty-c.c ruby/ext/guestfs/_guestfs.c src/actions-0.c src/actions-1.c diff --git a/po/POTFILES-ml b/po/POTFILES-ml index 566c6ae..34533ea 100644 --- a/po/POTFILES-ml +++ b/po/POTFILES-ml @@ -3,6 +3,7 @@ resize/common_utils.ml resize/common_utils_tests.ml resize/progress.ml resize/resize.ml +resize/tTY.ml sparsify/sparsify.ml sysprep/firstboot.ml sysprep/main.ml diff --git a/resize/Makefile.am b/resize/Makefile.am index 9a62f4c..a9c95ff 100644 --- a/resize/Makefile.am +++ b/resize/Makefile.am @@ -32,16 +32,21 @@ SOURCES = \ progress-c.c \ progress.mli \ progress.ml \ - resize.ml + resize.ml \ + tty-c.c \ + tTY.mli \ + tTY.ml if HAVE_OCAML # Note this list must be in dependency order. OBJECTS = \ $(top_builddir)/fish/guestfish-progress.o \ + tty-c.o \ progress-c.o \ common_gettext.cmx \ common_utils.cmx \ + tTY.cmx \ progress.cmx \ resize.cmx diff --git a/resize/progress-c.c b/resize/progress-c.c index 2813d0c..67913eb 100644 --- a/resize/progress-c.c +++ b/resize/progress-c.c @@ -104,12 +104,3 @@ virt_resize_progress_bar_set (value barv, CAMLreturn (Val_unit); } - -/* RHEL 5-era ocaml didn't have Unix.isatty. */ -value -virt_resize_isatty_stdout (value unitv) -{ - CAMLparam1 (unitv); - - CAMLreturn (isatty(1) ? Val_true : Val_false); -} diff --git a/resize/progress.ml b/resize/progress.ml index 1ff73c2..e53e693 100644 --- a/resize/progress.ml +++ b/resize/progress.ml @@ -28,13 +28,12 @@ external progress_bar_reset : progress_bar -> unit = "virt_resize_progress_bar_reset" external progress_bar_set : progress_bar -> int64 -> int64 -> unit = "virt_resize_progress_bar_set" -external isatty_stdout : unit -> bool = "virt_resize_isatty_stdout" let set_up_progress_bar ?(machine_readable = false) (g : Guestfs.guestfs) (* Only display progress bars if the machine_readable flag is set or * the output is a tty. *) - if machine_readable || isatty_stdout () then ( + if machine_readable || TTY.isatty_stdout () then ( (* Initialize the C mini library. *) let bar = progress_bar_init ~machine_readable in diff --git a/resize/tTY.ml b/resize/tTY.ml new file mode 100644 index 0000000..32c1f54 --- /dev/null +++ b/resize/tTY.ml @@ -0,0 +1,19 @@ +(* virt-resize + * 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 isatty_stdout : unit -> bool = "virt_resize_isatty_stdout" diff --git a/resize/tTY.mli b/resize/tTY.mli new file mode 100644 index 0000000..69441f1 --- /dev/null +++ b/resize/tTY.mli @@ -0,0 +1,23 @@ +(* virt-resize + * 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. + *) + +(** TTY utilities. *) + +val isatty_stdout : unit -> bool +(** RHEL 5-era ocaml didn't have Unix.isatty. This is not needed in + recent OCaml. *) diff --git a/resize/tty-c.c b/resize/tty-c.c new file mode 100644 index 0000000..040a132 --- /dev/null +++ b/resize/tty-c.c @@ -0,0 +1,35 @@ +/* virt-resize - interface to isatty + * 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 <unistd.h> + +#include <caml/memory.h> +#include <caml/mlvalues.h> + +/* RHEL 5-era ocaml didn't have Unix.isatty. */ +value +virt_resize_isatty_stdout (value unitv) +{ + CAMLparam1 (unitv); + + CAMLreturn (isatty (1) ? Val_true : Val_false); +} diff --git a/sparsify/Makefile.am b/sparsify/Makefile.am index e29cf17..25830bb 100644 --- a/sparsify/Makefile.am +++ b/sparsify/Makefile.am @@ -33,9 +33,11 @@ if HAVE_OCAML # Note this list must be in dependency order. OBJECTS = \ $(top_builddir)/fish/guestfish-progress.o \ + $(top_builddir)/resize/tty-c.o \ $(top_builddir)/resize/progress-c.o \ $(top_builddir)/resize/common_gettext.cmx \ $(top_builddir)/resize/common_utils.cmx \ + $(top_builddir)/resize/tTY.cmx \ $(top_builddir)/resize/progress.cmx \ sparsify.cmx -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 07/67] internal: Add CLEANUP_XMLFREEURI (cleanup function for xmlURIPtr).
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 0e1ba00059b5ebbca2e137f2685b2eb65ed33b13) --- src/cleanup.c | 10 ++++++++++ src/guestfs-internal-frontend.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/src/cleanup.c b/src/cleanup.c index 43d746e..13018f0 100644 --- a/src/cleanup.c +++ b/src/cleanup.c @@ -23,6 +23,7 @@ #include <unistd.h> #include <string.h> +#include <libxml/uri.h> #include <libxml/tree.h> #include <libxml/xpath.h> #include <libxml/xmlwriter.h> @@ -87,6 +88,15 @@ guestfs___cleanup_xmlFreeDoc (void *ptr) } void +guestfs___cleanup_xmlFreeURI (void *ptr) +{ + xmlURIPtr uri = * (xmlURIPtr *) ptr; + + if (uri) + xmlFreeURI (uri); +} + +void guestfs___cleanup_xmlFreeTextWriter (void *ptr) { xmlTextWriterPtr xo = * (xmlTextWriterPtr *) ptr; diff --git a/src/guestfs-internal-frontend.h b/src/guestfs-internal-frontend.h index 9cb3664..db6122f 100644 --- a/src/guestfs-internal-frontend.h +++ b/src/guestfs-internal-frontend.h @@ -47,6 +47,8 @@ __attribute__((cleanup(guestfs___cleanup_xmlBufferFree))) #define CLEANUP_XMLFREEDOC \ __attribute__((cleanup(guestfs___cleanup_xmlFreeDoc))) +#define CLEANUP_XMLFREEURI \ + __attribute__((cleanup(guestfs___cleanup_xmlFreeURI))) #define CLEANUP_XMLFREETEXTWRITER \ __attribute__((cleanup(guestfs___cleanup_xmlFreeTextWriter))) #define CLEANUP_XMLXPATHFREECONTEXT \ @@ -60,6 +62,7 @@ #define CLEANUP_UNLINK_FREE #define CLEANUP_XMLBUFFERFREE #define CLEANUP_XMLFREEDOC +#define CLEANUP_XMLFREEURI #define CLEANUP_XMLFREETEXTWRITER #define CLEANUP_XMLXPATHFREECONTEXT #define CLEANUP_XMLXPATHFREEOBJECT @@ -104,6 +107,7 @@ extern void guestfs___cleanup_hash_free (void *ptr); extern void guestfs___cleanup_unlink_free (void *ptr); extern void guestfs___cleanup_xmlBufferFree (void *ptr); extern void guestfs___cleanup_xmlFreeDoc (void *ptr); +extern void guestfs___cleanup_xmlFreeURI (void *ptr); extern void guestfs___cleanup_xmlFreeTextWriter (void *ptr); extern void guestfs___cleanup_xmlXPathFreeContext (void *ptr); extern void guestfs___cleanup_xmlXPathFreeObject (void *ptr); -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 08/67] fish: Don't store xmlURIPtr directly in the drive struct.
From: "Richard W.M. Jones" <rjones@redhat.com> Original drv_uri fields: xmlURIPtr uri; /* URI */ char *socket; /* ?socket parameter from URI. */ const char *format; /* format (NULL == autodetect) */ New drv_uri fields: char *path; /* disk path */ char *protocol; /* protocol (eg. "nbd") */ char **server; /* server(s) - can be NULL */ char *username; /* username - can be NULL */ const char *format; /* format (NULL == autodetect) */ const char *orig_uri; /* original URI (for error messages etc.) */ This is just code motion. (cherry picked from commit a3891430bc9fe408505277701962acaa664fc96a) --- df/main.c | 7 ++----- fish/options.c | 62 +++++++++++++++++++++++++++++++++++++++++++--------------- fish/options.h | 9 +++++---- 3 files changed, 53 insertions(+), 25 deletions(-) diff --git a/df/main.c b/df/main.c index e208e9a..5524070 100644 --- a/df/main.c +++ b/df/main.c @@ -30,8 +30,6 @@ #include <assert.h> #include <libintl.h> -#include <libxml/uri.h> - #ifdef HAVE_LIBVIRT #include <libvirt/libvirt.h> #include <libvirt/virterror.h> @@ -337,10 +335,9 @@ single_drive_display_name (struct drv *drvs) break; case drv_uri: - name = (char *) xmlSaveUri (drvs->uri.uri); + name = strdup (drvs->uri.orig_uri); if (name == NULL) { - fprintf (stderr, _("%s: xmlSaveUri: could not make printable URI\n"), - program_name); + perror ("strdup"); exit (EXIT_FAILURE); } /* Try to shorten the URI to just the final element, if it will diff --git a/fish/options.c b/fish/options.c index 387ce79..787402c 100644 --- a/fish/options.c +++ b/fish/options.c @@ -35,6 +35,7 @@ static int is_uri (const char *arg); static void parse_uri (const char *arg, const char *format, struct drv *drv); static char *query_get (xmlURIPtr uri, const char *search_name); +static char **make_server (xmlURIPtr uri, const char *socket); /* Handle the '-a' option when passed on the command line. */ void @@ -95,8 +96,12 @@ is_uri (const char *arg) static void parse_uri (const char *arg, const char *format, struct drv *drv) { - xmlURIPtr uri; - char *socket; + CLEANUP_XMLFREEURI xmlURIPtr uri = NULL; + CLEANUP_FREE char *socket = NULL; + char *path; + char *protocol; + char **server; + char *username; uri = xmlParseURI (arg); if (!uri) { @@ -132,11 +137,37 @@ parse_uri (const char *arg, const char *format, struct drv *drv) } */ + protocol = strdup (uri->scheme); + if (protocol == NULL) { + perror ("strdup"); + exit (EXIT_FAILURE); + } + + server = make_server (uri, socket); + + if (uri->user && STRNEQ (uri->user, "")) { + username = strdup (uri->user); + if (!username) { + perror ("username"); + exit (EXIT_FAILURE); + } + } + else username = NULL; + + path = strdup (uri->path ? uri->path : ""); + if (!path) { + perror ("path"); + exit (EXIT_FAILURE); + } + drv->type = drv_uri; drv->nr_drives = -1; - drv->uri.uri = uri; - drv->uri.socket = socket; + drv->uri.path = path; + drv->uri.protocol = protocol; + drv->uri.server = server; + drv->uri.username = username; drv->uri.format = format; + drv->uri.orig_uri = arg; } /* Code inspired by libvirt src/util/viruri.c, written by danpb, @@ -285,7 +316,6 @@ add_drives (struct drv *drv, char next_drive) { int r; struct guestfs_add_drive_opts_argv ad_optargs; - char **server; if (next_drive > 'z') { fprintf (stderr, @@ -336,22 +366,20 @@ add_drives (struct drv *drv, char next_drive) ad_optargs.format = drv->uri.format; } ad_optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_PROTOCOL_BITMASK; - ad_optargs.protocol = drv->uri.uri->scheme; - ad_optargs.server = server = make_server (drv->uri.uri, drv->uri.socket); - if (server) + ad_optargs.protocol = drv->uri.protocol; + if (drv->uri.server) { ad_optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_SERVER_BITMASK; - if (drv->uri.uri->user && STRNEQ (drv->uri.uri->user, "")) { + ad_optargs.server = drv->uri.server; + } + if (drv->uri.username) { ad_optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_USERNAME_BITMASK; - ad_optargs.username = drv->uri.uri->user; + ad_optargs.username = drv->uri.username; } - r = guestfs_add_drive_opts_argv (g, drv->uri.uri->path ? : "", - &ad_optargs); + r = guestfs_add_drive_opts_argv (g, drv->uri.path, &ad_optargs); if (r == -1) exit (EXIT_FAILURE); - guestfs___free_string_list (server); - drv->nr_drives = 1; next_drive++; break; @@ -463,8 +491,10 @@ free_drives (struct drv *drv) /* a.filename and a.format are optargs, don't free them */ break; case drv_uri: - xmlFreeURI (drv->uri.uri); - free (drv->uri.socket); + free (drv->uri.path); + free (drv->uri.protocol); + guestfs___free_string_list (drv->uri.server); + free (drv->uri.username); break; case drv_d: /* d.filename is optarg, don't free it */ diff --git a/fish/options.h b/fish/options.h index bdfabb2..507ec1c 100644 --- a/fish/options.h +++ b/fish/options.h @@ -21,8 +21,6 @@ #include <getopt.h> -#include <libxml/uri.h> - #include "guestfs-internal-frontend.h" /* Provided by guestfish or guestmount. */ @@ -64,9 +62,12 @@ struct drv { const char *format; /* format (NULL == autodetect) */ } a; struct { - xmlURIPtr uri; /* URI */ - char *socket; /* ?socket parameter from URI. */ + char *path; /* disk path */ + char *protocol; /* protocol (eg. "nbd") */ + char **server; /* server(s) - can be NULL */ + char *username; /* username - can be NULL */ const char *format; /* format (NULL == autodetect) */ + const char *orig_uri; /* original URI (for error messages etc.) */ } uri; struct { char *guest; /* guest name */ -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 09/67] fish: options: Fix optarg -> arg.
From: "Richard W.M. Jones" <rjones@redhat.com> Don't read the global variable optarg. Read arg instead. (In all cases they are the same, so this bug made no difference). (cherry picked from commit 671be806ae79df5d0a9e864d2f9b3461d08c7733) --- fish/options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fish/options.c b/fish/options.c index 787402c..5c55b38 100644 --- a/fish/options.c +++ b/fish/options.c @@ -61,7 +61,7 @@ option_a (const char *arg, const char *format, struct drv **drvsp) drv->type = drv_a; drv->nr_drives = -1; - drv->a.filename = optarg; + drv->a.filename = (char *) arg; drv->a.format = format; } -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 10/67] fish: Split off URI handling (for -a argument) from general options parsing.
From: "Richard W.M. Jones" <rjones@redhat.com> This is so we will be able to reuse the same code in the OCaml tools. This is just code motion. (cherry picked from commit 4d7c14fdbb372d6ad5ef729b6969078b5fdb68da) --- align/Makefile.am | 4 +- cat/Makefile.am | 4 +- cat/virt-cat.c | 6 +- cat/virt-ls.c | 6 +- df/Makefile.am | 4 +- df/main.c | 6 +- edit/Makefile.am | 4 +- edit/virt-edit.c | 6 +- fish/Makefile.am | 4 +- fish/fish.c | 6 +- fish/options.c | 283 ++++------------------------------------ fish/uri.c | 318 +++++++++++++++++++++++++++++++++++++++++++++ fish/uri.h | 46 +++++++ format/Makefile.am | 4 +- fuse/Makefile.am | 4 +- inspector/Makefile.am | 4 +- inspector/virt-inspector.c | 6 +- po/POTFILES | 1 + rescue/Makefile.am | 4 +- rescue/virt-rescue.c | 12 +- 20 files changed, 456 insertions(+), 276 deletions(-) create mode 100644 fish/uri.c create mode 100644 fish/uri.h diff --git a/align/Makefile.am b/align/Makefile.am index 285f9f1..b243823 100644 --- a/align/Makefile.am +++ b/align/Makefile.am @@ -38,7 +38,9 @@ SHARED_SOURCE_FILES = \ ../fish/inspect.c \ ../fish/keys.c \ ../fish/options.h \ - ../fish/options.c + ../fish/options.c \ + ../fish/uri.h \ + ../fish/uri.c virt_alignment_scan_SOURCES = \ $(SHARED_SOURCE_FILES) \ diff --git a/cat/Makefile.am b/cat/Makefile.am index 5f6c2fc..b9df9cd 100644 --- a/cat/Makefile.am +++ b/cat/Makefile.am @@ -35,7 +35,9 @@ SHARED_SOURCE_FILES = \ ../fish/inspect.c \ ../fish/keys.c \ ../fish/options.h \ - ../fish/options.c + ../fish/options.c \ + ../fish/uri.h \ + ../fish/uri.c virt_cat_SOURCES = \ $(SHARED_SOURCE_FILES) \ diff --git a/cat/virt-cat.c b/cat/virt-cat.c index f752a1a..e86ecf3 100644 --- a/cat/virt-cat.c +++ b/cat/virt-cat.c @@ -186,7 +186,11 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } drv->type = drv_a; - drv->a.filename = argv[optind]; + drv->a.filename = strdup (argv[optind]); + if (!drv->a.filename) { + perror ("strdup"); + exit (EXIT_FAILURE); + } drv->next = drvs; drvs = drv; } else { /* simulate -d option */ diff --git a/cat/virt-ls.c b/cat/virt-ls.c index 3ebd633..1c449c2 100644 --- a/cat/virt-ls.c +++ b/cat/virt-ls.c @@ -291,7 +291,11 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } drv->type = drv_a; - drv->a.filename = argv[optind]; + drv->a.filename = strdup (argv[optind]); + if (!drv->a.filename) { + perror ("strdup"); + exit (EXIT_FAILURE); + } drv->next = drvs; drvs = drv; } else { /* simulate -d option */ diff --git a/df/Makefile.am b/df/Makefile.am index 1288d10..38a628c 100644 --- a/df/Makefile.am +++ b/df/Makefile.am @@ -33,7 +33,9 @@ SHARED_SOURCE_FILES = \ ../fish/inspect.c \ ../fish/keys.c \ ../fish/options.h \ - ../fish/options.c + ../fish/options.c \ + ../fish/uri.h \ + ../fish/uri.c virt_df_SOURCES = \ $(SHARED_SOURCE_FILES) \ diff --git a/df/main.c b/df/main.c index 5524070..0eee3cb 100644 --- a/df/main.c +++ b/df/main.c @@ -220,7 +220,11 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } drv->type = drv_a; - drv->a.filename = argv[optind]; + drv->a.filename = strdup (argv[optind]); + if (!drv->a.filename) { + perror ("strdup"); + exit (EXIT_FAILURE); + } drv->next = drvs; drvs = drv; } else { /* simulate -d option */ diff --git a/edit/Makefile.am b/edit/Makefile.am index 01828a7..9d92be7 100644 --- a/edit/Makefile.am +++ b/edit/Makefile.am @@ -31,7 +31,9 @@ SHARED_SOURCE_FILES = \ ../fish/inspect.c \ ../fish/keys.c \ ../fish/options.h \ - ../fish/options.c + ../fish/options.c \ + ../fish/uri.h \ + ../fish/uri.c virt_edit_SOURCES = \ $(SHARED_SOURCE_FILES) \ diff --git a/edit/virt-edit.c b/edit/virt-edit.c index 05e88e2..5690f8d 100644 --- a/edit/virt-edit.c +++ b/edit/virt-edit.c @@ -223,7 +223,11 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } drv->type = drv_a; - drv->a.filename = argv[optind]; + drv->a.filename = strdup (argv[optind]); + if (!drv->a.filename) { + perror ("strdup"); + exit (EXIT_FAILURE); + } drv->next = drvs; drvs = drv; } else { /* simulate -d option */ diff --git a/fish/Makefile.am b/fish/Makefile.am index 3e4995c..0c8ad17 100644 --- a/fish/Makefile.am +++ b/fish/Makefile.am @@ -70,7 +70,9 @@ SHARED_SOURCE_FILES = \ options.h \ options.c \ progress.h \ - progress.c + progress.c \ + uri.h \ + uri.c guestfish_SOURCES = \ $(generator_built) \ diff --git a/fish/fish.c b/fish/fish.c index 2b5a877..7ca03d1 100644 --- a/fish/fish.c +++ b/fish/fish.c @@ -429,7 +429,11 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } drv->type = drv_a; - drv->a.filename = argv[optind]; + drv->a.filename = strdup (argv[optind]); + if (!drv->a.filename) { + perror ("strdup"); + exit (EXIT_FAILURE); + } drv->next = drvs; drvs = drv; } else { /* simulate -d option */ diff --git a/fish/options.c b/fish/options.c index 5c55b38..6d63afa 100644 --- a/fish/options.c +++ b/fish/options.c @@ -25,22 +25,15 @@ #include <errno.h> #include <libintl.h> -#include <libxml/uri.h> - -#include "c-ctype.h" - #include "guestfs.h" #include "options.h" - -static int is_uri (const char *arg); -static void parse_uri (const char *arg, const char *format, struct drv *drv); -static char *query_get (xmlURIPtr uri, const char *search_name); -static char **make_server (xmlURIPtr uri, const char *socket); +#include "uri.h" /* Handle the '-a' option when passed on the command line. */ void option_a (const char *arg, const char *format, struct drv **drvsp) { + struct uri uri; struct drv *drv; drv = calloc (1, sizeof (struct drv)); @@ -49,268 +42,39 @@ option_a (const char *arg, const char *format, struct drv **drvsp) exit (EXIT_FAILURE); } - /* Does it look like a URI? */ - if (is_uri (arg)) - parse_uri (arg, format, drv); - else { + if (parse_uri (arg, &uri) == -1) + exit (EXIT_FAILURE); + + if (STREQ (uri.protocol, "file")) { /* Ordinary file. */ - if (access (arg, R_OK) != 0) { - perror (arg); + if (access (uri.path, R_OK) != 0) { + perror (uri.path); exit (EXIT_FAILURE); } drv->type = drv_a; drv->nr_drives = -1; - drv->a.filename = (char *) arg; + drv->a.filename = uri.path; drv->a.format = format; + + free (uri.protocol); + } + else { + /* Remote storage. */ + drv->type = drv_uri; + drv->nr_drives = -1; + drv->uri.path = uri.path; + drv->uri.protocol = uri.protocol; + drv->uri.server = uri.server; + drv->uri.username = uri.username; + drv->uri.format = format; + drv->uri.orig_uri = arg; } drv->next = *drvsp; *drvsp = drv; } -/* Does it "look like" a URI? A short lower-case ASCII string - * followed by "://" will do. Note that we properly parse the URI - * later on using libxml2. - */ -static int -is_uri (const char *arg) -{ - const char *p; - - p = strstr (arg, "://"); - if (!p) - return 0; - - if (p - arg >= 8) - return 0; - - for (p--; p >= arg; p--) { - if (!c_islower (*p)) - return 0; - } - - return 1; -} - -static void -parse_uri (const char *arg, const char *format, struct drv *drv) -{ - CLEANUP_XMLFREEURI xmlURIPtr uri = NULL; - CLEANUP_FREE char *socket = NULL; - char *path; - char *protocol; - char **server; - char *username; - - uri = xmlParseURI (arg); - if (!uri) { - fprintf (stderr, _("%s: --add: could not parse URI '%s'\n"), - program_name, arg); - exit (EXIT_FAILURE); - } - - /* Note we don't do much checking of the parsed URI, since the - * underlying function 'guestfs_add_drive_opts' will check for us. - * So just the basics here. - */ - if (uri->scheme == NULL) { - /* Probably can never happen. */ - fprintf (stderr, _("%s: --add %s: scheme of URI is NULL\n"), - program_name, arg); - exit (EXIT_FAILURE); - } - - socket = query_get (uri, "socket"); - - if (uri->server && STRNEQ (uri->server, "") && socket) { - fprintf (stderr, _("%s: --add %s: cannot both a server name and a socket query parameter\n"), - program_name, arg); - exit (EXIT_FAILURE); - } - - /* Is this needed? XXX - if (socket && socket[0] != '/') { - fprintf (stderr, _("%s: --add %s: socket query parameter must be an absolute path\n"), - program_name, arg); - exit (EXIT_FAILURE); - } - */ - - protocol = strdup (uri->scheme); - if (protocol == NULL) { - perror ("strdup"); - exit (EXIT_FAILURE); - } - - server = make_server (uri, socket); - - if (uri->user && STRNEQ (uri->user, "")) { - username = strdup (uri->user); - if (!username) { - perror ("username"); - exit (EXIT_FAILURE); - } - } - else username = NULL; - - path = strdup (uri->path ? uri->path : ""); - if (!path) { - perror ("path"); - exit (EXIT_FAILURE); - } - - drv->type = drv_uri; - drv->nr_drives = -1; - drv->uri.path = path; - drv->uri.protocol = protocol; - drv->uri.server = server; - drv->uri.username = username; - drv->uri.format = format; - drv->uri.orig_uri = arg; -} - -/* Code inspired by libvirt src/util/viruri.c, written by danpb, - * released under a compatible license. - */ -static char * -query_get (xmlURIPtr uri, const char *search_name) -{ - /* XXX libvirt uses deprecated uri->query field. Why? */ - const char *query = uri->query_raw; - const char *end, *eq; - - if (!query || STREQ (query, "")) - return NULL; - - while (*query) { - CLEANUP_FREE char *name = NULL; - char *value = NULL; - - /* Find the next separator, or end of the string. */ - end = strchr (query, '&'); - if (!end) - end = strchr(query, ';'); - if (!end) - end = query + strlen (query); - - /* Find the first '=' character between here and end. */ - eq = strchr(query, '='); - if (eq && eq >= end) eq = NULL; - - /* Empty section (eg. "&&"). */ - if (end == query) - goto next; - - /* If there is no '=' character, then we have just "name" - * and consistent with CGI.pm we assume value is "". - */ - else if (!eq) { - name = xmlURIUnescapeString (query, end - query, NULL); - if (!name) goto no_memory; - } - /* Or if we have "name=" here (works around annoying - * problem when calling xmlURIUnescapeString with len = 0). - */ - else if (eq+1 == end) { - name = xmlURIUnescapeString (query, eq - query, NULL); - if (!name) goto no_memory; - } - /* If the '=' character is at the beginning then we have - * "=value" and consistent with CGI.pm we _ignore_ this. - */ - else if (query == eq) - goto next; - - /* Otherwise it's "name=value". */ - else { - name = xmlURIUnescapeString (query, eq - query, NULL); - if (!name) - goto no_memory; - value = xmlURIUnescapeString (eq+1, end - (eq+1), NULL); - if (!value) { - goto no_memory; - } - } - - /* Is it the name we're looking for? */ - if (STREQ (name, search_name)) { - if (!value) { - value = strdup (""); - if (!value) - goto no_memory; - } - return value; - } - - free (value); - - next: - query = end; - if (*query) - query++; /* skip '&' separator */ - } - - /* search_name not found */ - return NULL; - - no_memory: - perror ("malloc"); - exit (EXIT_FAILURE); -} - -/* Construct either a tcp: server list of a unix: server list or - * nothing at all from '-a' option URI. - */ -static char ** -make_server (xmlURIPtr uri, const char *socket) -{ - char **ret; - char *server; - - /* If the server part of the URI is specified, then this is a TCP - * connection. - */ - if (uri->server && STRNEQ (uri->server, "")) { - if (uri->port == 0) { - if (asprintf (&server, "tcp:%s", uri->server) == -1) { - perror ("asprintf"); - exit (EXIT_FAILURE); - } - } - else { - if (asprintf (&server, "tcp:%s:%d", uri->server, uri->port) == -1) { - perror ("asprintf"); - exit (EXIT_FAILURE); - } - } - } - /* Otherwise, ?socket query parameter means it's a Unix domain - * socket connection. - */ - else if (socket != NULL) { - if (asprintf (&server, "unix:%s", socket) == -1) { - perror ("asprintf"); - exit (EXIT_FAILURE); - } - } - /* Otherwise, no server parameter is needed. */ - else return NULL; - - /* The .server parameter is in fact a list of strings, although - * only a singleton is passed by us. - */ - ret = malloc (sizeof (char *) * 2); - if (ret == NULL) { - perror ("malloc"); - exit (EXIT_FAILURE); - } - ret[0] = server; - ret[1] = NULL; - - return ret; -} - char add_drives (struct drv *drv, char next_drive) { @@ -488,7 +252,8 @@ free_drives (struct drv *drv) switch (drv->type) { case drv_a: - /* a.filename and a.format are optargs, don't free them */ + free (drv->a.filename); + /* a.format is an optarg, so don't free it */ break; case drv_uri: free (drv->uri.path); diff --git a/fish/uri.c b/fish/uri.c new file mode 100644 index 0000000..9c0892f --- /dev/null +++ b/fish/uri.c @@ -0,0 +1,318 @@ +/* libguestfs - mini library for parsing -a URI parameters + * 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 <errno.h> +#include <libintl.h> + +#include <libxml/uri.h> + +#include "c-ctype.h" + +#include "guestfs.h" +#include "guestfs-internal-frontend.h" +#include "uri.h" + +static int is_uri (const char *arg); +static int parse (const char *arg, char **path_ret, char **protocol_ret, char ***server_ret, char **username_ret); +static char *query_get (xmlURIPtr uri, const char *search_name); +static int make_server (xmlURIPtr uri, const char *socket, char ***ret); + +int +parse_uri (const char *arg, struct uri *uri_ret) +{ + char *path; + char *protocol; + char **server; + char *username; + + /* Does it look like a URI? */ + if (is_uri (arg)) { + if (parse (arg, &path, &protocol, &server, &username) == -1) + return -1; + } + else { + /* Ordinary file. */ + path = strdup (arg); + if (!path) { + perror ("strdup"); + return -1; + } + protocol = strdup ("file"); + if (!protocol) { + perror ("strdup"); + free (path); + return -1; + } + server = NULL; + username = NULL; + } + + uri_ret->path = path; + uri_ret->protocol = protocol; + uri_ret->server = server; + uri_ret->username = username; + return 0; +} + +/* Does it "look like" a URI? A short lower-case ASCII string + * followed by "://" will do. Note that we properly parse the URI + * later on using libxml2. + */ +static int +is_uri (const char *arg) +{ + const char *p; + + p = strstr (arg, "://"); + if (!p) + return 0; + + if (p - arg >= 8) + return 0; + + for (p--; p >= arg; p--) { + if (!c_islower (*p)) + return 0; + } + + return 1; +} + +static int +parse (const char *arg, char **path_ret, char **protocol_ret, + char ***server_ret, char **username_ret) +{ + CLEANUP_XMLFREEURI xmlURIPtr uri = NULL; + CLEANUP_FREE char *socket = NULL; + + uri = xmlParseURI (arg); + if (!uri) { + fprintf (stderr, _("%s: --add: could not parse URI '%s'\n"), + program_name, arg); + return -1; + } + + /* Note we don't do much checking of the parsed URI, since the + * underlying function 'guestfs_add_drive_opts' will check for us. + * So just the basics here. + */ + if (uri->scheme == NULL || STREQ (uri->scheme, "")) { + /* Probably can never happen. */ + fprintf (stderr, _("%s: %s: scheme of URI is NULL or empty\n"), + program_name, arg); + return -1; + } + + socket = query_get (uri, "socket"); + + if (uri->server && STRNEQ (uri->server, "") && socket) { + fprintf (stderr, _("%s: %s: cannot both a server name and a socket query parameter\n"), + program_name, arg); + return -1; + } + + /* Is this needed? XXX + if (socket && socket[0] != '/') { + fprintf (stderr, _("%s: --add %s: socket query parameter must be an absolute path\n"), + program_name, arg); + return -1; + } + */ + + *protocol_ret = strdup (uri->scheme); + if (*protocol_ret == NULL) { + perror ("strdup"); + return -1; + } + + if (make_server (uri, socket, server_ret) == -1) { + free (*protocol_ret); + return -1; + } + + if (uri->user && STRNEQ (uri->user, "")) { + *username_ret = strdup (uri->user); + if (*username_ret == NULL) { + perror ("username"); + free (*protocol_ret); + guestfs___free_string_list (*server_ret); + return -1; + } + } + else *username_ret = NULL; + + *path_ret = strdup (uri->path ? uri->path : ""); + if (!*path_ret) { + perror ("path"); + free (*protocol_ret); + guestfs___free_string_list (*server_ret); + free (*username_ret); + return -1; + } + + return 0; +} + +/* Code inspired by libvirt src/util/viruri.c, written by danpb, + * released under a compatible license. + */ +static char * +query_get (xmlURIPtr uri, const char *search_name) +{ + /* XXX libvirt uses deprecated uri->query field. Why? */ + const char *query = uri->query_raw; + const char *end, *eq; + + if (!query || STREQ (query, "")) + return NULL; + + while (*query) { + CLEANUP_FREE char *name = NULL; + char *value = NULL; + + /* Find the next separator, or end of the string. */ + end = strchr (query, '&'); + if (!end) + end = strchr(query, ';'); + if (!end) + end = query + strlen (query); + + /* Find the first '=' character between here and end. */ + eq = strchr(query, '='); + if (eq && eq >= end) eq = NULL; + + /* Empty section (eg. "&&"). */ + if (end == query) + goto next; + + /* If there is no '=' character, then we have just "name" + * and consistent with CGI.pm we assume value is "". + */ + else if (!eq) { + name = xmlURIUnescapeString (query, end - query, NULL); + if (!name) goto no_memory; + } + /* Or if we have "name=" here (works around annoying + * problem when calling xmlURIUnescapeString with len = 0). + */ + else if (eq+1 == end) { + name = xmlURIUnescapeString (query, eq - query, NULL); + if (!name) goto no_memory; + } + /* If the '=' character is at the beginning then we have + * "=value" and consistent with CGI.pm we _ignore_ this. + */ + else if (query == eq) + goto next; + + /* Otherwise it's "name=value". */ + else { + name = xmlURIUnescapeString (query, eq - query, NULL); + if (!name) + goto no_memory; + value = xmlURIUnescapeString (eq+1, end - (eq+1), NULL); + if (!value) { + goto no_memory; + } + } + + /* Is it the name we're looking for? */ + if (STREQ (name, search_name)) { + if (!value) { + value = strdup (""); + if (!value) + goto no_memory; + } + return value; + } + + free (value); + + next: + query = end; + if (*query) + query++; /* skip '&' separator */ + } + + /* search_name not found */ + return NULL; + + no_memory: + perror ("malloc"); + return NULL; +} + +/* Construct either a tcp: server list of a unix: server list or + * nothing at all from '-a' option URI. + */ +static int +make_server (xmlURIPtr uri, const char *socket, char ***ret) +{ + char *server; + + /* If the server part of the URI is specified, then this is a TCP + * connection. + */ + if (uri->server && STRNEQ (uri->server, "")) { + if (uri->port == 0) { + if (asprintf (&server, "tcp:%s", uri->server) == -1) { + perror ("asprintf"); + return -1; + } + } + else { + if (asprintf (&server, "tcp:%s:%d", uri->server, uri->port) == -1) { + perror ("asprintf"); + return -1; + } + } + } + /* Otherwise, ?socket query parameter means it's a Unix domain + * socket connection. + */ + else if (socket != NULL) { + if (asprintf (&server, "unix:%s", socket) == -1) { + perror ("asprintf"); + return -1; + } + } + /* Otherwise, no server parameter is needed. */ + else { + *ret = NULL; + return 0; + } + + /* The .server parameter is in fact a list of strings, although + * only a singleton is passed by us. + */ + *ret = malloc (sizeof (char *) * 2); + if (*ret == NULL) { + perror ("malloc"); + return -1; + } + (*ret)[0] = server; + (*ret)[1] = NULL; + + return 0; +} diff --git a/fish/uri.h b/fish/uri.h new file mode 100644 index 0000000..420d20c --- /dev/null +++ b/fish/uri.h @@ -0,0 +1,46 @@ +/* libguestfs - mini library for parsing -a URI parameters + * 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> + +#ifndef FISH_URI_H +#define FISH_URI_H + +struct uri { + char *path; /* disk path */ + char *protocol; /* protocol (eg. "file", "nbd") */ + char **server; /* server(s) - can be NULL */ + char *username; /* username - can be NULL */ +}; + +/* Parse the '-a' option parameter 'arg', and place the result in + * '*uri_ret'. + * + * If it doesn't look like a URI then uri_ret->path will be the same + * as 'arg' (copied) and uri_ret->protocol will be "file". + * + * If it looks like a URI and can be parsed, then the other fields will + * be filled in as appropriate. + * + * The caller should free the fields from the struct after use. + * + * Returns 0 if parsing went OK, or -1 if there was an error. + */ +extern int parse_uri (const char *arg, struct uri *uri_ret); + +#endif /* FISH_URI_H */ diff --git a/format/Makefile.am b/format/Makefile.am index a0d1ed4..c93edc9 100644 --- a/format/Makefile.am +++ b/format/Makefile.am @@ -30,7 +30,9 @@ SHARED_SOURCE_FILES = \ ../fish/inspect.c \ ../fish/keys.c \ ../fish/options.h \ - ../fish/options.c + ../fish/options.c \ + ../fish/uri.h \ + ../fish/uri.c virt_format_SOURCES = \ $(SHARED_SOURCE_FILES) \ diff --git a/fuse/Makefile.am b/fuse/Makefile.am index 6335bbb..d10ff7d 100644 --- a/fuse/Makefile.am +++ b/fuse/Makefile.am @@ -42,7 +42,9 @@ SHARED_SOURCE_FILES = \ ../fish/inspect.c \ ../fish/keys.c \ ../fish/options.h \ - ../fish/options.c + ../fish/options.c \ + ../fish/uri.h \ + ../fish/uri.c # guestmount diff --git a/inspector/Makefile.am b/inspector/Makefile.am index 1967fe8..a5aa3c1 100644 --- a/inspector/Makefile.am +++ b/inspector/Makefile.am @@ -57,7 +57,9 @@ SHARED_SOURCE_FILES = \ ../fish/inspect.c \ ../fish/keys.c \ ../fish/options.h \ - ../fish/options.c + ../fish/options.c \ + ../fish/uri.h \ + ../fish/uri.c virt_inspector_SOURCES = \ $(SHARED_SOURCE_FILES) \ diff --git a/inspector/virt-inspector.c b/inspector/virt-inspector.c index 146f211..a070a3a 100644 --- a/inspector/virt-inspector.c +++ b/inspector/virt-inspector.c @@ -199,7 +199,11 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } drv->type = drv_a; - drv->a.filename = argv[optind]; + drv->a.filename = strdup (argv[optind]); + if (!drv->a.filename) { + perror ("strdup"); + exit (EXIT_FAILURE); + } drv->next = drvs; drvs = drv; } else { /* simulate -d option */ diff --git a/po/POTFILES b/po/POTFILES index 457e129..bcefe16 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -143,6 +143,7 @@ fish/setenv.c fish/supported.c fish/tilde.c fish/time.c +fish/uri.c format/format.c fuse/guestmount.c fuse/guestunmount.c diff --git a/rescue/Makefile.am b/rescue/Makefile.am index f694223..7d23ee2 100644 --- a/rescue/Makefile.am +++ b/rescue/Makefile.am @@ -31,7 +31,9 @@ SHARED_SOURCE_FILES = \ ../fish/inspect.c \ ../fish/keys.c \ ../fish/options.h \ - ../fish/options.c + ../fish/options.c \ + ../fish/uri.h \ + ../fish/uri.c virt_rescue_SOURCES = \ $(SHARED_SOURCE_FILES) \ diff --git a/rescue/virt-rescue.c b/rescue/virt-rescue.c index 6c6e306..65dd473 100644 --- a/rescue/virt-rescue.c +++ b/rescue/virt-rescue.c @@ -256,7 +256,11 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } drv->type = drv_a; - drv->a.filename = argv[optind]; + drv->a.filename = strdup (argv[optind]); + if (!drv->a.filename) { + perror ("strdup"); + exit (EXIT_FAILURE); + } drv->next = drvs; drvs = drv; } else { /* simulate -d option */ @@ -570,7 +574,11 @@ add_scratch_disk (struct drv **drvs) } drv->type = drv_a; drv->nr_drives = -1; - drv->a.filename = filename; + drv->a.filename = strdup (filename); + if (!drv->a.filename) { + perror ("strdup"); + exit (EXIT_FAILURE); + } drv->a.format = "raw"; drv->next = *drvs; *drvs = drv; -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 11/67] resize: Add bindings for the guestfish -a URI parsing mini-library.
From: "Richard W.M. Jones" <rjones@redhat.com> This allows -a options to be parsed from OCaml programs, reusing the same code that is being used by C. (cherry picked from commit 406522d1d2c9108c52f1356cbbb9bb4039d9ce84) --- po/POTFILES | 1 + po/POTFILES-ml | 1 + resize/Makefile.am | 15 ++++++++-- resize/uRI.ml | 26 +++++++++++++++++ resize/uRI.mli | 29 +++++++++++++++++++ resize/uri-c.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 resize/uRI.ml create mode 100644 resize/uRI.mli create mode 100644 resize/uri-c.c diff --git a/po/POTFILES b/po/POTFILES index bcefe16..92b9a18 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -233,6 +233,7 @@ rescue/test-virt-rescue.pl rescue/virt-rescue.c resize/progress-c.c resize/tty-c.c +resize/uri-c.c ruby/ext/guestfs/_guestfs.c src/actions-0.c src/actions-1.c diff --git a/po/POTFILES-ml b/po/POTFILES-ml index 34533ea..ba64fa3 100644 --- a/po/POTFILES-ml +++ b/po/POTFILES-ml @@ -4,6 +4,7 @@ resize/common_utils_tests.ml resize/progress.ml resize/resize.ml resize/tTY.ml +resize/uRI.ml sparsify/sparsify.ml sysprep/firstboot.ml sysprep/main.ml diff --git a/resize/Makefile.am b/resize/Makefile.am index a9c95ff..62e7659 100644 --- a/resize/Makefile.am +++ b/resize/Makefile.am @@ -35,19 +35,25 @@ SOURCES = \ resize.ml \ tty-c.c \ tTY.mli \ - tTY.ml + tTY.ml \ + uri-c.c \ + uRI.mli \ + uRI.ml if HAVE_OCAML # Note this list must be in dependency order. OBJECTS = \ $(top_builddir)/fish/guestfish-progress.o \ + $(top_builddir)/fish/guestfish-uri.o \ tty-c.o \ progress-c.o \ + uri-c.o \ common_gettext.cmx \ common_utils.cmx \ tTY.cmx \ progress.cmx \ + uRI.cmx \ resize.cmx bin_SCRIPTS = virt-resize @@ -63,10 +69,15 @@ endif OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX $(OCAMLPACKAGES) OCAMLOPTFLAGS = $(OCAMLCFLAGS) +OCAMLCLIBS = \ + $(LIBXML2_LIBS) -lncurses \ + -L../src/.libs -lutils \ + -L../gnulib/lib/.libs -lgnu + virt-resize: $(OBJECTS) $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \ mlguestfs.cmxa -linkpkg $^ \ - -cclib -lncurses \ + -cclib '$(OCAMLCLIBS)' \ $(OCAML_GCOV_LDFLAGS) \ -o $@ diff --git a/resize/uRI.ml b/resize/uRI.ml new file mode 100644 index 0000000..272f339 --- /dev/null +++ b/resize/uRI.ml @@ -0,0 +1,26 @@ +(* virt-resize - interface to -a URI option parsing mini library + * 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. + *) + +type uri = { + path : string; + protocol : string; + server : string array option; + username : string option; +} + +external parse_uri : string -> uri = "virt_resize_parse_uri" diff --git a/resize/uRI.mli b/resize/uRI.mli new file mode 100644 index 0000000..efd39dd --- /dev/null +++ b/resize/uRI.mli @@ -0,0 +1,29 @@ +(* virt-resize - interface to -a URI option parsing mini library + * 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. + *) + +(** Interface to [-a] URI option parsing mini library. *) + +type uri = { + path : string; (** path *) + protocol : string; (** protocol, eg. [file], [nbd] *) + server : string array option; (** list of servers *) + username : string option; (** username *) +} + +val parse_uri : string -> uri +(** See [fish/uri.h]. *) diff --git a/resize/uri-c.c b/resize/uri-c.c new file mode 100644 index 0000000..8c9c385 --- /dev/null +++ b/resize/uri-c.c @@ -0,0 +1,84 @@ +/* virt-resize - interface to -a URI option parsing mini library + * 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 <stdint.h> +#include <string.h> +#include <unistd.h> +#include <locale.h> + +#include <caml/alloc.h> +#include <caml/fail.h> +#include <caml/memory.h> +#include <caml/mlvalues.h> + +#include "uri.h" + +value +virt_resize_parse_uri (value argv /* arg value, not an array! */) +{ + CAMLparam1 (argv); + CAMLlocal4 (rv, sv, ssv, ov); + struct uri uri; + int r; + size_t len; + + r = parse_uri (String_val (argv), &uri); + if (r == -1) + caml_invalid_argument ("URI.parse_uri"); + + /* Convert the struct into an OCaml tuple. */ + rv = caml_alloc_tuple (4); + + /* path : string */ + sv = caml_copy_string (uri.path); + free (uri.path); + Store_field (rv, 0, sv); + + /* protocol : string */ + sv = caml_copy_string (uri.protocol); + free (uri.protocol); + Store_field (rv, 1, sv); + + /* server : string array option */ + if (uri.server) { + ssv = caml_copy_string_array (uri.server); + guestfs___free_string_list (uri.server); + ov = caml_alloc (1, 0); + Store_field (ov, 0, ssv); + } + else + ov = Val_int (0); + Store_field (rv, 2, ov); + + /* username : string option */ + if (uri.username) { + sv = caml_copy_string (uri.username); + free (uri.username); + ov = caml_alloc (1, 0); + Store_field (ov, 0, sv); + } + else + ov = Val_int (0); + Store_field (rv, 3, ov); + + CAMLreturn (rv); +} -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 12/67] sysprep: Allow -a URI options to be used (RHBZ#968875).
From: "Richard W.M. Jones" <rjones@redhat.com> This allows you to sysprep a remote guest by doing eg: virt-sysprep -a ssh://remote.example.com/disk.img (cherry picked from commit b65c1c667b26313abf312a7ab51f8bf947243d07) --- sysprep/Makefile.am | 10 +++++++++- sysprep/main.ml | 15 +++++++++++---- sysprep/virt-sysprep.pod | 7 +++++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am index 81ffcc7..fce639f 100644 --- a/sysprep/Makefile.am +++ b/sysprep/Makefile.am @@ -80,6 +80,9 @@ if HAVE_OCAML OBJECTS = \ $(top_builddir)/resize/common_gettext.cmx \ $(top_builddir)/resize/common_utils.cmx \ + $(top_builddir)/fish/guestfish-uri.o \ + $(top_builddir)/resize/uri-c.o \ + $(top_builddir)/resize/uRI.cmx \ firstboot.cmx \ sysprep_operation.cmx \ $(patsubst %,sysprep_operation_%.cmx,$(operations)) \ @@ -98,10 +101,15 @@ endif OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX $(OCAMLPACKAGES) OCAMLOPTFLAGS = $(OCAMLCFLAGS) +OCAMLCLIBS = \ + $(LIBXML2_LIBS) -lncurses \ + -L../src/.libs -lutils \ + -L../gnulib/lib/.libs -lgnu + virt-sysprep: $(OBJECTS) $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \ mlguestfs.cmxa -linkpkg $^ \ - -cclib -lncurses \ + -cclib '$(OCAMLCLIBS)' \ $(OCAML_GCOV_LDFLAGS) \ -o $@ diff --git a/sysprep/main.ml b/sysprep/main.ml index 63e4103..49b0eb3 100644 --- a/sysprep/main.ml +++ b/sysprep/main.ml @@ -50,9 +50,14 @@ let debug_gc, operations, g, selinux_relabel, quiet printf "virt-sysprep %Ld.%Ld.%Ld%s\n" version.G.major version.G.minor version.G.release version.G.extra; exit 0 - and add_file file + and add_file arg + let uri + try URI.parse_uri arg + with Invalid_argument "URI.parse_uri" -> + eprintf "Error parsing URI '%s'. Look for error messages printed above.\n" arg; + exit 1 in let format = match !format with "auto" -> None | fmt -> Some fmt in - files := (file, format) :: !files + files := (uri, format) :: !files and set_domain dom if !domain <> None then ( eprintf (f_"%s: --domain option can only be given once\n") prog; @@ -162,8 +167,10 @@ read the man page virt-sysprep(1). | files, None -> fun g readonly -> List.iter ( - fun (file, format) -> - g#add_drive ~readonly ?format file + fun (uri, format) -> + let { URI.path = path; protocol = protocol; + server = server; username = username } = uri in + g#add_drive ~readonly ?format ~protocol ?server ?username path ) files in diff --git a/sysprep/virt-sysprep.pod b/sysprep/virt-sysprep.pod index 1636770..73a3b29 100755 --- a/sysprep/virt-sysprep.pod +++ b/sysprep/virt-sysprep.pod @@ -54,6 +54,13 @@ Add I<file> which should be a disk image from a virtual machine. The format of the disk image is auto-detected. To override this and force a particular format use the I<--format> option. +=item B<-a URI> + +=item B<--add URI> + +Add a remote disk. The URI format is compatible with guestfish. +See L<guestfish(1)/ADDING REMOTE STORAGE>. + =item B<-c> URI =item B<--connect> URI -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 13/67] fish: Fix guestfish so it can recognize sheepdog://... as a valid URI.
From: "Richard W.M. Jones" <rjones@redhat.com> Because "sheepdog" is 8 characters, it wasn't recognized before. (cherry picked from commit e3df223a5aed82b7e502bef327d57dd54d98587b) --- fish/uri.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fish/uri.c b/fish/uri.c index 9c0892f..4c235e3 100644 --- a/fish/uri.c +++ b/fish/uri.c @@ -88,7 +88,7 @@ is_uri (const char *arg) if (!p) return 0; - if (p - arg >= 8) + if (p - arg > 8) return 0; for (p--; p >= arg; p--) { -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 14/67] fish: Add a test for -a URI options.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 23d429ff845f29b345ff76efab669daf92b5ab42) --- fish/Makefile.am | 2 ++ fish/test-add-uri.sh | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100755 fish/test-add-uri.sh diff --git a/fish/Makefile.am b/fish/Makefile.am index 0c8ad17..ceceb96 100644 --- a/fish/Makefile.am +++ b/fish/Makefile.am @@ -254,6 +254,7 @@ TESTS_ENVIRONMENT = $(top_builddir)/run --test TESTS = \ test-a.sh \ test-add-domain.sh \ + test-add-uri.sh \ test-d.sh \ test-escapes.sh \ test-events.sh \ @@ -283,6 +284,7 @@ check-valgrind: EXTRA_DIST += \ test-a.sh \ test-add-domain.sh \ + test-add-uri.sh \ test-copy.sh \ test-d.sh \ test-edit.sh \ diff --git a/fish/test-add-uri.sh b/fish/test-add-uri.sh new file mode 100755 index 0000000..dfeccf7 --- /dev/null +++ b/fish/test-add-uri.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. + +# Test guestfish -a URI. + +set -e +set -x + +rm -f test-add-uri.out +rm -f test-add-uri.img + +$VG ./guestfish sparse test-add-uri.img 10M + +function fail () +{ + echo "Test failed. Actual trace output was:" + cat test-add-uri.out + exit 1 +} + +# file:// URI should be handled exactly like a regular file. +$VG ./guestfish -x -a file://$(pwd)/test-add-uri.img </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive ".*/test-add-uri.img"' test-add-uri.out || fail + +# curl +$VG ./guestfish -x -a ftp://user@example.com/disk.img </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive "/disk.img" "protocol:ftp" "server:tcp:example.com" "username:user"' test-add-uri.out || fail + +# gluster +$VG ./guestfish -x -a gluster://example.com/disk </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive "/disk" "protocol:gluster" "server:tcp:example.com"' test-add-uri.out || fail + +# NBD +$VG ./guestfish -x -a nbd://example.com </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive "" "protocol:nbd" "server:tcp:example.com"' test-add-uri.out || fail + +$VG ./guestfish -x -a nbd://example.com:3000 </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive "" "protocol:nbd" "server:tcp:example.com:3000"' test-add-uri.out || fail + +$VG ./guestfish -x -a 'nbd://?socket=/sk' </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive "" "protocol:nbd" "server:unix:/sk"' test-add-uri.out || fail + +$VG ./guestfish -x -a 'nbd:///export?socket=/sk' </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive "/export" "protocol:nbd" "server:unix:/sk"' test-add-uri.out || fail + +# rbd +$VG ./guestfish -x -a rbd://example.com:3000/disk </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive "/disk" "protocol:rbd" "server:tcp:example.com:3000"' test-add-uri.out || fail + +# sheepdog +$VG ./guestfish -x -a sheepdog:///volume/image </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive "/volume/image" "protocol:sheepdog"' test-add-uri.out || fail + +$VG ./guestfish -x -a sheepdog://example.com:3000/volume/image </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive "/volume/image" "protocol:sheepdog" "server:tcp:example.com:3000"' test-add-uri.out || fail + +# ssh +$VG ./guestfish -x -a ssh://example.com/disk.img </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive "/disk.img" "protocol:ssh" "server:tcp:example.com"' test-add-uri.out || fail + +$VG ./guestfish -x -a ssh://user@example.com/disk.img </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive "/disk.img" "protocol:ssh" "server:tcp:example.com" "username:user"' test-add-uri.out || fail + +$VG ./guestfish -x -a ssh://user@example.com:2000/disk.img </dev/null >test-add-uri.out 2>&1 +grep -sq 'add_drive "/disk.img" "protocol:ssh" "server:tcp:example.com:2000" "username:user"' test-add-uri.out || fail + +rm test-add-uri.out +rm test-add-uri.img -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 15/67] FAQ: Common problem with Debian is not running update-guestfs-appliance.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 9268f1487970eb9884ba674ab75dc99f91adc0a7) --- examples/guestfs-faq.pod | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/guestfs-faq.pod b/examples/guestfs-faq.pod index f992c8f..ce251e6 100644 --- a/examples/guestfs-faq.pod +++ b/examples/guestfs-faq.pod @@ -156,6 +156,13 @@ To get further information about the failure, you have to run: If, after using this, you still don't understand the failure, contact us (see previous section). +=head2 libguestfs: error: cannot find any suitable libguestfs supermin, fixed or old-style appliance on LIBGUESTFS_PATH + +If you see this error on Debian/Ubuntu, you need to run the following +command as root: + + update-guestfs-appliance + =head2 Non-ASCII characters don't appear on VFAT filesystems. Typical symptoms of this problem: -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 16/67] FAQ: Tips about using direct backend and fixed appliance on Fedora/RHEL.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 0c512a52bdc2a88296d04900625822b34d567112) --- examples/guestfs-faq.pod | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/examples/guestfs-faq.pod b/examples/guestfs-faq.pod index ce251e6..c563569 100644 --- a/examples/guestfs-faq.pod +++ b/examples/guestfs-faq.pod @@ -536,6 +536,66 @@ to ensure libguestfs is basically working. =back +=head2 Errors during launch on Fedora E<ge> 18, RHEL E<ge> 7 + +In Fedora E<ge> 18 and RHEL E<ge> 7, libguestfs uses libvirt to manage +the appliance. Previously (and upstream) libguestfs runs qemu +directly: + + +----------------------------------+ + | libguestfs | + +----------------+-----------------+ + | direct backend | libvirt backend | + +----------------+-----------------+ + | | + v v + +-------+ +----------+ + | qemu | | libvirtd | + +-------+ +----------+ + | + v + +-------+ + | qemu | + +-------+ + + upstream Fedora 18+ + non-Fedora RHEL 7+ + non-RHEL + +The libvirt backend is more sophisticated, supporting SELinux/sVirt +(see above), hotplugging and more. It is, however, more complex and +so less robust. + +If you have permissions problems using the libvirt backend, you can +switch to the direct backend by setting this environment variable: + + export LIBGUESTFS_BACKEND=direct + +before running any libguestfs program or virt tool. + +=head2 How can I switch to a fixed / prebuilt appliance? + +This may improve the stability and performance of libguestfs on Fedora +and RHEL. + +Any time after installing libguestfs, run the following commands as +root: + + mkdir -p /usr/local/lib/guestfs/appliance + libguestfs-make-fixed-appliance /usr/local/lib/guestfs/appliance + ls -l /usr/local/lib/guestfs/appliance + +Now set the following environment variable before using libguestfs or +any virt tool: + + export LIBGUESTFS_PATH=/usr/local/lib/guestfs/appliance + +Of course you can change the path to any directory you want. You can +share the appliance across machines that have the same architecture +(eg. all x86-64), but note that libvirt will prevent you from sharing +the appliance across NFS because of permissions problems (so either +switch to the direct backend or don't use NFS). + =head2 How can I speed up libguestfs builds? By far the most important thing you can do is to install and properly -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 17/67] resize: Mark isatty function as "noalloc".
From: "Richard W.M. Jones" <rjones@redhat.com> This turns it into an ordinary C call without the unnecessary [in this case] GC frame overhead. See: http://camltastic.blogspot.co.uk/2008/08/tip-calling-c-functions-directly-with.html (cherry picked from commit 3d39549ded3e05df929547bb65ce620e6487a81b) --- resize/tTY.ml | 2 +- resize/tty-c.c | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/resize/tTY.ml b/resize/tTY.ml index 32c1f54..80f0e1e 100644 --- a/resize/tTY.ml +++ b/resize/tTY.ml @@ -16,4 +16,4 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *) -external isatty_stdout : unit -> bool = "virt_resize_isatty_stdout" +external isatty_stdout : unit -> bool = "virt_resize_isatty_stdout" "noalloc" diff --git a/resize/tty-c.c b/resize/tty-c.c index 040a132..64fa884 100644 --- a/resize/tty-c.c +++ b/resize/tty-c.c @@ -25,11 +25,14 @@ #include <caml/memory.h> #include <caml/mlvalues.h> -/* RHEL 5-era ocaml didn't have Unix.isatty. */ +/* RHEL 5-era ocaml didn't have Unix.isatty. + * + * Note this function is marked as "noalloc" so it must not call any + * OCaml allocation functions: + * http://camltastic.blogspot.co.uk/2008/08/tip-calling-c-functions-directly-with.html + */ value virt_resize_isatty_stdout (value unitv) { - CAMLparam1 (unitv); - - CAMLreturn (isatty (1) ? Val_true : Val_false); + return isatty (1) ? Val_true : Val_false; } -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 18/67] resize: Mark progress bar functions as "noalloc".
From: "Richard W.M. Jones" <rjones@redhat.com> Avoids GC overhead and turns these into simple C calls. See: http://camltastic.blogspot.co.uk/2008/08/tip-calling-c-functions-directly-with.html (cherry picked from commit 67fd809ca3ec711d80e69ab32646899e7ca047eb) --- resize/progress-c.c | 8 ++++---- resize/progress.ml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/resize/progress-c.c b/resize/progress-c.c index 67913eb..6d777b6 100644 --- a/resize/progress-c.c +++ b/resize/progress-c.c @@ -80,27 +80,27 @@ virt_resize_progress_bar_init (value machine_readablev) CAMLreturn (barv); } +/* NB: "noalloc" function. */ value virt_resize_progress_bar_reset (value barv) { - CAMLparam1 (barv); struct progress_bar *bar = Bar_val (barv); progress_bar_reset (bar); - CAMLreturn (Val_unit); + return Val_unit; } +/* NB: "noalloc" function. */ value virt_resize_progress_bar_set (value barv, value positionv, value totalv) { - CAMLparam3 (barv, positionv, totalv); struct progress_bar *bar = Bar_val (barv); uint64_t position = Int64_val (positionv); uint64_t total = Int64_val (totalv); progress_bar_set (bar, position, total); - CAMLreturn (Val_unit); + return Val_unit; } diff --git a/resize/progress.ml b/resize/progress.ml index e53e693..194120e 100644 --- a/resize/progress.ml +++ b/resize/progress.ml @@ -25,9 +25,9 @@ type progress_bar external progress_bar_init : machine_readable:bool -> progress_bar = "virt_resize_progress_bar_init" external progress_bar_reset : progress_bar -> unit - = "virt_resize_progress_bar_reset" + = "virt_resize_progress_bar_reset" "noalloc" external progress_bar_set : progress_bar -> int64 -> int64 -> unit - = "virt_resize_progress_bar_set" + = "virt_resize_progress_bar_set" "noalloc" let set_up_progress_bar ?(machine_readable = false) (g : Guestfs.guestfs) (* Only display progress bars if the machine_readable flag is set or -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 19/67] sysprep: Various code refactorings of the operations.
From: "Richard W.M. Jones" <rjones@redhat.com> - Use 'op' instead of 'xxx_op' for operation table. - Add a 'defaults' for the operation table and remove any default values. This is just code motion and there is no functional change. (cherry picked from commit 4cdbae926bb336c8d0dea8e7b6e0dcc3fb219c2d) --- sysprep/sysprep_operation.ml | 9 ++++++ sysprep/sysprep_operation.mli | 3 ++ sysprep/sysprep_operation_abrt_data.ml | 17 ++++++------ sysprep/sysprep_operation_bash_history.ml | 17 ++++++------ sysprep/sysprep_operation_blkid_tab.ml | 16 +++++------ sysprep/sysprep_operation_ca_certificates.ml | 16 +++++------ sysprep/sysprep_operation_crash_data.ml | 17 ++++++------ sysprep/sysprep_operation_cron_spool.ml | 16 +++++------ sysprep/sysprep_operation_dhcp_client_state.ml | 16 +++++------ sysprep/sysprep_operation_dhcp_server_state.ml | 16 +++++------ sysprep/sysprep_operation_dovecot_data.ml | 16 +++++------ sysprep/sysprep_operation_firstboot.ml | 32 +++++++++++----------- sysprep/sysprep_operation_flag_reconfiguration.ml | 17 ++++++------ sysprep/sysprep_operation_hostname.ml | 24 ++++++++-------- sysprep/sysprep_operation_kerberos_data.ml | 16 +++++------ sysprep/sysprep_operation_logfiles.ml | 19 ++++++------- sysprep/sysprep_operation_lvm_uuids.ml | 17 ++++++------ sysprep/sysprep_operation_machine_id.ml | 17 ++++++------ sysprep/sysprep_operation_mail_spool.ml | 16 +++++------ sysprep/sysprep_operation_net_hostname.ml | 17 ++++++------ sysprep/sysprep_operation_net_hwaddr.ml | 17 ++++++------ sysprep/sysprep_operation_pacct_log.ml | 17 ++++++------ sysprep/sysprep_operation_package_manager_cache.ml | 16 +++++------ sysprep/sysprep_operation_pam_data.ml | 16 +++++------ sysprep/sysprep_operation_puppet_data_log.ml | 16 +++++------ sysprep/sysprep_operation_random_seed.ml | 17 ++++++------ sysprep/sysprep_operation_rhn_systemid.ml | 16 +++++------ sysprep/sysprep_operation_samba_db_log.ml | 16 +++++------ sysprep/sysprep_operation_script.ml | 28 +++++++++---------- sysprep/sysprep_operation_smolt_uuid.ml | 16 +++++------ sysprep/sysprep_operation_ssh_hostkeys.ml | 17 ++++++------ sysprep/sysprep_operation_ssh_userdir.ml | 17 ++++++------ sysprep/sysprep_operation_sssd_db_log.ml | 16 +++++------ sysprep/sysprep_operation_udev_persistent_net.ml | 17 ++++++------ sysprep/sysprep_operation_user_account.ml | 17 ++++++------ sysprep/sysprep_operation_utmp.ml | 17 ++++++------ sysprep/sysprep_operation_yum_uuid.ml | 17 ++++++------ 37 files changed, 296 insertions(+), 331 deletions(-) diff --git a/sysprep/sysprep_operation.ml b/sysprep/sysprep_operation.ml index 2adddba..64a6390 100644 --- a/sysprep/sysprep_operation.ml +++ b/sysprep/sysprep_operation.ml @@ -35,6 +35,15 @@ type operation = { perform_on_filesystems : callback option; perform_on_devices : callback option; } +let defaults = { + name = ""; + enabled_by_default = false; + heading = ""; + pod_description = None; + extra_args = []; + perform_on_filesystems = None; + perform_on_devices = None; +} let all_operations = ref [] let enabled_by_default_operations = ref [] diff --git a/sysprep/sysprep_operation.mli b/sysprep/sysprep_operation.mli index 87a0b9a..6b792cd 100644 --- a/sysprep/sysprep_operation.mli +++ b/sysprep/sysprep_operation.mli @@ -75,6 +75,9 @@ type operation = { operation to work directly on block devices, LVs etc. *) } +val defaults : operation +(** This is so operations can write [let op = { defaults with ... }]. *) + val register_operation : operation -> unit (** Register an operation. *) diff --git a/sysprep/sysprep_operation_abrt_data.ml b/sysprep/sysprep_operation_abrt_data.ml index c830bd4..d923fec 100644 --- a/sysprep/sysprep_operation_abrt_data.ml +++ b/sysprep/sysprep_operation_abrt_data.ml @@ -32,16 +32,15 @@ let abrt_data_perform g root ) else [] -let abrt_data_op = { - name = "abrt-data"; - enabled_by_default = true; - heading = s_"Remove the crash data generated by ABRT"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "abrt-data"; + enabled_by_default = true; + heading = s_"Remove the crash data generated by ABRT"; + pod_description = Some (s_"\ Remove the automatically generated ABRT crash data in C</var/spool/abrt/>."); - extra_args = []; - perform_on_filesystems = Some abrt_data_perform; - perform_on_devices = None; + perform_on_filesystems = Some abrt_data_perform; } -let () = register_operation abrt_data_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_bash_history.ml b/sysprep/sysprep_operation_bash_history.ml index 6e1bd3f..56da23e 100644 --- a/sysprep/sysprep_operation_bash_history.ml +++ b/sysprep/sysprep_operation_bash_history.ml @@ -33,16 +33,15 @@ let bash_history_perform g root ) else [] -let bash_history_op = { - name = "bash-history"; - enabled_by_default = true; - heading = s_"Remove the bash history in the guest"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "bash-history"; + enabled_by_default = true; + heading = s_"Remove the bash history in the guest"; + pod_description = Some (s_"\ Remove the bash history of user \"root\" and any other users who have a C<.bash_history> file in their home directory."); - extra_args = []; - perform_on_filesystems = Some bash_history_perform; - perform_on_devices = None; + perform_on_filesystems = Some bash_history_perform; } -let () = register_operation bash_history_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_blkid_tab.ml b/sysprep/sysprep_operation_blkid_tab.ml index c75c3f3..fe9d10f 100644 --- a/sysprep/sysprep_operation_blkid_tab.ml +++ b/sysprep/sysprep_operation_blkid_tab.ml @@ -43,14 +43,12 @@ let blkid_tab_perform g root ) else [] -let blkid_tab_op = { - name = "blkid-tab"; - enabled_by_default = true; - heading = s_"Remove blkid tab in the guest"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some blkid_tab_perform; - perform_on_devices = None; +let op = { + defaults with + name = "blkid-tab"; + enabled_by_default = true; + heading = s_"Remove blkid tab in the guest"; + perform_on_filesystems = Some blkid_tab_perform; } -let () = register_operation blkid_tab_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_ca_certificates.ml b/sysprep/sysprep_operation_ca_certificates.ml index 9b0d396..86a9c54 100644 --- a/sysprep/sysprep_operation_ca_certificates.ml +++ b/sysprep/sysprep_operation_ca_certificates.ml @@ -47,14 +47,12 @@ let ca_certificates_perform g root ) else [] -let ca_certificates_op = { - name = "ca-certificates"; - enabled_by_default = false; - heading = s_"Remove CA certificates in the guest"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some ca_certificates_perform; - perform_on_devices = None; +let op = { + defaults with + name = "ca-certificates"; + enabled_by_default = false; + heading = s_"Remove CA certificates in the guest"; + perform_on_filesystems = Some ca_certificates_perform; } -let () = register_operation ca_certificates_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_crash_data.ml b/sysprep/sysprep_operation_crash_data.ml index 1746cac..edeb5e2 100644 --- a/sysprep/sysprep_operation_crash_data.ml +++ b/sysprep/sysprep_operation_crash_data.ml @@ -33,15 +33,14 @@ let crash_data_perform g root ); [] -let crash_data_op = { - name = "crash-data"; - enabled_by_default = true; - heading = s_"Remove the crash data generated by kexec-tools"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "crash-data"; + enabled_by_default = true; + heading = s_"Remove the crash data generated by kexec-tools"; + pod_description = Some (s_"\ Remove the automatically generated kdump kernel crash data."); - extra_args = []; - perform_on_filesystems = Some crash_data_perform; - perform_on_devices = None; + perform_on_filesystems = Some crash_data_perform; } -let () = register_operation crash_data_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_cron_spool.ml b/sysprep/sysprep_operation_cron_spool.ml index f61769d..1a036dd 100644 --- a/sysprep/sysprep_operation_cron_spool.ml +++ b/sysprep/sysprep_operation_cron_spool.ml @@ -33,14 +33,12 @@ let cron_spool_perform (g : Guestfs.guestfs) root Array.iter g#rm (g#glob_expand "/var/spool/at/spool/*"); [] -let cron_spool_op = { - name = "cron-spool"; - enabled_by_default = true; - heading = s_"Remove user at-jobs and cron-jobs"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some cron_spool_perform; - perform_on_devices = None; +let op = { + defaults with + name = "cron-spool"; + enabled_by_default = true; + heading = s_"Remove user at-jobs and cron-jobs"; + perform_on_filesystems = Some cron_spool_perform; } -let () = register_operation cron_spool_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_dhcp_client_state.ml b/sysprep/sysprep_operation_dhcp_client_state.ml index fcda3d5..69c506f 100644 --- a/sysprep/sysprep_operation_dhcp_client_state.ml +++ b/sysprep/sysprep_operation_dhcp_client_state.ml @@ -30,14 +30,12 @@ let dhcp_client_state_perform g root ); [] -let dhcp_client_state_op = { - name = "dhcp-client-state"; - enabled_by_default = true; - heading = s_"Remove DHCP client leases"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some dhcp_client_state_perform; - perform_on_devices = None; +let op = { + defaults with + name = "dhcp-client-state"; + enabled_by_default = true; + heading = s_"Remove DHCP client leases"; + perform_on_filesystems = Some dhcp_client_state_perform; } -let () = register_operation dhcp_client_state_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_dhcp_server_state.ml b/sysprep/sysprep_operation_dhcp_server_state.ml index a713cbd..9ef2abf 100644 --- a/sysprep/sysprep_operation_dhcp_server_state.ml +++ b/sysprep/sysprep_operation_dhcp_server_state.ml @@ -25,14 +25,12 @@ let dhcp_server_state_perform g root Array.iter g#rm_rf (g#glob_expand "/var/lib/dhcpd/*"); [] -let dhcp_server_state_op = { - name = "dhcp-server-state"; - enabled_by_default = true; - heading = s_"Remove DHCP server leases"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some dhcp_server_state_perform; - perform_on_devices = None; +let op = { + defaults with + name = "dhcp-server-state"; + enabled_by_default = true; + heading = s_"Remove DHCP server leases"; + perform_on_filesystems = Some dhcp_server_state_perform; } -let () = register_operation dhcp_server_state_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_dovecot_data.ml b/sysprep/sysprep_operation_dovecot_data.ml index 8a1fe49..c2004e8 100644 --- a/sysprep/sysprep_operation_dovecot_data.ml +++ b/sysprep/sysprep_operation_dovecot_data.ml @@ -32,14 +32,12 @@ let dovecot_data_perform g root ) else [] -let dovecot_data_op = { - name = "dovecot-data"; - enabled_by_default = true; - heading = s_"Remove Dovecot (mail server) data"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some dovecot_data_perform; - perform_on_devices = None; +let op = { + defaults with + name = "dovecot-data"; + enabled_by_default = true; + heading = s_"Remove Dovecot (mail server) data"; + perform_on_filesystems = Some dovecot_data_perform; } -let () = register_operation dovecot_data_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_firstboot.ml b/sysprep/sysprep_operation_firstboot.ml index 1e70c65..7c1c497 100644 --- a/sysprep/sysprep_operation_firstboot.ml +++ b/sysprep/sysprep_operation_firstboot.ml @@ -48,16 +48,17 @@ let firstboot_perform g root ) !files; [ `Created_files ] -let firstboot_op = { - name = "firstboot"; +let op = { + defaults with + name = "firstboot"; - (* enabled_by_default because we only do anything if the - * --firstboot parameter is used. - *) - enabled_by_default = true; + (* enabled_by_default because we only do anything if the + * --firstboot parameter is used. + *) + enabled_by_default = true; - heading = s_"Add scripts to run once at next boot"; - pod_description = Some (s_"\ + heading = s_"Add scripts to run once at next boot"; + pod_description = Some (s_"\ Supply one of more shell scripts (using the I<--firstboot> option). These are run the first time the guest boots, and then are @@ -71,16 +72,15 @@ C<~root/virt-sysprep-firstboot.log> (in the guest). Currently this is only implemented for Linux guests using either System V init, or systemd."); - extra_args = [ - ("--firstboot", Arg.String (fun s -> files := s :: !files), - s_"script" ^ " " ^ s_"run script once next time guest boots"), - s_"\ + extra_args = [ + ("--firstboot", Arg.String (fun s -> files := s :: !files), + s_"script" ^ " " ^ s_"run script once next time guest boots"), + s_"\ Run script(s) once next time the guest boots. You can supply the I<--firstboot> option as many times as needed." - ]; + ]; - perform_on_filesystems = Some firstboot_perform; - perform_on_devices = None; + perform_on_filesystems = Some firstboot_perform; } -let () = register_operation firstboot_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_flag_reconfiguration.ml b/sysprep/sysprep_operation_flag_reconfiguration.ml index 761d5eb..25abfef 100644 --- a/sysprep/sysprep_operation_flag_reconfiguration.ml +++ b/sysprep/sysprep_operation_flag_reconfiguration.ml @@ -29,16 +29,15 @@ let flag_reconfiguration g root ) else [] -let flag_reconfiguration_op = { - name = "flag-reconfiguration"; - enabled_by_default = false; - heading = s_"Flag the system for reconfiguration"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "flag-reconfiguration"; + enabled_by_default = false; + heading = s_"Flag the system for reconfiguration"; + pod_description = Some (s_"\ Note that this may require user intervention when the guest is booted."); - extra_args = []; - perform_on_filesystems = Some flag_reconfiguration; - perform_on_devices = None; + perform_on_filesystems = Some flag_reconfiguration; } -let () = register_operation flag_reconfiguration_op; +let () = register_operation op; diff --git a/sysprep/sysprep_operation_hostname.ml b/sysprep/sysprep_operation_hostname.ml index e8767f3..ec199f5 100644 --- a/sysprep/sysprep_operation_hostname.ml +++ b/sysprep/sysprep_operation_hostname.ml @@ -84,23 +84,23 @@ let hostname_perform (g : Guestfs.guestfs) root | _ -> [] -let hostname_op = { - name = "hostname"; - enabled_by_default = true; - heading = s_"Change the hostname of the guest"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "hostname"; + enabled_by_default = true; + heading = s_"Change the hostname of the guest"; + pod_description = Some (s_"\ This operation changes the hostname of the guest to the value given in the I<--hostname> parameter. If the I<--hostname> parameter is not given, then the hostname is changed to C<localhost.localdomain>."); - extra_args = [ - ("--hostname", Arg.Set_string hostname, s_"hostname" ^ " " ^ s_"New hostname"), - s_"\ + extra_args = [ + ("--hostname", Arg.Set_string hostname, s_"hostname" ^ " " ^ s_"New hostname"), + s_"\ Change the hostname. If not given, defaults to C<localhost.localdomain>." - ]; - perform_on_filesystems = Some hostname_perform; - perform_on_devices = None; + ]; + perform_on_filesystems = Some hostname_perform; } -let () = register_operation hostname_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_kerberos_data.ml b/sysprep/sysprep_operation_kerberos_data.ml index 1e120aa..0652719 100644 --- a/sysprep/sysprep_operation_kerberos_data.ml +++ b/sysprep/sysprep_operation_kerberos_data.ml @@ -40,14 +40,12 @@ let kerberos_data_perform g root ) else [] -let kerberos_data_op = { - name = "kerberos-data"; - enabled_by_default = false; - heading = s_"Remove Kerberos data in the guest"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some kerberos_data_perform; - perform_on_devices = None; +let op = { + defaults with + name = "kerberos-data"; + enabled_by_default = false; + heading = s_"Remove Kerberos data in the guest"; + perform_on_filesystems = Some kerberos_data_perform; } -let () = register_operation kerberos_data_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_logfiles.ml b/sysprep/sysprep_operation_logfiles.ml index 88b0977..842b855 100644 --- a/sysprep/sysprep_operation_logfiles.ml +++ b/sysprep/sysprep_operation_logfiles.ml @@ -90,18 +90,17 @@ let logfiles_perform g root ); [] -let logfiles_op = { - name = "logfiles"; - enabled_by_default = true; - heading = s_"Remove many log files from the guest"; - pod_description = Some ( - sprintf (f_"\ +let op = { + defaults with + name = "logfiles"; + enabled_by_default = true; + heading = s_"Remove many log files from the guest"; + pod_description = Some ( + sprintf (f_"\ On Linux the following files are removed: %s") globs_as_pod); - extra_args = []; - perform_on_filesystems = Some logfiles_perform; - perform_on_devices = None; + perform_on_filesystems = Some logfiles_perform; } -let () = register_operation logfiles_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_lvm_uuids.ml b/sysprep/sysprep_operation_lvm_uuids.ml index b116d66..7790d0b 100644 --- a/sysprep/sysprep_operation_lvm_uuids.ml +++ b/sysprep/sysprep_operation_lvm_uuids.ml @@ -38,16 +38,15 @@ let rec lvm_uuids_perform g root ); [] -let lvm_uuids_op = { - name = "lvm-uuids"; - enabled_by_default = true; - heading = s_"Change LVM2 PV and VG UUIDs"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "lvm-uuids"; + enabled_by_default = true; + heading = s_"Change LVM2 PV and VG UUIDs"; + pod_description = Some (s_"\ On Linux guests that have LVM2 physical volumes (PVs) or volume groups (VGs), new random UUIDs are generated and assigned to those PVs and VGs."); - extra_args = []; - perform_on_filesystems = None; - perform_on_devices = Some lvm_uuids_perform; + perform_on_devices = Some lvm_uuids_perform; } -let () = register_operation lvm_uuids_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_machine_id.ml b/sysprep/sysprep_operation_machine_id.ml index c826da4..5eadea4 100644 --- a/sysprep/sysprep_operation_machine_id.ml +++ b/sysprep/sysprep_operation_machine_id.ml @@ -31,18 +31,17 @@ let machine_id_perform g root ) else [] -let machine_id_op = { - name = "machine-id"; - enabled_by_default = true; - heading = s_"Remove the local machine ID"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "machine-id"; + enabled_by_default = true; + heading = s_"Remove the local machine ID"; + pod_description = Some (s_"\ The machine ID is usually generated from a random source during system installation and stays constant for all subsequent boots. Optionally, for stateless systems it is generated during runtime at boot if it is found to be empty."); - extra_args = []; - perform_on_filesystems = Some machine_id_perform; - perform_on_devices = None; + perform_on_filesystems = Some machine_id_perform; } -let () = register_operation machine_id_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_mail_spool.ml b/sysprep/sysprep_operation_mail_spool.ml index 1b0cbe3..fa2b4e7 100644 --- a/sysprep/sysprep_operation_mail_spool.ml +++ b/sysprep/sysprep_operation_mail_spool.ml @@ -30,14 +30,12 @@ let mail_spool_perform g root ]; [] -let mail_spool_op = { - name = "mail-spool"; - enabled_by_default = true; - heading = s_"Remove email from the local mail spool directory"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some mail_spool_perform; - perform_on_devices = None; +let op = { + defaults with + name = "mail-spool"; + enabled_by_default = true; + heading = s_"Remove email from the local mail spool directory"; + perform_on_filesystems = Some mail_spool_perform; } -let () = register_operation mail_spool_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_net_hostname.ml b/sysprep/sysprep_operation_net_hostname.ml index 37fb78b..a540357 100644 --- a/sysprep/sysprep_operation_net_hostname.ml +++ b/sysprep/sysprep_operation_net_hostname.ml @@ -43,16 +43,15 @@ let net_hostname_perform g root | _ -> [] -let net_hostname_op = { - name = "net-hostname"; - enabled_by_default = true; - heading = s_"Remove HOSTNAME in network interface configuration"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "net-hostname"; + enabled_by_default = true; + heading = s_"Remove HOSTNAME in network interface configuration"; + pod_description = Some (s_"\ For Fedora and Red Hat Enterprise Linux, this is removed from C<ifcfg-*> files."); - extra_args = []; - perform_on_filesystems = Some net_hostname_perform; - perform_on_devices = None; + perform_on_filesystems = Some net_hostname_perform; } -let () = register_operation net_hostname_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_net_hwaddr.ml b/sysprep/sysprep_operation_net_hwaddr.ml index fe7fac0..6409767 100644 --- a/sysprep/sysprep_operation_net_hwaddr.ml +++ b/sysprep/sysprep_operation_net_hwaddr.ml @@ -43,16 +43,15 @@ let net_hwaddr_perform g root | _ -> [] -let net_hwaddr_op = { - name = "net-hwaddr"; - enabled_by_default = true; - heading = s_"Remove HWADDR (hard-coded MAC address) configuration"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "net-hwaddr"; + enabled_by_default = true; + heading = s_"Remove HWADDR (hard-coded MAC address) configuration"; + pod_description = Some (s_"\ For Fedora and Red Hat Enterprise Linux, this is removed from C<ifcfg-*> files."); - extra_args = []; - perform_on_filesystems = Some net_hwaddr_perform; - perform_on_devices = None; + perform_on_filesystems = Some net_hwaddr_perform; } -let () = register_operation net_hwaddr_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_pacct_log.ml b/sysprep/sysprep_operation_pacct_log.ml index f2d47c7..10dc25f 100644 --- a/sysprep/sysprep_operation_pacct_log.ml +++ b/sysprep/sysprep_operation_pacct_log.ml @@ -45,16 +45,15 @@ let pacct_log_perform g root | _ -> [] -let pacct_log_op = { - name = "pacct-log"; - enabled_by_default = true; - heading = s_"Remove the process accounting log files"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "pacct-log"; + enabled_by_default = true; + heading = s_"Remove the process accounting log files"; + pod_description = Some (s_"\ The system wide process accounting will store to the pacct log files if the process accounting is on."); - extra_args = []; - perform_on_filesystems = Some pacct_log_perform; - perform_on_devices = None; + perform_on_filesystems = Some pacct_log_perform; } -let () = register_operation pacct_log_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_package_manager_cache.ml b/sysprep/sysprep_operation_package_manager_cache.ml index 69c9245..70fed03 100644 --- a/sysprep/sysprep_operation_package_manager_cache.ml +++ b/sysprep/sysprep_operation_package_manager_cache.ml @@ -36,14 +36,12 @@ let package_manager_cache_perform g root | Some dirs -> Array.iter g#rm_rf dirs; [] | _ -> [] -let package_manager_cache_op = { - name = "package-manager-cache"; - enabled_by_default = true; - heading = s_"Remove package manager cache"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some package_manager_cache_perform; - perform_on_devices = None; +let op = { + defaults with + name = "package-manager-cache"; + enabled_by_default = true; + heading = s_"Remove package manager cache"; + perform_on_filesystems = Some package_manager_cache_perform; } -let () = register_operation package_manager_cache_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_pam_data.ml b/sysprep/sysprep_operation_pam_data.ml index 931890d..82c88f9 100644 --- a/sysprep/sysprep_operation_pam_data.ml +++ b/sysprep/sysprep_operation_pam_data.ml @@ -40,14 +40,12 @@ let pam_data_perform g root ) else [] -let pam_data_op = { - name = "pam-data"; - enabled_by_default = true; - heading = s_"Remove the PAM data in the guest"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some pam_data_perform; - perform_on_devices = None; +let op = { + defaults with + name = "pam-data"; + enabled_by_default = true; + heading = s_"Remove the PAM data in the guest"; + perform_on_filesystems = Some pam_data_perform; } -let () = register_operation pam_data_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_puppet_data_log.ml b/sysprep/sysprep_operation_puppet_data_log.ml index 7c4fd89..8094b83 100644 --- a/sysprep/sysprep_operation_puppet_data_log.ml +++ b/sysprep/sysprep_operation_puppet_data_log.ml @@ -40,14 +40,12 @@ let puppet_data_log_perform g root ) else [] -let puppet_data_log_op = { - name = "puppet-data-log"; - enabled_by_default = true; - heading = s_"Remove the data and log files of puppet"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some puppet_data_log_perform; - perform_on_devices = None; +let op = { + defaults with + name = "puppet-data-log"; + enabled_by_default = true; + heading = s_"Remove the data and log files of puppet"; + perform_on_filesystems = Some puppet_data_log_perform; } -let () = register_operation puppet_data_log_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_random_seed.ml b/sysprep/sysprep_operation_random_seed.ml index c3d0dc5..fdb7b11 100644 --- a/sysprep/sysprep_operation_random_seed.ml +++ b/sysprep/sysprep_operation_random_seed.ml @@ -45,18 +45,17 @@ let random_seed_perform (g : Guestfs.guestfs) root ) else [] -let random_seed_op = { - name = "random-seed"; - enabled_by_default = true; - heading = s_"Generate random seed for guest"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "random-seed"; + enabled_by_default = true; + heading = s_"Generate random seed for guest"; + pod_description = Some (s_"\ Write some random bytes from the host into the random seed file of the guest. See L</RANDOM SEED> below."); - extra_args = []; - perform_on_filesystems = Some random_seed_perform; - perform_on_devices = None; + perform_on_filesystems = Some random_seed_perform; } -let () = register_operation random_seed_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_rhn_systemid.ml b/sysprep/sysprep_operation_rhn_systemid.ml index 99ab5e1..d3401b3 100644 --- a/sysprep/sysprep_operation_rhn_systemid.ml +++ b/sysprep/sysprep_operation_rhn_systemid.ml @@ -31,14 +31,12 @@ let rhn_systemid_perform g root [] | _ -> [] -let rhn_systemid_op = { - name = "rhn-systemid"; - enabled_by_default = true; - heading = s_"Remove the RHN system ID"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some rhn_systemid_perform; - perform_on_devices = None; +let op = { + defaults with + name = "rhn-systemid"; + enabled_by_default = true; + heading = s_"Remove the RHN system ID"; + perform_on_filesystems = Some rhn_systemid_perform; } -let () = register_operation rhn_systemid_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_samba_db_log.ml b/sysprep/sysprep_operation_samba_db_log.ml index 2f6370a..8ed86ca 100644 --- a/sysprep/sysprep_operation_samba_db_log.ml +++ b/sysprep/sysprep_operation_samba_db_log.ml @@ -41,14 +41,12 @@ let samba_db_log_perform g root ) else [] -let samba_db_log_op = { - name = "samba-db-log"; - enabled_by_default = true; - heading = s_"Remove the database and log files of Samba"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some samba_db_log_perform; - perform_on_devices = None; +let op = { + defaults with + name = "samba-db-log"; + enabled_by_default = true; + heading = s_"Remove the database and log files of Samba"; + perform_on_filesystems = Some samba_db_log_perform; } -let () = register_operation samba_db_log_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_script.ml b/sysprep/sysprep_operation_script.ml index 7dbbf1c..08c8709 100644 --- a/sysprep/sysprep_operation_script.ml +++ b/sysprep/sysprep_operation_script.ml @@ -104,11 +104,12 @@ trap cleanup INT TERM QUIT EXIT ERR\n" ); pid -let script_op = { - name = "script"; - enabled_by_default = true; - heading = s_"Run arbitrary scripts against the guest"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "script"; + enabled_by_default = true; + heading = s_"Run arbitrary scripts against the guest"; + pod_description = Some (s_"\ The C<script> module lets you run arbitrary shell scripts or programs against the guest. @@ -131,9 +132,9 @@ can choose a specific one by using the I<--scriptdir> parameter. B<Note:> This is different from I<--firstboot> scripts (which run in the context of the guest when it is booting first time). I<--script> scripts run on the host, not in the guest."); - extra_args = [ - ("--scriptdir", Arg.String set_scriptdir, s_"dir" ^ " " ^ s_"Mount point on host"), - s_"\ + extra_args = [ + ("--scriptdir", Arg.String set_scriptdir, s_"dir" ^ " " ^ s_"Mount point on host"), + s_"\ The mount point (an empty directory on the host) used when the C<script> operation is enabled and one or more scripts are specified using I<--script> parameter(s). @@ -142,17 +143,16 @@ B<Note:> C<scriptdir> B<must> be an absolute path. If I<--scriptdir> is not specified then a temporary mountpoint will be created."; - ("--script", Arg.String add_script, s_"script" ^ " " ^ s_"Script or program to run on guest"), - s_"\ + ("--script", Arg.String add_script, s_"script" ^ " " ^ s_"Script or program to run on guest"), + s_"\ Run the named C<script> (a shell script or program) against the guest. The script can be any program on the host. The script's current directory will be the guest's root directory. B<Note:> If the script is not on the $PATH, then you must give the full absolute path to the script."; - ]; - perform_on_filesystems = Some script_perform; - perform_on_devices = None; + ]; + perform_on_filesystems = Some script_perform; } -let () = register_operation script_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_smolt_uuid.ml b/sysprep/sysprep_operation_smolt_uuid.ml index 295a260..bb560c4 100644 --- a/sysprep/sysprep_operation_smolt_uuid.ml +++ b/sysprep/sysprep_operation_smolt_uuid.ml @@ -35,14 +35,12 @@ let smolt_uuid_perform g root ) else [] -let smolt_uuid_op = { - name = "smolt-uuid"; - enabled_by_default = true; - heading = s_"Remove the Smolt hardware UUID"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some smolt_uuid_perform; - perform_on_devices = None; +let op = { + defaults with + name = "smolt-uuid"; + enabled_by_default = true; + heading = s_"Remove the Smolt hardware UUID"; + perform_on_filesystems = Some smolt_uuid_perform; } -let () = register_operation smolt_uuid_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_ssh_hostkeys.ml b/sysprep/sysprep_operation_ssh_hostkeys.ml index a382c19..6ed7deb 100644 --- a/sysprep/sysprep_operation_ssh_hostkeys.ml +++ b/sysprep/sysprep_operation_ssh_hostkeys.ml @@ -30,11 +30,12 @@ let ssh_hostkeys_perform g root ) else [] -let ssh_hostkeys_op = { - name = "ssh-hostkeys"; - enabled_by_default = true; - heading = s_"Remove the SSH host keys in the guest"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "ssh-hostkeys"; + enabled_by_default = true; + heading = s_"Remove the SSH host keys in the guest"; + pod_description = Some (s_"\ The SSH host keys are regenerated (differently) next time the guest is booted. @@ -45,9 +46,7 @@ you a stark warning about the host key changing: @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); - extra_args = []; - perform_on_filesystems = Some ssh_hostkeys_perform; - perform_on_devices = None; + perform_on_filesystems = Some ssh_hostkeys_perform; } -let () = register_operation ssh_hostkeys_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_ssh_userdir.ml b/sysprep/sysprep_operation_ssh_userdir.ml index 280e365..54216f3 100644 --- a/sysprep/sysprep_operation_ssh_userdir.ml +++ b/sysprep/sysprep_operation_ssh_userdir.ml @@ -33,16 +33,15 @@ let ssh_userdir_perform g root ) else [] -let ssh_userdir_op = { - name = "ssh-userdir"; - enabled_by_default = true; - heading = s_"Remove \".ssh\" directories in the guest"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "ssh-userdir"; + enabled_by_default = true; + heading = s_"Remove \".ssh\" directories in the guest"; + pod_description = Some (s_"\ Remove the C<.ssh> directory of user \"root\" and any other users who have a C<.ssh> directory in their home directory."); - extra_args = []; - perform_on_filesystems = Some ssh_userdir_perform; - perform_on_devices = None; + perform_on_filesystems = Some ssh_userdir_perform; } -let () = register_operation ssh_userdir_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_sssd_db_log.ml b/sysprep/sysprep_operation_sssd_db_log.ml index 0e3c518..70c0c44 100644 --- a/sysprep/sysprep_operation_sssd_db_log.ml +++ b/sysprep/sysprep_operation_sssd_db_log.ml @@ -39,14 +39,12 @@ let sssd_db_log_perform g root ) else [] -let sssd_db_log_op = { - name = "sssd-db-log"; - enabled_by_default = true; - heading = s_"Remove the database and log files of sssd"; - pod_description = None; - extra_args = []; - perform_on_filesystems = Some sssd_db_log_perform; - perform_on_devices = None; +let op = { + defaults with + name = "sssd-db-log"; + enabled_by_default = true; + heading = s_"Remove the database and log files of sssd"; + perform_on_filesystems = Some sssd_db_log_perform; } -let () = register_operation sssd_db_log_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_udev_persistent_net.ml b/sysprep/sysprep_operation_udev_persistent_net.ml index 652b9ab..235ef98 100644 --- a/sysprep/sysprep_operation_udev_persistent_net.ml +++ b/sysprep/sysprep_operation_udev_persistent_net.ml @@ -30,11 +30,12 @@ let udev_persistent_net_perform g root ) else [] -let udev_persistent_net_op = { - name = "udev-persistent-net"; - enabled_by_default = true; - heading = s_"Remove udev persistent net rules"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "udev-persistent-net"; + enabled_by_default = true; + heading = s_"Remove udev persistent net rules"; + pod_description = Some (s_"\ Remove udev persistent net rules which map the guest's existing MAC address to a fixed ethernet device (eg. eth0). @@ -42,9 +43,7 @@ After a guest is cloned, the MAC address usually changes. Since the old MAC address occupies the old name (eg. eth0), this means the fresh MAC address is assigned to a new name (eg. eth1) and this is usually undesirable. Erasing the udev persistent net rules avoids this."); - extra_args = []; - perform_on_filesystems = Some udev_persistent_net_perform; - perform_on_devices = None; + perform_on_filesystems = Some udev_persistent_net_perform; } -let () = register_operation udev_persistent_net_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_user_account.ml b/sysprep/sysprep_operation_user_account.ml index c97b9f4..0be7772 100644 --- a/sysprep/sysprep_operation_user_account.ml +++ b/sysprep/sysprep_operation_user_account.ml @@ -58,16 +58,15 @@ let user_account_perform g root ) else [] -let user_account_op = { - name = "user-account"; - enabled_by_default = false; - heading = s_"Remove the user accounts in the guest"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "user-account"; + enabled_by_default = false; + heading = s_"Remove the user accounts in the guest"; + pod_description = Some (s_"\ Remove all the user accounts and their home directories. The \"root\" account is not removed."); - extra_args = []; - perform_on_filesystems = Some user_account_perform; - perform_on_devices = None; + perform_on_filesystems = Some user_account_perform; } -let () = register_operation user_account_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_utmp.ml b/sysprep/sysprep_operation_utmp.ml index 3e1cab5..be73e16 100644 --- a/sysprep/sysprep_operation_utmp.ml +++ b/sysprep/sysprep_operation_utmp.ml @@ -29,17 +29,16 @@ let utmp_perform g root ); [] -let utmp_op = { - name = "utmp"; - enabled_by_default = true; - heading = s_"Remove the utmp file"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "utmp"; + enabled_by_default = true; + heading = s_"Remove the utmp file"; + pod_description = Some (s_"\ This file records who is currently logged in on a machine. In modern Linux distros it is stored in a ramdisk and hence not part of the virtual machine's disk, but it was stored on disk in older distros."); - extra_args = []; - perform_on_filesystems = Some utmp_perform; - perform_on_devices = None; + perform_on_filesystems = Some utmp_perform; } -let () = register_operation utmp_op +let () = register_operation op diff --git a/sysprep/sysprep_operation_yum_uuid.ml b/sysprep/sysprep_operation_yum_uuid.ml index 8a864b1..8ffe664 100644 --- a/sysprep/sysprep_operation_yum_uuid.ml +++ b/sysprep/sysprep_operation_yum_uuid.ml @@ -29,16 +29,15 @@ let yum_uuid_perform g root ) else [] -let yum_uuid_op = { - name = "yum-uuid"; - enabled_by_default = true; - heading = s_"Remove the yum UUID"; - pod_description = Some (s_"\ +let op = { + defaults with + name = "yum-uuid"; + enabled_by_default = true; + heading = s_"Remove the yum UUID"; + pod_description = Some (s_"\ Yum creates a fresh UUID the next time it runs when it notices that the original UUID has been erased."); - extra_args = []; - perform_on_filesystems = Some yum_uuid_perform; - perform_on_devices = None; + perform_on_filesystems = Some yum_uuid_perform; } -let () = register_operation yum_uuid_op +let () = register_operation op -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 20/67] sysprep: Add "notes" field for notes on shortcomings, bugs, etc.
From: "Richard W.M. Jones" <rjones@redhat.com> Instead of keeping this information as comments in the source, put it into the virt-sysprep(1) man page. (cherry picked from commit 93f8baeb9a07cbbf9bdaa5d10c98c1c9d6af96f7) --- sysprep/Makefile.am | 2 +- sysprep/sysprep_operation.ml | 24 ++++++++++++++++++++++++ sysprep/sysprep_operation.mli | 4 ++++ sysprep/sysprep_operation_bash_history.ml | 4 ++++ sysprep/sysprep_operation_firstboot.ml | 5 +++-- sysprep/sysprep_operation_hostname.ml | 6 ++++++ sysprep/sysprep_operation_ssh_userdir.ml | 4 ++++ sysprep/sysprep_operation_user_account.ml | 4 ++++ sysprep/virt-sysprep.pod | 2 +- 9 files changed, 51 insertions(+), 4 deletions(-) diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am index fce639f..6bc5873 100644 --- a/sysprep/Makefile.am +++ b/sysprep/Makefile.am @@ -1,5 +1,5 @@ # libguestfs virt-sysprep tool -# Copyright (C) 2012 Red Hat Inc. +# Copyright (C) 2012-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 diff --git a/sysprep/sysprep_operation.ml b/sysprep/sysprep_operation.ml index 64a6390..9a41956 100644 --- a/sysprep/sysprep_operation.ml +++ b/sysprep/sysprep_operation.ml @@ -31,6 +31,7 @@ type operation = { enabled_by_default : bool; heading : string; pod_description : string option; + pod_notes : string option; extra_args : ((Arg.key * Arg.spec * Arg.doc) * string) list; perform_on_filesystems : callback option; perform_on_devices : callback option; @@ -40,6 +41,7 @@ let defaults = { enabled_by_default = false; heading = ""; pod_description = None; + pod_notes = None; extra_args = []; perform_on_filesystems = None; perform_on_devices = None; @@ -123,6 +125,20 @@ and check op op.name; exit 1 ) + ); + (match op.pod_notes with + | None -> () + | Some notes -> + let n = String.length notes in + if n = 0 then ( + eprintf (f_"virt-sysprep: operation %s has no POD notes\n") op.name; + exit 1 + ); + if notes.[n-1] = '\n' then ( + eprintf (f_"virt-sysprep: POD notes for %s must not end with newline\n") + op.name; + exit 1 + ) ) let extra_args () @@ -147,6 +163,14 @@ let dump_pod () (match op.pod_description with | None -> () | Some description -> printf "%s\n\n" description + ); + (match op.pod_notes with + | None -> () + | Some notes -> + printf "=head3 "; + printf (f_"Notes on %s") op.name; + printf "\n\n"; + printf "%s\n\n" notes ) ) !all_operations diff --git a/sysprep/sysprep_operation.mli b/sysprep/sysprep_operation.mli index 6b792cd..309ac89 100644 --- a/sysprep/sysprep_operation.mli +++ b/sysprep/sysprep_operation.mli @@ -38,6 +38,10 @@ type operation = { pod_description : string option; (** POD-format long description, used for the man page. *) + pod_notes : string option; + (** POD-format notes, used for the man page to describe any + problems, shortcomings or bugs with this operation. *) + extra_args : ((Arg.key * Arg.spec * Arg.doc) * string) list; (** Extra command-line arguments, if any. eg. The [hostname] operation has an extra [--hostname] parameter. diff --git a/sysprep/sysprep_operation_bash_history.ml b/sysprep/sysprep_operation_bash_history.ml index 56da23e..f9efa47 100644 --- a/sysprep/sysprep_operation_bash_history.ml +++ b/sysprep/sysprep_operation_bash_history.ml @@ -41,6 +41,10 @@ let op = { pod_description = Some (s_"\ Remove the bash history of user \"root\" and any other users who have a C<.bash_history> file in their home directory."); + pod_notes = Some (s_"\ +Currently this only looks in C</root> and C</home/*> for +home directories, so users with home directories in other +locations won't have the bash history removed."); perform_on_filesystems = Some bash_history_perform; } diff --git a/sysprep/sysprep_operation_firstboot.ml b/sysprep/sysprep_operation_firstboot.ml index 7c1c497..d2fc72b 100644 --- a/sysprep/sysprep_operation_firstboot.ml +++ b/sysprep/sysprep_operation_firstboot.ml @@ -67,10 +67,11 @@ configuration that must run in the context of the guest operating system, for example C<yum update>. Output or errors from the scripts are written to -C<~root/virt-sysprep-firstboot.log> (in the guest). +C<~root/virt-sysprep-firstboot.log> (in the guest)."); + pod_notes = Some (s_"\ Currently this is only implemented for Linux guests using -either System V init, or systemd."); +either SysVinit-style scripts, Upstart or systemd."); extra_args = [ ("--firstboot", Arg.String (fun s -> files := s :: !files), diff --git a/sysprep/sysprep_operation_hostname.ml b/sysprep/sysprep_operation_hostname.ml index ec199f5..f880f09 100644 --- a/sysprep/sysprep_operation_hostname.ml +++ b/sysprep/sysprep_operation_hostname.ml @@ -89,17 +89,23 @@ let op = { name = "hostname"; enabled_by_default = true; heading = s_"Change the hostname of the guest"; + pod_description = Some (s_"\ This operation changes the hostname of the guest to the value given in the I<--hostname> parameter. If the I<--hostname> parameter is not given, then the hostname is changed to C<localhost.localdomain>."); + + pod_notes = Some (s_"\ +Currently this can only set the hostname on Linux guests."); + extra_args = [ ("--hostname", Arg.Set_string hostname, s_"hostname" ^ " " ^ s_"New hostname"), s_"\ Change the hostname. If not given, defaults to C<localhost.localdomain>." ]; + perform_on_filesystems = Some hostname_perform; } diff --git a/sysprep/sysprep_operation_ssh_userdir.ml b/sysprep/sysprep_operation_ssh_userdir.ml index 54216f3..59cce9d 100644 --- a/sysprep/sysprep_operation_ssh_userdir.ml +++ b/sysprep/sysprep_operation_ssh_userdir.ml @@ -41,6 +41,10 @@ let op = { pod_description = Some (s_"\ Remove the C<.ssh> directory of user \"root\" and any other users who have a C<.ssh> directory in their home directory."); + pod_notes = Some (s_"\ +Currently this only looks in C</root> and C</home/*> for +home directories, so users with home directories in other +locations won't have the ssh files removed."); perform_on_filesystems = Some ssh_userdir_perform; } diff --git a/sysprep/sysprep_operation_user_account.ml b/sysprep/sysprep_operation_user_account.ml index 0be7772..fc39bc8 100644 --- a/sysprep/sysprep_operation_user_account.ml +++ b/sysprep/sysprep_operation_user_account.ml @@ -66,6 +66,10 @@ let op = { pod_description = Some (s_"\ Remove all the user accounts and their home directories. The \"root\" account is not removed."); + pod_notes = Some (s_"\ +Currently this does not remove the user accounts from +C</etc/shadow>. This is because there is no lens for +the shadow password file in Augeas."); perform_on_filesystems = Some user_account_perform; } diff --git a/sysprep/virt-sysprep.pod b/sysprep/virt-sysprep.pod index 73a3b29..5b4b058 100755 --- a/sysprep/virt-sysprep.pod +++ b/sysprep/virt-sysprep.pod @@ -512,6 +512,6 @@ Wanlong Gao, Fujitsu Ltd. =head1 COPYRIGHT -Copyright (C) 2011-2012 Red Hat Inc. +Copyright (C) 2011-2013 Red Hat Inc. Copyright (C) 2012 Fujitsu Ltd. -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 21/67] ./run: Omit timeout -k option on RHEL 6.
From: "Richard W.M. Jones" <rjones@redhat.com> If timeout doesn't have the -k option, don't use it. (cherry picked from commit 8d68f1c5ceb5ac613393654bde58127e50c0f7bf) --- run.in | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/run.in b/run.in index bd10d4e..5ab008b 100755 --- a/run.in +++ b/run.in @@ -204,12 +204,17 @@ fi # Originally 1h, but that is not long enough to run the C API # tests on Koji. timeout_period=4h +timeout_kill=30s # Do we have Padraig's timeout utility (from coreutils)? if timeout --help >/dev/null 2>&1; then + # Does this version of timeout have the -k option? (Not on RHEL 6) + if timeout -k 10s 10s true >/dev/null 2>&1; then + timeout_k_opt="-k $timeout_kill" + fi # Timeout (SIGTERM) after $timeout_period. - # Then send a second SIGKILL 30 seconds later. - timeout="timeout -k 30s $timeout_period" + # Then send a second SIGKILL $timeout_kill seconds later. + timeout="timeout $timeout_k_opt $timeout_period" fi pid=$$ -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 22/67] launch: direct: Add drives after machine parameters.
From: "Richard W.M. Jones" <rjones@redhat.com> This is just code motion. It should affect the semantics of the code, nor how the appliance VM is created. (cherry picked from commit 568368cdf524d3ef96fb3905e39cc859c4bb4258) --- src/launch-direct.c | 110 ++++++++++++++++++++++++++-------------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/src/launch-direct.c b/src/launch-direct.c index 26693e6..6414f60 100644 --- a/src/launch-direct.c +++ b/src/launch-direct.c @@ -290,56 +290,6 @@ launch_direct (guestfs_h *g, const char *arg) add_cmdline (g, "-nographic"); - /* Add drives */ - struct drive *drv; - size_t i; - - if (virtio_scsi) { - /* Create the virtio-scsi bus. */ - add_cmdline (g, "-device"); - add_cmdline (g, "virtio-scsi-pci,id=scsi"); - } - - ITER_DRIVES (g, i, drv) { - /* Construct the final -drive parameter. */ - CLEANUP_FREE char *buf = qemu_drive_param (g, drv, i); - - add_cmdline (g, "-drive"); - add_cmdline (g, buf); - - if (virtio_scsi && drv->iface == NULL) { - char buf2[64]; - snprintf (buf2, sizeof buf2, "scsi-hd,drive=hd%zu", i); - add_cmdline (g, "-device"); - add_cmdline (g, buf2); - } - } - - /* Add the ext2 appliance drive (after all the drives). */ - if (has_appliance_drive) { - const char *cachemode = ""; - if (qemu_supports (g, "cache=")) { - if (qemu_supports (g, "unsafe")) - cachemode = ",cache=unsafe"; - else if (qemu_supports (g, "writeback")) - cachemode = ",cache=writeback"; - } - - size_t buf2_len = strlen (appliance) + 64; - char buf2[buf2_len]; - add_cmdline (g, "-drive"); - snprintf (buf2, buf2_len, "file=%s,snapshot=on,id=appliance,if=%s%s", - appliance, virtio_scsi ? "none" : "virtio", cachemode); - add_cmdline (g, buf2); - - if (virtio_scsi) { - add_cmdline (g, "-device"); - add_cmdline (g, "scsi-hd,drive=appliance"); - } - - appliance_dev = make_appliance_dev (g, virtio_scsi); - } - /* The qemu -machine option (added 2010-12) is a bit more sane * since it falls back through various different acceleration * modes, so try that first (thanks Markus Armbruster). @@ -393,6 +343,61 @@ launch_direct (guestfs_h *g, const char *arg) if (qemu_supports (g, "-rtc-td-hack")) add_cmdline (g, "-rtc-td-hack"); + add_cmdline (g, "-kernel"); + add_cmdline (g, kernel); + add_cmdline (g, "-initrd"); + add_cmdline (g, initrd); + + /* Add drives */ + struct drive *drv; + size_t i; + + if (virtio_scsi) { + /* Create the virtio-scsi bus. */ + add_cmdline (g, "-device"); + add_cmdline (g, "virtio-scsi-pci,id=scsi"); + } + + ITER_DRIVES (g, i, drv) { + /* Construct the final -drive parameter. */ + CLEANUP_FREE char *buf = qemu_drive_param (g, drv, i); + + add_cmdline (g, "-drive"); + add_cmdline (g, buf); + + if (virtio_scsi && drv->iface == NULL) { + char buf2[64]; + snprintf (buf2, sizeof buf2, "scsi-hd,drive=hd%zu", i); + add_cmdline (g, "-device"); + add_cmdline (g, buf2); + } + } + + /* Add the ext2 appliance drive (after all the drives). */ + if (has_appliance_drive) { + const char *cachemode = ""; + if (qemu_supports (g, "cache=")) { + if (qemu_supports (g, "unsafe")) + cachemode = ",cache=unsafe"; + else if (qemu_supports (g, "writeback")) + cachemode = ",cache=writeback"; + } + + size_t buf2_len = strlen (appliance) + 64; + char buf2[buf2_len]; + add_cmdline (g, "-drive"); + snprintf (buf2, buf2_len, "file=%s,snapshot=on,id=appliance,if=%s%s", + appliance, virtio_scsi ? "none" : "virtio", cachemode); + add_cmdline (g, buf2); + + if (virtio_scsi) { + add_cmdline (g, "-device"); + add_cmdline (g, "scsi-hd,drive=appliance"); + } + + appliance_dev = make_appliance_dev (g, virtio_scsi); + } + /* Create the virtio serial bus. */ add_cmdline (g, "-device"); add_cmdline (g, "virtio-serial"); @@ -447,11 +452,6 @@ launch_direct (guestfs_h *g, const char *arg) add_cmdline (g, "virtio-net-pci,netdev=usernet"); } - add_cmdline (g, "-kernel"); - add_cmdline (g, kernel); - add_cmdline (g, "-initrd"); - add_cmdline (g, initrd); - add_cmdline (g, "-append"); CLEANUP_FREE char *cmdline guestfs___appliance_command_line (g, appliance_dev, 0); -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 23/67] augeas: Improve error reporting.
From: "Richard W.M. Jones" <rjones@redhat.com> Display all the information from the handle about errors. (cherry picked from commit f26a0407d2a61ed334b4a9d42b1269feb3cab76e) --- daemon/augeas.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/daemon/augeas.c b/daemon/augeas.c index c0c97e3..54830c7 100644 --- a/daemon/augeas.c +++ b/daemon/augeas.c @@ -64,6 +64,23 @@ optgroup_augeas_available (void) return 1; } +/* Calls reply_with_error, but includes the Augeas error details. */ +#define AUGEAS_ERROR(fs,...) \ + do { \ + int code = aug_error (aug); \ + if (code == AUG_ENOMEM) \ + reply_with_error (fs ": augeas out of memory", ##__VA_ARGS__); \ + else { \ + const char *message = aug_error_message (aug); \ + const char *minor = aug_error_minor_message (aug); \ + const char *details = aug_error_details (aug); \ + reply_with_error (fs ": %s%s%s%s%s", ##__VA_ARGS__, \ + message, \ + minor ? ": " : "", minor ? minor : "", \ + details ? ": " : "", details ? details : ""); \ + } \ + } while (0) + /* We need to rewrite the root path so it is based at /sysroot. */ int do_aug_init (const char *root, int flags) @@ -112,7 +129,7 @@ do_aug_defvar (const char *name, const char *expr) r = aug_defvar (aug, name, expr); if (r == -1) { - reply_with_error ("Augeas defvar failed"); + AUGEAS_ERROR ("aug_defvar: %s: %s", name, expr); return -1; } return r; @@ -133,7 +150,7 @@ do_aug_defnode (const char *name, const char *expr, const char *val) i = aug_defnode (aug, name, expr, val, &created); if (i == -1) { - reply_with_error ("Augeas defnode failed"); + AUGEAS_ERROR ("aug_defnode: %s: %s: %s", name, expr, val); return NULL; } @@ -168,7 +185,7 @@ do_aug_get (const char *path) return NULL; } if (r != 1) { - reply_with_error ("Augeas get failed"); + AUGEAS_ERROR ("aug_get: %s", path); return NULL; } @@ -200,7 +217,7 @@ do_aug_set (const char *path, const char *val) r = aug_set (aug, path, val); if (r == -1) { - reply_with_error ("Augeas set failed"); + AUGEAS_ERROR ("aug_set: %s: %s", path, val); return -1; } @@ -216,7 +233,7 @@ do_aug_clear (const char *path) r = aug_set (aug, path, NULL); if (r == -1) { - reply_with_error ("Augeas clear failed"); + AUGEAS_ERROR ("aug_clear: %s", path); return -1; } @@ -232,7 +249,7 @@ do_aug_insert (const char *path, const char *label, int before) r = aug_insert (aug, path, label, before); if (r == -1) { - reply_with_error ("Augeas insert failed"); + AUGEAS_ERROR ("aug_insert: %s: %s [before=%d]", path, label, before); return -1; } @@ -248,7 +265,7 @@ do_aug_rm (const char *path) r = aug_rm (aug, path); if (r == -1) { - reply_with_error ("Augeas rm failed"); + AUGEAS_ERROR ("aug_rm: %s", path); return -1; } @@ -264,7 +281,7 @@ do_aug_mv (const char *src, const char *dest) r = aug_mv (aug, src, dest); if (r == -1) { - reply_with_error ("Augeas mv failed"); + AUGEAS_ERROR ("aug_mv: %s: %s", src, dest); return -1; } @@ -282,7 +299,7 @@ do_aug_match (const char *path) r = aug_match (aug, path, &matches); if (r == -1) { - reply_with_error ("Augeas match failed"); + AUGEAS_ERROR ("aug_match: %s", path); return NULL; } @@ -307,7 +324,7 @@ do_aug_save (void) NEED_AUG (-1); if (aug_save (aug) == -1) { - reply_with_error ("Augeas save failed"); + AUGEAS_ERROR ("aug_save"); return -1; } @@ -321,7 +338,7 @@ do_aug_load (void) NEED_AUG (-1); if (aug_load (aug) == -1) { - reply_with_error ("Augeas load failed"); + AUGEAS_ERROR ("aug_load"); return -1; } -- 1.8.3.1
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit f6b2efcdffe8688fc415b3f1cd9d608dd396f253) --- TODO | 76 ++++++++++++++++++++++---------------------------------------------- 1 file changed, 24 insertions(+), 52 deletions(-) diff --git a/TODO b/TODO index 6e4c741..0a8cf57 100644 --- a/TODO +++ b/TODO @@ -95,10 +95,22 @@ two sides to a pty, and one has to be handled after the fork). work. qemu is implementing its own ptys, and they are broken. Need to fix qemu.] -Windows-based daemon/appliance ------------------------------- +Port to Windows +--------------- -See discussion on list: +"Port to Windows" means different things to different people. + +The easiest is to port the library to Windows, but reuse the Linux +appliance/daemon. This would allow people to use libguestfs on +Windows hosts and link libguestfs to Windows programs. Doing this is +just a matter of chugging through the code fixing portability issues, +using gnulib as far as possible as the portability layer. + +The hardest is probably a port of the daemon to Windows. The reason +to do this is so that you can use the native NTFS drivers (in Windows) +in order to edit Windows guests. Although back in 2009 we did some +work on this, I am now dubious about the utility of this, since +ntfs-3g works very well. See also discussion on list: https://www.redhat.com/archives/libguestfs/2009-November/msg00165.html virt-disk-explore @@ -141,11 +153,8 @@ http://sourceforge.net/projects/aide/ http://osiris.shmoo.com/ http://sourceforge.net/projects/tripwire/ -Freeze/thaw filesystems ------------------------ - -Access to these ioctls: -http://git.kernel.org/linus/fcccf502540e3d7 +See also: virt-aide; +https://rwmj.wordpress.com/2013/05/16/scanning-offline-guests-using-openscap-and-guestmount/#content Tips for new users in guestfish ------------------------------- @@ -198,7 +207,7 @@ There are some places where we call out to the 'blkid' program. This might be replaced by direct use of the library (if this is easier). But it is very hard to be compatible between RHEL6 and RHEL5 when -using direct library. +using the library directly. Visualization ------------- @@ -388,18 +397,8 @@ virt-sysprep ideas . run external guestfish script virt-sysprep --fish=/tmp/foo.fish - if drives are encrypted, then dm-crypt key should be changed and drives all re-encrypted - - /etc/pki - (Steve says ...) - Rpm uses nss. Nss sets up its crypto database in - /etc/pki. Depending on how long the machine ran before cloning, you - may have picked up some certificates or things. This is an area - that you would want to look into. - secure erase of inodes etc using scrub (Steve Grubb) - - other directories that could require cleaning include: - /var/run/* - (thanks Marko Myllynen, James Antill) - - remove or modify UUIDs in /etc/fstab (eg. on Ubuntu) - (thanks Joshua Daniel Franklin) + - fix the virt-sysprep fs-uuids plugin Kazuo Moriwaka adds: @@ -423,16 +422,9 @@ customized with the organization logo etc. Some ideas: - change the sign-on messages (/etc/issue.net etc) - Windows login script/service -Launch remote sessions over ssh -------------------------------- - -We had an idea you could add a launch method that uses ssh, ie. all -supermin and qemu commands happen the same as now, but prefixed by -ssh so it happens on a remote machine. - -Note that proper remote support and integration with libvirt is -different from this, and people are working on that. ssh would just -be "remote-lite". +Note that virt-sysprep has gradually gained some of these features, +eg. setting hostname, changing passwords. Since this precedent has +now been set, it could do more of the same. virt-make-fs and virt-win-reg need to not be in Perl ---------------------------------------------------- @@ -534,21 +526,6 @@ as data is reliably written out when g.sync, g.shutdown or g.close return. Also in libguestfs we effectively control the whole stack, so we can ensure write barriers happen when we want. -libvirt backend ---------------- - -Since libguestfs 1.19.24 this mostly works. Here are some suggested -items to work on: - - - SELinux labelling of guestfsd.sock, console.sock - https://bugzilla.redhat.com/show_bug.cgi?id=842307 - Once this is fixed, remove <seclabel type=none> from libvirt XML - - - Check feature parity between src/launch-appliance.c and - src/launch-libvirt.c. - - - Remote support. (This requires work on libvirt) - virt-sparsify should use discard -------------------------------- @@ -558,19 +535,14 @@ throughout the entire stack. Reimplement some APIs to avoid protocol limits ---------------------------------------------- -We should reimplement the following APIs to avoid protocol limits. -These would be changed from daemon_functions to non_daemon_functions, -with the non-daemon versions implemented using guestfs_upload and -guestfs_download (and others). This change should be transparent from -the p.o.v of the API and ABI. +Mostly this item was done (eg. commits a69f44f56f and before). The +most notable API with a protocol limit remaining is: - guestfs_readdir hivex ----- -Add more of hivex to the API, especially for writing. - Reimplement virt-win-reg to use this API. (This is difficult because the Perl libraries underneath access the hivex API directly). -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 25/67] Update gnulib to latest version.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 3197a2687c0b1d9ba5b9b3d32b5f0200e630628f) --- .gnulib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gnulib b/.gnulib index 9ceceed..03e96cc 160000 --- a/.gnulib +++ b/.gnulib @@ -1 +1 @@ -Subproject commit 9ceceed274f83094127f9ff0bf061293c9fe1e7f +Subproject commit 03e96cc338b5237e15fce73e9423526969ee768a -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 26/67] Update Transifex domain name from .net -> .com.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 56f613b13003b2ef44b25da360c5dac6eb5b0c71) --- .tx/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.tx/config b/.tx/config index 4e21dd5..26fb474 100644 --- a/.tx/config +++ b/.tx/config @@ -1,5 +1,5 @@ [main] -host = https://www.transifex.net +host = https://www.transifex.com [libguestfs.libguestfspot] file_filter = po/<lang>.po -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 27/67] Fix parsing of boot flag in do_part_get_bootable()
From: Paul Mackerras <paulus@samba.org> The code in do_part_get_bootable() assumes that if a partition has the bootable flag set, then that is the only flag. It compares the entire flags field with the string "boot". However, the boot flag isn't always the only flag. For instance, POWER systems typically have a bootable partition of type 0x41 (PPC PReP boot), which parted -m displays as: # parted -m -- f18.img unit b print BYT; /root/f18.img:16106127360B:file:512:512:msdos::; 1:1048576B:5242879B:4194304B:::boot, prep; That is, the flags field contains "boot, prep", and thus libguestfs fails to see that this partition is bootable. Ultimately this causes virt-resize to fail to set the bootable flag on the boot partition of the destination image, resulting in an image that won't boot. This patch fixes the problem by searching for the string "boot" within the flags field, instead of comparing the whole flags field. (cherry picked from commit 7c535c501b1ce131ae98dd948b22fc260d659d1b) --- daemon/parted.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/parted.c b/daemon/parted.c index 7b1afb1..2ada40f 100644 --- a/daemon/parted.c +++ b/daemon/parted.c @@ -628,7 +628,7 @@ do_part_get_bootable (const char *device, int partnum) if (boot == NULL) return -1; - return STREQ (boot, "boot"); + return strstr (boot, "boot") != NULL; } else { /* Old-style: First look for the line matching "^Number". */ -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 28/67] daemon: Close augeas, hivex handles in unmount_all.
From: "Richard W.M. Jones" <rjones@redhat.com> This is also called implicitly from internal_autosync, ensuring that exit won't fail because of an open handle. libguestfs: error: internal_autosync: umount: /sysroot: umount: /sysroot: target is busy. (In some cases useful info about processes that use the device is found by lsof(8) or fuser(1)) Cherry picked from commit ce6e5738fc4ca9533e73cfe6b5fe3db872b7ec9d and modified to remove references to the journal. --- daemon/augeas.c | 4 ++-- daemon/daemon.h | 4 ++++ daemon/hivex.c | 4 ++-- daemon/mount.c | 7 +++++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/daemon/augeas.c b/daemon/augeas.c index 54830c7..b2d1eb2 100644 --- a/daemon/augeas.c +++ b/daemon/augeas.c @@ -39,8 +39,8 @@ static augeas *aug = NULL; /* Clean up the augeas handle on daemon exit. */ -static void aug_finalize (void) __attribute__((destructor)); -static void +void aug_finalize (void) __attribute__((destructor)); +void aug_finalize (void) { if (aug) { diff --git a/daemon/daemon.h b/daemon/daemon.h index 853a500..4887d21 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -216,6 +216,10 @@ extern void copy_lvm (void); /*-- in zero.c --*/ extern void wipe_device_before_mkfs (const char *device); +/*-- in augeas.c, hivex.c --*/ +extern void aug_finalize (void); +extern void hivex_finalize (void); + /*-- in proto.c --*/ extern void main_loop (int sock) __attribute__((noreturn)); diff --git a/daemon/hivex.c b/daemon/hivex.c index 92e8fc3..ce6164e 100644 --- a/daemon/hivex.c +++ b/daemon/hivex.c @@ -47,8 +47,8 @@ optgroup_hivex_available (void) static hive_h *h = NULL; /* Clean up the hivex handle on daemon exit. */ -static void hivex_finalize (void) __attribute__((destructor)); -static void +void hivex_finalize (void) __attribute__((destructor)); +void hivex_finalize (void) { if (h) { diff --git a/daemon/mount.c b/daemon/mount.c index 452b938..b89bb88 100644 --- a/daemon/mount.c +++ b/daemon/mount.c @@ -373,6 +373,13 @@ do_umount_all (void) size_t i; int r; + /* This is called from internal_autosync and generally as a cleanup + * function, and since the umount will definitely fail if any + * handles are open, we may as well close them. + */ + aug_finalize (); + hivex_finalize (); + /* NB: Eventually we should aim to parse /proc/self/mountinfo, but * that requires custom parsing code. */ -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 29/67] appliance/init: Display uname -a in debug output.
From: "Richard W.M. Jones" <rjones@redhat.com> Useful for debugging kernel / architecture issues. Note this has no effect if debugging is disabled. (cherry picked from commit 6c2fad11ac9a68dcfd42ee18681dc9a552625be9) --- appliance/init | 1 + 1 file changed, 1 insertion(+) diff --git a/appliance/init b/appliance/init index 5c9f04a..681e59b 100755 --- a/appliance/init +++ b/appliance/init @@ -116,6 +116,7 @@ ldmtool create all # These are useful when debugging. if grep -sq guestfs_verbose=1 /proc/cmdline; then + uname -a ls -lR /dev cat /proc/mounts lvm pvs -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 30/67] proto: Fix --enable-packet-dump mode.
From: "Richard W.M. Jones" <rjones@redhat.com> This was broken when we rearranged the socket code. (cherry picked from commit 26309a1c3a4a8ae4c79cc72ed83dfea4bde5c1a0) --- src/proto.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/proto.c b/src/proto.c index 4b15efd..fdd7ecc 100644 --- a/src/proto.c +++ b/src/proto.c @@ -580,14 +580,14 @@ recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn) if (g->verbose) { ssize_t i, j; - for (i = 0; i < nr; i += 16) { + for (i = 0; i < n; i += 16) { printf ("%04zx: ", i); - for (j = i; j < MIN (i+16, nr); ++j) + for (j = i; j < MIN (i+16, n); ++j) printf ("%02x ", (*(unsigned char **)buf_rtn)[j]); for (; j < i+16; ++j) printf (" "); printf ("|"); - for (j = i; j < MIN (i+16, nr); ++j) + for (j = i; j < MIN (i+16, n); ++j) if (c_isprint ((*(char **)buf_rtn)[j])) printf ("%c", (*(char **)buf_rtn)[j]); else -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 31/67] Fix --enable-valgrind-daemon option.
From: "Richard W.M. Jones" <rjones@redhat.com> Don't add the "valgrind channel" to the appliance. Just dump out the valgrind.log to stderr while the daemon is running. Ensure that if valgrind tests fail in the appliance, that we don't exit with success in the library by checking for a canary message in the verbose daemon logs. This allows the option to be used routinely by developers. (cherry picked from commit 55e3b8711f340a2f8bdb8ee8ff99deb40b4e9108) --- appliance/init | 12 ++++-------- configure.ac | 1 - src/conn-socket.c | 14 ++++++++++++++ src/launch-direct.c | 10 ---------- src/launch.c | 3 +++ 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/appliance/init b/appliance/init index 681e59b..79083a4 100755 --- a/appliance/init +++ b/appliance/init @@ -135,21 +135,17 @@ fi if ! grep -sq guestfs_rescue=1 /proc/cmdline; then # Run the daemon under valgrind if ./configure --enable-valgrind-daemon - vg_channel=/dev/virtio-ports/org.libguestfs.valgrind - if [ -w $vg_channel ]; then + if grep -sq guestfs_valgrind_daemon=1 /proc/cmdline; then if [ -r /etc/guestfsd.suppressions ]; then suppressions="--suppressions=/etc/guestfsd.suppressions" fi - exec 3>$vg_channel - vg="valgrind --leak-check=full --log-fd=3 --error-exitcode=119 --max-stackframe=8388608 --child-silent-after-fork=yes $suppressions" + vg="valgrind --leak-check=full --error-exitcode=119 --max-stackframe=8388608 --child-silent-after-fork=yes $suppressions" echo "enabling valgrind: $vg" fi - # The host will kill qemu abruptly if guestfsd shuts down normally + # Run guestfsd, under valgrind if asked. $vg guestfsd - - # Otherwise we try to clean up gracefully. For example, this ensures that a - # core dump generated by the guest daemon will be written to disk. + if [ $? -eq 119 ]; then echo "DAEMON VALGRIND FAILED"; fi else # Use appliance in rescue mode, also used by the virt-rescue command. eval $(grep -Eo 'TERM=[^[:space:]]+' /proc/cmdline) diff --git a/configure.ac b/configure.ac index 396d9fd..61cae54 100644 --- a/configure.ac +++ b/configure.ac @@ -385,7 +385,6 @@ if test "x$enable_daemon" = "xyes"; then if test "x$enable_valgrind_daemon" = "xyes"; then AC_DEFINE([VALGRIND_DAEMON],[1],[Define to 1 to run the daemon under valgrind.]) - AC_DEFINE_UNQUOTED([VALGRIND_LOG_PATH],["$(pwd)"],[Path to save valgrind log files.]) fi dnl Which directory should we put the daemon in? NOTE: This diff --git a/src/conn-socket.c b/src/conn-socket.c index 2b3f222..e37ac23 100644 --- a/src/conn-socket.c +++ b/src/conn-socket.c @@ -321,6 +321,20 @@ handle_log_message (guestfs_h *g, /* It's an actual log message, send it upwards. */ guestfs___log_message_callback (g, buf, n); +#ifdef VALGRIND_DAEMON + /* Find the canary printed by appliance/init if valgrinding of the + * daemon fails, and exit abruptly. Note this is only used in + * developer builds, and should never be enabled in ordinary/ + * production builds. + */ + if (g->verbose) { + const char *valgrind_canary = "DAEMON VALGRIND FAILED"; + + if (memmem (buf, n, valgrind_canary, strlen (valgrind_canary)) != NULL) + exit (119); + } +#endif + return 1; } diff --git a/src/launch-direct.c b/src/launch-direct.c index 6414f60..8d05221 100644 --- a/src/launch-direct.c +++ b/src/launch-direct.c @@ -434,16 +434,6 @@ launch_direct (guestfs_h *g, const char *arg) add_cmdline (g, "-device"); add_cmdline (g, "virtserialport,chardev=channel0,name=org.libguestfs.channel.0"); -#ifdef VALGRIND_DAEMON - /* Set up virtio-serial channel for valgrind messages. */ - add_cmdline (g, "-chardev"); - snprintf (buf, sizeof buf, "file,path=%s/valgrind.log.%d,id=valgrind", - VALGRIND_LOG_PATH, getpid ()); - add_cmdline (g, buf); - add_cmdline (g, "-device"); - add_cmdline (g, "virtserialport,chardev=valgrind,name=org.libguestfs.valgrind"); -#endif - /* Enable user networking. */ if (g->enable_network) { add_cmdline (g, "-netdev"); diff --git a/src/launch.c b/src/launch.c index 894ca15..415edc2 100644 --- a/src/launch.c +++ b/src/launch.c @@ -320,6 +320,9 @@ guestfs___appliance_command_line (guestfs_h *g, const char *appliance_dev, ret = safe_asprintf (g, "panic=1" /* force kernel to panic if daemon exits */ +#ifdef VALGRIND_DAEMON + " guestfs_valgrind_daemon=1" +#endif #ifdef __i386__ " noapic" /* workaround for RHBZ#857026 */ #endif -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 32/67] daemon: Remove unnecessary sysroot_path (selinux).
From: "Richard W.M. Jones" <rjones@redhat.com> This fixes commit 72afcf450a78b7e58f65b4a7aaf94d71cd25fca5. (cherry picked from commit 7367729ec7a5d016878dd00b32cce45cec372931) --- daemon/command.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/daemon/command.c b/daemon/command.c index fde3826..db82b52 100644 --- a/daemon/command.c +++ b/daemon/command.c @@ -44,7 +44,7 @@ do_command (char *const *argv) CLEANUP_FREE char *err; int r; CLEANUP_FREE char *sysroot_dev = NULL, *sysroot_dev_pts = NULL, - *sysroot_proc = NULL, *sysroot_selinux = NULL, *sysroot_sys = NULL; + *sysroot_proc = NULL, *sysroot_sys = NULL; int dev_ok, dev_pts_ok, proc_ok, sys_ok; /* We need a root filesystem mounted to do this. */ @@ -70,12 +70,10 @@ do_command (char *const *argv) sysroot_dev = sysroot_path ("/dev"); sysroot_dev_pts = sysroot_path ("/dev/pts"); sysroot_proc = sysroot_path ("/proc"); - sysroot_selinux = sysroot_path ("/sys/fs/selinux"); sysroot_sys = sysroot_path ("/sys"); if (sysroot_dev == NULL || sysroot_dev_pts == NULL || - sysroot_proc == NULL || sysroot_selinux == NULL || - sysroot_sys == NULL) { + sysroot_proc == NULL || sysroot_sys == NULL) { reply_with_perror ("malloc"); return NULL; } -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 33/67] Print an error message if valgrind failure is detected in the daemon.
From: "Richard W.M. Jones" <rjones@redhat.com> This updates commit 55e3b8711f340a2f8bdb8ee8ff99deb40b4e9108. (cherry picked from commit e7b06f7cf84d0a87d0c80d56b06e7e0017e55adc) --- src/conn-socket.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/conn-socket.c b/src/conn-socket.c index e37ac23..1ad92cf 100644 --- a/src/conn-socket.c +++ b/src/conn-socket.c @@ -330,8 +330,14 @@ handle_log_message (guestfs_h *g, if (g->verbose) { const char *valgrind_canary = "DAEMON VALGRIND FAILED"; - if (memmem (buf, n, valgrind_canary, strlen (valgrind_canary)) != NULL) + if (memmem (buf, n, valgrind_canary, strlen (valgrind_canary)) != NULL) { + fprintf (stderr, + "Detected valgrind failure in the daemon! Exiting with exit code 119.\n" + "See log messages printed above.\n" + "Note: This happens because libguestfs was configured with\n" + "'--enable-valgrind-daemon' which should not be used in production builds.\n"); exit (119); + } } #endif -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 34/67] Fix --enable-valgrind-daemon so it doesn't break valgrind of the library.
From: "Richard W.M. Jones" <rjones@redhat.com> Using ./configure --enable-valgrind-daemon breaks valgrinding of the library because guestfs_close wouldn't call guestfs_shutdown in that case, resulting in some resources owned by the backend being leaked. After this commit, --enable-valgrind-daemon will shut down the handle normally. This updates commit 55e3b8711f340a2f8bdb8ee8ff99deb40b4e9108. (cherry picked from commit 94872348e852a9bdfa4d170b0f238d796789c73a) --- src/handle.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/handle.c b/src/handle.c index b4291e8..dc2b15b 100644 --- a/src/handle.c +++ b/src/handle.c @@ -294,16 +294,8 @@ guestfs_close (guestfs_h *g) debug (g, "closing guestfs handle %p (state %d)", g, g->state); - /* If we are valgrinding the daemon, then we *don't* want to kill - * the subprocess because we want the final valgrind messages sent - * when we close sockets below. However for normal production use, - * killing the subprocess is the right thing to do (in case the - * daemon or qemu is not responding). - */ -#ifndef VALGRIND_DAEMON if (g->state != CONFIG) shutdown_backend (g, 0); -#endif /* Run user close callbacks. */ guestfs___call_callbacks_void (g, GUESTFS_EVENT_CLOSE); @@ -382,15 +374,16 @@ shutdown_backend (guestfs_h *g, int check_for_errors) ret = -1; } + /* Shut down the backend. */ + if (g->backend_ops->shutdown (g, check_for_errors) == -1) + ret = -1; + /* Close sockets. */ if (g->conn) { g->conn->ops->free_connection (g, g->conn); g->conn = NULL; } - if (g->backend_ops->shutdown (g, check_for_errors) == -1) - ret = -1; - guestfs___free_drives (g); g->state = CONFIG; -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 35/67] tests/mountable: Better error messages.
From: "Richard W.M. Jones" <rjones@redhat.com> Better error messages (for diagnosis) when this test fails. Also this fixes the line endings which were broken before. (cherry picked from commit d9694362059e869da67c1333d62adb66f7d0aa1e) --- tests/mountable/test-internal-parse-mountable.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/mountable/test-internal-parse-mountable.c b/tests/mountable/test-internal-parse-mountable.c index e33db76..b12869b 100644 --- a/tests/mountable/test-internal-parse-mountable.c +++ b/tests/mountable/test-internal-parse-mountable.c @@ -92,9 +92,10 @@ main (int argc, char *argv[]) if (mountable == NULL) goto error; if (mountable->im_type != MOUNTABLE_DEVICE || - !STREQ ("/dev/VG/LV", mountable->im_device)) + STRNEQ ("/dev/VG/LV", mountable->im_device)) { - fprintf (stderr, "incorrectly parsed /dev/VG/LV"); + fprintf (stderr, "incorrectly parsed /dev/VG/LV: im_device=%s\n", + mountable->im_device); goto error; } @@ -104,10 +105,11 @@ main (int argc, char *argv[]) if (mountable == NULL) goto error; if (mountable->im_type != MOUNTABLE_BTRFSVOL || - !STREQ ("/dev/VG/LV", mountable->im_device) || - !STREQ ("sv", mountable->im_volume)) + STRNEQ ("/dev/VG/LV", mountable->im_device) || + STRNEQ ("sv", mountable->im_volume)) { - fprintf (stderr, "incorrectly parsed /dev/VG/LV/sv"); + fprintf (stderr, "incorrectly parsed /dev/VG/LV/sv: im_device=%s, im_volume=%s\n", + mountable->im_device, mountable->im_volume); goto error; } guestfs_free_internal_mountable (mountable); -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 36/67] daemon: Move all RESOLVE macros to daemon/stubs.c.
From: "Richard W.M. Jones" <rjones@redhat.com> These macros are pretty horrible to use, with unexpected side-effects. Move them exclusively into the generated code and rewrite the one place in the general C code which used them. There's no functional change in this code. (cherry picked from commit 89cf1c1163f5c01f2335b7c030bb884be3310394) --- daemon/daemon.h | 93 ------------------------------------- daemon/ext2.c | 13 +++++- generator/daemon.ml | 130 +++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 125 insertions(+), 111 deletions(-) diff --git a/daemon/daemon.h b/daemon/daemon.h index 4887d21..d3a0d01 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -338,99 +338,6 @@ is_zero (const char *buffer, size_t size) } \ } while (0) -/* All functions that need an argument that is a device or partition name - * must call this macro. It checks that the device exists and does - * device name translation (described in the guestfs(3) manpage). - * Note that the "path" argument may be modified. - * - * NB. Cannot be used for FileIn functions. - */ -#define RESOLVE_DEVICE(path,cancel_stmt,fail_stmt) \ - do { \ - if (STRNEQLEN ((path), "/dev/", 5)) { \ - cancel_stmt; \ - reply_with_error ("%s: %s: expecting a device name", __func__, (path)); \ - fail_stmt; \ - } \ - if (is_root_device (path)) { \ - cancel_stmt; \ - reply_with_error ("%s: %s: device not found", __func__, path); \ - fail_stmt; \ - } \ - if (device_name_translation ((path)) == -1) { \ - int err = errno; \ - cancel_stmt; \ - errno = err; \ - reply_with_perror ("%s: %s", __func__, path); \ - fail_stmt; \ - } \ - } while (0) - -/* All functions that take a mountable argument must call this macro. - * It parses the mountable into a mountable_t, ensures any - * underlying device exists, and does device name translation - * (described in the guestfs(3) manpage). - * - * Note that the "string" argument may be modified. - */ -#define RESOLVE_MOUNTABLE(string,mountable,cancel_stmt,fail_stmt) \ - do { \ - if (STRPREFIX ((string), "btrfsvol:")) { \ - if (parse_btrfsvol ((string) + strlen ("btrfsvol:"), &(mountable)) == -1)\ - { \ - cancel_stmt; \ - reply_with_error ("%s: %s: expecting a btrfs volume", \ - __func__, (string)); \ - fail_stmt; \ - } \ - } \ - \ - else { \ - (mountable).type = MOUNTABLE_DEVICE; \ - (mountable).device = (string); \ - (mountable).volume = NULL; \ - RESOLVE_DEVICE((string), cancel_stmt, fail_stmt); \ - } \ - } while (0) - -/* Helper for functions which need either an absolute path in the - * mounted filesystem, OR a /dev/ device which exists. - * - * NB. Cannot be used for FileIn functions. - * - * NB #2: Functions which mix filenames and device paths should be - * avoided, and existing functions should be deprecated. This is - * because we intend in future to make device parameters a distinct - * type from filenames. - */ -#define REQUIRE_ROOT_OR_RESOLVE_DEVICE(path,cancel_stmt,fail_stmt) \ - do { \ - if (STREQLEN ((path), "/dev/", 5)) \ - RESOLVE_DEVICE ((path), cancel_stmt, fail_stmt); \ - else { \ - NEED_ROOT (cancel_stmt, fail_stmt); \ - ABS_PATH ((path), cancel_stmt, fail_stmt); \ - } \ - } while (0) - -/* Helper for functions which need either an absolute path in the - * mounted filesystem, OR a valid mountable description. - */ -#define REQUIRE_ROOT_OR_RESOLVE_MOUNTABLE(string, mountable, \ - cancel_stmt, fail_stmt) \ - do { \ - if (STREQLEN ((string), "/dev/", strlen ("/dev/")) || (string)[0] != '/') {\ - RESOLVE_MOUNTABLE (string, mountable, cancel_stmt, fail_stmt); \ - } \ - \ - else { \ - NEED_ROOT (cancel_stmt, fail_stmt); \ - (mountable).type = MOUNTABLE_PATH; \ - (mountable).device = (string); \ - } \ - } while (0) \ - - /* NB: * (1) You must match CHROOT_IN and CHROOT_OUT even along error paths. * (2) You must not change directory! cwd must always be "/", otherwise diff --git a/daemon/ext2.c b/daemon/ext2.c index ff785b7..d1ce020 100644 --- a/daemon/ext2.c +++ b/daemon/ext2.c @@ -946,6 +946,17 @@ do_mke2fs (const char *device, /* 0 */ * have to do it manually here, but note that LABEL=.. and * UUID=.. are valid strings which do not require translation. */ + if (STRPREFIX (journaldevice, "/dev/")) { + if (is_root_device (journaldevice)) { + reply_with_error ("%s: device not found", journaldevice); + return -1; + } + if (device_name_translation ((char *) journaldevice) == -1) { + reply_with_perror ("%s", journaldevice); + return -1; + } + } + journaldevice_s = malloc (strlen (journaldevice) + 8); if (!journaldevice_s) { reply_with_perror ("malloc"); @@ -953,8 +964,6 @@ do_mke2fs (const char *device, /* 0 */ } sprintf (journaldevice_s, "device=%s", journaldevice); - if (STRPREFIX (&journaldevice_s[7], "/dev/")) - RESOLVE_DEVICE (&journaldevice_s[7], , return -1); ADD_ARG (argv, i, "-J"); ADD_ARG (argv, i, journaldevice_s); diff --git a/generator/daemon.ml b/generator/daemon.ml index e68622b..b08a9c2 100644 --- a/generator/daemon.ml +++ b/generator/daemon.ml @@ -74,22 +74,120 @@ let generate_daemon_actions_h () and generate_daemon_actions () generate_header CStyle GPLv2plus; - pr "#include <config.h>\n"; - pr "\n"; - pr "#include <stdio.h>\n"; - pr "#include <stdlib.h>\n"; - pr "#include <string.h>\n"; - pr "#include <inttypes.h>\n"; - pr "#include <errno.h>\n"; - pr "#include <rpc/types.h>\n"; - pr "#include <rpc/xdr.h>\n"; - pr "\n"; - pr "#include \"daemon.h\"\n"; - pr "#include \"c-ctype.h\"\n"; - pr "#include \"guestfs_protocol.h\"\n"; - pr "#include \"actions.h\"\n"; - pr "#include \"optgroups.h\"\n"; - pr "\n"; + pr "\ +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <errno.h> +#include <rpc/types.h> +#include <rpc/xdr.h> + +#include \"daemon.h\" +#include \"c-ctype.h\" +#include \"guestfs_protocol.h\" +#include \"actions.h\" +#include \"optgroups.h\" + +/* Some macros to make resolving devices easier. These used to + * be available in daemon.h but now they are only used by stubs. + */ + +/* All functions that need an argument that is a device or partition name + * must call this macro. It checks that the device exists and does + * device name translation (described in the guestfs(3) manpage). + * Note that the \"path\" argument may be modified. + * + * NB. Cannot be used for FileIn functions. + */ +#define RESOLVE_DEVICE(path,cancel_stmt,fail_stmt) \\ + do { \\ + if (STRNEQLEN ((path), \"/dev/\", 5)) { \\ + cancel_stmt; \\ + reply_with_error (\"%%s: %%s: expecting a device name\", __func__, (path)); \\ + fail_stmt; \\ + } \\ + if (is_root_device (path)) { \\ + cancel_stmt; \\ + reply_with_error (\"%%s: %%s: device not found\", __func__, path); \\ + fail_stmt; \\ + } \\ + if (device_name_translation ((path)) == -1) { \\ + int err = errno; \\ + cancel_stmt; \\ + errno = err; \\ + reply_with_perror (\"%%s: %%s\", __func__, path); \\ + fail_stmt; \\ + } \\ + } while (0) + +/* All functions that take a mountable argument must call this macro. + * It parses the mountable into a mountable_t, ensures any + * underlying device exists, and does device name translation + * (described in the guestfs(3) manpage). + * + * Note that the \"string\" argument may be modified. + */ +#define RESOLVE_MOUNTABLE(string,mountable,cancel_stmt,fail_stmt) \\ + do { \\ + if (STRPREFIX ((string), \"btrfsvol:\")) { \\ + if (parse_btrfsvol ((string) + strlen (\"btrfsvol:\"), &(mountable)) == -1)\\ + { \\ + cancel_stmt; \\ + reply_with_error (\"%%s: %%s: expecting a btrfs volume\", \\ + __func__, (string)); \\ + fail_stmt; \\ + } \\ + } \\ + \\ + else { \\ + (mountable).type = MOUNTABLE_DEVICE; \\ + (mountable).device = (string); \\ + (mountable).volume = NULL; \\ + RESOLVE_DEVICE((string), cancel_stmt, fail_stmt); \\ + } \\ + } while (0) + +/* Helper for functions which need either an absolute path in the + * mounted filesystem, OR a /dev/ device which exists. + * + * NB. Cannot be used for FileIn functions. + * + * NB #2: Functions which mix filenames and device paths should be + * avoided, and existing functions should be deprecated. This is + * because we intend in future to make device parameters a distinct + * type from filenames. + */ +#define REQUIRE_ROOT_OR_RESOLVE_DEVICE(path,cancel_stmt,fail_stmt) \\ + do { \\ + if (STREQLEN ((path), \"/dev/\", 5)) \\ + RESOLVE_DEVICE ((path), cancel_stmt, fail_stmt); \\ + else { \\ + NEED_ROOT (cancel_stmt, fail_stmt); \\ + ABS_PATH ((path), cancel_stmt, fail_stmt); \\ + } \\ + } while (0) + +/* Helper for functions which need either an absolute path in the + * mounted filesystem, OR a valid mountable description. + */ +#define REQUIRE_ROOT_OR_RESOLVE_MOUNTABLE(string, mountable, \\ + cancel_stmt, fail_stmt) \\ + do { \\ + if (STREQLEN ((string), \"/dev/\", strlen (\"/dev/\")) || (string)[0] != '/') {\\ + RESOLVE_MOUNTABLE (string, mountable, cancel_stmt, fail_stmt); \\ + } \\ + \\ + else { \\ + NEED_ROOT (cancel_stmt, fail_stmt); \\ + (mountable).type = MOUNTABLE_PATH; \\ + (mountable).device = (string); \\ + } \\ + } while (0) \\ + +"; List.iter ( fun { name = name; style = ret, args, optargs; optional = optional } -> -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 37/67] daemon: ldm: Don't return an error if /dev/mapper doesn't exist.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 2089f7a21a307402c3efa43e5d10ee8d5ff554fb) --- daemon/daemon.h | 2 ++ daemon/guestfsd.c | 14 ++++++++++++-- daemon/ldm.c | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/daemon/daemon.h b/daemon/daemon.h index d3a0d01..9a32bea 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -105,6 +105,8 @@ extern char *join_strings (const char *separator, char *const *argv); extern char **split_lines (char *str); +extern char **empty_list (void); + #define command(out,err,name,...) commandf((out),(err),0,(name),__VA_ARGS__) #define commandr(out,err,name,...) commandrf((out),(err),0,(name),__VA_ARGS__) #define commandv(out,err,argv) commandvf((out),(err),0,(argv)) diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index 580315a..343c489 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -1019,7 +1019,7 @@ split_lines (char *str) char *p, *pend; if (STREQ (str, "")) - goto empty_list; + return empty_list (); p = str; while (p) { @@ -1040,13 +1040,23 @@ split_lines (char *str) p = pend; } - empty_list: if (end_stringsbuf (&lines) == -1) return NULL; return lines.argv; } +char ** +empty_list (void) +{ + DECLARE_STRINGSBUF (ret); + + if (end_stringsbuf (&ret) == -1) + return NULL; + + return ret.argv; +} + /* Skip leading and trailing whitespace, updating the original string * in-place. */ diff --git a/daemon/ldm.c b/daemon/ldm.c index b7ef301..aed8a0d 100644 --- a/daemon/ldm.c +++ b/daemon/ldm.c @@ -20,6 +20,9 @@ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> #include <glob.h> #if HAVE_YAJL @@ -91,6 +94,16 @@ get_devices (const char *pattern) char ** do_list_ldm_volumes (void) { + struct stat buf; + + /* If /dev/mapper doesn't exist at all, don't give an error. */ + if (stat ("/dev/mapper", &buf) == -1) { + if (errno == ENOENT) + return empty_list (); + reply_with_perror ("/dev/mapper"); + return NULL; + } + return get_devices ("/dev/mapper/ldm_vol_*"); } @@ -98,6 +111,16 @@ do_list_ldm_volumes (void) char ** do_list_ldm_partitions (void) { + struct stat buf; + + /* If /dev/mapper doesn't exist at all, don't give an error. */ + if (stat ("/dev/mapper", &buf) == -1) { + if (errno == ENOENT) + return empty_list (); + reply_with_perror ("/dev/mapper"); + return NULL; + } + return get_devices ("/dev/mapper/ldm_part_*"); } -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 38/67] utils: Remove duplicate inclusion of <string.h>.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 467fd96e7e7537a5aa706dd5ca2edb513aa833e9) --- src/utils.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils.c b/src/utils.c index 61d0d4c..358c124 100644 --- a/src/utils.c +++ b/src/utils.c @@ -22,7 +22,6 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <libintl.h> -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 39/67] lib: Turn 'random_chars' function used by libvirt backend into utility function.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit e5285cc4210683887a5a4a853fe4e6a72c23e74d) --- src/guestfs-internal-frontend.h | 1 + src/launch-libvirt.c | 34 ++-------------------------------- src/utils.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/guestfs-internal-frontend.h b/src/guestfs-internal-frontend.h index db6122f..2070fa8 100644 --- a/src/guestfs-internal-frontend.h +++ b/src/guestfs-internal-frontend.h @@ -97,6 +97,7 @@ extern size_t guestfs___count_strings (char *const *); extern char *guestfs___concat_strings (char *const *); extern char *guestfs___join_strings (const char *sep, char *const *); extern char *guestfs___exit_status_to_string (int status, const char *cmd_name, char *buffer, size_t buflen); +extern int guestfs___random_string (char *ret, size_t len); /* These functions are used internally by the CLEANUP_* macros. * Don't call them directly. diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c index 826d40d..de725e0 100644 --- a/src/launch-libvirt.c +++ b/src/launch-libvirt.c @@ -131,7 +131,6 @@ static void debug_socket_permissions (guestfs_h *g); static void libvirt_error (guestfs_h *g, const char *fs, ...) __attribute__((format (printf,2,3))); static int is_custom_qemu (guestfs_h *g); static int is_blk (const char *path); -static int random_chars (char *ret, size_t len); static void ignore_errors (void *ignore, virErrorPtr ignore2); static char *make_qcow2_overlay (guestfs_h *g, const char *backing_device, const char *format, const char *selinux_imagelabel); static int make_drive_priv (guestfs_h *g, struct drive *drv, const char *selinux_imagelabel); @@ -791,8 +790,8 @@ construct_libvirt_xml_name (guestfs_h *g, { char name[DOMAIN_NAME_LEN+1]; - if (random_chars (name, DOMAIN_NAME_LEN) == -1) { - perrorf (g, "/dev/urandom"); + if (guestfs___random_string (name, DOMAIN_NAME_LEN) == -1) { + perrorf (g, "guestfs___random_string"); return -1; } @@ -1487,35 +1486,6 @@ is_blk (const char *path) return S_ISBLK (statbuf.st_mode); } -static int -random_chars (char *ret, size_t len) -{ - int fd; - size_t i; - unsigned char c; - int saved_errno; - - fd = open ("/dev/urandom", O_RDONLY|O_CLOEXEC); - if (fd == -1) - return -1; - - for (i = 0; i < len; ++i) { - if (read (fd, &c, 1) != 1) { - saved_errno = errno; - close (fd); - errno = saved_errno; - return -1; - } - ret[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[c % 36]; - } - ret[len] = '\0'; - - if (close (fd) == -1) - return -1; - - return 0; -} - static void ignore_errors (void *ignore, virErrorPtr ignore2) { diff --git a/src/utils.c b/src/utils.c index 358c124..4a9ae96 100644 --- a/src/utils.c +++ b/src/utils.c @@ -22,6 +22,8 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> +#include <errno.h> #include <sys/types.h> #include <sys/wait.h> #include <libintl.h> @@ -125,3 +127,40 @@ guestfs___exit_status_to_string (int status, const char *cmd_name, return buffer; } + +/* Notes: + * + * The 'ret' buffer must have length len+1 in order to store the final + * \0 character. + * + * There is about 5 bits of randomness per output character (so about + * 5*len bits of randomness in the resulting string). + */ +int +guestfs___random_string (char *ret, size_t len) +{ + int fd; + size_t i; + unsigned char c; + int saved_errno; + + fd = open ("/dev/urandom", O_RDONLY|O_CLOEXEC); + if (fd == -1) + return -1; + + for (i = 0; i < len; ++i) { + if (read (fd, &c, 1) != 1) { + saved_errno = errno; + close (fd); + errno = saved_errno; + return -1; + } + ret[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[c % 36]; + } + ret[len] = '\0'; + + if (close (fd) == -1) + return -1; + + return 0; +} -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 40/67] conn: Make sure we display all log messages when qemu goes away.
From: "Richard W.M. Jones" <rjones@redhat.com> If qemu goes away it is (more in theory than in reality) possible for log messages to be lost in the kernel's socket buffer. This turns out to matter more for User-Mode Linux. (cherry picked from commit 236415e33939803565ae88a9222d3bae56ea16f9) --- src/conn-socket.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/conn-socket.c b/src/conn-socket.c index 1ad92cf..2d93f47 100644 --- a/src/conn-socket.c +++ b/src/conn-socket.c @@ -169,12 +169,22 @@ read_data (guestfs_h *g, struct connection *connv, void *bufv, size_t len) if (errno == EINTR || errno == EAGAIN) continue; if (errno == ECONNRESET) /* essentially the same as EOF case */ - return 0; + goto closed; perrorf (g, "read_data: read"); return -1; } - if (n == 0) + if (n == 0) { + closed: + /* Even though qemu has gone away, there could be more log + * messages in the console socket buffer in the kernel. Read + * them out here. + */ + if (g->verbose && conn->console_sock >= 0) { + while (handle_log_message (g, conn) == 1) + ; + } return 0; + } buf += n; len -= n; -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 41/67] launch: direct: Print \n after printing qemu command line.
From: "Richard W.M. Jones" <rjones@redhat.com> This makes it easier to see error messages printed by qemu. (cherry picked from commit 19ee64303e65766b4a1b1ac55adbbb646a1c3500) --- src/launch-direct.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/launch-direct.c b/src/launch-direct.c index 8d05221..ce39e0c 100644 --- a/src/launch-direct.c +++ b/src/launch-direct.c @@ -748,6 +748,8 @@ print_qemu_command_line (guestfs_h *g, char **argv) if (needs_quote) fputc ('\'', stderr); i++; } + + fputc ('\n', stderr); } static void parse_qemu_version (guestfs_h *g); -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 42/67] docs: The old make check-with-appliance/etc rules were renamed.
From: "Richard W.M. Jones" <rjones@redhat.com> This fixes commit 68990840b64491b39ab8da5f1e46367ae5f01594. (cherry picked from commit 4cc99ea2e99c90263aaeeefc8ed952596865abfc) --- src/guestfs.pod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guestfs.pod b/src/guestfs.pod index 740c773..65fb00f 100644 --- a/src/guestfs.pod +++ b/src/guestfs.pod @@ -3916,13 +3916,13 @@ will be run by this rule. Runs a subset of the test suite under valgrind using locally installed libvirt guests (read-only). -=item C<make check-with-appliance> +=item C<make check-direct> Runs all tests using default appliance back-end. This only has any effect if a non-default backend was selected using C<./configure --with-default-backend=...> -=item C<make check-valgrind-with-appliance> +=item C<make check-valgrind-direct> Run a subset of the test suite under valgrind using the default appliance back-end. -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 43/67] tests/md: Fix error path to display the correct output.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 42abbf096932bd1e6c9c1bef64f602a67107d088) --- tests/md/test-list-filesystems.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/md/test-list-filesystems.sh b/tests/md/test-list-filesystems.sh index 642e033..b4e41e9 100755 --- a/tests/md/test-list-filesystems.sh +++ b/tests/md/test-list-filesystems.sh @@ -73,7 +73,7 @@ expected="/dev/sda1: ext3 # Check the output of list-filesystems if [ "$(cat test.output)" != "$expected" ]; then echo "$0: error: output of list-filesystems did not match expected output" - printf "%s\n" "$output" + cat list-fs.output exit 1; fi -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 44/67] tests/regressions: Allow regression test for bug 914931 to be skipped.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 071d7fb6d703a1184af93ff2e9ee1812606bd16e) --- tests/regressions/rhbz914931.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/regressions/rhbz914931.c b/tests/regressions/rhbz914931.c index c33ab3c..faa3dd2 100644 --- a/tests/regressions/rhbz914931.c +++ b/tests/regressions/rhbz914931.c @@ -37,6 +37,15 @@ main (int argc, char *argv[]) { guestfs_h *g; int r; + char *str; + + /* Allow this test to be skipped. */ + str = getenv ("SKIP_TEST_RHBZ914931"); + if (str && STREQ (str, "1")) { + printf ("%s: test skipped because environment variable is set.\n", + program_name); + exit (77); + } g = guestfs_create (); if (!g) { -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 45/67] daemon: If /proc/modules doesn't exist, linuxmodules optgroup is disabled.
From: "Richard W.M. Jones" <rjones@redhat.com> It likely means the kernel was compiled without modules support. (cherry picked from commit 8ad634877cf315288497a8580fb4afc7658deae9) --- daemon/modprobe.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/daemon/modprobe.c b/daemon/modprobe.c index 24d2a5b..0b7896a 100644 --- a/daemon/modprobe.c +++ b/daemon/modprobe.c @@ -20,6 +20,8 @@ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> +#include <errno.h> #include "daemon.h" #include "actions.h" @@ -30,6 +32,13 @@ GUESTFSD_EXT_CMD(str_modprobe, modprobe); int optgroup_linuxmodules_available (void) { + /* If /proc/modules doesn't exist, then the appliance kernel + * probably has modules support compiled out. This means modprobe + * is not supported. + */ + if (access ("/proc/modules", R_OK) == -1 && errno == ENOENT) + return 0; + return prog_exists (str_modprobe); } @@ -37,7 +46,9 @@ int do_modprobe (const char *module) { CLEANUP_FREE char *err = NULL; - int r = command (NULL, &err, str_modprobe, module, NULL); + int r; + + r = command (NULL, &err, str_modprobe, module, NULL); if (r == -1) { reply_with_error ("%s", err); -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 46/67] daemon: md: Whitespace fixes.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 52188f1ea308225ab948141b1f23e0b47f7dcf4f) --- daemon/md.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/daemon/md.c b/daemon/md.c index b302a8c..e9a3f09 100644 --- a/daemon/md.c +++ b/daemon/md.c @@ -202,18 +202,21 @@ do_list_md_devices (void) } for (size_t i = 0; i < mds.gl_pathc; i++) { - size_t len = strlen (mds.gl_pathv[i]) - strlen (PREFIX) - strlen (SUFFIX); + size_t len; + char *dev, *n; + + len = strlen (mds.gl_pathv[i]) - strlen (PREFIX) - strlen (SUFFIX); #define DEV "/dev/md" - char *dev = malloc (strlen(DEV) + len + 1); + dev = malloc (strlen (DEV) + len + 1); if (NULL == dev) { - reply_with_perror("malloc"); + reply_with_perror ("malloc"); goto error; } - char *n = dev; - n = mempcpy(n, DEV, strlen(DEV)); - n = mempcpy(n, &mds.gl_pathv[i][strlen(PREFIX)], len); + n = dev; + n = mempcpy (n, DEV, strlen (DEV)); + n = mempcpy (n, &mds.gl_pathv[i][strlen(PREFIX)], len); *n = '\0'; if (add_string_nodup (&ret, dev) == -1) goto error; -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 47/67] virt-list-filesystems: Fix to use $g->canonical_device_name instead of homebrew function.
From: "Richard W.M. Jones" <rjones@redhat.com> The homebrew function didn't recognize /dev/ubd* device names, and in any case using the API function is shorter and clearer. (cherry picked from commit 42754046269806a6b6385fee0b72115c73461221) --- tools/virt-list-filesystems | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/tools/virt-list-filesystems b/tools/virt-list-filesystems index 197308b..7b472ae 100755 --- a/tools/virt-list-filesystems +++ b/tools/virt-list-filesystems @@ -172,7 +172,7 @@ foreach $dev (sort keys %fses) { $fstype = $fses{$dev}; if ($all || ($fstype ne "swap" && $fstype ne "unknown")) { - print canonicalize($dev); + print $g->canonical_device_name ($dev); if ($long) { print " $fstype"; } @@ -180,18 +180,6 @@ foreach $dev (sort keys %fses) { } } -# The reverse of device name translation, see -# BLOCK DEVICE NAMING in guestfs(3). -sub canonicalize -{ - local $_ = shift; - - if (m{^/dev/[hv]d([a-z]\d)$}) { - return "/dev/sd$1"; - } - $_; -} - =head1 SHELL QUOTING Libvirt guest names can contain arbitrary characters, some of which -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 48/67] Remove contrib/guestfsd-in-wine.sh.
From: "Richard W.M. Jones" <rjones@redhat.com> Added in 2009, unlikely it still works since I doubt it has been compiled since then. (cherry picked from commit 36d29700dcef01d681d41f0b593a16e7814e3ee1) --- contrib/README | 4 -- contrib/guestfsd-in-wine.sh | 117 -------------------------------------------- 2 files changed, 121 deletions(-) delete mode 100755 contrib/guestfsd-in-wine.sh diff --git a/contrib/README b/contrib/README index 081a116..6a7acca 100644 --- a/contrib/README +++ b/contrib/README @@ -5,10 +5,6 @@ autobuild/ The autobuild script that we use to build and test the tarballs on Debian and elsewhere. -guestfsd-in-wine.sh - Run a Windows-compiled guestfsd under Wine. Read the - instructions at the top of this file carefully. - intro/ "Slides" for an intro to libguestfs. This is a short (10-15 min) talk that I give to introduce the main features of libguestfs. The slides are in the form of a complete diff --git a/contrib/guestfsd-in-wine.sh b/contrib/guestfsd-in-wine.sh deleted file mode 100755 index 8cfd3c1..0000000 --- a/contrib/guestfsd-in-wine.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/bin/bash - -# Copyright (C) 2009 Red Hat Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -# INSTRUCTIONS -#---------------------------------------------------------------------- -# -# This is a QEMU wrapper script that allows you to run a -# Windows-compiled guestfsd.exe (daemon) under Wine from a Linux main -# program. You need to read and understand all the instructions below -# before use. -# -# To understand how to compile the daemon for Windows, please read: -# http://www.redhat.com/archives/libguestfs/2009-November/msg00255.html -# -# Adjust the Wine configuration so it can find the libraries, as -# described here: -# http://fedoraproject.org/wiki/MinGW/Configure_wine -# -# On Fedora 13 there is a serious bug in Wine. See: -# https://bugzilla.redhat.com/show_bug.cgi?id=533806#c11 -# -# If necessary, adjust the line 'guestfsd=...' below so it points to -# the correct location of the guestfsd.exe program. You can use an -# absolute path here if you want. -guestfsd=daemon/guestfsd.exe -# -# This script is a QEMU wrapper. It pretends to be qemu as far as -# libguestfs programs are concerned. Read this to understand the -# purpose of QEMU wrappers: -# http://libguestfs.org/guestfs.3.html#qemu_wrappers -# -# With this script, the qemu program is not actually run. Instead we -# pretend to be qemu, parse out the necessary parts of the long -# command line that libguestfs passes to qemu, and run the Windows -# daemon, under Wine, with the right command line. The Windows daemon -# then hopefully connects back to the libguestfs socket, and as far as -# the libguestfs program is concerned, it looks like a full appliance -# is running. -# -# To use this script, you must set the environment variable -# LIBGUESTFS_QEMU=/path/to/contrib/guestfsd-in-wine.sh (ie. the path -# to this script). -# -# You can then run libguestfs test programs, and (hopefully!) they'll -# use the Windows guestfsd.exe, simulating calls using Wine. -# -# For example from the top build directory: -# -# LIBGUESTFS_QEMU=contrib/guestfsd-in-wine.sh ./run ./fish/guestfish -# -# Another suggested environment variable is LIBGUESTFS_DEBUG=1 which -# will give you must more detail about what is going on. Also look at -# the contents of the log file 'guestfsd-in-wine.log' after each run. -# -#---------------------------------------------------------------------- - -# Note that stdout & stderr messages will get eaten by libguestfs -# early on in the process. Therefore write log messages to -# a log file. -exec 5>>guestfsd-in-wine.log -echo "Environment:" >&5 -printenv | grep LIBGUESTFS >&5 -echo "Command line:" >&5 -echo " $@" >&5 - -# We're called several times, first with -help and -version, and we -# have to pretend to be qemu! (At least enough to trick libguestfs). -if [ "$1" = "-help" ]; then - echo -- " -net user " - echo -- " -no-hpet " - echo -- " -rtc-td-hack " - exit 0 -elif [ "$1" = "-version" ]; then - echo -- "0.0.0" - exit 0 -fi - -# The interesting parameter is -append. -append-while [ $# -gt 0 ]; do - if [ $1 = "-append" ]; then - append="$2" - shift - fi - shift -done -echo "Append parameter:" >&5 -echo " $append" >&5 - -# guestfs_vmchannel parameter. -vmchannel_param=$(echo "$append" | grep -Eo 'guestfs_vmchannel=[^[:space:]]+') -echo "Vmchannel parameter:" >&5 -echo " $vmchannel_param" >&5 - -# Port number. -port=$(echo "$vmchannel_param" | grep -Eo '[[:digit:]]+$') -echo "Port number:" >&5 -echo " $vmchannel_param" >&5 - -# Run guestfsd.exe. -echo "Command:" >&5 -echo " $guestfsd -f -v -c tcp:localhost:$port" >&5 -$guestfsd -f -v -c tcp:127.0.0.1:$port -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 49/67] Remove contrib file from EXTRA_DIST.
From: "Richard W.M. Jones" <rjones@redhat.com> This fixes commit 36d29700dcef01d681d41f0b593a16e7814e3ee1. (cherry picked from commit b1a8733511836591bcf8931f25f0fb5cec7924ff) --- Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index a96581d..071fc43 100644 --- a/Makefile.am +++ b/Makefile.am @@ -141,7 +141,6 @@ EXTRA_DIST = \ autogen.sh \ bindtests \ contrib/autobuild/autobuild.sh \ - contrib/guestfsd-in-wine.sh \ contrib/intro/libguestfs-intro.html \ contrib/intro/overview.png \ contrib/intro/overview.svg \ -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 50/67] podwrapper: guestunmount is a libguestfs page, don't link it to he.net.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit bd30d3a61ce9d14f2f744870a5d4ed8167d609e2) --- podwrapper.pl.in | 1 + 1 file changed, 1 insertion(+) diff --git a/podwrapper.pl.in b/podwrapper.pl.in index af21ef0..c14044c 100755 --- a/podwrapper.pl.in +++ b/podwrapper.pl.in @@ -447,6 +447,7 @@ SUBHTML: { return 1 if /^libguestf/; return 1 if /^guestf/; return 1 if /^guestmount/; + return 1 if /^guestunmount/; return 1 if /^hivex/; return 1 if /^febootstrap/; return 1 if /^supermin/; -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 51/67] utils: Move guestfs___drive_name function to the utilities library.
From: "Richard W.M. Jones" <rjones@redhat.com> For some historical reason, it was stuck in src/launch-direct.c and the comment referred to launch-appliance.c! (cherry picked from commit 00cbb5c1854a52a5b4742aa7ca9601a9aaaab529) --- src/guestfs-internal-frontend.h | 1 + src/guestfs-internal.h | 3 --- src/launch-direct.c | 12 ------------ src/utils.c | 23 +++++++++++++++++++++++ 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/guestfs-internal-frontend.h b/src/guestfs-internal-frontend.h index 2070fa8..3e2c433 100644 --- a/src/guestfs-internal-frontend.h +++ b/src/guestfs-internal-frontend.h @@ -98,6 +98,7 @@ extern char *guestfs___concat_strings (char *const *); extern char *guestfs___join_strings (const char *sep, char *const *); extern char *guestfs___exit_status_to_string (int status, const char *cmd_name, char *buffer, size_t buflen); extern int guestfs___random_string (char *ret, size_t len); +extern char *guestfs___drive_name (size_t index, char *ret); /* These functions are used internally by the CLEANUP_* macros. * Don't call them directly. diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index 28e40a2..1c3fea9 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -641,9 +641,6 @@ extern void guestfs___launch_send_progress (guestfs_h *g, int perdozen); extern char *guestfs___appliance_command_line (guestfs_h *g, const char *appliance_dev, int flags); #define APPLIANCE_COMMAND_LINE_IS_TCG 1 -/* launch-appliance.c */ -extern char *guestfs___drive_name (size_t index, char *ret); - /* inspect.c */ extern void guestfs___free_inspect_info (guestfs_h *g); extern char *guestfs___download_to_tmp (guestfs_h *g, struct inspect_fs *fs, const char *filename, const char *basename, uint64_t max_size); diff --git a/src/launch-direct.c b/src/launch-direct.c index ce39e0c..ac4f7fc 100644 --- a/src/launch-direct.c +++ b/src/launch-direct.c @@ -1003,18 +1003,6 @@ qemu_drive_param (guestfs_h *g, const struct drive *drv, size_t index) iface); } -/* https://rwmj.wordpress.com/2011/01/09/how-are-linux-drives-named-beyond-drive-26-devsdz/ */ -char * -guestfs___drive_name (size_t index, char *ret) -{ - if (index >= 26) - ret = guestfs___drive_name (index/26 - 1, ret); - index %= 26; - *ret++ = 'a' + index; - *ret = '\0'; - return ret; -} - static int shutdown_direct (guestfs_h *g, int check_for_errors) { diff --git a/src/utils.c b/src/utils.c index 4a9ae96..f8d2509 100644 --- a/src/utils.c +++ b/src/utils.c @@ -31,6 +31,11 @@ #include "guestfs.h" #include "guestfs-internal-frontend.h" +/* Note that functions in libutils are used by the tools and language + * bindings. Therefore these must not call internal library functions + * such as safe_*, error or perrorf. + */ + void guestfs___free_string_list (char **argv) { @@ -164,3 +169,21 @@ guestfs___random_string (char *ret, size_t len) return 0; } + +/* This turns a drive index (eg. 27) into a drive name (eg. "ab"). + * Drive indexes count from 0. The return buffer has to be large + * enough for the resulting string, and the returned pointer points to + * the *end* of the string. + * + * https://rwmj.wordpress.com/2011/01/09/how-are-linux-drives-named-beyond-drive-26-devsdz/ + */ +char * +guestfs___drive_name (size_t index, char *ret) +{ + if (index >= 26) + ret = guestfs___drive_name (index/26 - 1, ret); + index %= 26; + *ret++ = 'a' + index; + *ret = '\0'; + return ret; +} -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 52/67] cmd: Better type checking in CLEANUP_CMD_CLOSE macro.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit d0a205778698ea3b70623ad73302e739cf631d3c) --- src/command.c | 4 ++-- src/guestfs-internal.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/command.c b/src/command.c index e674cef..7c0da6e 100644 --- a/src/command.c +++ b/src/command.c @@ -674,9 +674,9 @@ guestfs___cmd_close (struct command *cmd) } void -guestfs___cleanup_cmd_close (void *ptr) +guestfs___cleanup_cmd_close (struct command **ptr) { - guestfs___cmd_close (* (struct command **) ptr); + guestfs___cmd_close (*ptr); } /* Deal with buffering stdout for the callback. */ diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index 1c3fea9..1d08375 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -741,6 +741,6 @@ extern void guestfs___cmd_close (struct command *); #else #define CLEANUP_CMD_CLOSE #endif -extern void guestfs___cleanup_cmd_close (void *ptr); +extern void guestfs___cleanup_cmd_close (struct command **); #endif /* GUESTFS_INTERNAL_H_ */ -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 53/67] list-filesystems: Don't fail if there are no filesystems found (RHBZ#995711).
From: "Richard W.M. Jones" <rjones@redhat.com> list-filesystems was returning NULL (but not setting an error) if no filesystems were found. Instead return an empty list. (cherry picked from commit f1d2934216d3fca0501946c8ae0e5c7cd370e6b6) --- src/listfs.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/listfs.c b/src/listfs.c index eb4019d..bd3ee71 100644 --- a/src/listfs.c +++ b/src/listfs.c @@ -46,7 +46,7 @@ char ** guestfs__list_filesystems (guestfs_h *g) { size_t i; - char **ret = NULL; + char **ret; size_t ret_size = 0; const char *lvm2[] = { "lvm2", NULL }; const char *ldm[] = { "ldm", NULL }; @@ -58,6 +58,13 @@ guestfs__list_filesystems (guestfs_h *g) CLEANUP_FREE_STRING_LIST char **ldmvols = NULL; CLEANUP_FREE_STRING_LIST char **ldmparts = NULL; + /* We need to initialize this with an empty list so that if there + * are no filesystems at all, we return an empty list (not NULL). + * See also add_vfs function below. + */ + ret = safe_malloc (g, sizeof (char *)); + ret[0] = NULL; + /* Look to see if any devices directly contain filesystems * (RHBZ#590167). However vfs-type will fail to tell us anything * useful about devices which just contain partitions, so we also -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 54/67] lib: Add stringsbuf mini-library for constructing lists of strings.
From: "Richard W.M. Jones" <rjones@redhat.com> This is modelled on similar code in the daemon that we have used successfully for a long time. (cherry picked from commit 35278e4c186badb9e243628771da4cbd068ffaa0) --- po/POTFILES | 1 + src/Makefile.am | 1 + src/guestfs-internal.h | 24 ++++++++++++++ src/stringsbuf.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 src/stringsbuf.c diff --git a/po/POTFILES b/po/POTFILES index 92b9a18..bc4be6f 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -284,6 +284,7 @@ src/match.c src/osinfo.c src/private-data.c src/proto.c +src/stringsbuf.c src/tmpdirs.c src/utils.c test-tool/test-tool.c diff --git a/src/Makefile.am b/src/Makefile.am index 57cdf34..3facf16 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -116,6 +116,7 @@ libguestfs_la_SOURCES = \ osinfo.c \ private-data.c \ proto.c \ + stringsbuf.c \ tmpdirs.c \ libguestfs.syms diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index 1d08375..8fd6388 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -597,6 +597,30 @@ extern int guestfs___match6 (guestfs_h *g, const char *str, const pcre *re, char #define match3 guestfs___match3 #define match6 guestfs___match6 +/* stringsbuf.c */ +struct stringsbuf { + char **argv; + size_t size; + size_t alloc; +}; +#define DECLARE_STRINGSBUF(v) \ + struct stringsbuf (v) = { .argv = NULL, .size = 0, .alloc = 0 } + +extern void guestfs___add_string_nodup (guestfs_h *g, struct stringsbuf *sb, char *str); +extern void guestfs___add_string (guestfs_h *g, struct stringsbuf *sb, const char *str); +extern void guestfs___add_sprintf (guestfs_h *g, struct stringsbuf *sb, const char *fs, ...) + __attribute__((format (printf,3,4))); +extern void guestfs___end_stringsbuf (guestfs_h *g, struct stringsbuf *sb); + +extern void guestfs___free_stringsbuf (struct stringsbuf *sb); + +#ifdef HAVE_ATTRIBUTE_CLEANUP +#define CLEANUP_FREE_STRINGSBUF __attribute__((cleanup(guestfs___cleanup_free_stringsbuf))) +#else +#define CLEANUP_FREE_STRINGSBUF +#endif +extern void guestfs___cleanup_free_stringsbuf (struct stringsbuf *sb); + /* proto.c */ extern int guestfs___send (guestfs_h *g, int proc_nr, uint64_t progress_hint, uint64_t optargs_bitmask, xdrproc_t xdrp, char *args); extern int guestfs___recv (guestfs_h *g, const char *fn, struct guestfs_message_header *hdr, struct guestfs_message_error *err, xdrproc_t xdrp, char *ret); diff --git a/src/stringsbuf.c b/src/stringsbuf.c new file mode 100644 index 0000000..df1dfd6 --- /dev/null +++ b/src/stringsbuf.c @@ -0,0 +1,88 @@ +/* libguestfs + * Copyright (C) 2013 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Note: Don't confuse this with stringsbuf in the daemon. */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#include "guestfs.h" +#include "guestfs-internal.h" + +void +guestfs___add_string_nodup (guestfs_h *g, struct stringsbuf *sb, char *str) +{ + if (sb->size >= sb->alloc) { + sb->alloc += 64; + sb->argv = safe_realloc (g, sb->argv, sb->alloc * sizeof (char *)); + } + + sb->argv[sb->size] = str; + sb->size++; +} + +void +guestfs___add_string (guestfs_h *g, struct stringsbuf *sb, const char *str) +{ + guestfs___add_string_nodup (g, sb, safe_strdup (g, str)); +} + +void +guestfs___add_sprintf (guestfs_h *g, struct stringsbuf *sb, + const char *fs, ...) +{ + va_list args; + char *str; + int r; + + va_start (args, fs); + r = vasprintf (&str, fs, args); + va_end (args); + if (r == -1) + g->abort_cb (); + + guestfs___add_string_nodup (g, sb, str); +} + +void +guestfs___end_stringsbuf (guestfs_h *g, struct stringsbuf *sb) +{ + guestfs___add_string_nodup (g, sb, NULL); +} + +void +guestfs___free_stringsbuf (struct stringsbuf *sb) +{ + size_t i; + + if (sb->argv) { + for (i = 0; i < sb->size; ++i) + free (sb->argv[i]); + } + free (sb->argv); +} + +void +guestfs___cleanup_free_stringsbuf (struct stringsbuf *sb) +{ + guestfs___free_stringsbuf (sb); +} -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 55/67] lib: Use stringsbuf at various places in the library to simplify the code.
From: "Richard W.M. Jones" <rjones@redhat.com> This is just code refactoring. (cherry picked from commit d2ae632d3bc0a4fcdbf4150a33406d7646f8cdf9) --- src/command.c | 38 ++++++++------------------- src/drives.c | 18 ++++--------- src/inspect.c | 59 +++++++++++------------------------------ src/libvirt-auth.c | 14 +++++----- src/listfs.c | 77 ++++++++++++++++++------------------------------------ 5 files changed, 63 insertions(+), 143 deletions(-) diff --git a/src/command.c b/src/command.c index 7c0da6e..02e5801 100644 --- a/src/command.c +++ b/src/command.c @@ -108,10 +108,7 @@ struct command enum command_style style; union { /* COMMAND_STYLE_EXECV */ - struct { - char **args; - size_t len, alloc; - } argv; + struct stringsbuf argv; /* COMMAND_STYLE_SYSTEM */ struct { char *str; @@ -161,16 +158,7 @@ add_arg_no_strdup (struct command *cmd, char *arg) assert (cmd->style != COMMAND_STYLE_SYSTEM); cmd->style = COMMAND_STYLE_EXECV; - if (cmd->argv.len >= cmd->argv.alloc) { - if (cmd->argv.alloc == 0) - cmd->argv.alloc = 16; - else - cmd->argv.alloc *= 2; - cmd->argv.args = safe_realloc (cmd->g, cmd->argv.args, - cmd->argv.alloc * sizeof (char *)); - } - cmd->argv.args[cmd->argv.len] = arg; - cmd->argv.len++; + guestfs___add_string_nodup (cmd->g, &cmd->argv, arg); } static void @@ -328,7 +316,7 @@ finish_command (struct command *cmd) { switch (cmd->style) { case COMMAND_STYLE_EXECV: - add_arg_no_strdup (cmd, NULL); + guestfs___end_stringsbuf (cmd->g, &cmd->argv); break; case COMMAND_STYLE_SYSTEM: @@ -347,17 +335,17 @@ debug_command (struct command *cmd) switch (cmd->style) { case COMMAND_STYLE_EXECV: - debug (cmd->g, "command: run: %s", cmd->argv.args[0]); - last = cmd->argv.len-1; /* omit final NULL pointer */ + debug (cmd->g, "command: run: %s", cmd->argv.argv[0]); + last = cmd->argv.size-1; /* omit final NULL pointer */ for (i = 1; i < last; ++i) { if (i < last-1 && - cmd->argv.args[i][0] == '-' && cmd->argv.args[i+1][0] != '-') { + cmd->argv.argv[i][0] == '-' && cmd->argv.argv[i+1][0] != '-') { debug (cmd->g, "command: run: \\ %s %s", - cmd->argv.args[i], cmd->argv.args[i+1]); + cmd->argv.argv[i], cmd->argv.argv[i+1]); i++; } else - debug (cmd->g, "command: run: \\ %s", cmd->argv.args[i]); + debug (cmd->g, "command: run: \\ %s", cmd->argv.argv[i]); } break; @@ -472,8 +460,8 @@ run_command (struct command *cmd) /* Run the command. */ switch (cmd->style) { case COMMAND_STYLE_EXECV: - execvp (cmd->argv.args[0], cmd->argv.args); - perror (cmd->argv.args[0]); + execvp (cmd->argv.argv[0], cmd->argv.argv); + perror (cmd->argv.argv[0]); _exit (EXIT_FAILURE); case COMMAND_STYLE_SYSTEM: @@ -638,8 +626,6 @@ guestfs___cmd_run (struct command *cmd) void guestfs___cmd_close (struct command *cmd) { - size_t i; - if (!cmd) return; @@ -649,9 +635,7 @@ guestfs___cmd_close (struct command *cmd) break; case COMMAND_STYLE_EXECV: - for (i = 0; i < cmd->argv.len; ++i) - free (cmd->argv.args[i]); - free (cmd->argv.args); + guestfs___free_stringsbuf (&cmd->argv); break; case COMMAND_STYLE_SYSTEM: diff --git a/src/drives.c b/src/drives.c index cb2360a..df6f7e0 100644 --- a/src/drives.c +++ b/src/drives.c @@ -1167,25 +1167,17 @@ guestfs___rollback_drives (guestfs_h *g, size_t old_i) char ** guestfs__debug_drives (guestfs_h *g) { - size_t i, count; - char **ret; + size_t i; + DECLARE_STRINGSBUF (ret); struct drive *drv; - count = 0; ITER_DRIVES (g, i, drv) { - count++; + guestfs___add_string_nodup (g, &ret, drive_to_string (g, drv)); } - ret = safe_malloc (g, sizeof (char *) * (count + 1)); + guestfs___end_stringsbuf (g, &ret); - count = 0; - ITER_DRIVES (g, i, drv) { - ret[count++] = drive_to_string (g, drv); - } - - ret[count] = NULL; - - return ret; /* caller frees */ + return ret.argv; /* caller frees */ } /* The drive_source struct is also used in the backends, so we diff --git a/src/inspect.c b/src/inspect.c index 6c8dcda..46bb4ab 100644 --- a/src/inspect.c +++ b/src/inspect.c @@ -84,34 +84,21 @@ compare_strings (const void *vp1, const void *vp2) char ** guestfs__inspect_get_roots (guestfs_h *g) { + size_t i; + DECLARE_STRINGSBUF (ret); + /* NB. Doesn't matter if g->nr_fses == 0. We just return an empty * list in this case. */ - - size_t i; - size_t count = 0; - for (i = 0; i < g->nr_fses; ++i) + for (i = 0; i < g->nr_fses; ++i) { if (g->fses[i].is_root) - count++; - - char **ret = calloc (count+1, sizeof (char *)); - if (ret == NULL) { - perrorf (g, "calloc"); - return NULL; - } - - count = 0; - for (i = 0; i < g->nr_fses; ++i) { - if (g->fses[i].is_root) { - ret[count] = safe_strdup (g, g->fses[i].mountable); - count++; - } + guestfs___add_string (g, &ret, g->fses[i].mountable); } - ret[count] = NULL; + guestfs___end_stringsbuf (g, &ret); - qsort (ret, count, sizeof (char *), compare_strings); + qsort (ret.argv, ret.size-1, sizeof (char *), compare_strings); - return ret; + return ret.argv; } char * @@ -392,37 +379,21 @@ guestfs__inspect_get_filesystems (guestfs_h *g, const char *root) char ** guestfs__inspect_get_drive_mappings (guestfs_h *g, const char *root) { - char **ret; - size_t i, count; + DECLARE_STRINGSBUF (ret); + size_t i; struct inspect_fs *fs; fs = guestfs___search_for_root (g, root); if (!fs) return NULL; - /* If no drive mappings, return an empty hashtable. */ - if (!fs->drive_mappings) - count = 0; - else { - for (count = 0; fs->drive_mappings[count] != NULL; count++) - ; + if (fs->drive_mappings) { + for (i = 0; fs->drive_mappings[i] != NULL; ++i) + guestfs___add_string (g, &ret, fs->drive_mappings[i]); } - ret = calloc (count+1, sizeof (char *)); - if (ret == NULL) { - perrorf (g, "calloc"); - return NULL; - } - - /* We need to make a deep copy of the hashtable since the caller - * will free it. - */ - for (i = 0; i < count; ++i) - ret[i] = safe_strdup (g, fs->drive_mappings[i]); - - ret[count] = NULL; - - return ret; + guestfs___end_stringsbuf (g, &ret); + return ret.argv; } char * diff --git a/src/libvirt-auth.c b/src/libvirt-auth.c index cd90378..fb18f8a 100644 --- a/src/libvirt-auth.c +++ b/src/libvirt-auth.c @@ -215,20 +215,18 @@ guestfs___open_libvirt_connection (guestfs_h *g, const char *uri, char ** guestfs__get_libvirt_requested_credentials (guestfs_h *g) { - char **ret; + DECLARE_STRINGSBUF (ret); size_t i; CHECK_IN_EVENT_HANDLER (NULL); /* Convert the requested_credentials types to a list of strings. */ - ret = safe_malloc (g, sizeof (char *) * (g->nr_requested_credentials+1)); - for (i = 0; i < g->nr_requested_credentials; ++i) { - ret[i] = safe_strdup (g, - get_string_of_credtype (g->requested_credentials[i].type)); - } - ret[i] = NULL; + for (i = 0; i < g->nr_requested_credentials; ++i) + guestfs___add_string (g, &ret, + get_string_of_credtype (g->requested_credentials[i].type)); + guestfs___end_stringsbuf (g, &ret); - return ret; /* caller frees */ + return ret.argv; /* caller frees */ } char * diff --git a/src/listfs.c b/src/listfs.c index bd3ee71..9102c55 100644 --- a/src/listfs.c +++ b/src/listfs.c @@ -39,15 +39,14 @@ */ static void remove_from_list (char **list, const char *item); -static void check_with_vfs_type (guestfs_h *g, const char *dev, char ***ret, size_t *ret_size); +static void check_with_vfs_type (guestfs_h *g, const char *dev, struct stringsbuf *sb); static int is_mbr_partition_type_42 (guestfs_h *g, const char *partition); char ** guestfs__list_filesystems (guestfs_h *g) { size_t i; - char **ret; - size_t ret_size = 0; + DECLARE_STRINGSBUF (ret); const char *lvm2[] = { "lvm2", NULL }; const char *ldm[] = { "ldm", NULL }; @@ -58,13 +57,6 @@ guestfs__list_filesystems (guestfs_h *g) CLEANUP_FREE_STRING_LIST char **ldmvols = NULL; CLEANUP_FREE_STRING_LIST char **ldmparts = NULL; - /* We need to initialize this with an empty list so that if there - * are no filesystems at all, we return an empty list (not NULL). - * See also add_vfs function below. - */ - ret = safe_malloc (g, sizeof (char *)); - ret[0] = NULL; - /* Look to see if any devices directly contain filesystems * (RHBZ#590167). However vfs-type will fail to tell us anything * useful about devices which just contain partitions, so we also @@ -86,17 +78,17 @@ guestfs__list_filesystems (guestfs_h *g) /* Use vfs-type to check for filesystems on devices. */ for (i = 0; devices[i] != NULL; ++i) - check_with_vfs_type (g, devices[i], &ret, &ret_size); + check_with_vfs_type (g, devices[i], &ret); /* Use vfs-type to check for filesystems on partitions. */ for (i = 0; partitions[i] != NULL; ++i) { if (! is_mbr_partition_type_42 (g, partitions[i])) - check_with_vfs_type (g, partitions[i], &ret, &ret_size); + check_with_vfs_type (g, partitions[i], &ret); } /* Use vfs-type to check for filesystems on md devices. */ for (i = 0; mds[i] != NULL; ++i) - check_with_vfs_type (g, mds[i], &ret, &ret_size); + check_with_vfs_type (g, mds[i], &ret); if (guestfs_feature_available (g, (char **) lvm2)) { /* Use vfs-type to check for filesystems on LVs. */ @@ -104,7 +96,7 @@ guestfs__list_filesystems (guestfs_h *g) if (lvs == NULL) goto error; for (i = 0; lvs[i] != NULL; ++i) - check_with_vfs_type (g, lvs[i], &ret, &ret_size); + check_with_vfs_type (g, lvs[i], &ret); } if (guestfs_feature_available (g, (char **) ldm)) { @@ -113,19 +105,21 @@ guestfs__list_filesystems (guestfs_h *g) if (ldmvols == NULL) goto error; for (i = 0; ldmvols[i] != NULL; ++i) - check_with_vfs_type (g, ldmvols[i], &ret, &ret_size); + check_with_vfs_type (g, ldmvols[i], &ret); ldmparts = guestfs_list_ldm_partitions (g); if (ldmparts == NULL) goto error; for (i = 0; ldmparts[i] != NULL; ++i) - check_with_vfs_type (g, ldmparts[i], &ret, &ret_size); + check_with_vfs_type (g, ldmparts[i], &ret); } - return ret; + /* Finish off the list and return it. */ + guestfs___end_stringsbuf (g, &ret); + return ret.argv; error: - if (ret) guestfs___free_string_list (ret); + guestfs___free_stringsbuf (&ret); return NULL; } @@ -145,50 +139,34 @@ remove_from_list (char **list, const char *item) } } -static void -add_vfs (guestfs_h *g, char *mountable, char *vfs_type, - char ***ret, size_t *ret_size) -{ - /* Extend the return array. */ - size_t i = *ret_size; - *ret_size += 2; - *ret = safe_realloc (g, *ret, (*ret_size + 1) * sizeof (char *)); - - (*ret)[i] = mountable; - (*ret)[i+1] = vfs_type; - (*ret)[i+2] = NULL; -} - /* Use vfs-type to look for a filesystem of some sort on 'dev'. * Apart from some types which we ignore, add the result to the * 'ret' string list. */ static void -check_with_vfs_type (guestfs_h *g, const char *device, - char ***ret, size_t *ret_size) +check_with_vfs_type (guestfs_h *g, const char *device, struct stringsbuf *sb) { - char *v; - char *vfs_type; + const char *v; + CLEANUP_FREE char *vfs_type = NULL; guestfs_push_error_handler (g, NULL, NULL); vfs_type = guestfs_vfs_type (g, device); guestfs_pop_error_handler (g); if (!vfs_type) - v = safe_strdup (g, "unknown"); - else if (STREQ (vfs_type, "")) { - v = safe_strdup (g, "unknown"); - free (vfs_type); - } + v = "unknown"; + else if (STREQ (vfs_type, "")) + v = "unknown"; else if (STREQ (vfs_type, "btrfs")) { CLEANUP_FREE_BTRFSSUBVOLUME_LIST struct guestfs_btrfssubvolume_list *vols guestfs_btrfs_subvolume_list (g, device); for (size_t i = 0; i < vols->len; i++) { struct guestfs_btrfssubvolume *this = &vols->val[i]; - char *mountable = safe_asprintf (g, "btrfsvol:%s/%s", - device, this->btrfssubvolume_path); - add_vfs (g, mountable, safe_strdup (g, "btrfs"), ret, ret_size); + guestfs___add_sprintf (g, sb, + "btrfsvol:%s/%s", + device, this->btrfssubvolume_path); + guestfs___add_string (g, sb, "btrfs"); } v = vfs_type; @@ -199,21 +177,18 @@ check_with_vfs_type (guestfs_h *g, const char *device, * importantly "LVM2_member" which is a PV. */ size_t n = strlen (vfs_type); - if (n >= 7 && STREQ (&vfs_type[n-7], "_member")) { - free (vfs_type); + if (n >= 7 && STREQ (&vfs_type[n-7], "_member")) return; - } /* Ignore LUKS-encrypted partitions. These are also containers. */ - if (STREQ (vfs_type, "crypto_LUKS")) { - free (vfs_type); + if (STREQ (vfs_type, "crypto_LUKS")) return; - } v = vfs_type; } - add_vfs (g, safe_strdup (g, device), v, ret, ret_size); + guestfs___add_string (g, sb, device); + guestfs___add_string (g, sb, v); } /* We should ignore partitions that have MBR type byte 0x42, because -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 56/67] cleanups: Use correct types for some cleanup functions.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit f68d5ee16c88df4a3fe2233ba948fb4780fa2a09) --- src/cleanup.c | 8 ++++---- src/guestfs-internal-frontend.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cleanup.c b/src/cleanup.c index 13018f0..86bb547 100644 --- a/src/cleanup.c +++ b/src/cleanup.c @@ -44,9 +44,9 @@ guestfs___cleanup_free (void *ptr) } void -guestfs___cleanup_free_string_list (void *ptr) +guestfs___cleanup_free_string_list (char ***ptr) { - guestfs___free_string_list (* (char ***) ptr); + guestfs___free_string_list (*ptr); } void @@ -59,9 +59,9 @@ guestfs___cleanup_hash_free (void *ptr) } void -guestfs___cleanup_unlink_free (void *ptr) +guestfs___cleanup_unlink_free (char **ptr) { - char *filename = * (char **) ptr; + char *filename = *ptr; if (filename) { unlink (filename); diff --git a/src/guestfs-internal-frontend.h b/src/guestfs-internal-frontend.h index 3e2c433..d8da33e 100644 --- a/src/guestfs-internal-frontend.h +++ b/src/guestfs-internal-frontend.h @@ -104,9 +104,9 @@ extern char *guestfs___drive_name (size_t index, char *ret); * Don't call them directly. */ extern void guestfs___cleanup_free (void *ptr); -extern void guestfs___cleanup_free_string_list (void *ptr); +extern void guestfs___cleanup_free_string_list (char ***ptr); extern void guestfs___cleanup_hash_free (void *ptr); -extern void guestfs___cleanup_unlink_free (void *ptr); +extern void guestfs___cleanup_unlink_free (char **ptr); extern void guestfs___cleanup_xmlBufferFree (void *ptr); extern void guestfs___cleanup_xmlFreeDoc (void *ptr); extern void guestfs___cleanup_xmlFreeURI (void *ptr); -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 57/67] FAQ: Delete section about Ubuntu 10.04.
From: "Richard W.M. Jones" <rjones@redhat.com> The link was broken, and we don't support Ubuntu 10.04 (maybe the 'oldlinux' branch does). (cherry picked from commit 937a9a35320edb781721de5537d750c004872c98) --- examples/guestfs-faq.pod | 5 ----- 1 file changed, 5 deletions(-) diff --git a/examples/guestfs-faq.pod b/examples/guestfs-faq.pod index c563569..2171b81 100644 --- a/examples/guestfs-faq.pod +++ b/examples/guestfs-faq.pod @@ -322,11 +322,6 @@ So every user should do this: =over 4 -=item Ubuntu 10.04 - -See: -L<http://libguestfs.org/download/binaries/ubuntu1004-packages/> - =item Ubuntu 12.04 libguestfs in this version of Ubuntu works, but you need to update -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 58/67] FAQ: Move #debug anchor back to the right place.
From: "Richard W.M. Jones" <rjones@redhat.com> This was accidentally moved by this commit: commit b8b5ed65c26dd19a0bc9f8282a50c6dff90c456a Author: Richard W.M. Jones <rjones@redhat.com> Date: Wed May 23 11:46:23 2012 +0100 FAQ: Add section about using libguestfs in closed source programs. (cherry picked from commit 0a484e868f5f0b7f6245a80f67e09c8210721dac) --- examples/guestfs-faq.pod | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/guestfs-faq.pod b/examples/guestfs-faq.pod index 2171b81..cf2f67f 100644 --- a/examples/guestfs-faq.pod +++ b/examples/guestfs-faq.pod @@ -735,13 +735,6 @@ Once you're familiar with the API overview, you should look at this list of starting points for other language bindings: L<guestfs(3)/USING LIBGUESTFS WITH OTHER PROGRAMMING LANGUAGES>. -=begin html - -<!-- old anchor for the next section --> -<a name="debug"/> - -=end html - =head2 Can I use libguestfs in my proprietary / closed source / commercial program? @@ -753,6 +746,13 @@ In the source tree the license is in the file C<COPYING.LIB> (LGPLv2+ for the library and bindings) and C<COPYING> (GPLv2+ for the standalone programs). +=begin html + +<!-- old anchor for the next section --> +<a name="debug"/> + +=end html + =head1 DEBUGGING LIBGUESTFS B<In summary:> enable debugging by setting these two environment -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:04 UTC
[Libguestfs] [PATCH 59/67] FAQ: Replace the debugging section (again) with a checklist of information we need to start to fix bugs.
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit abc59d776a12fb96de6ff927054f3db2a9ed4fc4) --- examples/guestfs-faq.pod | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/examples/guestfs-faq.pod b/examples/guestfs-faq.pod index cf2f67f..071fd0f 100644 --- a/examples/guestfs-faq.pod +++ b/examples/guestfs-faq.pod @@ -755,26 +755,47 @@ standalone programs). =head1 DEBUGGING LIBGUESTFS -B<In summary:> enable debugging by setting these two environment -variables before running the program: +=head2 Help, it's not working! + +Please supply all the information in this checklist, in an +email sent to C<libguestfs> @ C<redhat.com>: + +=over 4 + +=item * + +What are you trying to achieve? + +=item * + +What exact commands did you run? + +=item * + +What was the precise error / output of these commands? + +=item * + +Enable debugging, run the commands again, and capture the B<complete> +output. B<Do not edit the output.> export LIBGUESTFS_DEBUG=1 export LIBGUESTFS_TRACE=1 -This will produce a lot of output. Put the B<complete> output in an -email message or pastebin and send it -L<to the mailing list|/What mailing lists or chat rooms are available?>. -B<Do not edit the output.> +=item * Include the version of libguestfs, the operating system version, and how you installed libguestfs (eg. from source, C<yum install>, etc.) -If no libguestfs program works, run the program below and paste the -B<complete, unedited> output into an email or pastebin and send it to -the mailing list: +=item * + +If no libguestfs program seems to work at all, run the program below +and paste the B<complete, unedited> output into the email: libguestfs-test-tool +=back + =head2 How do I debug when using any libguestfs program or tool (eg. virt-v2v or virt-df)? -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:05 UTC
[Libguestfs] [PATCH 60/67] Fix to src/proto.c in libguestfs so it will compile with portablexdr under mingw.
From: Or Goshen <oberonc@gmail.com> (cherry picked from commit 18b40a88925df737d3552fa646d35a185feb6c62) --- src/proto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/proto.c b/src/proto.c index fdd7ecc..315d945 100644 --- a/src/proto.c +++ b/src/proto.c @@ -213,7 +213,7 @@ guestfs___send (guestfs_h *g, int proc_nr, { struct guestfs_message_header hdr; XDR xdr; - u_int32_t len; + uint32_t len; int serial = g->msg_next_serial++; ssize_t r; CLEANUP_FREE char *msg_out = NULL; @@ -411,7 +411,7 @@ send_file_complete (guestfs_h *g) static int send_file_chunk (guestfs_h *g, int cancel, const char *buf, size_t buflen) { - u_int32_t len; + uint32_t len; ssize_t r; guestfs_chunk chunk; XDR xdr; -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:05 UTC
[Libguestfs] [PATCH 61/67] launch: direct: Don't try to wait for qemu if parent process forked (RHBZ#998482).
From: "Richard W.M. Jones" <rjones@redhat.com> When using guestfish --remote, libguestfs is not the parent of qemu, so waitpid is expected to return -ECHILD. And indeed guestfish --remote would print a bogus error message in this case: libguestfs: error: waitpid (qemu): No child processes If the parent process forked into the background, then it should have called 'set_recovery_proc 0' so we can use this to determine if we need to wait for qemu. Thanks: Kazuya Saito for reporting and identifying the issue. (cherry picked from commit a843b5e5e32c151e7b0c74bb4f7be1030f9ac85b) --- src/launch-direct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/launch-direct.c b/src/launch-direct.c index ac4f7fc..f1edb53 100644 --- a/src/launch-direct.c +++ b/src/launch-direct.c @@ -1017,7 +1017,7 @@ shutdown_direct (guestfs_h *g, int check_for_errors) if (g->direct.recoverypid > 0) kill (g->direct.recoverypid, 9); /* Wait for subprocess(es) to exit. */ - if (g->direct.pid > 0) { + if (g->recovery_proc /* RHBZ#998482 */ && g->direct.pid > 0) { if (waitpid (g->direct.pid, &status, 0) == -1) { perrorf (g, "waitpid (qemu)"); ret = -1; -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:05 UTC
[Libguestfs] [PATCH 62/67] fish: Document that guestfish --remote --add won't work as expected (RHBZ#998513).
From: "Richard W.M. Jones" <rjones@redhat.com> (cherry picked from commit 7e396954611d827dc236a114ed22a781687c002d) --- fish/guestfish.pod | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fish/guestfish.pod b/fish/guestfish.pod index 772c6f9..06663ac 100644 --- a/fish/guestfish.pod +++ b/fish/guestfish.pod @@ -1039,6 +1039,24 @@ and cleans up guestfish when the script exits: # ... +=head2 REMOTE CONTROL DOES NOT WORK WITH I<-a> ETC. OPTIONS + +Options such as I<-a>, I<--add>, I<-N>, I<--new> etc don't interact +properly with remote support. They are processed locally, and not +sent through to the remote guestfish. In particular this won't do +what you expect: + + guestfish --remote --add disk.img + +Don't use these options. Use the equivalent commands instead, eg: + + guestfish --remote add-drive disk.img + +or: + + guestfish --remote + ><fs> add disk.img + =head2 REMOTE CONTROL RUN COMMAND HANGING Using the C<run> (or C<launch>) command remotely in a command -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:05 UTC
[Libguestfs] [PATCH 63/67] tests: change noinst to check
From: Olaf Hering <olaf@aepfle.de> This change avoids the hard requirement for qemu-tools during package build. Signed-off-by: Olaf Hering <olaf@aepfle.de> (cherry picked from commit cb7b1c56b7cf447dd9f2ea4dde5cf65e9f9f8cf8) --- tests/data/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 03315de..5aa3219 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -82,7 +82,7 @@ images_files_build = \ initrd-x86_64.img.gz \ test-grep.txt.gz -noinst_DATA = $(images_files_build) test.iso +check_DATA = $(images_files_build) test.iso CLEANFILES = $(images_files_build) test.iso -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:05 UTC
[Libguestfs] [PATCH 64/67] daemon: hivex: Define empty hivex_finalize function in case !HAVE_HIVEX.
From: "Richard W.M. Jones" <rjones@redhat.com> Thanks: Olaf Hering (see previous commit). (cherry picked from commit d188594b11f2a16fe72b963a55edf41d4aa2e3aa) --- daemon/hivex.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/daemon/hivex.c b/daemon/hivex.c index ce6164e..b47329e 100644 --- a/daemon/hivex.c +++ b/daemon/hivex.c @@ -417,4 +417,9 @@ do_hivex_node_set_value (int64_t nodeh, OPTGROUP_HIVEX_NOT_AVAILABLE +void +hivex_finalize (void) +{ +} + #endif /* !HAVE_HIVEX */ -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:05 UTC
[Libguestfs] [PATCH 65/67] daemon: sh: Fix missing initializer which caused segfault (RHBZ#1000121).
From: "Richard W.M. Jones" <rjones@redhat.com> Thanks: Olaf Hering. (cherry picked from commit fc2947b1125aa34b5f04efd2d39cb82b2ebba586) --- daemon/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/command.c b/daemon/command.c index db82b52..99a58c1 100644 --- a/daemon/command.c +++ b/daemon/command.c @@ -41,7 +41,7 @@ char * do_command (char *const *argv) { char *out; - CLEANUP_FREE char *err; + CLEANUP_FREE char *err = NULL; int r; CLEANUP_FREE char *sysroot_dev = NULL, *sysroot_dev_pts = NULL, *sysroot_proc = NULL, *sysroot_sys = NULL; -- 1.8.3.1
Richard W.M. Jones
2013-Aug-24 11:05 UTC
[Libguestfs] [PATCH 66/67] Initialize CLEANUP_* stack variables with NULL in various places.
From: "Richard W.M. Jones" <rjones@redhat.com> Code like: CLEANUP_FREE char *buf; /* some code which might return early */ buf = malloc (10); is a potential bug because the free (*buf) might be called when buf is an uninitialized pointer. Initialize buf = NULL to avoid this. Several of these are bugs, most are not bugs (because there is no early return statement before the variable gets initialized). However the compiler can elide the initialization, and even if it does not the performance "penalty" is miniscule, and correctness is better. (cherry picked from commit b1919066ca3d83f11b72d38d64f25739bd0ff67e) --- cat/virt-filesystems.c | 2 +- daemon/augeas.c | 2 +- daemon/debug.c | 6 +++--- daemon/ext2.c | 4 ++-- daemon/file.c | 2 +- daemon/guestfsd.c | 4 ++-- daemon/initrd.c | 2 +- daemon/ls.c | 2 +- daemon/xattr.c | 2 +- fish/copy.c | 2 +- fish/inspect.c | 2 +- src/inspect-fs-unix.c | 2 +- src/inspect-fs-windows.c | 2 +- src/launch-libvirt.c | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) diff --git a/cat/virt-filesystems.c b/cat/virt-filesystems.c index 6e86bfc..434a7b4 100644 --- a/cat/virt-filesystems.c +++ b/cat/virt-filesystems.c @@ -688,7 +688,7 @@ do_output_blockdevs (void) for (i = 0; devices[i] != NULL; ++i) { int64_t size = -1; CLEANUP_FREE_STRING_LIST char **parents = NULL; - CLEANUP_FREE char *dev; + CLEANUP_FREE char *dev = NULL; dev = guestfs_canonical_device_name (g, devices[i]); if (!dev) diff --git a/daemon/augeas.c b/daemon/augeas.c index b2d1eb2..83e2739 100644 --- a/daemon/augeas.c +++ b/daemon/augeas.c @@ -373,7 +373,7 @@ do_aug_ls (const char *path) if (STREQ (path, "/")) matches = do_aug_match ("/*"); else { - CLEANUP_FREE char *buf; + CLEANUP_FREE char *buf = NULL; len += 3; /* / * + terminating \0 */ buf = malloc (len); diff --git a/daemon/debug.c b/daemon/debug.c index 8d10316..1ab76b0 100644 --- a/daemon/debug.c +++ b/daemon/debug.c @@ -321,7 +321,7 @@ debug_binaries (const char *subcmd, size_t argc, char *const *const argv) { int r; char *out; - CLEANUP_FREE char *err; + CLEANUP_FREE char *err = NULL; char cmd[256]; snprintf (cmd, sizeof (cmd), @@ -391,7 +391,7 @@ debug_ls (const char *subcmd, size_t argc, char *const *const argv) size_t i; int r; char *out; - CLEANUP_FREE char *err; + CLEANUP_FREE char *err = NULL; cargv[0] = str_ls; cargv[1] = "-a"; @@ -418,7 +418,7 @@ debug_ll (const char *subcmd, size_t argc, char *const *const argv) size_t i; int r; char *out; - CLEANUP_FREE char *err; + CLEANUP_FREE char *err = NULL; cargv[0] = str_ls; cargv[1] = "-la"; diff --git a/daemon/ext2.c b/daemon/ext2.c index d1ce020..4fb6ee2 100644 --- a/daemon/ext2.c +++ b/daemon/ext2.c @@ -643,9 +643,9 @@ char * do_get_e2attrs (const char *filename) { int r; - CLEANUP_FREE char *buf; + CLEANUP_FREE char *buf = NULL; char *out; - CLEANUP_FREE char *err; + CLEANUP_FREE char *err = NULL; size_t i, j; buf = sysroot_path (filename); diff --git a/daemon/file.c b/daemon/file.c index 9c29ec3..7f39e62 100644 --- a/daemon/file.c +++ b/daemon/file.c @@ -492,7 +492,7 @@ do_file (const char *path) const char *flags = is_dev ? "-zbsL" : "-zb"; char *out; - CLEANUP_FREE char *err; + CLEANUP_FREE char *err = NULL; int r = command (&out, &err, str_file, flags, path, NULL); if (r == -1) { diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index 343c489..74228e5 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -664,7 +664,7 @@ commandf (char **stdoutput, char **stderror, int flags, const char *name, ...) { va_list args; /* NB: Mustn't free the strings which are on the stack. */ - CLEANUP_FREE const char **argv; + CLEANUP_FREE const char **argv = NULL; char *s; size_t i; int r; @@ -708,7 +708,7 @@ int commandrf (char **stdoutput, char **stderror, int flags, const char *name, ...) { va_list args; - CLEANUP_FREE const char **argv; + CLEANUP_FREE const char **argv = NULL; char *s; int i, r; diff --git a/daemon/initrd.c b/daemon/initrd.c index e26d984..ea34000 100644 --- a/daemon/initrd.c +++ b/daemon/initrd.c @@ -86,7 +86,7 @@ char * do_initrd_cat (const char *path, const char *filename, size_t *size_r) { char tmpdir[] = "/tmp/initrd-cat-XXXXXX"; - CLEANUP_FREE char *cmd; + CLEANUP_FREE char *cmd = NULL; struct stat statbuf; int fd, r; char *ret = NULL; diff --git a/daemon/ls.c b/daemon/ls.c index 96e7bf2..d3689cd 100644 --- a/daemon/ls.c +++ b/daemon/ls.c @@ -131,7 +131,7 @@ do_llz (const char *path) int r; char *out; CLEANUP_FREE char *err = NULL; - CLEANUP_FREE char *spath; + CLEANUP_FREE char *spath = NULL; spath = sysroot_path (path); if (!spath) { diff --git a/daemon/xattr.c b/daemon/xattr.c index b0a818b..16a01a6 100644 --- a/daemon/xattr.c +++ b/daemon/xattr.c @@ -280,7 +280,7 @@ do_internal_lxattrlist (const char *path, char *const *names) for (k = 0; names[k] != NULL; ++k) { void *newptr; - CLEANUP_FREE char *pathname; + CLEANUP_FREE char *pathname = NULL; /* Be careful in this loop about which errors cause the whole call * to abort, and which errors allow us to continue processing diff --git a/fish/copy.c b/fish/copy.c index 477bfe9..07a36a2 100644 --- a/fish/copy.c +++ b/fish/copy.c @@ -217,7 +217,7 @@ run_copy_out (const char *cmd, size_t argc, char *argv[]) /* Download each remote one at a time using tar-out. */ int i, r; for (i = 0; i < nr_remotes; ++i) { - CLEANUP_FREE char *remote; + CLEANUP_FREE char *remote = NULL; /* Allow win:... prefix on remotes. */ remote = win_prefix (argv[i]); diff --git a/fish/inspect.c b/fish/inspect.c index 12ceaa7..801d867 100644 --- a/fish/inspect.c +++ b/fish/inspect.c @@ -161,7 +161,7 @@ print_inspect_prompt (void) { size_t i; CLEANUP_FREE char *name = NULL; - CLEANUP_FREE_STRING_LIST char **mountpoints; + CLEANUP_FREE_STRING_LIST char **mountpoints = NULL; name = guestfs_inspect_get_product_name (g, root); if (name && STRNEQ (name, "unknown")) diff --git a/src/inspect-fs-unix.c b/src/inspect-fs-unix.c index 3f06310..5c517e1 100644 --- a/src/inspect-fs-unix.c +++ b/src/inspect-fs-unix.c @@ -892,7 +892,7 @@ check_fstab (guestfs_h *g, struct inspect_fs *fs) CLEANUP_FREE_STRING_LIST char **entries = NULL; char **entry; char augpath[256]; - CLEANUP_HASH_FREE Hash_table *md_map; + CLEANUP_HASH_FREE Hash_table *md_map = NULL; /* Generate a map of MD device paths listed in /etc/mdadm.conf to MD device * paths in the guestfs appliance */ diff --git a/src/inspect-fs-windows.c b/src/inspect-fs-windows.c index ba062eb..4f49112 100644 --- a/src/inspect-fs-windows.c +++ b/src/inspect-fs-windows.c @@ -480,7 +480,7 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs) if (STRCASEEQLEN (key, "\\DosDevices\\", 12) && c_isalpha (key[12]) && key[13] == ':') { /* Get the binary value. Is it a fixed disk? */ - CLEANUP_FREE char *blob; + CLEANUP_FREE char *blob = NULL; char *device; size_t len; int64_t type; diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c index de725e0..6fcb880 100644 --- a/src/launch-libvirt.c +++ b/src/launch-libvirt.c @@ -1602,7 +1602,7 @@ make_drive_priv (guestfs_h *g, struct drive *drv, drv_priv->format = drv->format ? safe_strdup (g, drv->format) : NULL; } else { - CLEANUP_FREE char *qemu_device; + CLEANUP_FREE char *qemu_device = NULL; drv_priv->real_src.protocol = drive_protocol_file; qemu_device = guestfs___drive_source_qemu_param (g, &drv->src); -- 1.8.3.1
From: "Richard W.M. Jones" <rjones@redhat.com> --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 61cae54..f48f3a3 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ # freeform string. m4_define([libguestfs_major], [1]) m4_define([libguestfs_minor], [22]) -m4_define([libguestfs_release], [5]) +m4_define([libguestfs_release], [6]) AC_INIT([libguestfs],libguestfs_major.libguestfs_minor.libguestfs_release) AC_CONFIG_AUX_DIR([build-aux]) -- 1.8.3.1