Symlink loop is still an unsolved problem

· Read in about 2 min · (370 Words)

How do I dereference a symbolic link?

$ ls -l /usr/bin/java
lrwxrwxrwx. 1 root root 22 Jul 20  2010 /usr/bin/java -> /etc/alternatives/java
$ ls -l /etc/alternatives/java
lrwxrwxrwx. 1 root root 30 Aug  9  2010 /etc/alternatives/java -> /usr/java/jdk1.6.0_20/bin/java
$ ls -l /usr/java/jdk1.6.0_20/bin/java
-rwxr-xr-x. 1 root root 50810 Apr 13  2010 /usr/java/jdk1.6.0_20/bin/java

Lets create a chain of symbolic links:

mkdir /tmp/symlink
cd /tmp/symlink
echo "this is a test file" >  abc.txt
ln -s abc.txt link1
ln -s link1 link2
ln -s link2 link3
ln -s link3 link4

Now lets use the last link that we created:

cat link4
this is a test file

What if we make it a circular link?

rm link1
ln -s link4 link1

Now lets try to use one of the symbolic links:

cat link4
cat: link4: Too many levels of symbolic links

You noticed that? Okay, lets move further:

# we will create a chain of symlinks, which is 50 links deep
mkdir /tmp/links
cd /tmp/links
for i in {0..50}
  ln -s l${i} l$(expr $i + 1)
echo hello > l0

Lets see what files/links this script has generated:

cd /tmp/links
ls -l

You will notice that all the symlinks upto l40 resolve correctly:

$ cat l40
$ # notice that:
$ # all links from l41 and above will not resolve
$ cat l41 
cat: l41: Too many levels of symbolic links
$ cat l51
cat: l51: Too many levels of symbolic links

Lets print the whole link path now:

# doesn't handle circular symlink loops at the moment
while [ -h "$F" ]
  G=$(readlink $F)
  echo "$F -> $G"
echo "Finally -> $F"


l51 -> l50
l50 -> l49
l49 -> l48
l3 -> l2
l2 -> l1
l1 -> l0
Finally -> l0

What’s the bottomline?

  • Even if there is no circular symlink loop, the symlink might fail to resolve. This depends on the MAXSYMLINK limit.
  • UNIX / Linux doesn’t handle symlink loops at all. The whole assumption is based on a limit. If the symlink chain grows more than a certain limit, we will get a Too many levels of symbolic links error, regardless of the symlink loop or not.