Linux – How to unlink (remove) the special hardlink “.” created for a folder

filesystemshard linklinuxrm

On Linux, when you a create folder, it automatically creates two hard links to the corresponding inode.
One which is the folder you asked to create, the other being the . special folder this folder.

Example:

$ mkdir folder
$ ls -li
total 0
124596048 drwxr-xr-x    2 fantattitude  staff    68 18 oct 16:52 folder
$ ls -lai folder
total 0
124596048 drwxr-xr-x  2 fantattitude  staff   68 18 oct 16:52 .
124593716 drwxr-xr-x  3 fantattitude  staff  102 18 oct 16:52 ..

As you can see, both folder and .'s inside folder have the same inode number (shown with -i option).

Is there anyway to delete this special . hardlink?

It's only for experimentation and curiosity.
Also I guess the answer could apply to .. special file as well.

I tried to look into rm man but couldn't find any way to do it. When I try to remove . all I get is:

rm: "." and ".." may not be removed

I'm really curious about the whole way these things work so don't refrain from being very verbose on the subject.

EDIT: Maybe I wasn't clear with my post, but I want to understand the underlying mechanism which is responsible for . files and the reasons why they can't be deleted.

I know the POSIX standard disallows a folder with less than 2 hardlinks, but don't really get why. I want to know if it could be possible to do it anyway.

Best Answer

It is technically possible to delete ., at least on EXT4 filesystems. If you create a filesystem image in test.img, mount it and create a test folder, then unmount it again, you can edit it using debugfs:

debugfs -w test.img
cd test
unlink .

debugfs doesn't complain and dutifully deletes the . directory entry in the filesystem. The test directory is still usable, with one surprise:

sudo mount test.img /mnt/temp
cd /mnt/temp/test
ls

shows only

..

so . really is gone. Yet cd ., ls ., pwd still behave as usual!

I'd previously done this test using rmdir ., but that deletes the directory's inode (huge thanks to BowlOfRed for pointing this out), which leaves test a dangling directory entry and is the real reason for the problems encountered. In this scenario, the test folder then becomes unusable; after mounting the image, running ls produces

ls: cannot access '/mnt/test': Structure needs cleaning

and the kernel log shows

EXT4-fs error (device loop2): ext4_lookup:1606: inode #2: comm ls: deleted inode referenced: 38913

Running e2fsck in this situation on the image deletes the test directory entirely (the directory inode is gone so there's nothing to restore).

All this shows that . exists as a specific entity in the EXT4 filesystem. I got the impression from the filesystem code in the kernel that it expects . and .. to exist, and warns if they don't (see namei.c), but with the unlink .-based test I didn't see that warning. e2fsck doesn't like the missing . directory entry, and offers to fix it:

$ /sbin/e2fsck -f test.img
e2fsck 1.43.3 (04-Sep-2016)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Missing '.' in directory inode 30721.
Fix<y>?

This re-creates the . directory entry.

Related Question