Fun with symlinks
Symbolic links complicate the processing greatly.
Let's spend a little more time with the line:
if (
S_ISLNK (components [ncomponents - 1].attr -> attr.mode)
&&
(
components [ncomponents].name
|| (cmsg -> eflag & _IO_CONNECT_EFLAG_DIR)
|| !S_ISLNK (cmsg -> mode)
)
)
{
I've broken it out over a few more lines to clarify the logical relationships.
The very first condition (the one that uses the macro S_ISLNK()) gates the entire
if clause.
If the entry we are looking at is not a symlink, we can give up right away, and continue to the next statement.
Next, we examine a three-part OR condition. We perform the redirection if any of the following conditions is true:
- We have an intermediate component. This would be the case in the example /valid/symlink/extra where we are currently positioned at the symlink part of the pathname. In this case, we must look through the symlink.
- The _IO_CONNECT_EFLAG_DIR flag of the connect message's eflag member is set. This indicates that we wish to proceed as if the entity is a directory, and that means that we need to look through the symbolic link.
- The connect message's mode member indicates symlink operation. This is a flag that's set to indicate that the connect message refers to the contents of the symlink, so we need to redirect.
In case we need to follow the symlink, we don't do it ourselves! It's not the job of this resource manager's connect functions to follow the symlink. All we need to do is call redirect_symlink() and it will reply with a redirect message back to the client's open() (or other connect function call). All clients' open() calls know how to handle the redirection, and they (the clients) are responsible for retrying the operation with the new information from the resource manager.
To clarify:
- We have a symlink in our RAM disk: s -> /dev/ser1.
- A client issues an
open ("/ramdisk/s", O_WRONLY);call. - The process manager directs the client to the RAM disk, where it sends an open() message.
- The RAM disk processes the s pathname component, then redirects it. This means that
the client gets a message of
Redirect: Look in /dev/ser1 instead.
- The client asks the process manager who it should talk to about /dev/ser1 and the client is told the serial port driver.
- The client opens the serial port.
So, it's important to note that after the RAM disk performed the redirect
function,
it was out of the loop after that point.
