We were using remove_tree in the RHEV cleanup code. remove_tree seems to use
chdir. Unfortunately, as this code will be running seteuid(36), it is not
unlikely that the current working directory will not be readable. This causes
remove_tree to fail.
This patch replaces remove_tree with a simple recursive remove, obviously
without using chdir.
Fixes RHBZ#670778
---
lib/Sys/VirtV2V/Connection/RHEVTarget.pm | 56 +++++++++++++++++++-----------
1 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/lib/Sys/VirtV2V/Connection/RHEVTarget.pm
b/lib/Sys/VirtV2V/Connection/RHEVTarget.pm
index 7ea84f8..b02e9ff 100644
--- a/lib/Sys/VirtV2V/Connection/RHEVTarget.pm
+++ b/lib/Sys/VirtV2V/Connection/RHEVTarget.pm
@@ -243,7 +243,6 @@ sub DESTROY
package Sys::VirtV2V::Connection::RHEVTarget::Vol;
-use File::Path qw(remove_tree);
use File::Spec::Functions;
use File::Temp qw(tempdir);
use POSIX;
@@ -373,6 +372,41 @@ sub _move_vols
$class->_cleanup();
}
+# We used to use remove_tree from File::Path here. Unfortunately it does
+# something unexpected involving chdir which means it will fail bizarrely if the
+# current directory (not the target directory) is not readable by the current
+# user.
+sub _remove_tree
+{
+ my $dir = shift;
+
+ opendir(my $dh, $dir) or die user_message(__x("Unable to open {dir} while
".
+ "removing temporary ".
+ "directory: {error}",
+ dir => $dir,
+ error => $!));
+ while (my $entry = readdir($dh)) {
+ next if $entry eq '.';
+ next if $entry eq '..';
+
+ my $path = $dir.'/'.$entry;
+ if (-d $path) {
+ _remove_tree($path);
+ } else {
+ unlink($path) or die user_message(__x("Unable to remove {path} ".
+ "while removing temporary ".
+ "directory: {error}",
+ path => $path,
+ error => $!));
+ }
+ }
+ closedir($dh);
+ rmdir($dir) or die user_message(__x("Unable to remove {path} while ".
+ "removing temporary directory:
{error}",
+ path => $dir,
+ error => $!));
+}
+
# Must be called in rhev_helper context
sub _cleanup
{
@@ -380,25 +414,7 @@ sub _cleanup
return unless (defined($tmpdir));
- my $errors = [];
- eval {
- remove_tree($tmpdir, { error => \$errors });
- };
- push(@$errors, $@) if ($@);
-
- if (@$errors > 0) {
- foreach my $error (@$errors) {
- foreach my $file (keys(%$error)) {
- warn(user_message(__x("Error removing {file}: {error}",
- file => $file,
- error => $error->{$file})));
- }
- }
-
- die(user_message(__x("Unable to remove temporary directory ".
- "{dir}", dir => $tmpdir)));
- }
-
+ _remove_tree($tmpdir);
$tmpdir = undef;
}
--
1.7.3.5