Richard W.M. Jones
2012-Sep-28 12:14 UTC
[Libguestfs] [PATCH v2] inspection: Fix calls to case_sensitive_path (RHBZ#858126).
From: "Richard W.M. Jones" <rjones at 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