The c_link() function is responsible for soft and hard links. A hard link is the original link from the dawn of history. It's a method that allows one resource (be it a directory or a file, depending on the support) to have multiple names. In the example in the symlink redirection, we created a symlink from resume.htm to ../resume.html; we could just as easily have created a hard link:
# ln ../resume.html resume.htm
In this case, both ../resume.html and resume.htm would be considered identical; there's no concept of original and link as there is with symlinks.
When the client calls link() or symlink() (or uses the command-line command ln), our RAM-disk resource manager's c_link() function will be called.
The c_link() function follows a similar code path as all of the other connect functions we've discussed so far (c_open() and c_readlink()), so once again we'll just focus on the differences:
int cfs_c_link (resmgr_context_t *ctp, io_link_t *msg, RESMGR_HANDLE_T *handle, io_link_extra_t *extra) { RESMGR_OCB_T *ocb; des_t parent, target; int sts, sts2; char *p, *s; struct _client_info *cinfo; if ((sts = iofunc_client_info_ext (ctp, 0, &cinfo, IOFUNC_CLIENTINFO_GETGROUPS)) != EOK) { return (sts); } 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); } if (target.attr) { return (EEXIST); } // 1) find out what type of link we are creating switch (msg -> connect.extra_type) { // process a hard link case _IO_CONNECT_EXTRA_LINK: ocb = extra -> ocb; p = strdup (target.name); if (p == NULL) { return (ENOMEM); } // 2) add a new directory entry if (sts = add_new_dirent (parent.attr, ocb -> attr, p)) { free (p); return (sts); } // 3) bump the link count ocb -> attr -> attr.nlink++; return (EOK); // process a symbolic link case _IO_CONNECT_EXTRA_SYMLINK: p = target.name; s = strdup (extra -> path); if (s == NULL) { return (ENOMEM); } // 4) create a symlink entry target.attr = cfs_a_mksymlink (parent.attr, p, NULL); if (!target.attr) { free (s); return (errno); } // 5) write data target.attr -> type.symlinkdata = s; target.attr -> attr.nbytes = strlen (s); return (EOK); default: return (ENOSYS); } return (_RESMGR_DEFAULT); }
The following is the code walkthrough for creating hard or symbolic links: