From: "Richard W.M. Jones" <rjones(a)redhat.com>
Don't assume that if guestfs_case_sensitive_path returns NULL, that it
means the file does not exist.
The (previously undefined) behaviour of case_sensitive_path was that a
NULL return meant "either the file doesn't exist or some other error".
However in commit 973581780d8a006f336684fef6762801402d775d this was
changed so that if the last element of the path didn't exist, it was
assumed to be a new file and the (non-NULL) path of the new file is
returned.
This change breaks code (including in libguestfs) which tries to use
case_sensitive_path as a dual-purpose call to fix-up a path for
Windows and test if the file exists. Such code should be rewritten so
that it explicitly tests for file existence after calling
case_sensitive_path.
I examined all the calls to case_sensitive_path in libguestfs and
modified them where necessary.
---
examples/virt-dhcp-address.c | 4 +---
perl/lib/Sys/Guestfs/Lib.pm | 3 +++
src/inspect-apps.c | 7 ++-----
src/inspect-fs-windows.c | 41 +++++++++++++++++++++++++++--------------
tools/virt-win-reg | 14 ++------------
5 files changed, 35 insertions(+), 34 deletions(-)
diff --git a/examples/virt-dhcp-address.c b/examples/virt-dhcp-address.c
index c4e3647..df06ebe 100644
--- a/examples/virt-dhcp-address.c
+++ b/examples/virt-dhcp-address.c
@@ -206,10 +206,8 @@ print_dhcp_address_windows (guestfs_h *g, char *root_fs)
/* Locate the SYSTEM hive case-sensitive path. */
system_path =
guestfs_case_sensitive_path (g, "/windows/system32/config/system");
- if (!system_path) {
- fprintf (stderr, "virt-dhcp-address: HKLM\\System not found in this
guest.");
+ if (!system_path)
exit (EXIT_FAILURE);
- }
/* 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
diff --git a/perl/lib/Sys/Guestfs/Lib.pm b/perl/lib/Sys/Guestfs/Lib.pm
index 33e8acb..5dde409 100644
--- a/perl/lib/Sys/Guestfs/Lib.pm
+++ b/perl/lib/Sys/Guestfs/Lib.pm
@@ -356,6 +356,9 @@ sub resolve_windows_path
my $r;
eval { $r = $g->case_sensitive_path ($path); };
+
+ $r = undef if defined $r && ! $g->exists ($r);
+
return $r;
}
diff --git a/src/inspect-apps.c b/src/inspect-apps.c
index e9f020a..f65c70a 100644
--- a/src/inspect-apps.c
+++ b/src/inspect-apps.c
@@ -418,12 +418,9 @@ list_applications_windows (guestfs_h *g, struct inspect_fs *fs)
snprintf (software, len, "%s/system32/config/software",
fs->windows_systemroot);
- char *software_path = guestfs___case_sensitive_path_silently (g, software);
- if (!software_path) {
- /* Missing software hive is a problem. */
- error (g, "no HKLM\\SOFTWARE hive found in the guest");
+ char *software_path = guestfs_case_sensitive_path (g, software);
+ if (!software_path)
return NULL;
- }
struct guestfs_application_list *ret = NULL;
const char *hivepath[] =
diff --git a/src/inspect-fs-windows.c b/src/inspect-fs-windows.c
index c3a5aba..af75871 100644
--- a/src/inspect-fs-windows.c
+++ b/src/inspect-fs-windows.c
@@ -157,11 +157,9 @@ guestfs___check_windows_root (guestfs_h *g, struct inspect_fs *fs)
return -1;
}
- systemroot = guestfs___case_sensitive_path_silently (g, systemroots[i]);
- if (!systemroot) {
- error (g, _("cannot resolve Windows %%SYSTEMROOT%%"));
+ systemroot = guestfs_case_sensitive_path (g, systemroots[i]);
+ if (!systemroot)
return -1;
- }
debug (g, "windows %%SYSTEMROOT%% = %s", systemroot);
@@ -189,9 +187,10 @@ check_windows_arch (guestfs_h *g, struct inspect_fs *fs)
char cmd_exe[len];
snprintf (cmd_exe, len, "%s/system32/cmd.exe", fs->windows_systemroot);
- char *cmd_exe_path = guestfs___case_sensitive_path_silently (g, cmd_exe);
+ /* Should exist because of previous check above in has_windows_systemroot. */
+ char *cmd_exe_path = guestfs_case_sensitive_path (g, cmd_exe);
if (!cmd_exe_path)
- return 0;
+ return -1;
char *arch = guestfs_file_architecture (g, cmd_exe_path);
free (cmd_exe_path);
@@ -210,17 +209,24 @@ static int
check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
{
int ret = -1;
+ int r;
size_t len = strlen (fs->windows_systemroot) + 64;
char software[len];
snprintf (software, len, "%s/system32/config/software",
fs->windows_systemroot);
- char *software_path = guestfs___case_sensitive_path_silently (g, software);
+ char *software_path = guestfs_case_sensitive_path (g, software);
if (!software_path)
- /* If the software hive doesn't exist, just accept that we cannot
- * find product_name etc.
- */
+ return -1;
+
+ r = guestfs_is_file (g, software_path);
+ if (r == -1)
+ return -1;
+ /* If the software hive doesn't exist, just accept that we cannot
+ * find product_name etc.
+ */
+ if (r == 0)
return 0;
int64_t node;
@@ -312,16 +318,23 @@ check_windows_software_registry (guestfs_h *g, struct inspect_fs
*fs)
static int
check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
{
+ int r;
size_t len = strlen (fs->windows_systemroot) + 64;
char system[len];
snprintf (system, len, "%s/system32/config/system",
fs->windows_systemroot);
- char *system_path = guestfs___case_sensitive_path_silently (g, system);
+ char *system_path = guestfs_case_sensitive_path (g, system);
if (!system_path)
- /* If the system hive doesn't exist, just accept that we cannot
- * find hostname etc.
- */
+ return -1;
+
+ r = guestfs_is_file (g, system_path);
+ if (r == -1)
+ return -1;
+ /* If the system hive doesn't exist, just accept that we cannot
+ * find hostname etc.
+ */
+ if (r == 0)
return 0;
int ret = -1;
diff --git a/tools/virt-win-reg b/tools/virt-win-reg
index 9e053dd..0a1b754 100755
--- a/tools/virt-win-reg
+++ b/tools/virt-win-reg
@@ -516,12 +516,7 @@ sub download_hive
my $hivefile = shift;
my $hiveshortname = shift;
- my $winfile;
- eval { $winfile = $g->case_sensitive_path ($hivefile); };
- if ($@) {
- die __x("virt-win-reg: {p}: file not found in guest: {err}\n",
- p => $hivefile, err => $@);
- }
+ my $winfile = $g->case_sensitive_path ($hivefile);
warn "downloading $winfile ..." if $debug;
eval { $g->download ($winfile, "$tmpdir/$hiveshortname"); };
@@ -538,12 +533,7 @@ sub upload_hive
my $hiveshortname = shift;
my $hivefile = shift;
- my $winfile;
- eval { $winfile = $g->case_sensitive_path ($hivefile); };
- if ($@) {
- die __x("virt-win-reg: {p}: file not found in guest: {err}\n",
- p => $hivefile, err => $@);
- }
+ my $winfile = $g->case_sensitive_path ($hivefile);
warn "uploading $winfile ..." if $debug;
eval { $g->upload ("$tmpdir/$hiveshortname", $winfile); };
--
1.7.11.4