Skip to content
academia.sh

Lesson 09 / 20

Links

The distinction between a directory entry and an inode, a hard link sharing the same inode, a symbolic link holding a path string, and a comparison of the two kinds' constraints.

Contents

The previous lesson defined deletion as “unlinking” and ended by saying a file can have more than one name. This lesson builds that possibility.

The foundation is the distinction introduced in the navigation lesson: a directory entry maps a name to an inode, while an inode holds the file’s metadata and the location of its data blocks. The name is not stored inside the inode, so nothing prevents more than one entry from pointing to the same inode.

A hard link is adding a new directory entry to an existing inode.

$ ln data/raw/measurement-03.csv data/latest-measurement.csv
$ ls -li data/raw/measurement-03.csv data/latest-measurement.csv
22143 -rw-r--r-- 2 student student 47 Jul 26 19:03 data/raw/measurement-03.csv
22143 -rw-r--r-- 2 student student 47 Jul 26 19:03 data/latest-measurement.csv

Both lines show inode number 22143, and the link count column has risen from 1 to 2. This is not a copy: there is a single file with two names. No extra disk space has been used; only a directory entry has been added.

There is no hierarchy between the two names. Which one is “real” is meaningless; both are equally close to the same inode. This shows up in deletion:

$ rm data/raw/measurement-03.csv
$ ls -li data/latest-measurement.csv
22143 -rw-r--r-- 1 student student 47 Jul 26 19:03 data/latest-measurement.csv
$ cat data/latest-measurement.csv
zaman,sicaklik,nem
08:00,22.6,58
12:00,26.3,44

One of the names has been deleted, the link count has dropped to 1, and the data remains in place. The rule from the previous lesson is confirmed here: data blocks are freed only when the link count reaches zero.

The deleted name can be put back, because the inode is still reachable:

$ ln data/latest-measurement.csv data/raw/measurement-03.csv
$ ls -li data/raw/measurement-03.csv data/latest-measurement.csv
22143 -rw-r--r-- 2 student student 47 Jul 26 19:03 data/raw/measurement-03.csv
22143 -rw-r--r-- 2 student student 47 Jul 26 19:03 data/latest-measurement.csv

Hard links have two constraints, and both are a direct consequence of the concept of an inode.

It cannot cross a file system boundary. An inode number is meaningful only within its own file system; an entry cannot be written to an inode on another file system.

$ ln data/raw/measurement-01.csv /dev/shm/measurement-01.csv
ln: failed to create hard link '/dev/shm/measurement-01.csv' => 'data/raw/measurement-01.csv': Invalid cross-device link

This is the twin, from the same root, of the observation in the moving lesson: moving within the same file system is cheap, moving outside it turns into copying — because a directory entry can only point to inodes within its own file system.

It cannot be placed on directories.

$ ln data/raw data/raw-link
ln: data/raw: hard link not allowed for directory

The prohibition exists to keep the file system a tree. If a hard link could be placed on directories, cycles could form, and any tool traversing the tree could fall into infinite recursion. The only exception to this prohibition is two entries the system itself sets up:

$ ls -lid data/. data/raw/..
21906 drwxr-xr-x 4 student student 4096 Jul 26 19:08 data/.
21906 drwxr-xr-x 4 student student 4096 Jul 26 19:08 data/raw/..

data/. and data/raw/.. point to the same inode: both are the data directory itself. This also explains a number left unexplained in the navigation lesson. A directory’s link count consists of: its name in the parent directory, its own . entry, and the .. entry of every subdirectory. Because the data directory has two subdirectories, the number is 1+1+2=41 + 1 + 2 = 4.

A symbolic link is an entirely different object: a small file with its own inode, whose content consists of nothing but a path string. When the kernel reads this file, it goes on to resolve the path inside it.

A symbolic link suits accessing the most recent file in the measurements directory under a fixed name:

$ ln -s raw/measurement-03.csv data/current.csv
$ ls -li data
total 8
28322 lrwxrwxrwx 1 student student   22 Jul 26 19:08 current.csv -> raw/measurement-03.csv
21908 drwxr-xr-x 2 student student 4096 Jul 26 19:07 raw
21909 drwxr-xr-x 2 student student 4096 Jul 26 19:03 processed

The output has four details worth noting. The type character is l. The inode number differs from the target’s — it is a separate file. The size is 22; this is not the content of the target, but the length of the raw/measurement-03.csv string. The permission bits appear as rwxrwxrwx and are meaningless: access control is done according to the target’s permissions.

The target is read with readlink, while the content is accessed directly:

$ readlink data/current.csv
raw/measurement-03.csv
$ cat data/current.csv
zaman,sicaklik,nem
08:00,22.6,58
12:00,26.3,44

Most commands follow a symbolic link: cat reads the target, not the link. Commands that deal with the link itself (rm, mv, ls -l) do not follow it. rm current.csv deletes the link, and does not touch the target.

Which Directory a Relative Target Is Resolved Against

The path inside a symbolic link can be relative. In that case, resolution is done not against the directory the command is run from, but against the directory the link is located in.

The link above sits inside data/ and its target is raw/measurement-03.csv; resolution gives data/raw/measurement-03.csv. If the same link were created in a different directory, the target could not be found:

$ ln -s data/raw/measurement-01.csv /dev/shm/measurement-01.csv
$ ls -l /dev/shm/measurement-01.csv
lrwxrwxrwx 1 student student 27 Jul 26 19:08 /dev/shm/measurement-01.csv -> data/raw/measurement-01.csv
$ cat /dev/shm/measurement-01.csv
cat: /dev/shm/measurement-01.csv: No such file or directory

The link has been created — whether the target exists is not checked — but it cannot be resolved. There is no data/raw path inside /dev/shm. This situation is called a dangling link.

A dangling link is not an error but the natural consequence of the definition: a symbolic link is a path string, not a handle to the target. If the target is deleted, moved, or the link is copied somewhere else, the link breaks.

The selection criterion follows from this. A relative target makes the link movable with its target: when the whole tree is copied elsewhere, the link keeps working. An absolute target points to the same file wherever the link goes, but breaks when the tree is moved. Inside a tree, a relative target is preferred; for fixed, system-wide locations, an absolute target is preferred.

Comparing the Two Kinds

Criterion Hard link Symbolic link
What it holds A second entry to the same inode The target’s path string
Its own inode No Yes
File system boundary Cannot cross Can cross
Can be placed on a directory No Yes
When the target is deleted Data survives, count decreases Link breaks
How to tell them apart Same number with ls -i l and -> in ls -l output

The choice reduces to a simple question: is a second name needed for the same data, or a fixed pointer to a target that can change? The first case uses a hard link, the second a symbolic link. current.csv in the project tree is an example of the second: when a new measurement file arrives, the link’s target changes, its name stays fixed.

The same approach appears in system layout too. The /bin -> usr/bin link from the directory hierarchy lesson keeps the old path working — it could not be a hard link, since it is placed on a directory.

Summary

  • A name is not a property of a file; a directory entry maps a name to an inode.
  • A hard link adds a second entry to the same inode; the link count rises and there is no hierarchy among the names.
  • A hard link cannot cross a file system boundary and cannot be placed on directories; . and .. are the system’s own exceptions to this prohibition.
  • A symbolic link is a file with its own inode, whose content is a path string; its size is the length of the target string.
  • A relative-target symbolic link is resolved against the directory the link is located in; if the target does not exist, the link is dangling, and this is a consequence of the definition, not an error.
  • Inside a tree, a relative target is preferred; for fixed, system-wide locations, an absolute target is preferred.

Next Step

The project tree now contains files, copies, and links. Packaging this whole tree into a single file — to send it to another machine or to preserve a point in time — raises a separate set of problems: how are links stored, how is the directory structure converted into a flat byte sequence, and where does compression fit into this? The next lesson begins by separating archiving from compression.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close