| Updated: October 28, 2024 |
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
Figure 1. A hard link implemented as two different attributes structures pointing to the same file.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: