+/*
+ * Return target name of a symbolic link
+ */
+readlink()
+{
+ register struct inode *ip;
+ register struct a {
+ char *name;
+ char *buf;
+ int count;
+ } *uap;
+
+ ip = namei(uchar, 0, 0);
+ if (ip == NULL)
+ return;
+ if ((ip->i_mode&IFMT) != IFLNK) {
+ u.u_error = ENXIO;
+ goto out;
+ }
+ uap = (struct a *)u.u_ap;
+ u.u_offset = 0;
+ u.u_base = uap->buf;
+ u.u_count = uap->count;
+ u.u_segflg = 0;
+ readi(ip);
+out:
+ iput(ip);
+ u.u_r.r_val1 = uap->count - u.u_count;
+}
+
+/*
+ * symlink -- make a symbolic link
+ */
+symlink()
+{
+ register struct a {
+ char *target;
+ char *linkname;
+ } *uap;
+ register struct inode *ip;
+ register char *tp;
+ register c, nc;
+
+ uap = (struct a *)u.u_ap;
+ tp = uap->target;
+ nc = 0;
+ while (c = fubyte(tp)) {
+ if (c < 0) {
+ u.u_error = EFAULT;
+ return;
+ }
+ tp++;
+ nc++;
+ }
+ u.u_dirp = uap->linkname;
+ ip = namei(uchar, 1, 0);
+ if (ip) {
+ iput(ip);
+ u.u_error = EEXIST;
+ return;
+ }
+ if (u.u_error)
+ return;
+ ip = maknode(IFLNK | 0777);
+ if (ip == NULL)
+ return;
+ u.u_base = uap->target;
+ u.u_count = nc;
+ u.u_offset = 0;
+ u.u_segflg = 0;
+ writei(ip);
+ iput(ip);
+}
+