This article will cover *nix links, specifically what they are and how to make them.
Because I’m more of a visual learner, I thought it’d be a good idea to cover *nix-links using a very simple example. This makes it a lot easier to follow.
Stay One Step Ahead of Cyber Threats
We start with an empty directory.
$ ls -alh
total 8.0K
drwxr-xr-x 2 ubuntu ubuntu 4.0K Oct 14 15:26 .
drwxr-xr-x 7 ubuntu ubuntu 4.0K Oct 14 15:15 ..
Let’s create a file, which we’ll call “theFile.”
As you see, contained within it will be the phrase “hello world.”
$ echo “hello world” > theFile
$ cat theFile
hello world
Now let’s create 2 links — a soft link, which we’ll call “theSoftLink” and a hard link, which we’ll call “theHardLink.”
Soft links are created using the “ln” (short for link) command with the “-s” switch, whereas hard links require “ln” with no switches. See the example below.
$ ln -s theFile theSoftLink
$ ln theFile theHardLink
We now have 3 files — “theFile”, “theHardLink”, and “theSoftLink.”
Let’s again list our directory using the ls (short for list) command with flags “-alhi,” which will give us:
- all files (-a) in the directory
- display the files using a long format (-l)
- in “human-readable format” (-h)
- with inodes (-i) [inodes are data structures that store information about a file and are uniquely represented numerically]
Seeing inodes in our directory listing is important because it illustrates the difference visually between a soft and hard link.
Notice below that “theFile” and “theHardLink” have the same inode value — 281949, whereas “theSoftLink” has an inode value of 282744.
In other words, “theFile” and “theHardLink” are actually the same file with 2 filenames.
$ ls -alhi
total 16K
275812 drwxr-xr-x 2 ubuntu ubuntu 4.0K Oct 14 15:27 .
267106 drwxr-xr-x 7 ubuntu ubuntu 4.0K Oct 14 15:15 ..
281949 -rw-r–r– 2 ubuntu root 12 Oct 14 15:26 theFile
281949 -rw-r–r– 2 ubuntu ubuntu 12 Oct 14 15:26 theHardLink
282744 lrwxrwxrwx 1 ubuntu ubuntu 7 Oct 14 15:27 theSoftLink -> theFile
Let’s see the contents of “theHardLink.”
$ cat theHardLink
hello world
Let’s now see the contents of “theSoftLink.”
$ cat theSoftLink
hello world
Let’s now remove “theFile.”
$ rm theFile
Now let’s see if we can still see the contents of “theHardLink” after deleting “theFile.”
$ cat theHardLink
hello world
We sure can. We discuss why shortly.
Now, let’s see if we can still see the contents of “theSoftLink.”
$ cat theSoftLink
cat: theSoftLink: No such file or directory
No, we can’t. But why?
“theSoftLink” was pointing to the filename “theFile,” which we’ve now deleted. So when we attempted to output the contents of “theSoftLink” it couldn’t find the filename it was referencing.
theSoftLink (references a deleted file) -> theFile
So, let’s again review our directory. We now only have 2 files remaining — “theHardLink” and “theSoftLink.”
$ ls -alhi
total 12K
275812 drwxr-xr-x 2 ubuntu ubuntu 4.0K Oct 14 15:27 .
267106 drwxr-xr-x 7 ubuntu ubuntu 4.0K Oct 14 15:15 ..
281949 -rw-r–r– 1 ubuntu ubuntu 12 Oct 14 15:26 theHardLink
282744 lrwxrwxrwx 1 ubuntu ubuntu 7 Oct 14 15:27 theSoftLink -> theFile
But what happens if we again re-create “theFile?” Will “theSoftLink” be resurrected?
Let’s do it now.
$ echo “hello world, again” >> theFile
Let’s verify that “theFile” exists by outputting its contents.
$ cat theFile
hello world, again
Wonderful!
Now that we’ve recreated “theFile,” does “theSoftLink” still point to it?
$ cat theSoftLink
hello world, again
It sure does!
And as you can see from the below output, “theHardLink” still maintains its original content — “hello world.”
$ cat theHardLink
hello world
If we again relist our directory’s content, we see there are 3 files.
What’s most interesting is that they all have different inode values. When we deleted and re-created “theFile,” *nix gave it a different inode, because despite having the same name, it’s a different file. This is expected behavior.
$ ls -alhi
total 16K
275812 drwxr-xr-x 2 ubuntu ubuntu 4.0K Oct 14 15:28 .
267106 drwxr-xr-x 7 ubuntu ubuntu 4.0K Oct 14 15:15 ..
282789 -rw-r–r– 1 ubuntu ubuntu 19 Oct 14 15:28 theFile
281949 -rw-r–r– 1 ubuntu ubuntu 12 Oct 14 15:26 theHardLink
282744 lrwxrwxrwx 1 ubuntu ubuntu 7 Oct 14 15:27 theSoftLink -> theFile
So, let’s recap.
At the beginning of this exercise, “theFile” and “theHardLink” were the same file, which we could validate by reviewing its inode. All this meant was that a single file had 2 filenames. Deleting the original filename “theFile” didn’t delete the file; *nix only removed the filename reference. It could still be accessed using “theHardLink.”
“theSoftLink” was never altered. Its only job was to provide a link to a file — one named “theFile.” It didn’t depend on an inode, only a filename.
I hope this helped bring some clarity to links in *nix. They’re not tricky once you understand what’s happening under the hood.
"Amateurs hack systems, professionals hack people."
-- Bruce Schneier, a renown computer security professional