30

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.

muru
  • 72,889
  • 11
  • @StephenKitt Please see my edit. – Fantattitude Oct 18 '16 at 15:27
  • 1
    I've retracted my vote, let's see how the voting plays out... – Stephen Kitt Oct 18 '16 at 15:38
  • 2
    Both are needed for relative paths. why would you want to remove these (other than plain curiosity)? – HalosGhost Oct 18 '16 at 16:00
  • @HalosGhost I'm just being very curious haha, exploring the limitations of the system and how and why it was designed this way. – Fantattitude Oct 18 '16 at 16:04
  • Linux does not have folders. It has directories. . and .. aren't really links, they simply refer to the current and parent directories, and are a fundamental part of the file system structure. If for instance you did "rmdir ." (note that it's 'rmdir', not 'rmfol' :-)), you'd remove the directory you are in. Likewise doing "rmdir .." would remove the parent and all its contents, including your current directory. Either case would be confusing, if not catastrophic, much like sawing off the branch you're sitting on :-) – jamesqf Oct 18 '16 at 18:51
  • @jamesqf Sure, what about rmdir somefolder/.. I'm not on the branch so I don't see a problem. The answer by Stephen Kitt is super interesting in this way :) – Fantattitude Oct 18 '16 at 19:11
  • @jamesqf you should try it — rmdir . refuses to do anything, as does rmdir somefolder/., and rmdir .. will always fail because the directory isn't empty. – Stephen Kitt Oct 18 '16 at 19:12
  • @Stephen Kitt: Sure, the commands won't do anything, because doing it would break the filesystem. You need to remember that the *nix filesystem is fundamentally a tree, and '.' & '..' are pointers to nodes in the tree. Remove them (which you could do with some low-level tool), and you break the filesystem. The only way I know to get around it is to use a completely different design, like the flat file systems of MVS or VM (IIRC - it's been a long, long time), and then you'd still have equivalent problems with destroying your structure/indices. – jamesqf Oct 19 '16 at 05:23
  • @jamesqf please don't tell me what I need to remember... The tree structure only really needs .., and at least EXT4 is still usable to some extent without . (EXT2 possibly even more). – Stephen Kitt Oct 19 '16 at 05:32
  • If you are working with a FUSE filesystem, the code behind it gets to control what the readdir syscall returns, so it can decide to not return those special files. Of course, almost all FUSE filesystems do, because a) it's conventional and b) most FUSE filesystems (but not all) derive their readdir results from a readdir call to an actual filesystem which does return them. You can easily cobble together a Python script that creates a FUSE filesystem that returns any list of files you want when you ls a folder in the filesystem :) – Thomas Oct 19 '16 at 11:20

4 Answers4

46

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.

Stephen Kitt
  • 434,908
  • Very interesting! Thank you! So the . folder is really existing inside the FS and tools expect it to work properly. – Fantattitude Oct 18 '16 at 15:51
  • Really nice of you, I don't know Linux and its FS enough to find this kind of infos myself so I'm very thankful you take time to answer me :) – Fantattitude Oct 18 '16 at 15:54
  • 3
    Can you try changing "rmdir" (which actually removes the inode) to "unlink" (which only removes the directory entry). It appears to leave a mostly-functioning directory (no errors on mount or ls). I haven't seen if other problems arise. – BowlOfRed Oct 18 '16 at 17:43
  • @BowlOfRed thank you very much, that is a very good point — so my rmdir . was actually destroying test and leaving that as a dangling directory entry, which you'd expect to cause issues. I'll check with unlink and update my answer! – Stephen Kitt Oct 18 '16 at 18:21
  • . and .. are implemented directly in the path descend algorithms now. I patched . and .. out of a fs driver and found they still work. .. is still looked at via NFS shares though. – Joshua Oct 19 '16 at 02:08
  • Also don't do this in ext4. The htree expand code expects them to be there and will choke if they aren't. – Joshua Oct 19 '16 at 02:09
  • @Fantattitude Some code requires it to be there, some code doesn't and just assumes it's there. – user253751 Oct 19 '16 at 03:46
  • I assume that the act of deleting . will also remove the permission and owner of the directory. – Giacomo Catenazzi Oct 19 '16 at 07:34
  • 1
    @GiacomoCatenazzi not directly, permissions and ownership are stored in the inode, not the directory entry. – Stephen Kitt Oct 19 '16 at 07:40
5

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.

John
  • 17,011
  • I know about that, I'm just curious if it's possible since they seem to be hardlinks. If they are not why would they add up to the hard link count of the inode? – Fantattitude Oct 18 '16 at 15:06
  • 3

    They're not actually hard links, that's just how the directory structure gets created / represented. Also, duplicate. http://unix.stackexchange.com/questions/289385/why-cant-i-remove-the-directory?rq=1

    – Jeter-work Oct 18 '16 at 15:11
  • @Xalorous And so what exactly represents these special files, if they are not hardlinks, what are they? They exist so they must be somewhere, except if they just get shown by ls or other tools automatically which doesn't seem realistic to me. – Fantattitude Oct 18 '16 at 15:18
  • @Fantattitude they are the how the folder represents itself to implement the POSIX requirement that rmdir not be able to remove the PWD. – Jeter-work Oct 18 '16 at 15:24
  • @Xalorous Do you know at what level this feature is implemented? FS? Kernel? – Fantattitude Oct 18 '16 at 15:26
  • 1
    In traditional Unix filesystems they're real hard links. They're synthesized on the fly by the driver for other filesystems. – Barmar Oct 19 '16 at 18:37
2

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.

0

As the 'possible duplicate of' post's answer says, the POSIX standard specifies that if rmdir attempts to remove the current directory, it shall fail.

With anything you build you have to have a foundation. It's hard to define relative paths without a way to say 'here'. So the '.' is defined as 'here'.

Also, you can remove 'dot' and 'dot dot'. Write your own OS that does not define them. Though Unix (and by extension Mac OSX), Linux, and even MS DOS and Windows all use dot and dotdot.

TL;DR - 'dot' is in the definition of the OS.

Jeter-work
  • 265
  • 1
  • 8