Now that we understand all of the steps involved in processing the c_open() (and, coincidentally, large chunks of all other connect functions), it's time to look at the code.
int
cfs_c_open (resmgr_context_t *ctp, io_open_t *msg,
RESMGR_HANDLE_T *handle, void *extra)
{
int sts;
des_t parent, target;
struct _client_info cinfo;
// 1) fetch the client information
if (sts = iofunc_client_info (ctp, 0, &cinfo)) {
return (sts);
}
// 2) call the helper connect_msg_to_attr
if (connect_msg_to_attr (ctp, &msg -> connect, handle,
&parent, &target, &sts, &cinfo)) {
return (sts);
}
// if the target doesn't exist
if (!target.attr) {
// 3) and we're not creating it, error
if (!(msg -> connect.ioflag & O_CREAT)) {
return (ENOENT);
}
// 4) else we are creating it, call the helper iofunc_open
sts = iofunc_open (ctp, msg, NULL, &parent.attr -> attr,
NULL);
if (sts != EOK) {
return (sts);
}
// 5) create an attributes structure for the new entry
target.attr = cfs_a_mkfile (parent.attr,
target.name, &cinfo);
if (!target.attr) {
return (errno);
}
// else the target exists
} else {
// 6) call the helper function iofunc_open
sts = iofunc_open (ctp, msg, &target.attr -> attr,
NULL, NULL);
if (sts != EOK) {
return (sts);
}
}
// 7) Target existed or just created, truncate if required.
if (msg -> connect.ioflag & O_TRUNC) {
// truncate at offset zero because we're opening it:
cfs_a_truncate (target.attr, 0, TRUNCATE_ERASE);
}
// 8) bind the OCB and attributes structures
sts = iofunc_ocb_attach (ctp, msg, NULL,
&target.attr -> attr, NULL);
return (sts);
}