Index: uspace/app/getterm/getterm.c
===================================================================
--- uspace/app/getterm/getterm.c	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/app/getterm/getterm.c	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -43,4 +43,5 @@
 #include <errno.h>
 #include <loc.h>
+#include <vfs/vfs.h>
 #include "version.h"
 #include "welcome.h"
@@ -71,5 +72,5 @@
 	
 	if (oldfd != fd) {
-		if (dup2(oldfd, fd) != fd)
+		if (vfs_clone(oldfd, fd, false) != fd)
 			return;
 		
Index: uspace/app/redir/redir.c
===================================================================
--- uspace/app/redir/redir.c	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/app/redir/redir.c	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -44,4 +44,5 @@
 #include <str_error.h>
 #include <errno.h>
+#include <vfs/vfs.h>
 
 #define NAME  "redir"
@@ -65,5 +66,5 @@
 	
 	if (oldfd != fd) {
-		if (dup2(oldfd, fd) != fd)
+		if (vfs_clone(oldfd, fd, false) != fd)
 			return;
 		
Index: uspace/lib/bithenge/src/failure.c
===================================================================
--- uspace/lib/bithenge/src/failure.c	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/lib/bithenge/src/failure.c	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -152,6 +152,6 @@
 		if (null == -1)
 			exit(127);
-		dup2(null, STDOUT_FILENO);
-		dup2(null, STDERR_FILENO);
+		vfs_clone(null, STDOUT_FILENO, false);
+		vfs_clone(null, STDERR_FILENO, false);
 		close(null);
 		return 1;
Index: uspace/lib/c/generic/elf/elf_mod.c
===================================================================
--- uspace/lib/c/generic/elf/elf_mod.c	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/lib/c/generic/elf/elf_mod.c	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -96,5 +96,5 @@
 	elf_ld_t elf;
 
-	int ofile = vfs_clone(file, true);
+	int ofile = vfs_clone(file, -1, true);
 	int rc = _vfs_open(ofile, MODE_READ);
 	if (rc != EOK) {
Index: uspace/lib/c/generic/io/io.c
===================================================================
--- uspace/lib/c/generic/io/io.c	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/lib/c/generic/io/io.c	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -114,5 +114,5 @@
 	int infd = inbox_get("stdin");
 	if (infd >= 0) {
-		int stdinfd = vfs_clone(infd, false);
+		int stdinfd = vfs_clone(infd, -1, false);
 		assert(stdinfd == 0);
 		_vfs_open(stdinfd, MODE_READ);
@@ -125,9 +125,8 @@
 	int outfd = inbox_get("stdout");
 	if (outfd >= 0) {
-		int stdoutfd = vfs_clone(outfd, false);
+		int stdoutfd = vfs_clone(outfd, -1, false);
 		assert(stdoutfd <= 1);
-		while (stdoutfd < 1) {
-			stdoutfd = vfs_clone(outfd, false);
-		}
+		while (stdoutfd < 1)
+			stdoutfd = vfs_clone(outfd, -1, false);
 		_vfs_open(stdoutfd, MODE_APPEND);
 		stdout = fdopen(stdoutfd, "a");
@@ -139,9 +138,8 @@
 	int errfd = inbox_get("stderr");
 	if (errfd >= 0) {
-		int stderrfd = vfs_clone(errfd, false);
+		int stderrfd = vfs_clone(errfd, -1, false);
 		assert(stderrfd <= 2);
-		while (stderrfd < 2) {
-			stderrfd = vfs_clone(errfd, false);
-		}
+		while (stderrfd < 2)
+			stderrfd = vfs_clone(errfd, -1, false);
 		_vfs_open(stderrfd, MODE_APPEND);
 		stderr = fdopen(stderrfd, "a");
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -76,5 +76,5 @@
 		r = ENOENT;
 	else
-		r = vfs_clone(root_fd, true);
+		r = vfs_clone(root_fd, -1, true);
 	fibril_mutex_unlock(&root_mutex);
 	return r;
@@ -86,5 +86,5 @@
 	if (root_fd >= 0)
 		close(root_fd);
-	root_fd = vfs_clone(nroot, true);
+	root_fd = vfs_clone(nroot, -1, true);
 	fibril_mutex_unlock(&root_mutex);
 }
@@ -1071,32 +1071,4 @@
 }
 
-/** Duplicate open file.
- *
- * Duplicate open file under a new file descriptor.
- *
- * @param oldfd Old file descriptor
- * @param newfd New file descriptor
- * @return 0 on success. On error -1 is returned and errno is set
- */
-int dup2(int oldfd, int newfd)
-{
-	async_exch_t *exch = vfs_exchange_begin();
-	
-	sysarg_t ret;
-	sysarg_t rc = async_req_2_1(exch, VFS_IN_DUP, oldfd, newfd, &ret);
-	
-	vfs_exchange_end(exch);
-	
-	if (rc == EOK)
-		rc = ret;
-	
-	if (rc != EOK) {
-		errno = rc;
-		return -1;
-	}
-	
-	return 0;
-}
-
 static void process_mp(const char *path, struct stat *stat, list_t *mtab_list)
 {
@@ -1254,9 +1226,9 @@
 }
 
-int vfs_clone(int file, bool high_descriptor)
+int vfs_clone(int file_from, int file_to, bool high_descriptor)
 {
 	async_exch_t *vfs_exch = vfs_exchange_begin();
-	int rc = async_req_2_0(vfs_exch, VFS_IN_CLONE, (sysarg_t) file,
-	    (sysarg_t) high_descriptor);
+	int rc = async_req_3_0(vfs_exch, VFS_IN_CLONE, (sysarg_t) file_from,
+	    (sysarg_t) file_to, (sysarg_t) high_descriptor);
 	vfs_exchange_end(vfs_exch);
 	return rc;
Index: uspace/lib/c/include/ipc/vfs.h
===================================================================
--- uspace/lib/c/include/ipc/vfs.h	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/lib/c/include/ipc/vfs.h	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -73,5 +73,4 @@
 	VFS_IN_REGISTER,
 	VFS_IN_RENAME,
-	VFS_IN_DUP,
 	VFS_IN_WAIT_HANDLE,
 	VFS_IN_STATFS,
Index: uspace/lib/c/include/unistd.h
===================================================================
--- uspace/lib/c/include/unistd.h	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/lib/c/include/unistd.h	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -58,6 +58,4 @@
 #define getpagesize()  (PAGE_SIZE)
 
-extern int dup2(int, int);
-
 extern ssize_t write(int, aoff64_t *, const void *, size_t);
 extern ssize_t read(int, aoff64_t *, void *, size_t);
Index: uspace/lib/c/include/vfs/vfs.h
===================================================================
--- uspace/lib/c/include/vfs/vfs.h	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/lib/c/include/vfs/vfs.h	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -69,5 +69,5 @@
 extern int vfs_receive_handle(bool);
 
-extern int vfs_clone(int, bool);
+extern int vfs_clone(int, int, bool);
 extern int vfs_root(void);
 extern void vfs_root_set(int);
Index: uspace/lib/posix/source/unistd.c
===================================================================
--- uspace/lib/posix/source/unistd.c	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/lib/posix/source/unistd.c	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -306,5 +306,5 @@
 int posix_dup2(int fildes, int fildes2)
 {
-	return negerrno(dup2, fildes, fildes2);
+	return negerrno(vfs_clone, fildes, fildes2, false);
 }
 
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/srv/vfs/vfs.h	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -204,7 +204,6 @@
 extern int vfs_open_node_remote(vfs_node_t *);
 
-extern int vfs_op_clone(int oldfd, bool desc);
+extern int vfs_op_clone(int oldfd, int newfd, bool desc);
 extern int vfs_op_close(int fd);
-extern int vfs_op_dup(int oldfd, int newfd);
 extern int vfs_op_fstat(int fd);
 extern int vfs_op_mount(int mpfd, unsigned servid, unsigned flags, unsigned instance, const char *opts, const char *fsname, int *outfd);
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/srv/vfs/vfs_file.c	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -304,7 +304,11 @@
 
 	fibril_mutex_lock(&VFS_DATA->lock);	
-	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] != NULL)) {
+	if ((fd < 0) || (fd >= MAX_OPEN_FILES)) {
 		fibril_mutex_unlock(&VFS_DATA->lock);
-		return EINVAL;
+		return EBADF;
+	}
+	if (FILES[fd] != NULL) {
+		fibril_mutex_unlock(&VFS_DATA->lock);
+		return EEXIST;
 	}
 	
Index: uspace/srv/vfs/vfs_ipc.c
===================================================================
--- uspace/srv/vfs/vfs_ipc.c	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/srv/vfs/vfs_ipc.c	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -37,7 +37,8 @@
 {
 	int oldfd = IPC_GET_ARG1(*request);
-	bool desc = IPC_GET_ARG2(*request);
-	
-	int ret = vfs_op_clone(oldfd, desc);
+	int newfd = IPC_GET_ARG2(*request);
+	bool desc = IPC_GET_ARG3(*request);
+	
+	int ret = vfs_op_clone(oldfd, newfd, desc);
 	async_answer_0(rid, ret);
 }
@@ -48,12 +49,4 @@
 	int rc = vfs_op_close(fd);
 	async_answer_0(rid, rc);
-}
-
-static void vfs_in_dup(ipc_callid_t rid, ipc_call_t *request)
-{
-	int oldfd = IPC_GET_ARG1(*request);
-	int newfd = IPC_GET_ARG2(*request);
-	int rc = vfs_op_dup(oldfd, newfd);
-	async_answer_1(rid, rc, newfd);
 }
 
@@ -279,7 +272,4 @@
 			vfs_in_close(callid, &call);
 			break;
-		case VFS_IN_DUP:
-			vfs_in_dup(callid, &call);
-			break;
 		case VFS_IN_FSTAT:
 			vfs_in_fstat(callid, &call);
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision f644472b977cc4e82d0187fb58bd63ad7bd5962a)
+++ uspace/srv/vfs/vfs_ops.c	(revision fcab7ef52ce87f4e12983237693d25d80bdb4fd7)
@@ -88,6 +88,12 @@
 }
 
-int vfs_op_clone(int oldfd, bool desc)
-{
+int vfs_op_clone(int oldfd, int newfd, bool desc)
+{
+	int rc;
+
+	/* If the file descriptors are the same, do nothing. */
+	if (oldfd == newfd)
+		return EOK;
+	
 	/* Lookup the file structure corresponding to fd. */
 	vfs_file_t *oldfile = vfs_file_get(oldfd);
@@ -96,17 +102,25 @@
 
 	assert(oldfile->node != NULL);
-	
-	vfs_file_t *newfile;
-	int newfd = vfs_fd_alloc(&newfile, desc);
-	if (newfd >= 0) {
-		newfile->node = oldfile->node;
-		newfile->permissions = oldfile->permissions;
-		vfs_node_addref(newfile->node);
-	
-		vfs_file_put(newfile);
+
+	if (newfd != -1) {
+		/* Make sure newfd is closed. */
+		(void) vfs_fd_free(newfd);
+		/* Assign the old file to newfd. */
+		rc = vfs_fd_assign(oldfile, newfd);
+	} else {
+		vfs_file_t *newfile;
+		int newfd = vfs_fd_alloc(&newfile, desc);
+		if (newfd >= 0) {
+			newfile->node = oldfile->node;
+			newfile->permissions = oldfile->permissions;
+			vfs_node_addref(newfile->node);
+	
+			vfs_file_put(newfile);
+		}
+		rc = newfd;
 	}
 	vfs_file_put(oldfile);
 	
-	return newfd;
+	return rc;
 }
 
@@ -114,25 +128,4 @@
 {
 	return vfs_fd_free(fd);
-}
-
-int vfs_op_dup(int oldfd, int newfd)
-{
-	/* If the file descriptors are the same, do nothing. */
-	if (oldfd == newfd)
-		return EOK;
-	
-	/* Lookup the file structure corresponding to oldfd. */
-	vfs_file_t *oldfile = vfs_file_get(oldfd);
-	if (!oldfile)
-		return EBADF;
-	
-	/* Make sure newfd is closed. */
-	(void) vfs_fd_free(newfd);
-	
-	/* Assign the old file to newfd. */
-	int ret = vfs_fd_assign(oldfile, newfd);
-	vfs_file_put(oldfile);
-	
-	return ret;
 }
 
