10

Is a directory removed when its number of hard links becomes 0?

A directory always has at least 2 as its number of hard links, because of .. When rm -r a directory, does it decrease the number of hard link from 2 to 0 by 2 instead of 1?

Can the number of hard links of a directory ever be 1?

Thanks.

2 Answers 2

11

Any file on a conventionally designed UNIX filesystem whose reference count (e.g. the sum of the hardlink count and the number of open file handles*) reaches 0 is removed. However, on modern UNIX systems, the rmdir system call removes an empty directory in a single operation rather than removing . and .. one-by-one.

In historical UNIX systems, however, this system call did not exist. Instead, the rmdir command was a setuid program (source code can be found here) which checked that a directory was empty (other than the special entries), and then removed .. and ., in that order, and then removed the directory itself, all with the unlink system call which only root was permitted to use on directories (hence why the command was setuid). So, on those systems, the link count of a directory would momentarily be 1 after . was removed but before the directory was removed from the parent directory, then it would be 0.

The rm command, incidentally, prevented even root from removing directories. And rm -r would call out to the rmdir command to remove directories after emptying their contents.

On these historical systems, misusing the unlink call from a program running as root, running into a race condition with rmdir or mv, or creating a file in a process whose current directory has been deleted (modern systems prevent this), could result in dangling files or directories which have a hardlink count above 0 but do not exist in the directory tree. This condition was detected by dcheck, and is still one of the checks in fsck since it remains physically possible on most filesystems.


Filesystems are, incidentally, not required to implement directories (including . and ..) as normal files that have hardlinks. On these filesystems, the hardlink count of a directory will always be reported as 0 (but of course, its existence within the parent directory qualifies for a "reference count" of 1).


The behavior of of a removed directory (e.g. when examined by a process which has it already open or has it as its current directory) and the exact meaning of the "link count" of a directory are unspecified. On Mac OS X, for example, it will report a hardlink count of 2, even though it has no real hardlinks. Even though . and .. do not appear in the listing, the directory can be opened and stat may be called with the name . or ... On Linux, the link count is 0 but . and .. likewise still work.

Mac OS X also reports the number of all files in a directory as the link count, instead of just the number of subdirectories. But it is 2 even when . and .. are gone.


*This includes normal open descriptors, memory-mapped sections (including e.g. executing binaries and shared libraries), and process current directories.

5
  • 2
    strcpy to a fixed-size array in a setuid executable... these were good times! May 7, 2015 at 6:57
  • @AndreaCorbellini There's actually a published exploit for mkdir based on the fact that it has to do the same thing in reverse.
    – Random832
    May 7, 2015 at 13:42
  • 1
    I think I found it: securityfocus.com/archive/1/365038/2004-05-31/2004-06-06/0 :) May 7, 2015 at 15:15
  • asking about rmdir, wouldn't removin .. remove the parent directory?
    – Alex Jones
    Feb 9, 2016 at 14:28
  • @edwardtorvalds No, I was referring to the removal of the ".." link itself, not the parent directory it points at.
    – Random832
    Feb 9, 2016 at 15:07
9

Firstly not all filesystems use . and .. as hard links. this is documented in the gnu find manual. I am going to ignore those filesystems for the rest of my answer because they were not designed for unix and only complicate things without adding clarity. I am also going to ignore the root directory and mount points for the same reason.

the number of links to a directory is never less than two because of . and ... The number of subdirectories is equal to the number of links minus two. Because of this you cannot link or unlink a directory, so rm -r will stat a file before deleting and use rmdir instead of unlink on directories. The two system calls use completely different code paths in the kernel.

8
  • Thanks. A directory has a hard link .., only when it has a subdirectory, correct? So .. isn't always present for a directory, right?
    – Tim
    May 7, 2015 at 0:44
  • .. is present in each directory that is a subdirectory. which is all but / which has one too, so all directories.
    – hildred
    May 7, 2015 at 0:48
  • 1
    (1) If a directory has no subdir, the directory doesn't have a hard link .. to itself. What are the hard links to the dir? the file with the pathname, and .? (2) why do you ignore mount points?
    – Tim
    May 7, 2015 at 0:55
  • If the directory is a sub-directory. the entry .. will point to the parent. As a special case the root directory link points to itself. This allows cd ..\.. and similar commands to work as expected no matter where you are. You can test with the stat command.
    – BillThor
    May 7, 2015 at 1:04
  • 1
    You're correct that the link count is never less than 2, but it's not because of ... It's because of . and the name in the parent directory that points to it. The only exception is the root, which has no parent. But it has .. pointing to itself, so it also has link count = 2.
    – Barmar
    May 13, 2015 at 19:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .