I am currently building a custom shell that can handle a few internal and external commands along with their options. One of these internal commands is pwd. From the man page of pwd, I got that pwd -L is going to output the current working directory even if it contains symlinks.
Now for implementing this, I want to know what functionality is available in C that can provide the working directory without resolving symlinks.
OS: GNU/Linux
PS: getcwd() gives the actual path and resolves the symlink. (Correct me if I am wrong somewhere).
The
pwdcommand has 2 different modes:pwd -Ldisplays the logical current working directory.pwd -Pdisplays the physical current working directory (all symbolic links resolved).If no options are specified, the -L option is assumed.
pwd -Puses thegetcwd()function: it resolves the..chain from the current directory of the process.Starting from the current directory, whose inode and device number are retrieved, it opens the parent directory as with
opendir("..")and enumerates the entries until one is found with the same inode and device number. This entry is the last component of the current directory name. If no such entry is found,getcwd()fails and setserrnotoENOENT.The process keeps going on the next parent directory until the root directory is reached.
This is very inefficient.
pwd -L, which is the default, uses a different method: the shell maintains an environment variablePWDthat contains the unresolved path to the current directory as reached by the shell viachdir/cdcommands. This path may differ from that obtained bygetcwd()if symbolic links were followed to reach the current directory or if some parts of the path have been renamed, moved or even removed. Thus the path stored in$PWDmay not even exist anymore, or may lead to a different place.To implement
pwd -Lin your shell, you can just output the value of thePWDenvironment variable, and you should update this variable when you executechdir/cdshell commands.Note also that for this
chdir/cdcommand, paths relative to the current directory should be resolved logically relative to this unresolved path by dropping the previous component for each../in the destination path. Only the resulting string that contains no.or..component is passed to the OS via thechdirsystem call.