[PATCH] fish, sysprep: run FUSE-related tests only when FUSE is available
by Pino Toscano
They will fail anyway in that case, so run them only when the FUSE
support is built in.
---
fish/Makefile.am | 6 +++++-
sysprep/Makefile.am | 6 +++++-
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/fish/Makefile.am b/fish/Makefile.am
index fc7c729..5ffa0f1 100644
--- a/fish/Makefile.am
+++ b/fish/Makefile.am
@@ -297,7 +297,6 @@ TESTS += \
test-find0.sh \
test-inspect.sh \
test-glob.sh \
- test-mount-local.sh \
test-prep.sh \
test-read-file.sh \
test-remote.sh \
@@ -306,6 +305,11 @@ TESTS += \
test-run.sh \
test-stringlist.sh \
test-upload-to-dir.sh
+
+if HAVE_FUSE
+TESTS += \
+ test-mount-local.sh
+endif
endif
check-valgrind:
diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am
index b3ad3c3..50eda8f 100644
--- a/sysprep/Makefile.am
+++ b/sysprep/Makefile.am
@@ -213,8 +213,12 @@ TESTS_ENVIRONMENT = \
if ENABLE_APPLIANCE
TESTS = \
test-virt-sysprep.sh \
- test-virt-sysprep-passwords.sh \
+ test-virt-sysprep-passwords.sh
+
+if HAVE_FUSE
+TESTS += \
test-virt-sysprep-script.sh
+endif HAVE_FUSE
endif ENABLE_APPLIANCE
check-valgrind:
--
2.5.0
8 years, 10 months
[PATCH] v2v: move virtio_win to windows_virtio
by Roman Kagan
Now that all the stuff related to Windows virtio drivers has been moved
into a dedicated module, it makes sense to move the definition of
virtio_win there, too, and stop passing it around as a parameter.
Signed-off-by: Roman Kagan <rkagan(a)virtuozzo.com>
---
v2v/convert_windows.ml | 9 +--------
v2v/windows_virtio.ml | 13 ++++++++++---
v2v/windows_virtio.mli | 2 +-
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index 38fa300..f6f0911 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -43,13 +43,6 @@ let convert ~keep_serial_console (g : G.guestfs) inspect source =
try Sys.getenv "VIRT_TOOLS_DATA_DIR"
with Not_found -> Guestfs_config.datadir // "virt-tools" in
- let virtio_win =
- try Sys.getenv "VIRTIO_WIN"
- with Not_found ->
- try Sys.getenv "VIRTIO_WIN_DIR" (* old name for VIRTIO_WIN *)
- with Not_found ->
- Guestfs_config.datadir // "virtio-win" in
-
(* Check if RHEV-APT exists. This is optional. *)
let rhev_apt_exe = virt_tools_data_dir // "rhev-apt.exe" in
let rhev_apt_exe =
@@ -289,7 +282,7 @@ if errorlevel 3010 exit /b 0
disable_services root current_cs;
disable_autoreboot root current_cs;
- Windows_virtio.install_drivers g inspect systemroot virtio_win
+ Windows_virtio.install_drivers g inspect systemroot
root current_cs
and disable_services root current_cs =
diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml
index 7441169..bdce038 100644
--- a/v2v/windows_virtio.ml
+++ b/v2v/windows_virtio.ml
@@ -26,12 +26,19 @@ open Regedit
open Types
open Utils
-let rec install_drivers g inspect systemroot virtio_win root current_cs =
+let virtio_win =
+ try Sys.getenv "VIRTIO_WIN"
+ with Not_found ->
+ try Sys.getenv "VIRTIO_WIN_DIR" (* old name for VIRTIO_WIN *)
+ with Not_found ->
+ Guestfs_config.datadir // "virtio-win"
+
+let rec install_drivers g inspect systemroot root current_cs =
(* Copy the virtio drivers to the guest. *)
let driverdir = sprintf "%s/Drivers/VirtIO" systemroot in
g#mkdir_p driverdir;
- if not (copy_drivers g inspect virtio_win driverdir) then (
+ if not (copy_drivers g inspect driverdir) then (
warning (f_"there are no virtio drivers available for this version of Windows (%d.%d %s %s). virt-v2v looks for drivers in %s\n\nThe guest will be configured to use slower emulated devices.")
inspect.i_major_version inspect.i_minor_version inspect.i_arch
inspect.i_product_variant virtio_win;
@@ -349,7 +356,7 @@ and add_viostor_to_driver_database g root arch current_cs =
(* Copy the matching drivers to the driverdir; return true if any have
* been copied.
*)
-and copy_drivers g inspect virtio_win driverdir =
+and copy_drivers g inspect driverdir =
let ret = ref false in
if is_directory virtio_win then (
let cmd = sprintf "cd %s && find -type f" (quote virtio_win) in
diff --git a/v2v/windows_virtio.mli b/v2v/windows_virtio.mli
index 9edf4ec..eb7a57a 100644
--- a/v2v/windows_virtio.mli
+++ b/v2v/windows_virtio.mli
@@ -19,7 +19,7 @@
(** Functions for installing Windows virtio drivers. *)
val install_drivers
- : Guestfs.guestfs -> Types.inspect -> string -> string -> int64 -> string ->
+ : Guestfs.guestfs -> Types.inspect -> string -> int64 -> string ->
Types.guestcaps_block_type * Types.guestcaps_net_type * Types.guestcaps_video_type
(** [install_drivers g inspect systemroot virtio_win root current_cs]
installs virtio drivers from the driver directory or driver
--
2.5.0
8 years, 10 months
[PATCH 1/2] tmpdirs: centralize permissions handling
by Pino Toscano
Move to lazy_make_tmpdir the logic for making world-readable (but only
for root) newly-created temporary directories, removing the non-fatal
code doing that in guestfs_impl_launch.
Followup of commit 772f649e595d202bdb67f05aeb62157c1104be89.
---
src/launch.c | 7 -------
src/tmpdirs.c | 30 ++++++++++++------------------
2 files changed, 12 insertions(+), 25 deletions(-)
diff --git a/src/launch.c b/src/launch.c
index 9273c58..958d4b3 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -60,13 +60,6 @@ guestfs_impl_launch (guestfs_h *g)
if (guestfs_int_lazy_make_tmpdir (g) == -1)
return -1;
- /* Allow anyone to read the temporary directory. The socket in this
- * directory won't be readable but anyone can see it exists if they
- * want. (RHBZ#610880).
- */
- if (chmod (g->tmpdir, 0755) == -1)
- warning (g, "chmod: %s: %m (ignored)", g->tmpdir);
-
/* Some common debugging information. */
if (g->verbose) {
CLEANUP_FREE_VERSION struct guestfs_version *v =
diff --git a/src/tmpdirs.c b/src/tmpdirs.c
index 76bf1c5..0a36f2f 100644
--- a/src/tmpdirs.c
+++ b/src/tmpdirs.c
@@ -160,6 +160,17 @@ lazy_make_tmpdir (guestfs_h *g, char *(*getdir) (guestfs_h *g), char **dest)
free (tmpdir);
return -1;
}
+ /* Allow qemu (which may be running as qemu.qemu) to read in this
+ * temporary directory; we are storing either sockets, or temporary
+ * disks which qemu needs to access to. (RHBZ#610880).
+ * We do this only for root, as for normal users qemu will be run
+ * under the same user.
+ */
+ if (geteuid () == 0 && chmod (tmppath, 0755) == -1) {
+ perrorf (g, "chmod: %s", tmppath);
+ free (tmppath);
+ return -1;
+ }
*dest = tmppath;
}
return 0;
@@ -178,24 +189,7 @@ guestfs_int_lazy_make_tmpdir (guestfs_h *g)
int
guestfs_int_lazy_make_sockdir (guestfs_h *g)
{
- int ret;
- uid_t euid = geteuid ();
-
- ret = lazy_make_tmpdir (g, guestfs_get_sockdir, &g->sockdir);
- if (ret == -1)
- return ret;
-
- if (euid == 0) {
- /* Allow qemu (which may be running as qemu.qemu) to read the socket
- * temporary directory. (RHBZ#610880).
- */
- if (chmod (g->sockdir, 0755) == -1) {
- perrorf (g, "chmod: %s", g->sockdir);
- return -1;
- }
- }
-
- return ret;
+ return lazy_make_tmpdir (g, guestfs_get_sockdir, &g->sockdir);
}
/* Recursively remove a temporary directory. If removal fails, just
--
2.5.0
8 years, 10 months
[PATCH v2 1/2] launch: add internal helper for socket paths creation
by Pino Toscano
Introduce an internal helper to create paths for sockets -- will be
useful for changing later the logic for placing sockets.
Futhermore, check that the length of sockets won't overflow the buffer
for their filenames.
---
src/guestfs-internal.h | 1 +
src/launch-direct.c | 4 +++-
src/launch-libvirt.c | 10 ++++++----
src/launch.c | 17 +++++++++++++++++
4 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 5ecd322..bff9f64 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -782,6 +782,7 @@ extern void guestfs_int_launch_send_progress (guestfs_h *g, int perdozen);
extern char *guestfs_int_appliance_command_line (guestfs_h *g, const char *appliance_dev, int flags);
#define APPLIANCE_COMMAND_LINE_IS_TCG 1
const char *guestfs_int_get_cpu_model (int kvm);
+int guestfs_int_create_socketname (guestfs_h *g, const char *filename, char (*sockname)[UNIX_PATH_MAX]);
extern void guestfs_int_register_backend (const char *name, const struct backend_ops *);
extern int guestfs_int_set_backend (guestfs_h *g, const char *method);
diff --git a/src/launch-direct.c b/src/launch-direct.c
index b8e453d..a81d4b3 100644
--- a/src/launch-direct.c
+++ b/src/launch-direct.c
@@ -295,7 +295,9 @@ launch_direct (guestfs_h *g, void *datav, const char *arg)
/* Using virtio-serial, we need to create a local Unix domain socket
* for qemu to connect to.
*/
- snprintf (data->guestfsd_sock, sizeof data->guestfsd_sock, "%s/guestfsd.sock", g->tmpdir);
+ if (guestfs_int_create_socketname (g, "guestfsd.sock",
+ &data->guestfsd_sock) == -1)
+ goto cleanup0;
daemon_accept_sock = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
if (daemon_accept_sock == -1) {
diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c
index 8a5d93e..376bd80 100644
--- a/src/launch-libvirt.c
+++ b/src/launch-libvirt.c
@@ -395,8 +395,9 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
/* Using virtio-serial, we need to create a local Unix domain socket
* for qemu to connect to.
*/
- snprintf (data->guestfsd_path, sizeof data->guestfsd_path,
- "%s/guestfsd.sock", g->tmpdir);
+ if (guestfs_int_create_socketname (g, "guestfsd.sock",
+ &data->guestfsd_path) == -1)
+ goto cleanup;
set_socket_create_context (g);
@@ -421,8 +422,9 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri)
}
/* For the serial console. */
- snprintf (data->console_path, sizeof data->console_path,
- "%s/console.sock", g->tmpdir);
+ if (guestfs_int_create_socketname (g, "console.sock",
+ &data->console_path) == -1)
+ goto cleanup;
console_sock = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
if (console_sock == -1) {
diff --git a/src/launch.c b/src/launch.c
index f59818f..60f02a7 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -418,6 +418,23 @@ guestfs_int_get_cpu_model (int kvm)
#endif
}
+/* Create the path for a socket with the selected filename in the
+ * tmpdir.
+ */
+int
+guestfs_int_create_socketname (guestfs_h *g, const char *filename,
+ char (*sockpath)[UNIX_PATH_MAX])
+{
+ if (strlen (g->tmpdir) + 1 + strlen (filename) > UNIX_PATH_MAX-1) {
+ error (g, _("socket path too long: %s/%s"), g->tmpdir, filename);
+ return -1;
+ }
+
+ snprintf (*sockpath, UNIX_PATH_MAX, "%s/%s", g->tmpdir, filename);
+
+ return 0;
+}
+
/* glibc documents, but does not actually implement, a 'getumask(3)'
* call. This implements a thread-safe way to get the umask. Note
* this is only called when g->verbose is true and after g->tmpdir
--
2.5.0
8 years, 10 months
[PATCH] tests: reduce sizes of scratch disks to 2 GB
by Pino Toscano
1 GB should be enough to create a btrfs filesystem, even with 64K page
size; hence, make the /dev/sda and /dev/sdb test devices smaller so
there is less space taken during the test run.
Followup of commit 8ffad75e5b610274a664a00f1f1186070b602e18 and
commit 9e9b648770f9b8dbe8f280e4b5d1f80c4d689130.
---
docs/guestfs-hacking.pod | 4 ++--
generator/actions.ml | 10 +++++-----
tests/c-api/tests-main.c | 4 ++--
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/docs/guestfs-hacking.pod b/docs/guestfs-hacking.pod
index 42d7759..ae667c9 100644
--- a/docs/guestfs-hacking.pod
+++ b/docs/guestfs-hacking.pod
@@ -105,11 +105,11 @@ The test environment has 4 block devices:
=over 4
-=item F</dev/sda> 10 GB
+=item F</dev/sda> 2 GB
General block device for testing.
-=item F</dev/sdb> 10 GB
+=item F</dev/sdb> 2 GB
F</dev/sdb1> is an ext2 filesystem used for testing
filesystem write operations.
diff --git a/generator/actions.ml b/generator/actions.ml
index 36b8680..eb45392 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -4780,7 +4780,7 @@ C<blocksize> option of C<guestfs_mkfs>." };
tests = [
InitEmpty, Always, TestResult (
[["blockdev_getsz"; "/dev/sda"]],
- "ret == INT64_C(10)*1024*1024*1024/512"), []
+ "ret == INT64_C(2)*1024*1024*1024/512"), []
];
shortdesc = "get total size of device in 512-byte sectors";
longdesc = "\
@@ -4800,7 +4800,7 @@ This uses the L<blockdev(8)> command." };
tests = [
InitEmpty, Always, TestResult (
[["blockdev_getsize64"; "/dev/sda"]],
- "ret == INT64_C(10)*1024*1024*1024"), []
+ "ret == INT64_C(2)*1024*1024*1024"), []
];
shortdesc = "get total size of device in bytes";
longdesc = "\
@@ -9884,7 +9884,7 @@ device is stopped, but it is not destroyed or zeroed." };
"check_hash (ret, \"PART_ENTRY_NUMBER\", \"1\") == 0 && "^
"check_hash (ret, \"PART_ENTRY_TYPE\", \"0x83\") == 0 && "^
"check_hash (ret, \"PART_ENTRY_OFFSET\", \"128\") == 0 && "^
- "check_hash (ret, \"PART_ENTRY_SIZE\", \"20971265\") == 0"), [];
+ "check_hash (ret, \"PART_ENTRY_SIZE\", \"4194049\") == 0"), [];
];
shortdesc = "print block device attributes";
longdesc = "\
@@ -12712,8 +12712,8 @@ This enable skinny metadata extent refs." };
tests = [
InitEmpty, Always, TestRun (
[["part_init"; "/dev/sda"; "mbr"];
- ["part_add"; "/dev/sda"; "p"; "64"; "4095999"];
- ["part_add"; "/dev/sda"; "p"; "4096000"; "8191999"];
+ ["part_add"; "/dev/sda"; "p"; "64"; "2047999"];
+ ["part_add"; "/dev/sda"; "p"; "2048000"; "4095999"];
["mkfs_btrfs"; "/dev/sda1"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""];
["mkfs_btrfs"; "/dev/sda2"; ""; ""; "NOARG"; ""; "NOARG"; "NOARG"; ""; ""];
["mount"; "/dev/sda1"; "/"];
diff --git a/tests/c-api/tests-main.c b/tests/c-api/tests-main.c
index 517d8a3..85208b1 100644
--- a/tests/c-api/tests-main.c
+++ b/tests/c-api/tests-main.c
@@ -440,12 +440,12 @@ create_handle (void)
exit (EXIT_FAILURE);
}
- if (guestfs_add_drive_scratch (g, INT64_C(10)*1024*1024*1024, -1) == -1) {
+ if (guestfs_add_drive_scratch (g, INT64_C(2)*1024*1024*1024, -1) == -1) {
printf ("FAIL: guestfs_add_drive_scratch\n");
exit (EXIT_FAILURE);
}
- if (guestfs_add_drive_scratch (g, INT64_C(10)*1024*1024*1024, -1) == -1) {
+ if (guestfs_add_drive_scratch (g, INT64_C(2)*1024*1024*1024, -1) == -1) {
printf ("FAIL: guestfs_add_drive_scratch\n");
exit (EXIT_FAILURE);
}
--
2.5.0
8 years, 10 months
[PATCH v3] inspect: get windows drive letters for GPT disks.
by Dawid Zamirski
This patch updates the guestfs_inspect_get_drive_mappings API call to
also return drive letters for GPT paritions. Previously this worked
only for MBR partitions. This is achieved by matching the GPT partition
GUID with the info stored in the blob from
HKLM\SYSTEM\MountedDevices\DosDevices keys. For GPT partions this blob
contains a "DMIO:ID:" prefix followed by a 16 byte binary GUID.
---
changes since v2:
* added code review changes as per rjones
src/inspect-fs-windows.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 94 insertions(+), 2 deletions(-)
diff --git a/src/inspect-fs-windows.c b/src/inspect-fs-windows.c
index ccf5cba..ba72727 100644
--- a/src/inspect-fs-windows.c
+++ b/src/inspect-fs-windows.c
@@ -25,6 +25,7 @@
#include <string.h>
#include <errno.h>
#include <iconv.h>
+#include <inttypes.h>
#ifdef HAVE_ENDIAN_H
#include <endian.h>
@@ -57,6 +58,8 @@ static int check_windows_arch (guestfs_h *g, struct inspect_fs *fs);
static int check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs);
static int check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs);
static char *map_registry_disk_blob (guestfs_h *g, const void *blob);
+static char *map_registry_disk_blob_gpt (guestfs_h *g, const void *blob);
+static char *extract_guid_from_registry_blob (guestfs_h *g, const void *blob);
/* XXX Handling of boot.ini in the Perl version was pretty broken. It
* essentially didn't do anything for modern Windows guests.
@@ -386,6 +389,7 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
int r;
size_t len = strlen (fs->windows_systemroot) + 64;
char system[len];
+ char gpt_prefix[] = "DMIO:ID:";
snprintf (system, len, "%s/system32/config/system",
fs->windows_systemroot);
@@ -490,12 +494,18 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
CLEANUP_FREE char *blob = NULL;
char *device;
int64_t type;
+ bool is_gpt;
type = guestfs_hivex_value_type (g, v);
blob = guestfs_hivex_value_value (g, v, &len);
- if (blob != NULL && type == 3 && len == 12) {
+ is_gpt = memcmp (blob, gpt_prefix, 8) == 0;
+ if (blob != NULL && type == 3 && (len == 12 || is_gpt)) {
/* Try to map the blob to a known disk and partition. */
- device = map_registry_disk_blob (g, blob);
+ if (is_gpt)
+ device = map_registry_disk_blob_gpt (g, blob);
+ else
+ device = map_registry_disk_blob (g, blob);
+
if (device != NULL) {
fs->drive_mappings[count++] = safe_strndup (g, &key[12], 1);
fs->drive_mappings[count++] = device;
@@ -605,6 +615,88 @@ map_registry_disk_blob (guestfs_h *g, const void *blob)
return safe_asprintf (g, "%s%d", devices[i], partitions->val[j].part_num);
}
+/* Matches Windows registry HKLM\SYSYTEM\MountedDevices\DosDevices blob to
+ * to libguestfs GPT partition device. For GPT disks, the blob is made of
+ * "DMIO:ID:" prefix followed by the GPT partition GUID.
+ */
+static char *
+map_registry_disk_blob_gpt (guestfs_h *g, const void *blob)
+{
+ CLEANUP_FREE_STRING_LIST char **parts = NULL;
+ CLEANUP_FREE char *blob_guid = extract_guid_from_registry_blob (g, blob);
+ size_t i;
+
+ parts = guestfs_list_partitions (g);
+ if (parts == NULL)
+ return NULL;
+
+ for (i = 0; parts[i] != NULL; ++i) {
+ CLEANUP_FREE char *fs_guid = NULL;
+ int partnum;
+ CLEANUP_FREE char *device = NULL;
+ CLEANUP_FREE char *type = NULL;
+
+ partnum = guestfs_part_to_partnum (g, parts[i]);
+ if (partnum == -1)
+ continue;
+
+ device = guestfs_part_to_dev (g, parts[i]);
+ if (device == NULL)
+ continue;
+
+ type = guestfs_part_get_parttype (g, device);
+ if (type == NULL)
+ continue;
+
+ if (STRCASENEQ (type, "gpt"))
+ continue;
+
+ /* get the GPT parition GUID from the partition block device */
+ fs_guid = guestfs_part_get_gpt_guid (g, device, partnum);
+ if (fs_guid == NULL)
+ continue;
+
+ /* if both GUIDs match, we have found the mapping for our device */
+ if (STRCASEEQ (fs_guid, blob_guid))
+ return safe_strdup (g, parts[i]);
+ }
+
+ return NULL;
+}
+
+/* Extracts the binary GUID stored in blob from Windows registry
+ * HKLM\SYSTYEM\MountedDevices\DosDevices value and converts it to a
+ * GUID string so that it can be matched against libguestfs partition
+ * device GPT GUID.
+ */
+static char *
+extract_guid_from_registry_blob (guestfs_h *g, const void *blob)
+{
+ char guid_bytes[16];
+ uint32_t data1;
+ uint16_t data2, data3;
+ uint64_t data4;
+
+ /* get the GUID bytes from blob (skip 8 byte "DMIO:ID:" prefix) */
+ memcpy (&guid_bytes, (char *) blob + 8, sizeof (guid_bytes));
+
+ /* copy relevant sections from blob to respective ints */
+ memcpy (&data1, guid_bytes, sizeof (data1));
+ memcpy (&data2, guid_bytes + 4, sizeof (data2));
+ memcpy (&data3, guid_bytes + 6, sizeof (data3));
+ memcpy (&data4, guid_bytes + 8, sizeof (data4));
+
+ /* ensure proper endianness */
+ data1 = le32toh (data1);
+ data2 = le16toh (data2);
+ data3 = le16toh (data3);
+ data4 = be64toh (data4);
+
+ return safe_asprintf (g,
+ "%08" PRIX32 "-%04" PRIX16 "-%04" PRIX16 "-%04" PRIX64 "-%012" PRIX64,
+ data1, data2, data3, data4 >> 48, data4 & 0xffffffffffff);
+}
+
/* NB: This function DOES NOT test for the existence of the file. It
* will return non-NULL even if the file/directory does not exist.
* You have to call guestfs_is_file{,_opts} etc.
--
2.5.0
8 years, 10 months
[PATCHv2] inspect: get windows drive letters for GPT disks.
by Dawid Zamirski
This patch updates the guestfs_inspect_get_drive_mappings API call to
also return drive letters for GPT paritions. Previously this worked
only for MBR partitions. This is achieved by matching the GPT partition
GUID with the info stored in the blob from
HKLM\SYSTEM\MountedDevices\DosDevices keys. For GPT partions this blob
contains a "DMIO:ID:" prefix followed by a 16 byte binary GUID.
---
changes since v1:
* applied style changes from review
* use guestfs_list_partitions instead of guestfs_list_filesystems
* do the GUID endianness conversion correctly
* check all API calls for errors
* do not call guestfs_canonical_device_name to prevent from changing
* block device names, i.e /dev/vda1 as it comes from list_partitions
* to /dev/sda1 in inspect_get_drive_mappings
src/inspect-fs-windows.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 102 insertions(+), 2 deletions(-)
diff --git a/src/inspect-fs-windows.c b/src/inspect-fs-windows.c
index ccf5cba..1698e81 100644
--- a/src/inspect-fs-windows.c
+++ b/src/inspect-fs-windows.c
@@ -25,6 +25,7 @@
#include <string.h>
#include <errno.h>
#include <iconv.h>
+#include <inttypes.h>
#ifdef HAVE_ENDIAN_H
#include <endian.h>
@@ -57,6 +58,8 @@ static int check_windows_arch (guestfs_h *g, struct inspect_fs *fs);
static int check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs);
static int check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs);
static char *map_registry_disk_blob (guestfs_h *g, const void *blob);
+static char *map_registry_disk_blob_gpt (guestfs_h *g, const void *blob);
+static char *extract_guid_from_registry_blob (guestfs_h *g, const void *blob);
/* XXX Handling of boot.ini in the Perl version was pretty broken. It
* essentially didn't do anything for modern Windows guests.
@@ -386,6 +389,7 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
int r;
size_t len = strlen (fs->windows_systemroot) + 64;
char system[len];
+ char gpt_prefix[] = "DMIO:ID:";
snprintf (system, len, "%s/system32/config/system",
fs->windows_systemroot);
@@ -490,12 +494,18 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
CLEANUP_FREE char *blob = NULL;
char *device;
int64_t type;
+ bool is_gpt;
type = guestfs_hivex_value_type (g, v);
blob = guestfs_hivex_value_value (g, v, &len);
- if (blob != NULL && type == 3 && len == 12) {
+ is_gpt = memcmp (blob, gpt_prefix, 8) == 0;
+ if (blob != NULL && type == 3 && (len == 12 || is_gpt)) {
/* Try to map the blob to a known disk and partition. */
- device = map_registry_disk_blob (g, blob);
+ if (is_gpt)
+ device = map_registry_disk_blob_gpt (g, blob);
+ else
+ device = map_registry_disk_blob (g, blob);
+
if (device != NULL) {
fs->drive_mappings[count++] = safe_strndup (g, &key[12], 1);
fs->drive_mappings[count++] = device;
@@ -605,6 +615,96 @@ map_registry_disk_blob (guestfs_h *g, const void *blob)
return safe_asprintf (g, "%s%d", devices[i], partitions->val[j].part_num);
}
+/* Matches Windows registry HKLM\SYSYTEM\MountedDevices\DosDevices blob to
+ * to libguestfs GPT partition device. For GPT disks, the blob is made of
+ * "DMIO:ID:" prefix followed by the GPT partition GUID.
+ */
+static char *
+map_registry_disk_blob_gpt (guestfs_h *g, const void *blob)
+{
+ CLEANUP_FREE_STRING_LIST char **parts = NULL;
+ size_t i;
+
+ parts = guestfs_list_partitions (g);
+
+ if (parts == NULL)
+ return NULL;
+
+ for (i = 0; parts[i] != NULL; i += 2) {
+ CLEANUP_FREE char *fs_guid = NULL;
+ CLEANUP_FREE char *blob_guid = NULL;
+ int partnum;
+ CLEANUP_FREE char *device = NULL;
+ CLEANUP_FREE char *type = NULL;
+
+ partnum = guestfs_part_to_partnum (g, parts[i]);
+
+ if (partnum == -1)
+ continue;
+
+ device = guestfs_part_to_dev (g, parts[i]);
+
+ if (device == NULL)
+ continue;
+
+ type = guestfs_part_get_parttype (g, device);
+
+ if (type == NULL)
+ continue;
+
+ if (STRCASENEQ (type, "gpt"))
+ continue;
+
+ /* get the GPT parition GUID from the partition block device */
+ fs_guid = guestfs_part_get_gpt_guid (g, device, partnum);
+
+ if (fs_guid == NULL)
+ continue;
+
+ /* extract the GUID from the Windows registry blob */
+ blob_guid = extract_guid_from_registry_blob (g, blob);
+
+ /* if both GUIDs match, we have found mapping for out device */
+ if (STRCASEEQ (fs_guid, blob_guid))
+ return safe_strdup (g, parts[i]);
+ }
+
+ return NULL;
+}
+
+/* Extracts the binary GUID stored in blob from Windows registry
+ * HKLM\SYSTYEM\MountedDevices\DosDevices value and converts it to a
+ * GUID string so that it can be matched against libguestfs partition
+ * device GPT GUID.
+ */
+static char *
+extract_guid_from_registry_blob (guestfs_h *g, const void *blob)
+{
+ char guid_bytes[16];
+ uint32_t data1;
+ uint16_t data2, data3;
+ uint64_t data4;
+
+ /* get the GUID bytes from blob (skip 8 byte "DMIO:ID:" prefix) */
+ memcpy (&guid_bytes, (char *) blob + 8, sizeof (guid_bytes));
+
+ /* copy relevant sections from blob to respective ints */
+ memcpy (&data1, guid_bytes, sizeof (data1));
+ memcpy (&data2, guid_bytes + 4, sizeof (data2));
+ memcpy (&data3, guid_bytes + 6, sizeof (data3));
+ memcpy (&data4, guid_bytes + 8, sizeof (data4));
+
+ /* ensure proper endianness */
+ data1 = le32toh (data1);
+ data2 = le16toh (data2);
+ data3 = le16toh (data3);
+ data4 = be64toh (data4);
+
+ return safe_asprintf (g,
+ "%08" PRIX32 "-%04" PRIX16 "-%04" PRIX16 "-%04" PRIX64 "-%06" PRIX64,
+ data1, data2, data3, (data4 >> 48), (data4 << 16));
+}
+
/* NB: This function DOES NOT test for the existence of the file. It
* will return non-NULL even if the file/directory does not exist.
* You have to call guestfs_is_file{,_opts} etc.
--
2.5.0
8 years, 10 months
[PATCH] inspect: get windows drive letters for GPT disks.
by Dawid Zamirski
This patch updates the guestfs_inspect_get_drive_mappings API call to
also return drive letters for GPT paritions. Previously this worked
only for MBR partitions. This is achieved by matching the GPT partition
GUID with the info stored in the blob from
HKLM\SYSTEM\MountedDevices\DosDevices keys. For GPT partions this blob
contains a "DMIO:ID:" prefix followed by a 16 byte binary GUID.
---
src/inspect-fs-windows.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 96 insertions(+), 2 deletions(-)
diff --git a/src/inspect-fs-windows.c b/src/inspect-fs-windows.c
index ccf5cba..6571d37 100644
--- a/src/inspect-fs-windows.c
+++ b/src/inspect-fs-windows.c
@@ -25,6 +25,7 @@
#include <string.h>
#include <errno.h>
#include <iconv.h>
+#include <inttypes.h>
#ifdef HAVE_ENDIAN_H
#include <endian.h>
@@ -57,6 +58,8 @@ static int check_windows_arch (guestfs_h *g, struct inspect_fs *fs);
static int check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs);
static int check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs);
static char *map_registry_disk_blob (guestfs_h *g, const void *blob);
+static char *map_registry_disk_blob_gpt(guestfs_h *g, const void *blob);
+static char *extract_guid_from_registry_blob(guestfs_h *g, const void *blob);
/* XXX Handling of boot.ini in the Perl version was pretty broken. It
* essentially didn't do anything for modern Windows guests.
@@ -386,6 +389,7 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
int r;
size_t len = strlen (fs->windows_systemroot) + 64;
char system[len];
+ char gpt_prefix[] = "DMIO:ID:";
snprintf (system, len, "%s/system32/config/system",
fs->windows_systemroot);
@@ -493,9 +497,14 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
type = guestfs_hivex_value_type (g, v);
blob = guestfs_hivex_value_value (g, v, &len);
- if (blob != NULL && type == 3 && len == 12) {
+ bool is_gpt = memcmp(blob, gpt_prefix, 8) == 0;
+ if (blob != NULL && type == 3 && (len == 12 || is_gpt)) {
/* Try to map the blob to a known disk and partition. */
- device = map_registry_disk_blob (g, blob);
+ if (is_gpt)
+ device = map_registry_disk_blob_gpt (g, blob);
+ else
+ device = map_registry_disk_blob (g, blob);
+
if (device != NULL) {
fs->drive_mappings[count++] = safe_strndup (g, &key[12], 1);
fs->drive_mappings[count++] = device;
@@ -605,6 +614,91 @@ map_registry_disk_blob (guestfs_h *g, const void *blob)
return safe_asprintf (g, "%s%d", devices[i], partitions->val[j].part_num);
}
+/* Matches Windows registry HKLM\SYSYTEM\MountedDevices\DosDevices blob to
+ * to libguestfs GPT partition device. For GPT disks, the blob is made of
+ * "DMIO:ID:" prefix followed by the GPT parition GUID.
+ */
+static char *
+map_registry_disk_blob_gpt (guestfs_h *g, const void *blob)
+{
+ CLEANUP_FREE_STRING_LIST char **fses = NULL;
+ size_t i;
+
+ fses = guestfs_list_filesystems (g);
+ if (fses == NULL)
+ return NULL;
+
+ for (i = 0; fses[i] != NULL; i += 2) {
+ CLEANUP_FREE char *fs_guid = NULL;
+ CLEANUP_FREE char *blob_guid = NULL;
+ CLEANUP_FREE char *fs_dev = NULL;
+
+ fs_dev = guestfs_canonical_device_name (g, fses[i]);
+
+ if (fs_dev == NULL)
+ continue;
+
+ int partnum = guestfs_part_to_partnum (g, fs_dev);
+ CLEANUP_FREE char *device = guestfs_part_to_dev (g, fs_dev);
+ CLEANUP_FREE char *type = guestfs_part_get_parttype (g, device);
+
+ if (STRCASENEQ(type, "gpt"))
+ continue;
+
+ /* get the GPT parition GUID from the partition block device */
+ fs_guid = guestfs_part_get_gpt_guid (g, device, partnum);
+
+ if (fs_guid == NULL)
+ continue;
+
+ /* extract the GUID from the Windows registry blob */
+ blob_guid = extract_guid_from_registry_blob (g, blob);
+
+ /* if both GUIDs match, we have found mapping for out device */
+ if (STRCASEEQ (fs_guid, blob_guid))
+ return safe_strdup (g, fs_dev);
+ }
+
+ return NULL;
+}
+
+/* Extracts the binary GUID stored in blob from Windows registry
+ * HKLM\SYSTYEM\MountedDevices\DosDevices value and converts it to a GUID string
+ * so that it can be matched against libguestfs partition device GPT GUID.
+ */
+static char *
+extract_guid_from_registry_blob (guestfs_h *g, const void *blob)
+{
+ char guid_bytes[16];
+ size_t len = 37;
+ uint32_t data1;
+ uint16_t data2, data3;
+ uint64_t data4;
+
+ char *guid = (char *) safe_calloc(g, len, sizeof (char * ));
+
+ /* get the GUID bytes from blob (skip 8 byte "DMIO:ID:" prefix) */
+ memcpy (&guid_bytes, (char *) blob + 8, sizeof (guid_bytes));
+
+ /* copy relevant sections from blob to respective ints */
+ memcpy (&data1, guid_bytes, sizeof (data1));
+ memcpy (&data2, guid_bytes + 4, sizeof (data2));
+ memcpy (&data3, guid_bytes + 6, sizeof (data3));
+ memcpy (&data4, guid_bytes + 8, sizeof (data4));
+
+ /* ensure proper endianness */
+ data1 = htole32 (data1);
+ data2 = htole16 (data2);
+ data3 = htole16 (data3);
+ data4 = htobe64 (data4);
+
+ snprintf (guid, len,
+ "%08" PRIX32 "-%04" PRIX16 "-%04" PRIX16 "-%04" PRIX64 "-%06" PRIX64,
+ data1, data2, data3, (data4 >> 48), (data4 << 16));
+
+ return guid;
+}
+
/* NB: This function DOES NOT test for the existence of the file. It
* will return non-NULL even if the file/directory does not exist.
* You have to call guestfs_is_file{,_opts} etc.
--
2.5.0
8 years, 10 months
[PATCH 0/7] lib: Stop exporting the safe_malloc, etc. functions.
by Richard W.M. Jones
The safe_malloc (etc) functions call g->abort_fn on failure. That's
not appropriate for language bindings, and we never intended that
these internal functions be used from language bindings, that was just
a historical accident.
This patch series removes any external use of the safe_* functions.
Rich.
8 years, 10 months
[PATCH] aarch64: Use a common table of AAVMF paths.
by Richard W.M. Jones
Previously the code had two places where an identical set of AAVMF
paths were stored. Put this information into one place.
This is just refactoring.
---
src/appliance.c | 26 +++++---------------------
src/guestfs-internal-frontend.h | 1 +
src/utils.c | 12 ++++++++++++
v2v/utils-c.c | 27 +++++++++++++++++++++++++++
v2v/utils.ml | 7 +++----
5 files changed, 48 insertions(+), 25 deletions(-)
diff --git a/src/appliance.c b/src/appliance.c
index 1dbf9c7..dbde35e 100644
--- a/src/appliance.c
+++ b/src/appliance.c
@@ -443,32 +443,15 @@ dir_contains_files (const char *dir, ...)
*
* XXX See also v2v/utils.ml:find_uefi_firmware
*/
-#ifdef __aarch64__
-
-static const char *uefi_firmware[] = {
- "/usr/share/AAVMF/AAVMF_CODE.fd",
- "/usr/share/AAVMF/AAVMF_VARS.fd",
-
- "/usr/share/edk2.git/aarch64/QEMU_EFI-pflash.raw",
- "/usr/share/edk2.git/aarch64/vars-template-pflash.raw",
-
- NULL
-};
-
-#else
-
-static const char *uefi_firmware[] = { NULL };
-
-#endif
-
int
guestfs_int_get_uefi (guestfs_h *g, char **code, char **vars)
{
+#ifdef __aarch64__
size_t i;
- for (i = 0; uefi_firmware[i] != NULL; i += 2) {
- const char *codefile = uefi_firmware[i];
- const char *varsfile = uefi_firmware[i+1];
+ for (i = 0; guestfs_int_aavmf_firmware[i] != NULL; i += 2) {
+ const char *codefile = guestfs_int_aavmf_firmware[i];
+ const char *varsfile = guestfs_int_aavmf_firmware[i+1];
if (access (codefile, R_OK) == 0 && access (varsfile, R_OK) == 0) {
CLEANUP_CMD_CLOSE struct command *copycmd = guestfs_int_new_command (g);
@@ -495,6 +478,7 @@ guestfs_int_get_uefi (guestfs_h *g, char **code, char **vars)
return 0;
}
}
+#endif
/* Not found. */
*code = *vars = NULL;
diff --git a/src/guestfs-internal-frontend.h b/src/guestfs-internal-frontend.h
index 2fbf875..6f54a73 100644
--- a/src/guestfs-internal-frontend.h
+++ b/src/guestfs-internal-frontend.h
@@ -107,6 +107,7 @@ extern int guestfs_int_random_string (char *ret, size_t len);
extern char *guestfs_int_drive_name (size_t index, char *ret);
extern ssize_t guestfs_int_drive_index (const char *);
extern int guestfs_int_is_true (const char *str);
+extern const char *guestfs_int_aavmf_firmware[];
/* These functions are used internally by the CLEANUP_* macros.
* Don't call them directly.
diff --git a/src/utils.c b/src/utils.c
index 36fd458..9244d16 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -314,3 +314,15 @@ guestfs_int_is_true (const char *str)
return -1;
}
+
+/* See src/appliance.c:guestfs_int_get_uefi. */
+const char *
+guestfs_int_aavmf_firmware[] = {
+ "/usr/share/AAVMF/AAVMF_CODE.fd",
+ "/usr/share/AAVMF/AAVMF_VARS.fd",
+
+ "/usr/share/edk2.git/aarch64/QEMU_EFI-pflash.raw",
+ "/usr/share/edk2.git/aarch64/vars-template-pflash.raw",
+
+ NULL
+};
diff --git a/v2v/utils-c.c b/v2v/utils-c.c
index 66291b2..4ec4063 100644
--- a/v2v/utils-c.c
+++ b/v2v/utils-c.c
@@ -57,3 +57,30 @@ v2v_utils_drive_index (value strv)
CAMLreturn (Val_int (r));
}
+
+value
+v2v_utils_aavmf_firmware (value unitv)
+{
+ CAMLparam1 (unitv);
+ CAMLlocal5 (rv, v, v1, v2, cons);
+ /* Initialize the list backwards. */
+ size_t i = guestfs_int_count_strings ((char **) guestfs_int_aavmf_firmware);
+
+ rv = Val_int (0);
+
+ while (i > 0) {
+ v1 = caml_copy_string (guestfs_int_aavmf_firmware[i-2]);
+ v2 = caml_copy_string (guestfs_int_aavmf_firmware[i-1]);
+ v = caml_alloc (2, 0);
+ Store_field (v, 0, v1);
+ Store_field (v, 1, v2);
+ cons = caml_alloc (2, 0);
+ Store_field (cons, 1, rv);
+ rv = cons;
+ Store_field (cons, 0, v);
+
+ i -= 2;
+ }
+
+ CAMLreturn (rv);
+}
diff --git a/v2v/utils.ml b/v2v/utils.ml
index 82f4377..636f3c2 100644
--- a/v2v/utils.ml
+++ b/v2v/utils.ml
@@ -81,6 +81,8 @@ let qemu_supports_sound_card = function
| Types.USBAudio
-> true
+external aavmf_firmware : unit -> (string * string) list = "v2v_utils_aavmf_firmware"
+
(* Find the UEFI firmware. *)
let find_uefi_firmware guest_arch =
let files =
@@ -96,10 +98,7 @@ let find_uefi_firmware guest_arch =
"/usr/share/qemu/ovmf-x86_64-code.bin",
"/usr/share/qemu/ovmf-x86_64-vars.bin" ]
| "aarch64" ->
- [ "/usr/share/AAVMF/AAVMF_CODE.fd",
- "/usr/share/AAVMF/AAVMF_VARS.fd";
- "/usr/share/edk2.git/aarch64/QEMU_EFI-pflash.raw",
- "/usr/share/edk2.git/aarch64/vars-template-pflash.raw" ]
+ aavmf_firmware () (* actually defined in src/utils.c *)
| arch ->
error (f_"don't know how to convert UEFI guests for architecture %s")
guest_arch in
--
2.5.0
8 years, 10 months