From 839ef7bfbb446db531983e391a52df4e4a0eb8aa Mon Sep 17 00:00:00 2001 From: akr Date: Mon, 13 Oct 2003 19:46:07 +0000 Subject: [PATCH] * lib/pathname.rb (realpath): make ELOOP check bit more robust. (children): prepend self by default. (chroot): obsoleted. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4757 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 ++++++ lib/pathname.rb | 48 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index f8f94e8246..ad21f144b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Tue Oct 14 04:43:55 2003 Tanaka Akira + + * lib/pathname.rb (realpath): make ELOOP check bit more robust. + (children): prepend self by default. + (chroot): obsoleted. + Tue Oct 14 02:29:31 2003 Nobuyoshi Nakada * eval.c (rb_require_safe): segfault after loading .so. diff --git a/lib/pathname.rb b/lib/pathname.rb index 8df49159c4..d104be6897 100644 --- a/lib/pathname.rb +++ b/lib/pathname.rb @@ -111,11 +111,20 @@ class Pathname # it may return relative pathname. # Otherwise it returns absolute pathname. def realpath(force_absolute=true) + # Check file existence at first by File.stat. + # This test detects ELOOP. + # + # /tmp/a -> a + # /tmp/b -> b/b + # /tmp/c -> ./c + # /tmp/d -> ../tmp/d + File.stat(@path) top = %r{\A/} =~ @path ? '/' : '' unresolved = @path.scan(%r{[^/]+}) resolved = [] + checked_path = {} until unresolved.empty? case unresolved.last @@ -125,7 +134,9 @@ class Pathname resolved.unshift unresolved.pop else path = top + unresolved.join('/') - if FileTest.symlink? path + raise Errno::ELOOP.new(path) if checked_path[path] + checked_path[path] = true + if File.lstat(path).symlink? link = File.readlink(path) if %r{\A/} =~ link top = '/' @@ -211,14 +222,27 @@ class Pathname end # Pathname#children returns the children of the directory as an array of - # pathnames. I.e. it is similar to Pathname#entries except '.' and '..' - # is not returned. + # pathnames. + # + # By default, self is prepended to each pathname in the result. + # It is disabled if false is given for the optional argument + # prepend_directory. + # + # Note that the result never contain '.' and '..' because they are not + # child. # # This method is exist since 1.8.1. - def children - Dir.entries(@path).map {|f| - f == '.' || f == '..' ? nil : Pathname.new(f) - }.compact + def children(prepend_directory=true) + result = [] + Dir.foreach(@path) {|e| + next if e == '.' || e == '..' + if prepend_directory + result << Pathname.new(File.join(@path, e)) + else + result << Pathname.new(e) + end + } + result end # Pathname#relative_path_from returns a relative path from the argument to @@ -355,14 +379,20 @@ class Pathname def Pathname.getwd() Pathname.new(Dir.getwd) end class << self; alias pwd getwd end - # This method is obsoleted at 1.8.1. + # Pathname#chdir is obsoleted at 1.8.1. # def chdir(&block) # compatibility to 1.8.0. warn "Pathname#chdir is obsoleted. Use Dir.chdir." Dir.chdir(@path, &block) end - def chroot() Dir.chroot(@path) end + # Pathname#chroot is obsoleted at 1.8.1. + # + def chroot # compatibility to 1.8.0. + warn "Pathname#chroot is obsoleted. Use Dir.chroot." + Dir.chroot(@path) + end + def rmdir() Dir.rmdir(@path) end def entries() Dir.entries(@path).map {|f| Pathname.new(f) } end