+ return DO_STATUS(errno);
+}
+
+int
+__vfs_dup_fd(struct v_fd* old, struct v_fd** new)
+{
+ int errno = 0;
+ struct v_fd* copied = cake_grab(fd_pile);
+
+ memcpy(copied, old, sizeof(struct v_fd));
+ old->file->ref_count++;
+
+ return errno;
+}
+
+__DEFINE_LXSYSCALL2(int, dup2, int, oldfd, int, newfd)
+{
+ if (newfd == oldfd) {
+ return newfd;
+ }
+
+ int errno;
+ struct v_fd *oldfd_s, *newfd_s;
+ if (!GET_FD(oldfd, oldfd_s) || TEST_FD(newfd)) {
+ errno = EBADF;
+ goto done;
+ }
+ newfd_s = __current->fdtable->fds[newfd];
+ if (newfd_s && (errno = vfs_close(newfd_s))) {
+ goto done;
+ }
+
+ if (!(errno = __vfs_dup_fd(oldfd_s, &newfd_s))) {
+ __current->fdtable->fds[newfd] = newfd_s;
+ return newfd;
+ }
+
+done:
+ return DO_STATUS(errno);
+}
+
+__DEFINE_LXSYSCALL1(int, dup, int, oldfd)
+{
+ int errno, newfd;
+ struct v_fd *oldfd_s, *newfd_s;
+ if (!GET_FD(oldfd, oldfd_s)) {
+ errno = EBADF;
+ } else if (!(errno = vfs_alloc_fdslot(&newfd)) &&
+ !(errno = __vfs_dup_fd(oldfd_s, &newfd_s))) {
+ __current->fdtable->fds[newfd] = newfd_s;
+ return newfd;
+ }
+
+ return DO_STATUS(errno);
+}
+
+__DEFINE_LXSYSCALL2(int,
+ symlink,
+ const char*,
+ pathname,
+ const char*,
+ link_target)
+{
+ int errno;
+ struct v_dnode* dnode;
+ if ((errno = vfs_walk(NULL, pathname, &dnode, NULL, 0))) {
+ goto done;
+ }
+ if ((dnode->super_block->fs->types & FSTYPE_ROFS)) {
+ errno = EROFS;
+ goto done;
+ }
+ if (!dnode->inode->ops.symlink) {
+ errno = ENOTSUP;
+ goto done;
+ }
+
+ errno = dnode->inode->ops.symlink(dnode->inode, link_target);
+
+done: