This is a simple one. You've already seen how symlinks are stored internally in the RAM-disk resource manager. The job of c_readlink() is to return the value of the symbolic link. It's called when you do a full ls, for example:
# ls -lF /my_temp lrwxrwxrwx 1 root root 4 Aug 16 14:06 /my_temp@ -> /tmp
Since this code shares a lot in common with the processing for c_open(), I'll just point out the major differences.
int cfs_c_readlink (resmgr_context_t *ctp, io_readlink_t *msg, RESMGR_HANDLE_T *handle, void *reserved) { des_t parent, target; int sts, sts2; int eflag; struct _client_info *cinfo; int tmp; // get client info if ((sts = iofunc_client_info_ext (ctp, 0, &cinfo, IOFUNC_CLIENTINFO_GETGROUPS)) != EOK) { return (sts); } // get parent and target sts2 = connect_msg_to_attr (ctp, &msg -> connect, handle, &parent, &target, &sts, cinfo); (void)iofunc_client_info_ext_free (&cinfo); if (sts2 != EOK) { return (sts); } // there has to be a target! if (!target.attr) { return (sts); } // 1) call the helper function sts = iofunc_readlink (ctp, msg, &target.attr -> attr, NULL); if (sts != EOK) { return (sts); } // 2) preserve eflag... eflag = msg -> connect.eflag; memset (&msg -> link_reply, 0, sizeof (msg -> link_reply)); msg -> link_reply.eflag = eflag; // 3) return data tmp = strlen (target.attr -> type.symlinkdata); SETIOV (&ctp -> iov [0], &msg -> link_reply, sizeof (msg -> link_reply)); SETIOV (&ctp -> iov[1], target.attr -> type.symlinkdata, tmp); msg -> link_reply.path_len = tmp; MsgReplyv (ctp -> rcvid, EOK, ctp -> iov, 2); return (_RESMGR_NOREPLY); }
The detailed code walkthrough is as follows: