25

There's no directory above /, so what's the point of the .. in it?

EmmaV
  • 4,067
  • 1
    How do you know there's nothing above it? You may be in a chroot. Should the .. entry need to be created if you mount your root directory someplace else (like on another machine)? – Kusalananda Sep 14 '19 at 21:17
  • 3
    Not sure this is correct but it seems like it would be more work to omit it than it would be to just apply to all directories without prejudice. – jesse_b Sep 14 '19 at 21:17
  • 8
    @Kusalananda cd .. in a root dir of chroot won't get you out of the chroot, nor will it fail with an error. –  Sep 14 '19 at 21:39
  • 6
    I look at it this way: consistency with the rest of the filesystem and stopping point for iterative traversal up the tree. When the parent node in a tree points to itself, you know you've reached the root of the tree. – Sergiy Kolodyazhnyy Sep 14 '19 at 22:19
  • @Kusalananda, IIRC, on Linux the .. of a root directory points to the root directory itself, so if you chroot somewhere, the .. of the directory looks different inside the chroot and outside it. So there's already some trickery going on regarding it. Same if you mount a directory, the mounted FS doesn't know where it's going to be mounted, so the .. of the FS root needs to be patched to match the surrounding filesystem tree. – ilkkachu Sep 15 '19 at 11:21
  • 1
    @SergiyKolodyazhnyy I'm not sure the stopping point argument is really an advantage; you could just as easily say "when the node doesn't have a parent pointer, you know you've reached the root". Either way you still have to check for a special condition and handle it differently; a program recursively climbing up the tree that fails to check for the root specially will loop forever with /.. = /, whereas it would at least crash with an error if /.. didn't exist (you could even catch that error as your stopping condition, if you're into EAFP-style logic). – Ben Sep 16 '19 at 02:23
  • 2
    @Ben No advantage implied. It's just one way out of multiple how linked lists and trees may be implemented. It just happens Linux and most filesystems implement it this way, and as Kusalananda's answer points out it is open for implementation – Sergiy Kolodyazhnyy Sep 16 '19 at 03:19

4 Answers4

34

The .. entry in the root directory is a special case.

From the POSIX standard (4.13 Pathname Resolution, where the . and .. entries are referred to as "dot" and "dot-dot" repsectively):

The special filename dot shall refer to the directory specified by its predecessor. The special filename dot-dot shall refer to the parent directory of its predecessor directory. As a special case, in the root directory, dot-dot may refer to the root directory itself.

The rationale has this to add (A.4.13 Pathname Resolution)

What the filename dot-dot refers to relative to the root directory is implementation-defined. In Version 7 it refers to the root directory itself; this is the behavior mentioned in POSIX.1-2017. In some networked systems the construction /../hostname/ is used to refer to the root directory of another host, and POSIX.1 permits this behavior.

Other networked systems use the construct //hostname for the same purpose; that is, a double initial <slash> is used. [...]

So, in short, the POSIX standard says that every directory should have both . and .. entries, and permits the .. directory entry in / to refer to the / directory itself (notice the word "may" in the first text quoted), but it also allows an implementation to let it refer to something else.

Most common implementations of filesystems makes /.. resolve to /.

Kusalananda
  • 333,661
17

Kusalananda has already told you that this is the behavior specified by the POSIX standard. However, the history of UNIX began in earnest in the early 1970s. POSIX dates back only to the second half of the 1980s, a full decade and a half later. In practice, POSIX merely specified what was already being done by implementations.

Rather, UNIX did very early on support mounting file systems on different devices into its single unified directory hierarchy. Each file system, in effect, has its own root directory; the file system mounted at / isn't particularly special in any way. (Its contents might be, but the file system itself isn't.)

The sysmount and sysumount system calls appear to have been introduced in UNIX V1, in 1970-1971 (V1 is dated 1971-11, according to the Unix Tree at The Unix Heritage Society). They are defined in u1.s (system call numbers 21 and 22, respectively) and implemented in u7.s. (PDP7 UNIX, dated 1970-01, does not appear to have any obvious ancestor of those).

You probably see where this is going: when any file system can be mounted at any location in the hierarchy, to keep from having to special-case things, each directory, including the root directory of each file system, should contain an entry pointing to its own parent directory. On disk, the logical place to point a file system's root directory's parent directory entry at is the file system's root directory, because there is nothing else "above" the file system's root directory. The concept of having something "above" the root directory only comes into play when that file system is mounted at some location other than the root of the hierarchy.

During mounting, it is possible to rewrite the "parent directory" pointer in the memory copy of the root directory to point at the parent directory of the mount point directory. If there is no parent directory of the mount point directory (in other words, the file system is being mounted as /), then just leave that piece of data alone (because there's likely nowhere else sensible to point it to anyway) or handle it separately later (as would probably be the case for the /../hostname/path and //hostname/path cases mentioned in Kusalananda's answer).

The resulting behavior is that in any directory other than /, regardless of whether it's a particular file system's root directory or a subdirectory (at any level of nesting), .. points at that directory's parent directory; and in /, .. points back at /. The former is what would feel natural (.. always works in the same way, moving you one step toward the root directory), while the latter, while slightly idiosyncratic, at least doesn't obviously break anything (there's little harm in not being able to move further toward the root directory than to the root directory itself). For example, you can hammer out an arbitrary number of ../ and know that those at least will not cause an error because .. at some point does not exist.

user
  • 28,901
2

There is a directory above /, / itself. The parent directory of the root directory is itself. cd .. or cd ../.. inside the root directory should leave you at the same place, not cause an error.

Notice that neither . or .. may exist as actual directory entries in some filesystems, they may be simply emulated by the virtual file system layer of the OS.


A path like /../hostname is supposed to have let you access the root of another host in some early pre-vfs and pre-nfs systems like MUNIX (using the "Newcastle Connection") but I don't know of any such system still in use, and the source code is nowhere to be found.

The available info is highly contradictory, but it seems that the most usual way to deploy such a system was by recompiling all programs so that all path-using calls like open(2) could be redirected in userspace (there were no shared libs in that time).

There were probably hundreds of such hacks (scratchbox being a more recent one that I had the displeasure of having to use), so it's not at all clear why they felt the need to accomodate it in the POSIX standard.

1

Beyond all other reasons mentioned here it is design simplicity, something for which UNIX is known. All directories contain ..; special cases are always tripping hazards (for security or robustness) looming in the dark. So instead of forcing programmers to deal with one rare case in many places, all directories are designed to have . and .. entries and are dealt with uniformly, and consideration of what happens at / is not needed.

countermode
  • 7,533
  • 5
  • 31
  • 58