[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Getting to the last file in a chain of symlinks

Daniel Berger

3/9/2007 7:11:00 PM

Hi all,

Here's a little code snippet I thought I'd share. It follows a chain
of symlinks until you get down to the "real" file. Anyone got a better
approach?

# On Solaris 10, Sunblade 150
#
# /dev/fd0 -> fd0c
# /dev/fd0c -> diskette0
# /dev/diskett0 -> ../devices/pci@1f,0/isa@7/dma@0,0/floppy@0,3f0:c
#

file = '/dev/fd0'

while true
Dir.chdir(File.dirname(file))
file = File.expand_path(File.readlink(file))
break unless File.symlink?(file)
end

puts file # /devices/pci@1f,0/isa@7/dma@0,0/floppy@0,3f0:c

Regards,

Dan

3 Answers

Daniel Berger

3/9/2007 7:37:00 PM

0

On Mar 9, 12:10 pm, "Daniel Berger" <djber...@gmail.com> wrote:
> Hi all,
>
> Here's a little code snippet I thought I'd share. It follows a chain
> of symlinks until you get down to the "real" file. Anyone got a better
> approach?
>
> # On Solaris 10, Sunblade 150
> #
> # /dev/fd0 -> fd0c
> # /dev/fd0c -> diskette0
> # /dev/diskett0 -> ../devices/pci@1f,0/isa@7/dma@0,0/floppy@0,3f0:c
> #
>
> file = '/dev/fd0'
>
> while true
> Dir.chdir(File.dirname(file))
> file = File.expand_path(File.readlink(file))
> break unless File.symlink?(file)
> end
>
> 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
end
end


AdSR

3/9/2007 7:44:00 PM

0

On 9 Mar, 20:10, "Daniel Berger" <djber...@gmail.com> wrote:
> Hi all,
>
> Here's a little code snippet I thought I'd share. It follows a chain
> of symlinks until you get down to the "real" file. Anyone got a better
> approach?
>
> # On Solaris 10, Sunblade 150
> #
> # /dev/fd0 -> fd0c
> # /dev/fd0c -> diskette0
> # /dev/diskett0 -> ../devices/pci@1f,0/isa@7/dma@0,0/floppy@0,3f0:c
> #
>
> file = '/dev/fd0'
>
> while true
> Dir.chdir(File.dirname(file))
> file = File.expand_path(File.readlink(file))
> break unless File.symlink?(file)
> end
>
> puts file # /devices/pci@1f,0/isa@7/dma@0,0/floppy@0,3f0:c
>
> Regards,
>
> Dan

require 'pathname'

puts Pathname.new('/dev/fd0').realpath

I didn't check what would happen for cyclic dependencies.

Regards,
AdSR

Daniel Berger

3/9/2007 7:55:00 PM

0

On Mar 9, 12:44 pm, "AdSR" <artur_spr...@yahoo.com> wrote:
> On 9 Mar, 20:10, "Daniel Berger" <djber...@gmail.com> wrote:
>
>
>
> > Hi all,
>
> > Here's a little code snippet I thought I'd share. It follows a chain
> > of symlinks until you get down to the "real" file. Anyone got a better
> > approach?
>
> > # On Solaris 10, Sunblade 150
> > #
> > # /dev/fd0 -> fd0c
> > # /dev/fd0c -> diskette0
> > # /dev/diskett0 -> ../devices/pci@1f,0/isa@7/dma@0,0/floppy@0,3f0:c
> > #
>
> > file = '/dev/fd0'
>
> > while true
> > Dir.chdir(File.dirname(file))
> > file = File.expand_path(File.readlink(file))
> > break unless File.symlink?(file)
> > end
>
> > puts file # /devices/pci@1f,0/isa@7/dma@0,0/floppy@0,3f0:c
>
> > Regards,
>
> > Dan
>
> require 'pathname'
>
> puts Pathname.new('/dev/fd0').realpath

Oh, dang, forgot about that.

> 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

Dunno what happens on other platforms.

Regards,

Dan