Tuesday Tiny Techie Tip
Links
ln(1) creates a "link" to a file. To know what
that means, you need to know a little bit about how the
UNIX filesystem works. (note, I'm doing this off the top
of my head without references, so if you want to go write
your own UNIX filesystem, you might want to double check my
misconceptions).
In the UNIX filesystem, everything is a file. Even
directories are files. The directory file is a list of
references to the files which are "in" that directory. The
directory file also contains the names of the files. The
references are numbers called inodes. inodes are references
to a part of a disk partition. You can see the
actual inodes associated with files by using the
"-i" flag to ls(1):
% ls -lai
total 98
178560 drwxrwxr-x 3 jeffy 512 Dec 9 13:19 .
7332480 drwxrwxr-x 3 jeffy 512 Dec 9 13:15 ..
178564 -rw-r--r-- 1 jeffy 277 Dec 9 13:18 Makefile
178563 -rw-r--r-- 1 jeffy 11296 Dec 9 13:18 bar.c
178561 -rw-r--r-- 1 jeffy 61856 Dec 9 13:18 foo.c
178562 -rw-r--r-- 1 jeffy 21213 Dec 9 13:18 foo.h
180480 drwxrwxr-x 2 jeffy 512 Dec 9 13:18 hold
The number at the beginning of each line is the inode
associated with that file. Notice that the directories
have inodes too. Also notice that if we look into the
"hold" subdirectory:
% ls -lai hold
total 63
180480 drwxrwxr-x 2 jeffy 512 Dec 9 13:23 .
178560 drwxrwxr-x 3 jeffy 512 Dec 9 13:19 ..
180481 -rw-r--r-- 1 jeffy 61856 Dec 9 13:23 foo.c
the inode for the "." directory inside "hold" is the same
as the inode for "hold" up in its parent directory. In
other words, they are both references to the same file.
(This is what allows you to use "." as a shorthand for
the current directory)
ln(1) allows you to add two different kinds of
file references into directories.
Symbolic Links
The most commonly used kind of reference created by
ln is what is called a symbolic link. This type
of link is created using the "-s" flag to
ln. Creating a symbolic link (sometimes called
"soft link", or just "symlink") actually creates a new file
in the directory which contains a reference to another
file.
% ln -s bar.c barsym.c
% ls -li bar*
178563 -rw-r--r-- 1 jeffy 11296 Dec 9 13:18 bar.c
178565 lrwxrwxrwx 1 jeffy 5 Dec 9 13:33 barsym.c -> bar.c
The ls command (and the rest of the UNIX toolset)
knows about symlinks and shows them specially in its
long output, indicating the name of the link itself and a
pointer to the file being referenced: "link -> real/file"
Notice that the link has its own inode since it is an
actual file. The size of the link file is the length of
the filename it points to. (The string "bar.c" is
five characters long)
There are no restrictions on what a symlink can point
to. It can look at another file in the same directory
(foo.c), in a different directory by relative (../foo.c),
or absolute (/home/jeffy/foo.c) path, in the local
filesystem or another filesystem. The symlink
doesn't even have to point at an existing file, so if I had
made a typo in creating that link, it would have been
created looking for the non-existant file:
% ln -s bart.c bartsym.c
% ls -li bar*
178563 -rw-r--r-- 1 jeffy 11296 Dec 9 13:18 bar.c
178565 lrwxrwxrwx 1 jeffy 5 Dec 9 13:33 barsym.c -> bar.c
178566 lrwxrwxrwx 1 jeffy 6 Dec 9 13:47 bartsym.c -> bart.c
% cat bartsym.c
cat: bartsym.c: No such file or directory
Notice that the message here is kind of confusing in that
it says the name of the link (bartsym.c) doesn't
exist when what it means is that the link points to something
that doesn't exist. If you had done just a regular ls
to see the filename before trying to cat it, this
message would be very confusing to you:
% ls bar*
bar.c barsym.c bartsym.c
% cat bartsym.c
cat: bartsym.c: No such file or directory
This is where the "-F" flag to ls(1)
comes in handy. That flag causes ls to append
a character to filenames whose files are special in some
way. as follows:
file/ | => | file is a directory |
file* | => | file is executable |
file@ | => | file is a symbolic link |
So if you used ls -F:
% ls -F bar*
bar.c barsym.c@ bartsym.c@
% cat bartsym.c
cat: bartsym.c: No such file or directory
you at least have a clue why the cat failed.
This lack of connection between the link and the file
linked to means that even if the file pointed to existed
when the link was created, there's no guarantee that it
will still exist when you get around to trying to reference
it. You can check whether the linked-to thing exists by
using the "-L" flag to ls(1). This flag
tells ls to show information about the referenced
file (if it exists) instead of the link itself.
% ls -liL bar*
178563 -rw-r--r-- 1 jeffy 11296 Dec 9 13:18 bar.c
178563 -rw-r--r-- 1 jeffy 11296 Dec 9 13:18 barsym.c
178566 lrwxrwxrwx 1 jeffy 6 Dec 9 13:47 bartsym.c -> bart.c
In the example, ls followed the barsym.c
link and returned all the information (except the name)
about that file (including its inode) instead of the
information about the link. Since bart.c doesn't
exist, we get the information about the bartsym.c
link itself.
In the ln(1) man page, there are some valuable
warnings about the somewhat unexpected things that can
happen when you deal with symlinks to directories.
I won't recreate them here.
Hard Links
So symbolic links are basically textual references to
another file by name (path included).
The other kind of link (and the default) is called a
hard link.
The hard link is a second reference to an existing inode.
% ls -li *r.c
178563 -rw-r--r-- 1 jeffy se 11296 Dec 9 13:18 bar.c
% ln bar.c hardbar.c
% ls -li *r.c
178563 -rw-r--r-- 2 jeffy 11296 Dec 9 13:18 bar.c
178563 -rw-r--r-- 2 jeffy 11296 Dec 9 13:18 hardbar.c
A couple of things to notice here. First, notice that both
bar.c and hardbar.c have the same inode. That means they
are references to the same physical disk location. Also
notice the third column of the ls -li output. This
column shows the link count for the referenced inode. Before
the ln operation, there is only one link to the inode
associated with bar.c. After the ln operation there
are two references (and since hardbar.c has the same
inode, it shows two links to it as well).
There are three restrictions on the creation of hard
links.
- Since the reference is to an inode, and
inodes are only meaningful within their disk partition, it
is not possible to have a hard link to a file in another
partition.
- The file being linked to must exist
when the link is created (you can't create a second link to
nothing).
- Only the superuser can
create a hard link to a directory.
(It's a good thing,
too. I did it once ("What do you mean, I can't
create a link to a directory?! Watch this!") and never did
figure out how to undo it. The main problem is ".." - if you
reference the same directory from two different
directories, where does ".." point when you're in that
directory? Confused kernel. Confused tools. Confused
(ex)sysadmin. To make a long parenthetical even longer,
note that in a Clearcase multi-version filesystem, this
limitation does not exist since the MVFS is not strictly
treelike (as anyone who's ever ventured to do a
"cd .@@/main/LATEST" followed by a "cd ../../.." can
attest. (You're not in "." anymore!)))
Final note on hard links: look what happens when we remove the
original file:
% ls -li *r.c
178563 -rw-r--r-- 2 jeffy 11296 Dec 9 13:18 bar.c
178563 -rw-r--r-- 2 jeffy 11296 Dec 9 13:18 hardbar.c
% rm bar.c
% ls -li *r.c
178563 -rw-r--r-- 1 jeffy 11296 Dec 9 13:18 hardbar.c
It shouldn't be any surprise that when we had two references to
inode 178563 and we deleted one, we end up with one
reference to that disk location. The contents were not deleted,
just one of the references.
For your own amusement, explain the following:
% mkdir foo
% mv foo ~q345/Source
mv: can't mv directories across file systems
Tuesday Tiny Techie Tip -- 10 December 1996
Forward to (12/17/96)
Back to (12/03/96)
Written by Jeff Youngstrom
Up to the TTTT index
Tuesday Tiny Techie Tips are all © Copyright
1996-1997 by Jeff Youngstrom. Please ask permission before
reproducing any of this material.