diff --git a/lib/fileutils.rb b/lib/fileutils.rb index c115005..f04dfb7 100644 --- a/lib/fileutils.rb +++ b/lib/fileutils.rb @@ -680,8 +680,11 @@ def remove_entry_secure(path, force = false) return end fullpath = File.expand_path(path) - st = File.lstat(fullpath) - unless st.directory? + ent = Entry_.new(fullpath) + if force && !ent.exist? + return + end + unless ent.directory? File.unlink fullpath return end @@ -700,7 +703,7 @@ def remove_entry_secure(path, force = false) dot_file = fullpath + "/." begin File.open(dot_file) {|f| - unless fu_stat_identical_entry?(st, f.stat) + unless fu_stat_identical_entry?(ent, f.stat) # symlink (TOC-to-TOU attack?) File.unlink fullpath return @@ -710,7 +713,7 @@ def remove_entry_secure(path, force = false) } rescue Errno::EISDIR # JRuby in non-native mode can't open files as dirs File.lstat(dot_file).tap {|fstat| - unless fu_stat_identical_entry?(st, fstat) + unless fu_stat_identical_entry?(ent, fstat) # symlink (TOC-to-TOU attack?) File.unlink fullpath return @@ -720,7 +723,7 @@ def remove_entry_secure(path, force = false) } end - unless fu_stat_identical_entry?(st, File.lstat(fullpath)) + unless fu_stat_identical_entry?(ent, File.lstat(fullpath)) # TOC-to-TOU attack? File.unlink fullpath return @@ -735,14 +738,10 @@ def remove_entry_secure(path, force = false) end end root.postorder_traverse do |ent| - begin - ent.remove - rescue - raise unless force - end + next if force && !ent.exist? + + ent.remove end - rescue - raise unless force end module_function :remove_entry_secure @@ -769,14 +768,10 @@ def fu_stat_identical_entry?(a, b) #:nodoc: # def remove_entry(path, force = false) Entry_.new(path).postorder_traverse do |ent| - begin - ent.remove - rescue - raise unless force - end + next if force && !ent.exist? + + ent.remove end - rescue - raise unless force end module_function :remove_entry @@ -785,9 +780,10 @@ def remove_entry(path, force = false) # This method ignores StandardError if +force+ is true. # def remove_file(path, force = false) - Entry_.new(path).remove_file - rescue - raise unless force + ent = Entry_.new(path) + return if force && !ent.exist? + + ent.remove_file end module_function :remove_file @@ -1256,6 +1252,16 @@ def blockdev? s and s.blockdev? end + def dev + s = lstat! + s and s.dev + end + + def ino + s = lstat! + s and s.ino + end + def socket? s = lstat! s and s.socket? @@ -1485,7 +1491,7 @@ def postorder_traverse end end end - ensure + yield self end diff --git a/test/fileutils/test_fileutils.rb b/test/fileutils/test_fileutils.rb index 36b5d6e..b89da42 100644 --- a/test/fileutils/test_fileutils.rb +++ b/test/fileutils/test_fileutils.rb @@ -1790,12 +1790,32 @@ def test_rm_rf return if /mswin|mingw/ =~ RUBY_PLATFORM mkdir 'tmpdatadir' - chmod 700, 'tmpdatadir' + chmod 0700, 'tmpdatadir' rm_rf 'tmpdatadir' assert_file_not_exist 'tmpdatadir' end + def test_rm_rf_no_permissions + check_singleton :rm_rf + + return if /mswin|mingw/ =~ RUBY_PLATFORM + + mkdir 'tmpdatadir' + touch 'tmpdatadir/tmpdata' + chmod "-x", 'tmpdatadir' + + begin + assert_raise Errno::EACCES do + rm_rf 'tmpdatadir' + end + + assert_file_exist 'tmpdatadir' + ensure + chmod "+x", 'tmpdatadir' + end + end + def test_rmdir check_singleton :rmdir