mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
Update inspection and example programs to use new hivex* APIs (RHBZ#852394).
I tested this by comparing the output of virt-inspector over Windows guests before and after the change, which was identical: $ md5sum `ls -1 /tmp/*.before /tmp/*.after` c292d6629b5a761eccb4a279754399b4 /tmp/Win2003.after c292d6629b5a761eccb4a279754399b4 /tmp/Win2003.before eb1e1ff29208a9ee46e9c100dfec26b2 /tmp/Win2012.after eb1e1ff29208a9ee46e9c100dfec26b2 /tmp/Win2012.before d060a95d7ffe5dce6c4e66feb80c2837 /tmp/Win7x32.after d060a95d7ffe5dce6c4e66feb80c2837 /tmp/Win7x32.before 8914eee70ac4f8a0317659e09e00dcdc /tmp/Win7x32Dynamic.after 8914eee70ac4f8a0317659e09e00dcdc /tmp/Win7x32Dynamic.before a2dcdfc0f9d64054640875aa791889e0 /tmp/Win7x32TwoDisks.after a2dcdfc0f9d64054640875aa791889e0 /tmp/Win7x32TwoDisks.before 5ed49568a5147dce7517c99de41ebf2e /tmp/Win8previewx64.after 5ed49568a5147dce7517c99de41ebf2e /tmp/Win8previewx64.before fdfc7d272b79a665ae3313ae1ae30660 /tmp/WinXP.after fdfc7d272b79a665ae3313ae1ae30660 /tmp/WinXP.before 3c705444be664f1316b21c5d8d3cb0be /tmp/WinXPRecConsole.after 3c705444be664f1316b21c5d8d3cb0be /tmp/WinXPRecConsole.before
This commit is contained in:
8
TODO
8
TODO
@@ -570,3 +570,11 @@ mke2fs
|
||||
|
||||
Add a mke2fs API call allowing full configuration of filesystems.
|
||||
Then fix tests/bigdirs/test-big-dirs.pl to use it.
|
||||
|
||||
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).
|
||||
|
||||
@@ -95,10 +95,8 @@ virt_dhcp_address_SOURCES = virt-dhcp-address.c
|
||||
virt_dhcp_address_CFLAGS = \
|
||||
-DGUESTFS_WARN_DEPRECATED=1 \
|
||||
-I$(top_srcdir)/src -I$(top_builddir)/src \
|
||||
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
|
||||
$(HIVEX_CFLAGS)
|
||||
$(WARN_CFLAGS) $(WERROR_CFLAGS)
|
||||
virt_dhcp_address_LDADD = \
|
||||
$(HIVEX_LIBS) \
|
||||
$(top_builddir)/src/libguestfs.la
|
||||
endif
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include <guestfs.h>
|
||||
#include <hivex.h>
|
||||
|
||||
static int compare_keys_len (const void *p1, const void *p2);
|
||||
static size_t count_strings (char *const *argv);
|
||||
@@ -198,11 +197,8 @@ static void
|
||||
print_dhcp_address_windows (guestfs_h *g, char *root_fs)
|
||||
{
|
||||
char *system_path;
|
||||
char tmpfile[] = "/tmp/systemXXXXXX";
|
||||
int fd, err;
|
||||
hive_h *h;
|
||||
hive_node_h root, node, *nodes;
|
||||
hive_value_h value;
|
||||
int64_t root, node, value;
|
||||
struct guestfs_hivex_node_list *nodes;
|
||||
char *controlset;
|
||||
size_t i;
|
||||
char *p;
|
||||
@@ -215,71 +211,52 @@ print_dhcp_address_windows (guestfs_h *g, char *root_fs)
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fd = mkstemp (tmpfile);
|
||||
if (fd == -1) {
|
||||
perror ("mkstemp");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Download the SYSTEM hive. */
|
||||
if (guestfs_download (g, system_path, tmpfile) == -1)
|
||||
/* Open the hive to parse it. Note that before libguestfs 1.19.35
|
||||
* you had to download the file and parse it using hivex(3). Since
|
||||
* libguestfs 1.19.35, parts of the hivex(3) API are now exposed
|
||||
* through libguestfs, and that is what we'll use here because it is
|
||||
* more convenient and avoids having to download the hive.
|
||||
*/
|
||||
if (guestfs_hivex_open (g, system_path, -1) == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
free (system_path);
|
||||
|
||||
root = guestfs_hivex_root (g);
|
||||
if (root == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
/* Get ControlSetXXX\Services\Tcpip\Parameters\Interfaces. */
|
||||
controlset = guestfs_inspect_get_windows_current_control_set (g, root_fs);
|
||||
if (controlset == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
/* Open the hive to parse it. */
|
||||
h = hivex_open (tmpfile, 0);
|
||||
err = errno;
|
||||
close (fd);
|
||||
unlink (tmpfile);
|
||||
|
||||
if (h == NULL) {
|
||||
errno = err;
|
||||
perror ("hivex_open");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
root = hivex_root (h);
|
||||
if (root == 0) {
|
||||
perror ("hivex_root");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Get ControlSetXXX\Services\Tcpip\Parameters\Interfaces. */
|
||||
const char *path[] = { controlset, "Services", "Tcpip", "Parameters",
|
||||
"Interfaces" };
|
||||
node = root;
|
||||
errno = 0;
|
||||
for (i = 0; node != 0 && i < sizeof path / sizeof path[0]; ++i)
|
||||
node = hivex_node_get_child (h, node, path[i]);
|
||||
for (i = 0; node > 0 && i < sizeof path / sizeof path[0]; ++i)
|
||||
node = guestfs_hivex_node_get_child (g, node, path[i]);
|
||||
|
||||
if (node == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
if (node == 0) {
|
||||
if (errno != 0)
|
||||
perror ("hivex_node_get_child");
|
||||
else
|
||||
fprintf (stderr, "virt-dhcp-address: HKLM\\System\\%s\\Services\\Tcpip\\Parameters\\Interfaces not found.", controlset);
|
||||
fprintf (stderr, "virt-dhcp-address: HKLM\\System\\%s\\Services\\Tcpip\\Parameters\\Interfaces not found.", controlset);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
free (controlset);
|
||||
|
||||
/* Look for a node under here which has a "DhcpIPAddress" entry in it. */
|
||||
nodes = hivex_node_children (h, node);
|
||||
if (nodes == NULL) {
|
||||
perror ("hivex_node_children");
|
||||
nodes = guestfs_hivex_node_children (g, node);
|
||||
if (nodes == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
value = 0;
|
||||
for (i = 0; value == 0 && nodes[i] != 0; ++i) {
|
||||
errno = 0;
|
||||
value = hivex_node_get_value (h, nodes[i], "DhcpIPAddress");
|
||||
if (value == 0 && errno != 0) {
|
||||
perror ("hivex_node_get_value");
|
||||
for (i = 0; value == 0 && i < nodes->len; ++i) {
|
||||
value = guestfs_hivex_node_get_value (g, nodes->val[i].hivex_node_h,
|
||||
"DhcpIPAddress");
|
||||
if (value == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (value == 0) {
|
||||
@@ -287,21 +264,21 @@ print_dhcp_address_windows (guestfs_h *g, char *root_fs)
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Get the string and use hivex's auto-conversion to convert it to UTF-8
|
||||
* for output.
|
||||
guestfs_free_hivex_node_list (nodes);
|
||||
|
||||
/* Get the string and use libguestfs's auto-conversion to convert it
|
||||
* to UTF-8 for output.
|
||||
*/
|
||||
p = hivex_value_string (h, value);
|
||||
if (!p) {
|
||||
perror ("hivex_value_string");
|
||||
p = guestfs_hivex_value_utf8 (g, value);
|
||||
if (!p)
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf ("%s\n", p);
|
||||
|
||||
/* Close the hive handle. */
|
||||
hivex_close (h);
|
||||
free (p);
|
||||
|
||||
free (controlset);
|
||||
/* Close the hive handle. */
|
||||
guestfs_hivex_close (g);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -148,7 +148,7 @@ libguestfs_la_SOURCES = \
|
||||
libguestfs.syms
|
||||
|
||||
libguestfs_la_LIBADD = \
|
||||
$(HIVEX_LIBS) $(PCRE_LIBS) $(MAGIC_LIBS) \
|
||||
$(PCRE_LIBS) $(MAGIC_LIBS) \
|
||||
$(LIBVIRT_LIBS) $(LIBXML2_LIBS) \
|
||||
../gnulib/lib/libgnu.la \
|
||||
$(GETADDRINFO_LIB) \
|
||||
@@ -167,7 +167,7 @@ libguestfs_la_LIBADD += liberrnostring.la libprotocol.la
|
||||
libguestfs_la_CFLAGS = \
|
||||
-DGUESTFS_DEFAULT_PATH='"$(libdir)/guestfs"' \
|
||||
-DGUESTFS_WARN_DEPRECATED=1 \
|
||||
$(HIVEX_CFLAGS) $(PCRE_CFLAGS) \
|
||||
$(PCRE_CFLAGS) \
|
||||
$(LIBVIRT_CFLAGS) $(LIBXML2_CFLAGS) \
|
||||
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
|
||||
$(GCC_VISIBILITY_HIDDEN)
|
||||
|
||||
@@ -34,10 +34,6 @@
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
#ifdef HAVE_HIVEX
|
||||
#include <hivex.h>
|
||||
#endif
|
||||
|
||||
#include "c-ctype.h"
|
||||
#include "ignore-value.h"
|
||||
|
||||
|
||||
@@ -107,11 +107,6 @@
|
||||
#define MAX_SMALL_FILE_SIZE (2 * 1000 * 1000)
|
||||
#define MAX_AUGEAS_FILE_SIZE (100 * 1000)
|
||||
|
||||
/* Maximum Windows Registry hive that we will download to /tmp. Some
|
||||
* registries can be legitimately very large.
|
||||
*/
|
||||
#define MAX_REGISTRY_SIZE (100 * 1000 * 1000)
|
||||
|
||||
/* Maximum RPM or dpkg database we will download to /tmp. RPM
|
||||
* 'Packages' database can get very large: 70 MB is roughly the
|
||||
* standard size for a new Fedora install, and after lots of package
|
||||
@@ -474,8 +469,6 @@ extern char *guestfs___download_to_tmp (guestfs_h *g, struct inspect_fs *fs, con
|
||||
extern char *guestfs___case_sensitive_path_silently (guestfs_h *g, const char *);
|
||||
extern struct inspect_fs *guestfs___search_for_root (guestfs_h *g, const char *root);
|
||||
extern char *guestfs___drive_name (size_t index, char *ret);
|
||||
|
||||
#if defined(HAVE_HIVEX)
|
||||
extern int guestfs___check_for_filesystem_on (guestfs_h *g, const char *device, int is_block, int is_partnum);
|
||||
extern int guestfs___parse_unsigned_int (guestfs_h *g, const char *str);
|
||||
extern int guestfs___parse_unsigned_int_ignore_trailing (guestfs_h *g, const char *str);
|
||||
@@ -491,7 +484,6 @@ extern int guestfs___check_netbsd_root (guestfs_h *g, struct inspect_fs *fs);
|
||||
extern int guestfs___check_hurd_root (guestfs_h *g, struct inspect_fs *fs);
|
||||
extern int guestfs___has_windows_systemroot (guestfs_h *g);
|
||||
extern int guestfs___check_windows_root (guestfs_h *g, struct inspect_fs *fs);
|
||||
#endif
|
||||
|
||||
#define error(g,...) guestfs_error_errno((g),0,__VA_ARGS__)
|
||||
#define perrorf guestfs_perrorf
|
||||
|
||||
@@ -34,10 +34,6 @@
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
#ifdef HAVE_HIVEX
|
||||
#include <hivex.h>
|
||||
#endif
|
||||
|
||||
#include "c-ctype.h"
|
||||
#include "ignore-value.h"
|
||||
#include "xstrtol.h"
|
||||
@@ -47,8 +43,6 @@
|
||||
#include "guestfs-internal-actions.h"
|
||||
#include "guestfs_protocol.h"
|
||||
|
||||
#if defined(HAVE_HIVEX)
|
||||
|
||||
#ifdef DB_DUMP
|
||||
static struct guestfs_application_list *list_applications_rpm (guestfs_h *g, struct inspect_fs *fs);
|
||||
#endif
|
||||
@@ -414,7 +408,7 @@ list_applications_deb (guestfs_h *g, struct inspect_fs *fs)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void list_applications_windows_from_path (guestfs_h *g, hive_h *h, struct guestfs_application_list *apps, const char **path, size_t path_len);
|
||||
static void list_applications_windows_from_path (guestfs_h *g, struct guestfs_application_list *apps, const char **path, size_t path_len);
|
||||
|
||||
static struct guestfs_application_list *
|
||||
list_applications_windows (guestfs_h *g, struct inspect_fs *fs)
|
||||
@@ -431,24 +425,12 @@ list_applications_windows (guestfs_h *g, struct inspect_fs *fs)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *software_hive = NULL;
|
||||
struct guestfs_application_list *ret = NULL;
|
||||
hive_h *h = NULL;
|
||||
|
||||
software_hive = guestfs___download_to_tmp (g, fs, software_path, "software",
|
||||
MAX_REGISTRY_SIZE);
|
||||
if (software_hive == NULL)
|
||||
if (guestfs_hivex_open (g, software_path,
|
||||
GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose, -1) == -1)
|
||||
goto out;
|
||||
|
||||
free (software_path);
|
||||
software_path = NULL;
|
||||
|
||||
h = hivex_open (software_hive, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
|
||||
if (h == NULL) {
|
||||
perrorf (g, "hivex_open");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Allocate apps list. */
|
||||
ret = safe_malloc (g, sizeof *ret);
|
||||
ret->len = 0;
|
||||
@@ -457,7 +439,7 @@ list_applications_windows (guestfs_h *g, struct inspect_fs *fs)
|
||||
/* Ordinary native applications. */
|
||||
const char *hivepath[] =
|
||||
{ "Microsoft", "Windows", "CurrentVersion", "Uninstall" };
|
||||
list_applications_windows_from_path (g, h, ret, hivepath,
|
||||
list_applications_windows_from_path (g, ret, hivepath,
|
||||
sizeof hivepath / sizeof hivepath[0]);
|
||||
|
||||
/* 32-bit emulated Windows apps running on the WOW64 emulator.
|
||||
@@ -465,35 +447,34 @@ list_applications_windows (guestfs_h *g, struct inspect_fs *fs)
|
||||
*/
|
||||
const char *hivepath2[] =
|
||||
{ "WOW6432node", "Microsoft", "Windows", "CurrentVersion", "Uninstall" };
|
||||
list_applications_windows_from_path (g, h, ret, hivepath2,
|
||||
list_applications_windows_from_path (g, ret, hivepath2,
|
||||
sizeof hivepath2 / sizeof hivepath2[0]);
|
||||
|
||||
out:
|
||||
if (h) hivex_close (h);
|
||||
guestfs_hivex_close (g);
|
||||
free (software_path);
|
||||
free (software_hive);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
list_applications_windows_from_path (guestfs_h *g, hive_h *h,
|
||||
list_applications_windows_from_path (guestfs_h *g,
|
||||
struct guestfs_application_list *apps,
|
||||
const char **path, size_t path_len)
|
||||
{
|
||||
hive_node_h *children = NULL;
|
||||
hive_node_h node;
|
||||
struct guestfs_hivex_node_list *children = NULL;
|
||||
int64_t node;
|
||||
size_t i;
|
||||
|
||||
node = hivex_root (h);
|
||||
node = guestfs_hivex_root (g);
|
||||
|
||||
for (i = 0; node != 0 && i < path_len; ++i)
|
||||
node = hivex_node_get_child (h, node, path[i]);
|
||||
node = guestfs_hivex_node_get_child (g, node, path[i]);
|
||||
|
||||
if (node == 0)
|
||||
return;
|
||||
|
||||
children = hivex_node_children (h, node);
|
||||
children = guestfs_hivex_node_children (g, node);
|
||||
if (children == NULL)
|
||||
return;
|
||||
|
||||
@@ -501,8 +482,9 @@ list_applications_windows_from_path (guestfs_h *g, hive_h *h,
|
||||
* See also:
|
||||
* http://nsis.sourceforge.net/Add_uninstall_information_to_Add/Remove_Programs#Optional_values
|
||||
*/
|
||||
for (i = 0; children[i] != 0; ++i) {
|
||||
hive_value_h value;
|
||||
for (i = 0; i < children->len; ++i) {
|
||||
int64_t child = children->val[i].hivex_node_h;
|
||||
int64_t value;
|
||||
char *name = NULL;
|
||||
char *display_name = NULL;
|
||||
char *version = NULL;
|
||||
@@ -514,29 +496,29 @@ list_applications_windows_from_path (guestfs_h *g, hive_h *h,
|
||||
/* Use the node name as a proxy for the package name in Linux. The
|
||||
* display name is not language-independent, so it cannot be used.
|
||||
*/
|
||||
name = hivex_node_name (h, children[i]);
|
||||
name = guestfs_hivex_node_name (g, child);
|
||||
if (name == NULL)
|
||||
continue;
|
||||
|
||||
value = hivex_node_get_value (h, children[i], "DisplayName");
|
||||
value = guestfs_hivex_node_get_value (g, child, "DisplayName");
|
||||
if (value) {
|
||||
display_name = hivex_value_string (h, value);
|
||||
display_name = guestfs_hivex_value_utf8 (g, value);
|
||||
if (display_name) {
|
||||
value = hivex_node_get_value (h, children[i], "DisplayVersion");
|
||||
value = guestfs_hivex_node_get_value (g, child, "DisplayVersion");
|
||||
if (value)
|
||||
version = hivex_value_string (h, value);
|
||||
value = hivex_node_get_value (h, children[i], "InstallLocation");
|
||||
version = guestfs_hivex_value_utf8 (g, value);
|
||||
value = guestfs_hivex_node_get_value (g, child, "InstallLocation");
|
||||
if (value)
|
||||
install_path = hivex_value_string (h, value);
|
||||
value = hivex_node_get_value (h, children[i], "Publisher");
|
||||
install_path = guestfs_hivex_value_utf8 (g, value);
|
||||
value = guestfs_hivex_node_get_value (g, child, "Publisher");
|
||||
if (value)
|
||||
publisher = hivex_value_string (h, value);
|
||||
value = hivex_node_get_value (h, children[i], "URLInfoAbout");
|
||||
publisher = guestfs_hivex_value_utf8 (g, value);
|
||||
value = guestfs_hivex_node_get_value (g, child, "URLInfoAbout");
|
||||
if (value)
|
||||
url = hivex_value_string (h, value);
|
||||
value = hivex_node_get_value (h, children[i], "Comments");
|
||||
url = guestfs_hivex_value_utf8 (g, value);
|
||||
value = guestfs_hivex_node_get_value (g, child, "Comments");
|
||||
if (value)
|
||||
comments = hivex_value_string (h, value);
|
||||
comments = guestfs_hivex_value_utf8 (g, value);
|
||||
|
||||
add_application (g, apps, name, display_name, 0,
|
||||
version ? : "",
|
||||
@@ -557,7 +539,7 @@ list_applications_windows_from_path (guestfs_h *g, hive_h *h,
|
||||
free (comments);
|
||||
}
|
||||
|
||||
free (children);
|
||||
guestfs_free_hivex_node_list (children);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -606,19 +588,3 @@ sort_applications (struct guestfs_application_list *apps)
|
||||
qsort (apps->val, apps->len, sizeof (struct guestfs_application),
|
||||
compare_applications);
|
||||
}
|
||||
|
||||
#else /* no hivex at compile time */
|
||||
|
||||
/* XXX These functions should be in an optgroup. */
|
||||
|
||||
#define NOT_IMPL(r) \
|
||||
error (g, _("inspection API not available since this version of libguestfs was compiled without the hivex library")); \
|
||||
return r
|
||||
|
||||
struct guestfs_application_list *
|
||||
guestfs__inspect_list_applications (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
#endif /* no hivex at compile time */
|
||||
|
||||
@@ -34,10 +34,6 @@
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
#ifdef HAVE_HIVEX
|
||||
#include <hivex.h>
|
||||
#endif
|
||||
|
||||
#include "c-ctype.h"
|
||||
#include "ignore-value.h"
|
||||
#include "xstrtol.h"
|
||||
@@ -47,8 +43,6 @@
|
||||
#include "guestfs-internal-actions.h"
|
||||
#include "guestfs_protocol.h"
|
||||
|
||||
#if defined(HAVE_HIVEX)
|
||||
|
||||
/* Debian/Ubuntu install disks are easy ...
|
||||
*
|
||||
* These files are added by the debian-cd program, and it is worth
|
||||
@@ -484,5 +478,3 @@ guestfs___check_installer_root (guestfs_h *g, struct inspect_fs *fs)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_HIVEX) */
|
||||
|
||||
@@ -34,10 +34,6 @@
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
#ifdef HAVE_HIVEX
|
||||
#include <hivex.h>
|
||||
#endif
|
||||
|
||||
#include "c-ctype.h"
|
||||
#include "ignore-value.h"
|
||||
#include "xstrtol.h"
|
||||
@@ -49,8 +45,6 @@
|
||||
#include "guestfs-internal-actions.h"
|
||||
#include "guestfs_protocol.h"
|
||||
|
||||
#if defined(HAVE_HIVEX)
|
||||
|
||||
/* Compile all the regular expressions once when the shared library is
|
||||
* loaded. PCRE is thread safe so we're supposedly OK here if
|
||||
* multiple threads call into the libguestfs API functions below
|
||||
@@ -1536,5 +1530,3 @@ is_partition (guestfs_h *g, const char *partition)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_HIVEX) */
|
||||
|
||||
@@ -35,10 +35,6 @@
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
#ifdef HAVE_HIVEX
|
||||
#include <hivex.h>
|
||||
#endif
|
||||
|
||||
#include "c-ctype.h"
|
||||
#include "ignore-value.h"
|
||||
#include "xstrtol.h"
|
||||
@@ -48,8 +44,6 @@
|
||||
#include "guestfs-internal-actions.h"
|
||||
#include "guestfs_protocol.h"
|
||||
|
||||
#if defined(HAVE_HIVEX)
|
||||
|
||||
/* Compile all the regular expressions once when the shared library is
|
||||
* loaded. PCRE is thread safe so we're supposedly OK here if
|
||||
* multiple threads call into the libguestfs API functions below
|
||||
@@ -215,6 +209,8 @@ check_windows_arch (guestfs_h *g, struct inspect_fs *fs)
|
||||
static int
|
||||
check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
size_t len = strlen (fs->windows_systemroot) + 64;
|
||||
char software[len];
|
||||
snprintf (software, len, "%s/system32/config/software",
|
||||
@@ -227,60 +223,46 @@ check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
|
||||
*/
|
||||
return 0;
|
||||
|
||||
char *software_hive = NULL;
|
||||
int ret = -1;
|
||||
hive_h *h = NULL;
|
||||
hive_value_h *values = NULL;
|
||||
|
||||
software_hive = guestfs___download_to_tmp (g, fs, software_path, "software",
|
||||
MAX_REGISTRY_SIZE);
|
||||
if (software_hive == NULL)
|
||||
if (guestfs_hivex_open (g, software_path,
|
||||
GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose, -1) == -1)
|
||||
goto out;
|
||||
|
||||
h = hivex_open (software_hive, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
|
||||
if (h == NULL) {
|
||||
perrorf (g, "hivex_open");
|
||||
goto out;
|
||||
}
|
||||
|
||||
hive_node_h node = hivex_root (h);
|
||||
int64_t node = guestfs_hivex_root (g);
|
||||
const char *hivepath[] =
|
||||
{ "Microsoft", "Windows NT", "CurrentVersion" };
|
||||
size_t i;
|
||||
for (i = 0;
|
||||
node != 0 && i < sizeof hivepath / sizeof hivepath[0];
|
||||
++i) {
|
||||
node = hivex_node_get_child (h, node, hivepath[i]);
|
||||
}
|
||||
for (i = 0; node > 0 && i < sizeof hivepath / sizeof hivepath[0]; ++i)
|
||||
node = guestfs_hivex_node_get_child (g, node, hivepath[i]);
|
||||
|
||||
if (node == -1)
|
||||
goto out;
|
||||
|
||||
if (node == 0) {
|
||||
perrorf (g, "hivex: cannot locate HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
|
||||
goto out;
|
||||
}
|
||||
|
||||
values = hivex_node_values (h, node);
|
||||
struct guestfs_hivex_value_list *values = NULL;
|
||||
values = guestfs_hivex_node_values (g, node);
|
||||
|
||||
for (i = 0; values[i] != 0; ++i) {
|
||||
char *key = hivex_value_key (h, values[i]);
|
||||
if (key == NULL) {
|
||||
perrorf (g, "hivex_value_key");
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < values->len; ++i) {
|
||||
int64_t value = values->val[i].hivex_value_h;
|
||||
char *key = guestfs_hivex_value_key (g, value);
|
||||
if (key == NULL)
|
||||
goto out2;
|
||||
|
||||
if (STRCASEEQ (key, "ProductName")) {
|
||||
fs->product_name = hivex_value_string (h, values[i]);
|
||||
fs->product_name = guestfs_hivex_value_utf8 (g, value);
|
||||
if (!fs->product_name) {
|
||||
perrorf (g, "hivex_value_string");
|
||||
free (key);
|
||||
goto out;
|
||||
goto out2;
|
||||
}
|
||||
}
|
||||
else if (STRCASEEQ (key, "CurrentVersion")) {
|
||||
char *version = hivex_value_string (h, values[i]);
|
||||
char *version = guestfs_hivex_value_utf8 (g, value);
|
||||
if (!version) {
|
||||
perrorf (g, "hivex_value_string");
|
||||
free (key);
|
||||
goto out;
|
||||
goto out2;
|
||||
}
|
||||
char *major, *minor;
|
||||
if (match2 (g, version, re_windows_version, &major, &minor)) {
|
||||
@@ -290,25 +272,24 @@ check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
|
||||
free (minor);
|
||||
free (key);
|
||||
free (version);
|
||||
goto out;
|
||||
goto out2;
|
||||
}
|
||||
fs->minor_version = guestfs___parse_unsigned_int (g, minor);
|
||||
free (minor);
|
||||
if (fs->minor_version == -1) {
|
||||
free (key);
|
||||
free (version);
|
||||
goto out;
|
||||
goto out2;
|
||||
}
|
||||
}
|
||||
|
||||
free (version);
|
||||
}
|
||||
else if (STRCASEEQ (key, "InstallationType")) {
|
||||
fs->product_variant = hivex_value_string (h, values[i]);
|
||||
fs->product_variant = guestfs_hivex_value_utf8 (g, value);
|
||||
if (!fs->product_variant) {
|
||||
perrorf (g, "hivex_value_string");
|
||||
free (key);
|
||||
goto out;
|
||||
goto out2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,11 +298,11 @@ check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
|
||||
|
||||
ret = 0;
|
||||
|
||||
out2:
|
||||
guestfs_free_hivex_value_list (values);
|
||||
out:
|
||||
if (h) hivex_close (h);
|
||||
free (values);
|
||||
guestfs_hivex_close (g);
|
||||
free (software_path);
|
||||
free (software_hive);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -341,110 +322,94 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
|
||||
*/
|
||||
return 0;
|
||||
|
||||
char *system_hive = NULL;
|
||||
int ret = -1;
|
||||
hive_h *h = NULL;
|
||||
hive_node_h root, node;
|
||||
hive_value_h value, *values = NULL;
|
||||
int64_t root, node, value;
|
||||
struct guestfs_hivex_value_list *values = NULL;
|
||||
int32_t dword;
|
||||
size_t i, count;
|
||||
char *buf = NULL;
|
||||
size_t buflen;
|
||||
|
||||
system_hive =
|
||||
guestfs___download_to_tmp (g, fs, system_path, "system",
|
||||
MAX_REGISTRY_SIZE);
|
||||
if (system_hive == NULL)
|
||||
if (guestfs_hivex_open (g, system_path,
|
||||
GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose, -1) == -1)
|
||||
goto out;
|
||||
|
||||
h = hivex_open (system_hive, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
|
||||
if (h == NULL) {
|
||||
perrorf (g, "hivex_open");
|
||||
root = guestfs_hivex_root (g);
|
||||
if (root == 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
root = hivex_root (h);
|
||||
if (root == 0) {
|
||||
perrorf (g, "hivex_root");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get the CurrentControlSet. */
|
||||
errno = 0;
|
||||
node = hivex_node_get_child (h, root, "Select");
|
||||
node = guestfs_hivex_node_get_child (g, root, "Select");
|
||||
if (node == -1)
|
||||
goto out;
|
||||
|
||||
if (node == 0) {
|
||||
if (errno != 0)
|
||||
perrorf (g, "hivex_node_get_child");
|
||||
else
|
||||
error (g, "hivex: could not locate HKLM\\SYSTEM\\Select");
|
||||
error (g, "hivex: could not locate HKLM\\SYSTEM\\Select");
|
||||
goto out;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
value = hivex_node_get_value (h, node, "Current");
|
||||
value = guestfs_hivex_node_get_value (g, node, "Current");
|
||||
if (value == -1)
|
||||
goto out;
|
||||
|
||||
if (value == 0) {
|
||||
if (errno != 0)
|
||||
perrorf (g, "hivex_node_get_value");
|
||||
else
|
||||
error (g, "hivex: HKLM\\System\\Select Default entry not found.");
|
||||
error (g, "hivex: HKLM\\System\\Select Default entry not found");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* XXX Should check the type. */
|
||||
dword = hivex_value_dword (h, value);
|
||||
buf = guestfs_hivex_value_value (g, value, &buflen);
|
||||
if (buflen != 4) {
|
||||
error (g, "hivex: HKLM\\System\\Select\\Current expected to be DWORD");
|
||||
goto out;
|
||||
}
|
||||
dword = le32toh (*(int32_t *)buf);
|
||||
fs->windows_current_control_set = safe_asprintf (g, "ControlSet%03d", dword);
|
||||
|
||||
/* Get the drive mappings.
|
||||
* This page explains the contents of HKLM\System\MountedDevices:
|
||||
* http://www.goodells.net/multiboot/partsigs.shtml
|
||||
*/
|
||||
errno = 0;
|
||||
node = hivex_node_get_child (h, root, "MountedDevices");
|
||||
if (node == 0) {
|
||||
if (errno == 0)
|
||||
/* Not found: skip getting drive letter mappings (RHBZ#803664). */
|
||||
goto skip_drive_letter_mappings;
|
||||
/* errno != 0, so it's some other error from hivex */
|
||||
perrorf (g, "hivex_node_get_child");
|
||||
node = guestfs_hivex_node_get_child (g, root, "MountedDevices");
|
||||
if (node == -1)
|
||||
goto out;
|
||||
}
|
||||
|
||||
values = hivex_node_values (h, node);
|
||||
if (node == 0)
|
||||
/* Not found: skip getting drive letter mappings (RHBZ#803664). */
|
||||
goto skip_drive_letter_mappings;
|
||||
|
||||
values = guestfs_hivex_node_values (g, node);
|
||||
|
||||
/* Count how many DOS drive letter mappings there are. This doesn't
|
||||
* ignore removable devices, so it overestimates, but that doesn't
|
||||
* matter because it just means we'll allocate a few bytes extra.
|
||||
*/
|
||||
for (i = count = 0; values[i] != 0; ++i) {
|
||||
char *key = hivex_value_key (h, values[i]);
|
||||
if (key == NULL) {
|
||||
perrorf (g, "hivex_value_key");
|
||||
for (i = count = 0; i < values->len; ++i) {
|
||||
char *key = guestfs_hivex_value_key (g, values->val[i].hivex_value_h);
|
||||
if (key == NULL)
|
||||
goto out;
|
||||
}
|
||||
if (STRCASEEQLEN (key, "\\DosDevices\\", 12) &&
|
||||
c_isalpha (key[12]) && key[13] == ':')
|
||||
count++;
|
||||
free (key);
|
||||
}
|
||||
|
||||
fs->drive_mappings = calloc (2*count + 1, sizeof (char *));
|
||||
if (fs->drive_mappings == NULL) {
|
||||
perrorf (g, "calloc");
|
||||
goto out;
|
||||
}
|
||||
fs->drive_mappings = safe_calloc (g, 2*count + 1, sizeof (char *));
|
||||
|
||||
for (i = count = 0; values[i] != 0; ++i) {
|
||||
char *key = hivex_value_key (h, values[i]);
|
||||
if (key == NULL) {
|
||||
perrorf (g, "hivex_value_key");
|
||||
for (i = count = 0; i < values->len; ++i) {
|
||||
int64_t v = values->val[i].hivex_value_h;
|
||||
char *key = guestfs_hivex_value_key (g, v);
|
||||
if (key == NULL)
|
||||
goto out;
|
||||
}
|
||||
if (STRCASEEQLEN (key, "\\DosDevices\\", 12) &&
|
||||
c_isalpha (key[12]) && key[13] == ':') {
|
||||
/* Get the binary value. Is it a fixed disk? */
|
||||
char *blob, *device;
|
||||
size_t len;
|
||||
hive_type type;
|
||||
int64_t type;
|
||||
|
||||
blob = hivex_value_value (h, values[i], &type, &len);
|
||||
type = guestfs_hivex_value_type (g, v);
|
||||
blob = guestfs_hivex_value_value (g, v, &len);
|
||||
if (blob != NULL && type == 3 && len == 12) {
|
||||
/* Try to map the blob to a known disk and partition. */
|
||||
device = map_registry_disk_blob (g, blob);
|
||||
@@ -463,31 +428,34 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
|
||||
const char *hivepath[] =
|
||||
{ fs->windows_current_control_set, "Services", "Tcpip", "Parameters" };
|
||||
for (node = root, i = 0;
|
||||
node != 0 && i < sizeof hivepath / sizeof hivepath[0];
|
||||
node > 0 && i < sizeof hivepath / sizeof hivepath[0];
|
||||
++i) {
|
||||
node = hivex_node_get_child (h, node, hivepath[i]);
|
||||
node = guestfs_hivex_node_get_child (g, node, hivepath[i]);
|
||||
}
|
||||
|
||||
if (node == -1)
|
||||
goto out;
|
||||
|
||||
if (node == 0) {
|
||||
perrorf (g, "hivex: cannot locate HKLM\\SYSTEM\\%s\\Services\\Tcpip\\Parameters",
|
||||
fs->windows_current_control_set);
|
||||
goto out;
|
||||
}
|
||||
|
||||
free (values);
|
||||
values = hivex_node_values (h, node);
|
||||
guestfs_free_hivex_value_list (values);
|
||||
values = guestfs_hivex_node_values (g, node);
|
||||
if (values == NULL)
|
||||
goto out;
|
||||
|
||||
for (i = 0; values[i] != 0; ++i) {
|
||||
char *key = hivex_value_key (h, values[i]);
|
||||
if (key == NULL) {
|
||||
perrorf (g, "hivex_value_key");
|
||||
for (i = 0; i < values->len; ++i) {
|
||||
int64_t v = values->val[i].hivex_value_h;
|
||||
char *key = guestfs_hivex_value_key (g, v);
|
||||
if (key == NULL)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (STRCASEEQ (key, "Hostname")) {
|
||||
fs->hostname = hivex_value_string (h, values[i]);
|
||||
fs->hostname = guestfs_hivex_value_utf8 (g, v);
|
||||
if (!fs->hostname) {
|
||||
perrorf (g, "hivex_value_string");
|
||||
free (key);
|
||||
goto out;
|
||||
}
|
||||
@@ -500,10 +468,10 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
if (h) hivex_close (h);
|
||||
free (values);
|
||||
guestfs_hivex_close (g);
|
||||
if (values) guestfs_free_hivex_value_list (values);
|
||||
free (system_path);
|
||||
free (system_hive);
|
||||
free (buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -577,8 +545,6 @@ map_registry_disk_blob (guestfs_h *g, const char *blob)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_HIVEX) */
|
||||
|
||||
char *
|
||||
guestfs___case_sensitive_path_silently (guestfs_h *g, const char *path)
|
||||
{
|
||||
|
||||
@@ -34,10 +34,6 @@
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
#ifdef HAVE_HIVEX
|
||||
#include <hivex.h>
|
||||
#endif
|
||||
|
||||
#include "c-ctype.h"
|
||||
#include "ignore-value.h"
|
||||
#include "xstrtol.h"
|
||||
@@ -47,8 +43,6 @@
|
||||
#include "guestfs-internal-actions.h"
|
||||
#include "guestfs_protocol.h"
|
||||
|
||||
#if defined(HAVE_HIVEX)
|
||||
|
||||
/* Compile all the regular expressions once when the shared library is
|
||||
* loaded. PCRE is thread safe so we're supposedly OK here if
|
||||
* multiple threads call into the libguestfs API functions below
|
||||
@@ -603,5 +597,3 @@ guestfs___first_egrep_of_file (guestfs_h *g, const char *filename,
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_HIVEX) */
|
||||
|
||||
143
src/inspect.c
143
src/inspect.c
@@ -34,10 +34,6 @@
|
||||
|
||||
#include <pcre.h>
|
||||
|
||||
#ifdef HAVE_HIVEX
|
||||
#include <hivex.h>
|
||||
#endif
|
||||
|
||||
#include "c-ctype.h"
|
||||
#include "ignore-value.h"
|
||||
#include "xstrtol.h"
|
||||
@@ -47,8 +43,6 @@
|
||||
#include "guestfs-internal-actions.h"
|
||||
#include "guestfs_protocol.h"
|
||||
|
||||
#if defined(HAVE_HIVEX)
|
||||
|
||||
/* The main inspection code. */
|
||||
char **
|
||||
guestfs__inspect_os (guestfs_h *g)
|
||||
@@ -540,143 +534,6 @@ guestfs__inspect_get_hostname (guestfs_h *g, const char *root)
|
||||
return safe_strdup (g, fs->hostname ? : "unknown");
|
||||
}
|
||||
|
||||
#else /* no hivex at compile time */
|
||||
|
||||
/* XXX These functions should be in an optgroup. */
|
||||
|
||||
#define NOT_IMPL(r) \
|
||||
guestfs_error_errno (g, ENOTSUP, _("inspection API not available since this version of libguestfs was compiled without the hivex library")); \
|
||||
return r
|
||||
|
||||
char **
|
||||
guestfs__inspect_os (guestfs_h *g)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char **
|
||||
guestfs__inspect_get_roots (guestfs_h *g)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
guestfs__inspect_get_type (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
guestfs__inspect_get_arch (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
guestfs__inspect_get_distro (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
int
|
||||
guestfs__inspect_get_major_version (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(-1);
|
||||
}
|
||||
|
||||
int
|
||||
guestfs__inspect_get_minor_version (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(-1);
|
||||
}
|
||||
|
||||
char *
|
||||
guestfs__inspect_get_product_name (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
guestfs__inspect_get_product_variant (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
guestfs__inspect_get_windows_systemroot (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
guestfs__inspect_get_windows_current_control_set (guestfs_h *g,
|
||||
const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char **
|
||||
guestfs__inspect_get_mountpoints (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char **
|
||||
guestfs__inspect_get_filesystems (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char **
|
||||
guestfs__inspect_get_drive_mappings (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
guestfs__inspect_get_package_format (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
guestfs__inspect_get_package_management (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
guestfs__inspect_get_hostname (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
guestfs__inspect_get_format (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(NULL);
|
||||
}
|
||||
|
||||
int
|
||||
guestfs__inspect_is_live (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(-1);
|
||||
}
|
||||
|
||||
int
|
||||
guestfs__inspect_is_netinst (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(-1);
|
||||
}
|
||||
|
||||
int
|
||||
guestfs__inspect_is_multipart (guestfs_h *g, const char *root)
|
||||
{
|
||||
NOT_IMPL(-1);
|
||||
}
|
||||
|
||||
#endif /* no hivex at compile time */
|
||||
|
||||
void
|
||||
guestfs___free_inspect_info (guestfs_h *g)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user