[PATCH 0/3] generator: Allow returned strings to be annotated as devices.
by Richard W.M. Jones
If we want to permit more than 255 drives to be added, then we will
have to add the disks to the same virtio-scsi target using different
unit (LUN) numbers.
Unfortunately SCSI LUN enumeration in the Linux is not deterministic
(eg. two disks with target=0, lun=[0,1] can be enumerated as /dev/sda
or /dev/sdb randomly). Dealing with that will require some very
complex device name translation on the way in and out of the
appliance.
This commit does _not_ do any of that, but it lays the groundwork so
we could do that in future if the need arises.
Rich.
7 years, 7 months
[PATCH] v2v: bootloaders: search grub config for all distributions
by Pavel Butsykin
This patch improves the search of grub config on EFI partition. This
means that the config will be found not only for rhel but also for
many other distributions. Tests were performed on the following
distributions: centos, fedora, ubuntu, suse. In all cases, the config
path was /boot/efi/EFI/*distname*/grub.cfg
The main purpose of the patch is to improve support for converting of
vm with UEFI for most distributions. Unfortunately this patch does not
solve the problem for all distributions, for example Debian does not
store grub config on the EFI partition, therefore for such
distributions another solution is necessary.
Signed-off-by: Pavel Butsykin <pbutsykin(a)virtuozzo.com>
---
v2v/linux_bootloaders.ml | 80 ++++++++++++++++++++++++++++++------------------
1 file changed, 50 insertions(+), 30 deletions(-)
diff --git a/v2v/linux_bootloaders.ml b/v2v/linux_bootloaders.ml
index cad72a829..33a6dc4e9 100644
--- a/v2v/linux_bootloaders.ml
+++ b/v2v/linux_bootloaders.ml
@@ -49,6 +49,13 @@ let remove_hd_prefix path =
(* Grub1 (AKA grub-legacy) representation. *)
class bootloader_grub1 (g : G.guestfs) inspect grub_config =
+ let () =
+ (* Apply the "grub" lens if it is not handling the file
+ * already -- Augeas < 1.7.0 will error out otherwise.
+ *)
+ if g#aug_ls ("/files" ^ grub_config) = [||] then
+ g#aug_transform "grub" grub_config in
+
(* Grub prefix? Usually "/boot". *)
let grub_prefix =
let mounts = g#inspect_get_mountpoints inspect.i_root in
@@ -335,33 +342,46 @@ object (self)
end
let detect_bootloader (g : G.guestfs) inspect =
- let config_file, typ =
- let locations = [
- "/boot/grub2/grub.cfg", Grub2;
- "/boot/grub/grub.cfg", Grub2;
- "/boot/grub/menu.lst", Grub1;
- "/boot/grub/grub.conf", Grub1;
- ] in
- let locations =
- match inspect.i_firmware with
- | I_UEFI _ ->
- [
- "/boot/efi/EFI/redhat/grub.cfg", Grub2;
- "/boot/efi/EFI/redhat/grub.conf", Grub1;
- ] @ locations
- | I_BIOS -> locations in
- try
- List.find (
- fun (config_file, _) -> g#is_file ~followsymlinks:true config_file
- ) locations
- with
- Not_found ->
- error (f_"no bootloader detected") in
-
- match typ with
- | Grub1 ->
- if config_file = "/boot/efi/EFI/redhat/grub.conf" then
- g#aug_transform "grub" "/boot/efi/EFI/redhat/grub.conf";
-
- new bootloader_grub1 g inspect config_file
- | Grub2 -> new bootloader_grub2 g config_file
+ (* Where to start searching for bootloaders. *)
+ let mp =
+ match inspect.i_firmware with
+ | I_BIOS -> "/boot"
+ | I_UEFI _ -> "/boot/efi/EFI" in
+
+ (* Find all paths below the mountpoint, then filter them to find
+ * the grub config file.
+ *)
+ let paths =
+ try List.map ((^) mp) (Array.to_list (g#find mp))
+ with G.Error msg ->
+ error (f_"could not find bootloader mount point (%s): %s") mp msg in
+
+ (* We can determine if the bootloader config file is grub 1 or
+ * grub 2 just by looking at the filename.
+ *)
+ let bootloader_type_of_filename path =
+ match last_part_of path '/' with
+ | Some "grub.cfg" -> Some Grub2
+ | Some ("grub.conf" | "menu.lst") -> Some Grub1
+ | Some _
+ | None -> None
+ in
+
+ let grub_config, typ =
+ let rec loop = function
+ | [] -> error (f_"no bootloader detected")
+ | path :: paths ->
+ match bootloader_type_of_filename path with
+ | None -> loop paths
+ | Some typ ->
+ if not (g#is_file ~followsymlinks:true path) then loop paths
+ else path, typ
+ in
+ loop paths in
+
+ let bl =
+ (match typ with
+ | Grub1 -> new bootloader_grub1 g inspect grub_config
+ | Grub2 -> new bootloader_grub2 g grub_config) in
+ debug "detected bootloader %s at %s" bl#name grub_config;
+ bl
--
2.11.0
7 years, 7 months
[PATCH] perl: drop %guestfs_introspection stuff
by Pino Toscano
It is not something standard, and actually unused by libguestfs itself.
Possibly going to be used by the old virt-v2v (which was in Perl), but
never used for that either.
---
generator/perl.ml | 112 +--------------------------------------------
perl/t/900-introspection.t | 43 -----------------
2 files changed, 1 insertion(+), 154 deletions(-)
delete mode 100644 perl/t/900-introspection.t
diff --git a/generator/perl.ml b/generator/perl.ml
index ec11a04..f394a7e 100644
--- a/generator/perl.ml
+++ b/generator/perl.ml
@@ -724,8 +724,7 @@ use warnings;
# This is always 1.0, never changes, and is unrelated to the
# real libguestfs version. If you want to find the libguestfs
-# library version, use $g->version. If you want to test if
-# APIs/parameters are present, use %%guestfs_introspection.
+# library version, use $g->version.
use vars qw($VERSION);
$VERSION = '1.0';
@@ -927,88 +926,6 @@ C<$g-E<gt>feature-available>.\n\n" opt
pr "=cut\n\n";
- (* Introspection hash. *)
- pr "use vars qw(%%guestfs_introspection);\n";
- pr "%%guestfs_introspection = (\n";
- List.iter (
- fun { name = name; style = (ret, args, optargs); shortdesc = shortdesc } ->
- pr " \"%s\" => {\n" name;
- pr " ret => ";
- (match ret with
- | RErr -> pr "'void'"
- | RInt _ -> pr "'int'"
- | RBool _ -> pr "'bool'"
- | RInt64 _ -> pr "'int64'"
- | RConstString _ -> pr "'const string'"
- | RConstOptString _ -> pr "'const nullable string'"
- | RString _ -> pr "'string'"
- | RStringList _ -> pr "'string list'"
- | RHashtable _ -> pr "'hash'"
- | RStruct (_, typ) -> pr "'struct %s'" typ
- | RStructList (_, typ) -> pr "'struct %s list'" typ
- | RBufferOut _ -> pr "'buffer'"
- );
- pr ",\n";
- let pr_type i = function
- | String (PlainString, n) -> pr "[ '%s', 'string', %d ]" n i
- | String (Device, n) -> pr "[ '%s', 'string(device)', %d ]" n i
- | String (Mountable, n) -> pr "[ '%s', 'string(mountable)', %d ]" n i
- | String (Dev_or_Path, n) ->
- pr "[ '%s', 'string(dev_or_path)', %d ]" n i
- | String (Mountable_or_Path, n) ->
- pr "[ '%s', 'string(mountable_or_path)', %d ]" n i
- | String (GUID, n) -> pr "[ '%s', 'guid', %d ]" n i
- | String ((FileIn|FileOut), n) ->
- pr "[ '%s', 'string(filename)', %d ]" n i
- | String (Key, n) -> pr "[ '%s', 'string(key)', %d ]" n i
- | String (Filename, n) -> pr "[ '%s', 'string(file)', %d ]" n i
- | String (Pathname, n) -> pr "[ '%s', 'string(path)', %d ]" n i
- | BufferIn n -> pr "[ '%s', 'buffer', %d ]" n i
- | OptString n -> pr "[ '%s', 'nullable string', %d ]" n i
- | StringList (Device, n) -> pr "[ '%s', 'string(device) list', %d ]" n i
- | StringList (Filename, n) ->
- pr "[ '%s', 'string(file) list', %d ]" n i
- | StringList (_, n) -> pr "[ '%s', 'string list', %d ]" n i
- | Bool n -> pr "[ '%s', 'bool', %d ]" n i
- | Int n -> pr "[ '%s', 'int', %d ]" n i
- | Int64 n -> pr "[ '%s', 'int64', %d ]" n i
- | Pointer (t, n) -> pr "[ '%s', 'pointer(%s)', %d ]" n t i
- in
- pr " args => [\n";
- iteri (fun i arg ->
- pr " ";
- pr_type i arg;
- pr ",\n"
- ) args;
- pr " ],\n";
- if optargs <> [] then (
- pr " optargs => {\n";
- iteri (fun i arg ->
- pr " %s => " (name_of_argt arg);
- pr_type i arg;
- pr ",\n"
- ) (args_of_optargs optargs);
- pr " },\n";
- );
- pr " name => \"%s\",\n" name;
- pr " description => %S,\n" shortdesc;
- pr " },\n";
- ) (actions |> external_functions |> sort);
- pr ");\n\n";
-
- pr "# Add aliases to the introspection hash.\n";
- let i = ref 0 in
- List.iter (
- fun { name = name; non_c_aliases = non_c_aliases } ->
- List.iter (
- fun alias ->
- pr "my %%ielem%d = %%{$guestfs_introspection{%s}};\n" !i name;
- pr "$guestfs_introspection{%s} = \\%%ielem%d;\n" alias !i;
- incr i
- ) non_c_aliases
- ) (actions |> external_functions |> sort);
- pr "\n";
-
(* End of file. *)
pr "\
1;
@@ -1032,33 +949,6 @@ class, use the ordinary Perl UNIVERSAL method C<can(METHOD)>
print \"\\$g->set_verbose is available\\n\";
}
-Perl does not offer a way to list the arguments of a method, and
-from time to time we may add extra arguments to calls that take
-optional arguments. For this reason, we provide a global hash
-variable C<%%guestfs_introspection> which contains the arguments
-and their types for each libguestfs method. The keys of this
-hash are the method names, and the values are an hashref
-containing useful introspection information about the method
-(further fields may be added to this in future).
-
- use Sys::Guestfs;
- $Sys::Guestfs::guestfs_introspection{mkfs}
- => {
- ret => 'void', # return type
- args => [ # required arguments
- [ 'fstype', 'string', 0 ],
- [ 'device', 'string(device)', 1 ],
- ],
- optargs => { # optional arguments
- blocksize => [ 'blocksize', 'int', 0 ],
- features => [ 'features', 'string', 1 ],
- inode => [ 'inode', 'int', 2 ],
- sectorsize => [ 'sectorsize', 'int', 3 ],
- },
- name => \"mkfs\",
- description => \"make a filesystem\",
- }
-
To test if particular features are supported by the current
build, use the L</feature_available> method like the example below. Note
that the appliance must be launched first.
diff --git a/perl/t/900-introspection.t b/perl/t/900-introspection.t
deleted file mode 100644
index 0182250..0000000
--- a/perl/t/900-introspection.t
+++ /dev/null
@@ -1,43 +0,0 @@
-# libguestfs Perl bindings -*- perl -*-
-# Copyright (C) 2011 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 %guestfs_introspection.
-
-use strict;
-use warnings;
-use Test::More tests => 10;
-
-use Errno;
-
-use Sys::Guestfs;
-
-my %add_drive = %{$Sys::Guestfs::guestfs_introspection{add_drive}};
-ok(1);
-
-is ($add_drive{ret}, "void");
-is ($add_drive{args}[0][0], "filename");
-is ($add_drive{args}[0][1], "string");
-is ($add_drive{args}[0][2], 0);
-
-# In libguestfs >= 1.19.19, this is an alias.
-my %add_drive_opts = %{$Sys::Guestfs::guestfs_introspection{add_drive_opts}};
-ok(1);
-
-ok (exists $add_drive_opts{optargs});
-ok (exists $add_drive_opts{optargs}->{readonly});
-is ($add_drive_opts{optargs}->{readonly}[0], "readonly");
-is ($add_drive_opts{optargs}->{readonly}[1], "bool");
--
2.9.3
7 years, 7 months
[PATCH] common/options: Change drv struct to store drive index instead of device name.
by Richard W.M. Jones
The device name is only used by guestfish (when using the -N option to
prepare drives). We constructed the device name very naively,
basically ‘sprintf ("/dev/sd%c", next_drive)’.
This stores the device index instead, and only constructs the device
name in guestfish. Also the device name is constructed properly using
guestfs_int_drive_name so it can cope with #drives > 26.
---
align/scan.c | 2 +-
cat/cat.c | 2 +-
cat/filesystems.c | 2 +-
cat/log.c | 2 +-
cat/ls.c | 2 +-
cat/tail.c | 2 +-
common/options/options.c | 30 +++++++++---------------------
common/options/options.h | 20 ++++++++++----------
df/main.c | 2 +-
diff/diff.c | 4 ++--
edit/edit.c | 2 +-
fish/fish.c | 12 ++++++++----
format/format.c | 2 +-
fuse/guestmount.c | 2 +-
inspector/inspector.c | 2 +-
rescue/rescue.c | 3 +--
rescue/suggest.c | 2 +-
17 files changed, 42 insertions(+), 51 deletions(-)
diff --git a/align/scan.c b/align/scan.c
index 7ae8adf..26f77fd 100644
--- a/align/scan.c
+++ b/align/scan.c
@@ -236,7 +236,7 @@ main (int argc, char *argv[])
error (EXIT_FAILURE, 0, _("--uuid option cannot be used with -a or -d"));
/* Add domains/drives from the command line (for a single guest). */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
diff --git a/cat/cat.c b/cat/cat.c
index 9fa8b4f..990fc90 100644
--- a/cat/cat.c
+++ b/cat/cat.c
@@ -236,7 +236,7 @@ main (int argc, char *argv[])
}
/* Add drives, inspect and mount. */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
diff --git a/cat/filesystems.c b/cat/filesystems.c
index 3bedf88..39b8cc3 100644
--- a/cat/filesystems.c
+++ b/cat/filesystems.c
@@ -346,7 +346,7 @@ main (int argc, char *argv[])
}
/* Add drives. */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
diff --git a/cat/log.c b/cat/log.c
index eca8459..d1d22a7 100644
--- a/cat/log.c
+++ b/cat/log.c
@@ -209,7 +209,7 @@ main (int argc, char *argv[])
/* Add drives, inspect and mount. Note that inspector is always true,
* and there is no -m option.
*/
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
diff --git a/cat/ls.c b/cat/ls.c
index 590e645..774cab5 100644
--- a/cat/ls.c
+++ b/cat/ls.c
@@ -359,7 +359,7 @@ main (int argc, char *argv[])
}
/* Add drives, inspect and mount. */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
diff --git a/cat/tail.c b/cat/tail.c
index 0759c9d..2797b86 100644
--- a/cat/tail.c
+++ b/cat/tail.c
@@ -279,7 +279,7 @@ do_tail (int argc, char *argv[], /* list of files in the guest */
int processed;
/* Add drives, inspect and mount. */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
return -1;
diff --git a/common/options/options.c b/common/options/options.c
index c9948d7..1965e1f 100644
--- a/common/options/options.c
+++ b/common/options/options.c
@@ -67,7 +67,6 @@ option_a (const char *arg, const char *format, struct drv **drvsp)
error (EXIT_FAILURE, errno, "access: %s", uri.path);
drv->type = drv_a;
- drv->nr_drives = -1;
drv->a.filename = uri.path;
drv->a.format = format;
@@ -76,7 +75,6 @@ option_a (const char *arg, const char *format, struct drv **drvsp)
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;
@@ -103,7 +101,6 @@ option_d (const char *arg, struct drv **drvsp)
error (EXIT_FAILURE, errno, "calloc");
drv->type = drv_d;
- drv->nr_drives = -1;
drv->d.guest = optarg;
drv->next = *drvsp;
@@ -111,22 +108,15 @@ option_d (const char *arg, struct drv **drvsp)
}
char
-add_drives_handle (guestfs_h *g, struct drv *drv, char next_drive)
+add_drives_handle (guestfs_h *g, struct drv *drv, size_t drive_index)
{
int r;
struct guestfs_add_drive_opts_argv ad_optargs;
- if (next_drive > 'z')
- error (EXIT_FAILURE, 0, _("too many drives added on the command line"));
-
if (drv) {
- next_drive = add_drives (drv->next, next_drive);
+ drive_index = add_drives (drv->next, drive_index);
- free (drv->device);
- drv->device = NULL;
-
- if (asprintf (&drv->device, "/dev/sd%c", next_drive) == -1)
- error (EXIT_FAILURE, errno, "asprintf");
+ drv->drive_index = drive_index;
switch (drv->type) {
case drv_a:
@@ -153,7 +143,7 @@ add_drives_handle (guestfs_h *g, struct drv *drv, char next_drive)
exit (EXIT_FAILURE);
drv->nr_drives = 1;
- next_drive++;
+ drive_index++;
break;
case drv_uri:
@@ -186,7 +176,7 @@ add_drives_handle (guestfs_h *g, struct drv *drv, char next_drive)
exit (EXIT_FAILURE);
drv->nr_drives = 1;
- next_drive++;
+ drive_index++;
break;
case drv_d:
@@ -195,7 +185,7 @@ add_drives_handle (guestfs_h *g, struct drv *drv, char next_drive)
exit (EXIT_FAILURE);
drv->nr_drives = r;
- next_drive += r;
+ drive_index += r;
break;
case drv_N:
@@ -208,7 +198,7 @@ add_drives_handle (guestfs_h *g, struct drv *drv, char next_drive)
exit (EXIT_FAILURE);
drv->nr_drives = 1;
- next_drive++;
+ drive_index++;
break;
case drv_scratch:
@@ -218,7 +208,7 @@ add_drives_handle (guestfs_h *g, struct drv *drv, char next_drive)
exit (EXIT_FAILURE);
drv->nr_drives = 1;
- next_drive++;
+ drive_index++;
break;
default: /* keep GCC happy */
@@ -226,7 +216,7 @@ add_drives_handle (guestfs_h *g, struct drv *drv, char next_drive)
}
}
- return next_drive;
+ return drive_index;
}
static void display_mountpoints_on_failure (const char *mp_device, const char *user_supplied_options);
@@ -320,8 +310,6 @@ free_drives (struct drv *drv)
if (!drv) return;
free_drives (drv->next);
- free (drv->device);
-
switch (drv->type) {
case drv_a:
free (drv->a.filename);
diff --git a/common/options/options.h b/common/options/options.h
index 1598daf..7e4d269 100644
--- a/common/options/options.h
+++ b/common/options/options.h
@@ -43,14 +43,14 @@ extern int in_virt_rescue;
struct drv {
struct drv *next;
- char *device; /* Device name inside the appliance (eg. /dev/sda).
- * This is filled in when we add the drives in
- * add_drives. Note that guests (-d option) may
- * have multiple drives, in which case this is the
- * first drive, and nr_drives is the number of
- * drives used.
- */
- int nr_drives; /* number of drives for this guest */
+ /* Drive index. This is filled in by add_drives(). */
+ size_t drive_index;
+
+ /* Number of drives represented by this 'drv' struct. For -d this
+ * can be != 1 because a guest can have more than one disk. For
+ * others it is always 1. This is filled in by add_drives().
+ */
+ size_t nr_drives;
enum {
drv_a, /* -a option (without URI) */
@@ -123,8 +123,8 @@ extern char *read_key (const char *param);
/* in options.c */
extern void option_a (const char *arg, const char *format, struct drv **drvsp);
extern void option_d (const char *arg, struct drv **drvsp);
-extern char add_drives_handle (guestfs_h *g, struct drv *drv, char next_drive);
-#define add_drives(drv, next_drive) add_drives_handle (g, drv, next_drive)
+extern char add_drives_handle (guestfs_h *g, struct drv *drv, size_t drive_index);
+#define add_drives(drv, drive_index) add_drives_handle (g, drv, drive_index)
extern void mount_mps (struct mp *mp);
extern void free_drives (struct drv *drv);
extern void free_mps (struct mp *mp);
diff --git a/df/main.c b/df/main.c
index 19ae77a..1c8159d 100644
--- a/df/main.c
+++ b/df/main.c
@@ -278,7 +278,7 @@ main (int argc, char *argv[])
CLEANUP_FREE char *name = NULL;
/* Add domains/drives from the command line (for a single guest). */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
diff --git a/diff/diff.c b/diff/diff.c
index 92ebdf7..7effcba 100644
--- a/diff/diff.c
+++ b/diff/diff.c
@@ -362,7 +362,7 @@ main (int argc, char *argv[])
unsigned errors = 0;
/* Mount up first guest. */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
@@ -373,7 +373,7 @@ main (int argc, char *argv[])
errors++;
/* Mount up second guest. */
- add_drives_handle (g2, drvs2, 'a');
+ add_drives_handle (g2, drvs2, 0);
if (guestfs_launch (g2) == -1)
exit (EXIT_FAILURE);
diff --git a/edit/edit.c b/edit/edit.c
index a5ef7f9..6e608a8 100644
--- a/edit/edit.c
+++ b/edit/edit.c
@@ -261,7 +261,7 @@ main (int argc, char *argv[])
}
/* Add drives. */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
diff --git a/fish/fish.c b/fish/fish.c
index c47576f..183c800 100644
--- a/fish/fish.c
+++ b/fish/fish.c
@@ -362,7 +362,6 @@ main (int argc, char *argv[])
if (!drv)
error (EXIT_FAILURE, errno, "calloc");
drv->type = drv_N;
- drv->nr_drives = -1;
p = strchr (optarg, '=');
if (p != NULL) {
*p = '\0';
@@ -466,7 +465,7 @@ main (int argc, char *argv[])
CHECK_OPTION_format_consumed;
/* If we've got drives to add, add them now. */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
/* If we've got mountpoints or prepared drives or -i option, we must
* launch the guest and mount them.
@@ -586,8 +585,13 @@ prepare_drives (struct drv *drv)
{
if (drv) {
prepare_drives (drv->next);
- if (drv->type == drv_N)
- prepare_drive (drv->N.filename, drv->N.data, drv->device);
+ if (drv->type == drv_N) {
+ char device[64];
+
+ strcpy (device, "/dev/sd");
+ guestfs_int_drive_name (drv->drive_index, &device[7]);
+ prepare_drive (drv->N.filename, drv->N.data, device);
+ }
}
}
diff --git a/format/format.c b/format/format.c
index 4e6ed26..ec6d33f 100644
--- a/format/format.c
+++ b/format/format.c
@@ -249,7 +249,7 @@ main (int argc, char *argv[])
const char *wipefs[] = { "wipefs", NULL };
/* Add domains/drives from the command line (for a single guest). */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
diff --git a/fuse/guestmount.c b/fuse/guestmount.c
index 98933bc..a711603 100644
--- a/fuse/guestmount.c
+++ b/fuse/guestmount.c
@@ -360,7 +360,7 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
/* Do the guest drives and mountpoints. */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
if (inspector)
diff --git a/inspector/inspector.c b/inspector/inspector.c
index 1120776..3672e3c 100644
--- a/inspector/inspector.c
+++ b/inspector/inspector.c
@@ -271,7 +271,7 @@ main (int argc, char *argv[])
/* Add drives, inspect and mount. Note that inspector is always true,
* and there is no -m option.
*/
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
diff --git a/rescue/rescue.c b/rescue/rescue.c
index 19baa87..2bf5f26 100644
--- a/rescue/rescue.c
+++ b/rescue/rescue.c
@@ -372,7 +372,7 @@ main (int argc, char *argv[])
exit (EXIT_FAILURE);
/* Do the guest drives and mountpoints. */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
if (guestfs_launch (g) == -1)
exit (EXIT_FAILURE);
if (inspector)
@@ -673,7 +673,6 @@ add_scratch_disk (struct drv **drvs)
if (!drv)
error (EXIT_FAILURE, errno, "calloc");
drv->type = drv_scratch;
- drv->nr_drives = -1;
drv->scratch.size = INT64_C (10737418240);
drv->next = *drvs;
*drvs = drv;
diff --git a/rescue/suggest.c b/rescue/suggest.c
index 78792f2..f1d0fb6 100644
--- a/rescue/suggest.c
+++ b/rescue/suggest.c
@@ -54,7 +54,7 @@ do_suggestion (struct drv *drvs)
read_only = 1;
/* Add drives. */
- add_drives (drvs, 'a');
+ add_drives (drvs, 0);
/* Free up data structures, no longer needed after this point. */
free_drives (drvs);
--
2.9.3
7 years, 7 months
[PATCH v2] inspector: validate resulting XML files
by Pino Toscano
Run xmllint to validate the XML output files of virt-inspector, so the
schema is checked against actual output of virt-inspector.
---
.gitignore | 1 +
configure.ac | 2 ++
inspector/{test-virt-inspector.sh => test-virt-inspector.sh.in} | 2 ++
3 files changed, 5 insertions(+)
rename inspector/{test-virt-inspector.sh => test-virt-inspector.sh.in} (92%)
diff --git a/.gitignore b/.gitignore
index 152a400..89638f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -298,6 +298,7 @@ Makefile.in
/haskell/Guestfs.hs
/inspector/actual-*.xml
/inspector/stamp-virt-inspector.pod
+/inspector/test-virt-inspector.sh
/inspector/test-xmllint.sh
/inspector/virt-inspector
/inspector/virt-inspector.1
diff --git a/configure.ac b/configure.ac
index da7653e..a8d8127 100644
--- a/configure.ac
+++ b/configure.ac
@@ -151,6 +151,8 @@ AC_CONFIG_FILES([appliance/libguestfs-make-fixed-appliance],
[chmod +x,-w appliance/libguestfs-make-fixed-appliance])
AC_CONFIG_FILES([inspector/test-xmllint.sh],
[chmod +x,-w inspector/test-xmllint.sh])
+AC_CONFIG_FILES([inspector/test-virt-inspector.sh],
+ [chmod +x,-w inspector/test-virt-inspector.sh])
AC_CONFIG_FILES([installcheck.sh],
[chmod +x,-w installcheck.sh])
AC_CONFIG_FILES([p2v/virt-p2v-make-disk],
diff --git a/inspector/test-virt-inspector.sh b/inspector/test-virt-inspector.sh.in
similarity index 92%
rename from inspector/test-virt-inspector.sh
rename to inspector/test-virt-inspector.sh.in
index 2f55cdc..10e5268 100755
--- a/inspector/test-virt-inspector.sh
+++ b/inspector/test-virt-inspector.sh.in
@@ -30,6 +30,8 @@ for f in ../test-data/phony-guests/{debian,fedora,ubuntu,archlinux,coreos,window
if [ -s "$f" ]; then
b=$(basename "$f" .xml)
$VG virt-inspector --format=raw -a "$f" > "actual-$b.xml"
+ # Check the generated output validate the schema.
+ @XMLLINT@ --noout --relaxng "$srcdir/virt-inspector.rng" "actual-$b.xml"
# This 'diff' command will fail (because of -e option) if there
# are any differences.
diff -ur $diff_ignore "expected-$b.xml" "actual-$b.xml"
--
2.9.3
7 years, 7 months
[Bug #1406906] [PATCH] python: fix segmentation fault when setting non UTF-8 strings
by Matteo Cafasso
When constructing the returned objects, check the return value of
Python APIs.
A RuntimeError will be raised on failure pointing to the problematic
entry and the field name.
Signed-off-by: Matteo Cafasso <noxdafox(a)gmail.com>
---
generator/python.ml | 143 +++++++++++++++++++++++++++++++++++-----------------
1 file changed, 97 insertions(+), 46 deletions(-)
diff --git a/generator/python.ml b/generator/python.ml
index 11dc48102..7d86131b1 100644
--- a/generator/python.ml
+++ b/generator/python.ml
@@ -152,12 +152,20 @@ and generate_python_structs () =
pr "PyObject *\n";
pr "guestfs_int_py_put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
pr "{\n";
- pr " PyObject *list;\n";
+ pr " PyObject *list, *element;\n";
pr " size_t i;\n";
pr "\n";
pr " list = PyList_New (%ss->len);\n" typ;
- pr " for (i = 0; i < %ss->len; ++i)\n" typ;
- pr " PyList_SetItem (list, i, guestfs_int_py_put_%s (&%ss->val[i]));\n" typ typ;
+ pr " if (list == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError, \"PyList_New\");\n";
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
+ pr " element = guestfs_int_py_put_%s (&%ss->val[i]);\n" typ typ;
+ pr " if (element == NULL)\n";
+ pr " return NULL;\n";
+ pr " PyList_SetItem (list, i, element);\n";
+ pr " }\n";
pr " return list;\n";
pr "};\n";
pr "#endif\n";
@@ -171,73 +179,112 @@ and generate_python_structs () =
pr "PyObject *\n";
pr "guestfs_int_py_put_%s (struct guestfs_%s *%s)\n" typ typ typ;
pr "{\n";
- pr " PyObject *dict;\n";
+ pr " PyObject *dict, *value;\n";
pr "\n";
pr " dict = PyDict_New ();\n";
+ pr " if (dict == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError, \"PyDict_New\");\n";
+ pr " return NULL;\n";
+ pr " }\n";
List.iter (
function
| name, FString ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " PyString_FromString (%s->%s));\n"
- typ name;
+ pr " value = PyString_FromString (%s->%s);\n" typ name;
pr "#else\n";
- pr " PyUnicode_FromString (%s->%s));\n"
- typ name;
- pr "#endif\n"
+ pr " value = PyUnicode_FromString (%s->%s);\n" typ name;
+ pr "#endif\n";
+ pr " if (value == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError,\n";
+ pr " \"Error setting %s.%s\");\n" typ name;
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FBuffer ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
+ pr " value = PyString_FromStringAndSize (%s->%s, %s->%s_len);\n"
typ name typ name;
pr "#else\n";
- pr " PyBytes_FromStringAndSize (%s->%s, %s->%s_len));\n"
+ pr " value = PyBytes_FromStringAndSize (%s->%s, %s->%s_len);\n"
typ name typ name;
- pr "#endif\n"
+ pr "#endif\n";
+ pr " if (value == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError,\n";
+ pr " \"Error setting %s.%s\");\n" typ name;
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FUUID ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " PyString_FromStringAndSize (%s->%s, 32));\n"
- typ name;
+ pr " value = PyString_FromStringAndSize (%s->%s, 32);\n" typ name;
pr "#else\n";
- pr " PyBytes_FromStringAndSize (%s->%s, 32));\n"
- typ name;
- pr "#endif\n"
+ pr " value = PyBytes_FromStringAndSize (%s->%s, 32);\n" typ name;
+ pr "#endif\n";
+ pr " if (value == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError,\n";
+ pr " \"Error setting %s.%s\");\n" typ name;
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, (FBytes|FUInt64) ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
- typ name
+ pr " value = PyLong_FromUnsignedLongLong (%s->%s);\n" typ name;
+ pr " if (value == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError,\n";
+ pr " \"Error setting %s.%s\");\n" typ name;
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FInt64 ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyLong_FromLongLong (%s->%s));\n"
- typ name
+ pr " value = PyLong_FromLongLong (%s->%s);\n" typ name;
+ pr " if (value == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError,\n";
+ pr " \"Error setting %s.%s\");\n" typ name;
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FUInt32 ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyLong_FromUnsignedLong (%s->%s));\n"
- typ name
+ pr " value = PyLong_FromUnsignedLong (%s->%s);\n" typ name;
+ pr " if (value == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError,\n";
+ pr " \"Error setting %s.%s\");\n" typ name;
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FInt32 ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyLong_FromLong (%s->%s));\n"
- typ name
+ pr " value = PyLong_FromLong (%s->%s);\n" typ name;
+ pr " if (value == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError,\n";
+ pr " \"Error setting %s.%s\");\n" typ name;
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FOptPercent ->
- pr " if (%s->%s >= 0)\n" typ name;
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyFloat_FromDouble ((double) %s->%s));\n"
- typ name;
+ pr " if (%s->%s >= 0) {\n" typ name;
+ pr " value = PyFloat_FromDouble ((double) %s->%s);\n" typ name;
+ pr " if (value == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError,\n";
+ pr " \"Error setting %s.%s\");\n" typ name;
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
+ pr " }\n";
pr " else {\n";
pr " Py_INCREF (Py_None);\n";
pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
pr " }\n"
| name, FChar ->
pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyString_FromStringAndSize (&%s->%s, 1));\n"
- typ name;
+ pr " value = PyString_FromStringAndSize (&%s->%s, 1);\n" typ name;
pr "#else\n";
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyUnicode_FromStringAndSize (&%s->%s, 1));\n"
+ pr " value = PyUnicode_FromStringAndSize (&%s->%s, 1);\n"
typ name;
- pr "#endif\n"
+ pr "#endif\n";
+ pr " if (value == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError,\n";
+ pr " \"Error setting %s.%s\");\n" typ name;
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
) cols;
pr " return dict;\n";
pr "};\n";
@@ -517,16 +564,20 @@ and generate_python_actions actions () =
pr " if (py_r == NULL) goto out;\n";
| RStringList _ ->
pr " py_r = guestfs_int_py_put_string_list (r);\n";
- pr " guestfs_int_free_string_list (r);\n"
+ pr " guestfs_int_free_string_list (r);\n";
+ pr " if (py_r == NULL) goto out;\n";
| RStruct (_, typ) ->
pr " py_r = guestfs_int_py_put_%s (r);\n" typ;
- pr " guestfs_free_%s (r);\n" typ
+ pr " guestfs_free_%s (r);\n" typ;
+ pr " if (py_r == NULL) goto out;\n";
| RStructList (_, typ) ->
pr " py_r = guestfs_int_py_put_%s_list (r);\n" typ;
- pr " guestfs_free_%s_list (r);\n" typ
+ pr " guestfs_free_%s_list (r);\n" typ;
+ pr " if (py_r == NULL) goto out;\n";
| RHashtable n ->
pr " py_r = guestfs_int_py_put_table (r);\n";
- pr " guestfs_int_free_string_list (r);\n"
+ pr " guestfs_int_free_string_list (r);\n";
+ pr " if (py_r == NULL) goto out;\n";
| RBufferOut _ ->
pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
pr " py_r = PyString_FromStringAndSize (r, size);\n";
--
2.11.0
7 years, 7 months