| Updated: October 28, 2024 |
The next-higher function in the call hierarchy is connect_msg_to_attr(). It calls pathwalk() to break apart the pathname, and then looks at the return code, the type of request, and other parameters to make a decision.
You'll see this function used in most of the resource manager connect functions in the RAM disk.
After pathwalk(), several scenarios are possible:
This function accepts two parameters, parent and target, which are used extensively in the upper levels to describe the directory that contains the target, as well as the target itself (if it exists).
int
connect_msg_to_attr (resmgr_context_t *ctp,
struct _io_connect *cmsg,
RESMGR_HANDLE_T *handle,
des_t *parent, des_t *target,
int *sts, struct _client_info *cinfo)
{
des_t components [_POSIX_PATH_MAX];
int ncomponents;
// 1) Find target, validate accessibility of components
ncomponents = _POSIX_PATH_MAX;
*sts = pathwalk (ctp, cmsg -> path, handle, 0, components,
&ncomponents, cinfo);
// 2) Assign parent and target
*target = components [ncomponents - 1];
*parent = ncomponents == 1 ? *target
: components [ncomponents - 2];
// 3) See if we have an error, abort.
if (*sts == ENOTDIR || *sts == EACCES) {
return (1);
}
// 4) missing non-final component
if (components [ncomponents].name != NULL && *sts == ENOENT) {
return (1);
}
if (*sts == EOK) {
// 5) if they wanted a directory, and we aren't one, honk.
if (S_ISDIR (cmsg -> mode)
&& !S_ISDIR (components [ncomponents-1].attr->attr.mode)) {
*sts = ENOTDIR;
return (1);
}
// 6) yes, symbolic links are complicated!
// (See walkthrough and notes)
if (S_ISLNK (components [ncomponents - 1].attr -> attr.mode)
&& (components [ncomponents].name
|| (cmsg -> eflag & _IO_CONNECT_EFLAG_DIR)
|| !S_ISLNK (cmsg -> mode))) {
redirect_symlink (ctp, cmsg, target -> attr,
components, ncomponents);
*sts = _RESMGR_NOREPLY;
return (1);
}
}
// 7) all OK
return (0);
}