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
Richard W.M. Jones
2011-Jan-26 17:16 UTC
[Libguestfs] [PATCH] Replace File::Path's remove_tree
On Wed, Jan 26, 2011 at 05:05:42PM +0000, Matthew Booth wrote:> 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.Recursive removes like this are full of potential fail. I'd prefer it if you did: system ('rm', '-rf', $path); Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/
Reasonably Related Threads
- [PREVIEW ONLY] Refactor data transfer code
- [PATCH] RHEV: Ensure DESTROY won't be called for uninitialized object
- [PATCH] RHEV: Warn instead of die if rmtree dies during cleanup
- [PATCH] Move all interaction with the config file into Sys::VirtV2V::Config
- [PATCH] Add LocalCopy transfer method to transfer local files to a target