How to unlink (remove) the special hardlink "." created for a folder?

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.


There is no way to remove this directory entry. The . entry means "this directory", the .. entry means "this directory's parent directory". They're not actually hard links, that's just how the directory structure gets created / represented.


As described in Lion's Notes on the Unix 6 Source Code early Unix had a disk file where both files and directories were represented on the disk by inode structures. There was a special bit that indicated that the file contents were a directory. Each inode had a link to its owning inode that allowed a file to know what directory it was in. The exception was the '/' directory which owned itself. There was also a link to contents. If an inode had no contents it could be returned to the free list. Since a directory was just a blessed file even an empty directory had to have contents to keep it from being garbage collected. Thus the .. was the inode's link to the parent inode and the . was there to indicate the directory still was usable. rmdir (by calling unlink) could remove the . directory if there were no other contents and the inode would then move to the free list when there were no more references to it.