Index: uspace/lib/libc/generic/vfs/vfs.c
===================================================================
--- uspace/lib/libc/generic/vfs/vfs.c	(revision 81342f721696310b9531caaff48b0e5a37182a5e)
+++ uspace/lib/libc/generic/vfs/vfs.c	(revision 15b8e495a50e2460c084a79b7002f55d37a04f7e)
@@ -57,7 +57,7 @@
 static futex_t cwd_futex = FUTEX_INITIALIZER;
 
-DIR *cwd_dir = NULL;
-char *cwd_path = NULL;
-size_t cwd_size = 0;
+static int cwd_fd = -1;
+static char *cwd_path = NULL;
+static size_t cwd_size = 0;
 
 char *absolutize(const char *path, size_t *retlen)
@@ -197,37 +197,30 @@
 }
 
-static int _open(const char *path, int lflag, int oflag, ...)
-{
-	ipcarg_t rc;
+static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
+{
+	futex_down(&vfs_phone_futex);
+	async_serialize_start();
+	vfs_connect();
+	
 	ipc_call_t answer;
-	aid_t req;
-	
-	size_t pa_size;
-	char *pa = absolutize(path, &pa_size);
-	if (!pa)
-		return ENOMEM;
-	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
-	
-	req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer);
-	rc = async_data_write_start(vfs_phone, pa, pa_size);
+	aid_t req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer);
+	ipcarg_t rc = async_data_write_start(vfs_phone, abs, abs_size);
+	
 	if (rc != EOK) {
 		ipcarg_t rc_orig;
-	
-		async_wait_for(req, &rc_orig);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
-		free(pa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	async_wait_for(req, &rc);
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
-	free(pa);
+		async_wait_for(req, &rc_orig);
+		
+		async_serialize_end();
+		futex_up(&vfs_phone_futex);
+		
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	
+	async_wait_for(req, &rc);
+	async_serialize_end();
+	futex_up(&vfs_phone_futex);
 	
 	if (rc != EOK)
@@ -239,5 +232,13 @@
 int open(const char *path, int oflag, ...)
 {
-	return _open(path, L_FILE, oflag);
+	size_t abs_size;
+	char *abs = absolutize(path, &abs_size);
+	if (!abs)
+		return ENOMEM;
+	
+	int ret = open_internal(abs, abs_size, L_FILE, oflag);
+	free(abs);
+	
+	return ret;
 }
 
@@ -471,9 +472,21 @@
 	if (!dirp)
 		return NULL;
-	dirp->fd = _open(dirname, L_DIRECTORY, 0);
-	if (dirp->fd < 0) {
+	
+	size_t abs_size;
+	char *abs = absolutize(dirname, &abs_size);
+	if (!abs) {
+		free(dirp);
+		return ENOMEM;
+	}
+	
+	int ret = open_internal(abs, abs_size, L_DIRECTORY, 0);
+	free(abs);
+	
+	if (ret < 0) {
 		free(dirp);
 		return NULL;
 	}
+	
+	dirp->fd = ret;
 	return dirp;
 }
@@ -636,26 +649,29 @@
 int chdir(const char *path)
 {
-	size_t pa_size;
-	char *pa = absolutize(path, &pa_size);
-	if (!pa)
-		return ENOMEM;
-
-	DIR *d = opendir(pa);
-	if (!d) {
-		free(pa);
+	size_t abs_size;
+	char *abs = absolutize(path, &abs_size);
+	if (!abs)
+		return ENOMEM;
+	
+	int fd = open_internal(abs, abs_size, L_DIRECTORY, O_DESC);
+	
+	if (fd < 0) {
+		free(abs);
 		return ENOENT;
 	}
-
+	
 	futex_down(&cwd_futex);
-	if (cwd_dir) {
-		closedir(cwd_dir);
-		cwd_dir = NULL;
-		free(cwd_path);	
-		cwd_path = NULL;
-		cwd_size = 0;
-	}
-	cwd_dir = d;
-	cwd_path = pa;
-	cwd_size = pa_size;
+	
+	if (cwd_fd >= 0)
+		close(cwd_fd);
+	
+	
+	if (cwd_path)
+		free(cwd_path);
+	
+	cwd_fd = fd;
+	cwd_path = abs;
+	cwd_size = abs_size;
+	
 	futex_up(&cwd_futex);
 	return EOK;
@@ -664,15 +680,17 @@
 char *getcwd(char *buf, size_t size)
 {
-	if (!cwd_size)
+	if (size == 0)
 		return NULL;
-	if (!size)
-		return NULL;
+	
 	futex_down(&cwd_futex);
-	if (size < cwd_size + 1) {
+	
+	if ((cwd_size == 0) || (size < cwd_size + 1)) {
 		futex_up(&cwd_futex);
 		return NULL;
 	}
+	
 	str_cpy(buf, size, cwd_path);
 	futex_up(&cwd_futex);
+	
 	return buf;
 }
@@ -707,4 +725,22 @@
 }
 
+int dup2(int oldfd, int newfd)
+{
+	futex_down(&vfs_phone_futex);
+	async_serialize_start();
+	vfs_connect();
+	
+	ipcarg_t ret;
+	ipcarg_t rc = async_req_2_1(vfs_phone, VFS_IN_DUP, oldfd, newfd, &ret);
+	
+	async_serialize_end();
+	futex_up(&vfs_phone_futex);
+	
+	if (rc == EOK)
+		return (int) ret;
+	
+	return (int) rc;
+}
+
 /** @}
  */
