I didn’t check what would happen for cyclic dependencies.
ls -l
lrwxrwxrwx 1 djberge other 5 Mar 9 12:25 link1 → link2
lrwxrwxrwx 1 djberge other 5 Mar 9 12:23 link2 → link1
-rw-r–r-- 1 djberge other 57 Mar 9 12:45 test.rb
/usr/local/lib/ruby/1.8/pathname.rb:415:in realpath_rec': Number of symbolic links encountered during path name traversal exceeds MAXSYMLINKS - /export/home/djberge/workspace/ruby_test/lib/test/link2 (Errno::ELOOP) from /usr/local/lib/ruby/1.8/pathname.rb:425:in realpath_rec’
from /usr/local/lib/ruby/1.8/pathname.rb:453:in `realpath’
from test.rb:2
puts file # /devices/pci@1f,0/isa@7/dma@0,0/floppy@0,3f0:c
Alright, here’s a modified File.readlink method. This is an improved
version of the algorithm above in that it uses the block form of
Dir.chdir and handles circular symlinks:
class File
class << self
private
alias readlink_orig readlink
public
# Returns the given symbolic link as a string. If +recursive+ is
set
# to true then it will follow symbolic links until it gets to
the final
# file in the chain. The default is false, i.e. non-recursive.
#
# If circular symlinks are encountered, it will return the last
link
# that it has not already encountered.
#
def readlink(file, recursive=false)
if recursive
visited = {} # Used to avoid circular references
while true
Dir.chdir(File.dirname(file)){
file = File.expand_path(File.readlink(file))
}
if File.symlink?(file) || visited[file]
break
end
visited[file] = true
end
file
else
readlink_orig(file)
end
end