A directory may have different parent directories in different namespaces. Furthermore, a directory may appear multiple times in the same namespace, and so have multiple parents in that namespace. `..' does not fit well into a system based on object references. However, it is widely used by Unix programs, so we have to support it.
Rather than using the `..' parent directory facility provided by the underlying filesystem, the file server interprets `..' itself.
The semantics is that the parent of a directory is the directory that it was reached through, after symlinks have been expanded.
This means that the filename resolver maintains a stack of directory object references, called a dir_stack. When resolving the pathname `/a/b/..', it will first push the root directory onto the stack, then directory objects for `/a' and `/a/b', and then it will pop `/a/b' off the stack, leaving `/a' at the top of the stack as the result.
If `/a/b' is a symlink to `g/h', however, the filename resolver does not push `/a/b' onto the stack (since `/a/b' is not a directory object). It pushes `/a/g' and then `/a/g/h' onto the stack. Then, when it interprets `..' in the pathname, it pops `/a/g/h' off the stack to leave `/a/g' (the result) at the top.
The server represents the current working directory as one of these directory stacks. One of the consequences of these semantics is that if the current working directory is renamed or moved, the result of getcwd() will not reflect this.
This approach means that doing:
chdir("leafname") chdir("..")
has no effect (provided that the first call succeeds). This contrasts
with the usual Unix semantics, where the "leafname" directory could
be moved between the two calls, giving it a different parent directory.
This is partly why programs like "rm" use fchdir()
-- to avoid this
problem.