11

From the manpage for ln:

-d, -F, --directory
  allow the superuser to attempt to hard link directories (note: will 
  probably fail due to system restrictions, even for the superuser)

Are there any filesystem drivers that actually allow this, or is the only option mount --bind <src> <dest>? Or is this kind of behavior blocked by the kernel before it even gets to the filesystem-specific driver?

NOTE: I'm not actually planning on doing this on any machines, just curious.

6

First a note: the ln command does not have options like -d, -F, --directory, this is a non-portable GNUism.

The feature you are looking for, is implemented by the link(1)command.

Back to your original question:

On a typical UNIX system the decision, whether hard links on directories are possible, is made in the filesystem driver.

The Solaris UFS driver supports hard links on directories, the ZFS driver does not.

The reason why UFS on Solaris supports hard links is that AT&T was interested in this feature - UFS from BSD does not support hard linked directories.

The reason why ZFS does not support hardlinked directories is that Jeff Bonwick does not like that feature.

Regarding Linux, I would guess that Linux blocks attempts to created hard links on directories in the upper kernel layers. The reason for this assumption is that Linus Torvalds wrote code for GIT that did shred directories when git clone was called as root on a platform that supports hard linked directories.

Note that a filesystem that supports to create hard linked directories also needs to support unlink(1) to remove non-empty directories as root.

So if we assume that Torvalds knows how Linux works and if Linux did support hard linked directories, Torvalds should have known that calling unlink(2) on a directory while being root, will not return with an error but shred that directory. IN other words, it is unlikely that Linux permits a file system driver to implement hard linked directories.

3

OP's question mentions mount --bind. A quick check shows that it does not modify the link-count for the directory which is mounted. Hardlinking always modifies the link-count, which you can see using ls -ld.

Normally (most Unix-like systems), the number of hardlinks to a directory will be the number of directories connected to that name, e.g.,

  • ".." (the parent directory)
  • "." (the directory itself)
  • subdirectories

If you read the (usually) more informative info page, you may discover as others have done:

Oh great, one spends hours tying to find what is wrong only to
discover,
$ info ln
On all existing implementations, you cannot make a hard link to a
directory, and hard links cannot cross filesystem boundaries.  (These
restrictions are not mandated by POSIX, however.)

Therefore, kindly say everywhere you say super-user only,
instead say "few systems, super-user only".

though it currently is worded

Most systems prohibit making a hard link to a directory; on those where it is allowed, only the super-user can do so (and with caution, since creating a cycle will cause problems to many other utilities). Hard links cannot cross file system boundaries. (These restrictions are not mandated by POSIX, however.)

Creating (and removing) hardlinks to a directory is a restricted feature to guard against losing files if a directory is unlinked. Because the link/unlink operations at the C operating system interface are symmetric, the linking to directories is normally done only in mkdir/rmdir calls.

Keep in mind that much of GNU coreutils was written (and documented) 20-30 years ago, when some real museum pieces were still in use. As noted in Regarding Hard Link, originally there were no mkdir/rmdir calls; directories were created (as a privileged operation) using hard links. All of that went away when the system calls were added to solve the problems mentioned. But the documentation continues to refer to these systems past the memory of their maintainers. The option which was questioned was in the predecessor fileutils (which was combined with textutils and shellutils in the mid-1990s to form coreutils). A few items from the changelog may help to clarify the origin of the feature:

Mon Jul 23 16:57:44 1990  David J. MacKenzie  (djm at albert.ai.mit.edu)

        * cp.c (copy): Make +update operate silently, like +one-file-system.
        * ln.c: Add -F as synonym for -d, for SunOS compatibility.

Wed Feb 21 11:13:26 1990  David J. MacKenzie  (djm at albert.ai.mit.edu)

        * ln.c (error): New function.
        (main, do_link): Call error instead of fprintf and exit. 
        (main): Recognize new -d +directory option to allow superuser to
        make hard links to dirs, like the BSD ln -f option.
        (do_link): Don't allow hard links to dirs (they are hard to
        get rid of -- rmdir and unlink don't do it), unless -d was given.
        (usage): Mention -d +directory option.

So you can see for instance that one of the antiques for which this feature was applicable was SunOS. The corresponding manual page said this:

OPTIONS
       -f     Force a hard link to a directory -- this option is  only   avail-
              able to the super-user.

       -s     Create a symbolic link or links.

SYSTEM V OPTIONS
       -f     Force  files to be linked without displaying permissions, asking
              questions or reporting errors.

       -F     Force a hard link to a directory -- this option is  only  avail-
              able to the super-user.

       -s     Create a symbolic link or links.

As noted in the documentation, this feature (and the corresponding option are not in POSIX (and see the Rationale section which explains why). Rather, the feature was moved to a new command (provided also by GNU coreutils) called link. The description of the command itself is vague; you have to read the description of the function call to get any use from the standard. However, the standard does not clarify the conditions in which the command would work, aside from carrying forward the disclaimer about required privileges. For that, you have to go to system-dependent features outside the standard:

Linking to a directory is restricted to the superuser in most historical implementations because this capability may produce loops in the file hierarchy or otherwise corrupt the file system. This volume of POSIX.1-2008 continues that philosophy by prohibiting link() and unlink() from doing this. Other functions could do it if the implementor designed such an extension.

There are systems which use hardlinks to directories beyond the normal number (2 plus subdirectories).

OSX uses multiple hardlinks to directories for ordinary files. It does not support this using ln (see manual page). According to How Time Machine Works its Magic, it does this to provide the versions used for the Time Machine backup facility.

Further reading:

  • 3
    This doesn't seem to answer the question at all. – Michael Homer Mar 5 '16 at 3:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.