Skip to content

Commit ec5d3b8

Browse files
committed
Narrow the scope of ensure
The ensure in postorder_traverse was added for [Bug #6756]. The intention was to try to delete the parent directory if it failed to get the children. (It may be possible to delete the directory if it is empty.) However, the ensure region rescue'ed not only "failure to get children" but also "failure to delete each child". Thus, the following raised Errno::ENOTEMPTY, but we expect it to raise Errno::EACCES. ``` $ mkdir foo $ touch foo/bar $ chmod 555 foo $ ruby -rfileutils -e 'FileUtils.rm_rf("foo")' ``` This changeset narrows the ensure region so that it rescues only "failure to get children".
1 parent d6c2ab2 commit ec5d3b8

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

lib/fileutils.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2328,13 +2328,21 @@ def preorder_traverse
23282328

23292329
def postorder_traverse
23302330
if directory?
2331-
entries().each do |ent|
2331+
begin
2332+
children = entries()
2333+
rescue Errno::EACCES
2334+
# Failed to get the list of children.
2335+
# Assuming there is no children, try to process the parent directory.
2336+
yield self
2337+
return
2338+
end
2339+
2340+
children.each do |ent|
23322341
ent.postorder_traverse do |e|
23332342
yield e
23342343
end
23352344
end
23362345
end
2337-
ensure
23382346
yield self
23392347
end
23402348

test/fileutils/test_fileutils.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,24 @@ def test_rm_r_pathname
750750
assert_file_not_exist 'tmp/tmpdir3'
751751
end
752752

753+
def test_rm_r_no_permissions
754+
check_singleton :rm_rf
755+
756+
return if /mswin|mingw/ =~ RUBY_PLATFORM
757+
758+
mkdir 'tmpdatadir'
759+
touch 'tmpdatadir/tmpdata'
760+
chmod "-x", 'tmpdatadir'
761+
762+
begin
763+
assert_raise Errno::EACCES do
764+
rm_r 'tmpdatadir'
765+
end
766+
ensure
767+
chmod "+x", 'tmpdatadir'
768+
end
769+
end
770+
753771
def test_remove_entry_cjk_path
754772
dir = "tmpdir\u3042"
755773
my_rm_rf dir

0 commit comments

Comments
 (0)