Index: uspace/lib/libc/generic/vfs/vfs.c
===================================================================
--- uspace/lib/libc/generic/vfs/vfs.c	(revision 1526594cecdc714a8d598f097949f6f2939ec9fb)
+++ uspace/lib/libc/generic/vfs/vfs.c	(revision 5fec3551570815cfdb659a817d2ec7cc52c981d4)
@@ -33,5 +33,6 @@
  */
  
-#include <vfs.h>
+#include <vfs/vfs.h>
+#include <vfs/canonify.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -50,5 +51,42 @@
 
 int vfs_phone = -1;
-atomic_t vfs_phone_futex = FUTEX_INITIALIZER;
+futex_t vfs_phone_futex = FUTEX_INITIALIZER;
+
+futex_t cwd_futex = FUTEX_INITIALIZER;
+DIR *cwd_dir = NULL;
+char *cwd_path = NULL;
+size_t cwd_len = 0; 
+
+static char *absolutize(const char *path)
+{
+	char *ncwd_path;
+
+	futex_down(&cwd_futex);
+	size_t len = strlen(path);
+	if (*path != '/') {
+		if (!cwd_path) {
+			futex_up(&cwd_futex);
+			return NULL;
+		}
+		ncwd_path = malloc(len + cwd_len + 1);
+		if (!ncwd_path) {
+			futex_up(&cwd_futex);
+			return NULL;
+		}
+		strcpy(ncwd_path, cwd_path);
+		ncwd_path[cwd_len] = '/';
+		ncwd_path[cwd_len + 1] = '\0';
+	} else {
+		ncwd_path = malloc(len + 1);
+		if (!ncwd_path) {
+			futex_up(&cwd_futex);
+			return NULL;
+		}
+		ncwd_path[0] = '\0';
+	}
+	strcat(ncwd_path, path);
+	futex_up(&cwd_futex);
+	return ncwd_path;
+}
 
 static int vfs_connect(void)
@@ -67,11 +105,22 @@
 	int dev_handle = 0;	/* TODO */
 
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	if (vfs_phone < 0) {
-		res = vfs_connect();
-		if (res < 0) {
-			async_serialize_end();
-			futex_up(&vfs_phone_futex);
+	char *mpa = absolutize(mp);
+	if (!mpa)
+		return ENOMEM;
+	size_t mpc_len;
+	char *mpc = canonify(mpa, &mpc_len);
+	if (!mpc) {
+		free(mpa);
+		return EINVAL;
+	}
+
+	futex_down(&vfs_phone_futex);
+	async_serialize_start();
+	if (vfs_phone < 0) {
+		res = vfs_connect();
+		if (res < 0) {
+			async_serialize_end();
+			futex_up(&vfs_phone_futex);
+			free(mpa);
 			return res;
 		}
@@ -83,11 +132,13 @@
 		async_serialize_end();
 		futex_up(&vfs_phone_futex);
+		free(mpa);
 		return (int) rc;
 	}
-	rc = ipc_data_write_start(vfs_phone, (void *)mp, strlen(mp));
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+	rc = ipc_data_write_start(vfs_phone, (void *)mpc, mpc_len);
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		async_serialize_end();
+		futex_up(&vfs_phone_futex);
+		free(mpa);
 		return (int) rc;
 	}
@@ -95,4 +146,5 @@
 	async_serialize_end();
 	futex_up(&vfs_phone_futex);
+	free(mpa);
 	return (int) rc;
 }
@@ -105,20 +157,32 @@
 	aid_t req;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	if (vfs_phone < 0) {
-		res = vfs_connect();
-		if (res < 0) {
-			async_serialize_end();
-			futex_up(&vfs_phone_futex);
+	char *pa = absolutize(path);
+	if (!pa)
+		return ENOMEM;
+	size_t pc_len;
+	char *pc = canonify(pa, &pc_len);
+	if (!pc) {
+		free(pa);
+		return EINVAL;
+	}
+	
+	futex_down(&vfs_phone_futex);
+	async_serialize_start();
+	if (vfs_phone < 0) {
+		res = vfs_connect();
+		if (res < 0) {
+			async_serialize_end();
+			futex_up(&vfs_phone_futex);
+			free(pa);
 			return res;
 		}
 	}
 	req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer);
-	rc = ipc_data_write_start(vfs_phone, path, strlen(path));
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+	rc = ipc_data_write_start(vfs_phone, pc, pc_len);
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		async_serialize_end();
+		futex_up(&vfs_phone_futex);
+		free(pa);
 		return (int) rc;
 	}
@@ -126,4 +190,5 @@
 	async_serialize_end();
 	futex_up(&vfs_phone_futex);
+	free(pa);
 	return (int) IPC_GET_ARG1(answer);
 }
@@ -315,20 +380,32 @@
 	aid_t req;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	if (vfs_phone < 0) {
-		res = vfs_connect();
-		if (res < 0) {
-			async_serialize_end();
-			futex_up(&vfs_phone_futex);
+	char *pa = absolutize(path);
+	if (!pa)
+		return ENOMEM;
+	size_t pc_len;
+	char *pc = canonify(pa, &pc_len);
+	if (!pc) {
+		free(pa);
+		return EINVAL;
+	}
+
+	futex_down(&vfs_phone_futex);
+	async_serialize_start();
+	if (vfs_phone < 0) {
+		res = vfs_connect();
+		if (res < 0) {
+			async_serialize_end();
+			futex_up(&vfs_phone_futex);
+			free(pa);
 			return res;
 		}
 	}
 	req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL);
-	rc = ipc_data_write_start(vfs_phone, path, strlen(path));
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+	rc = ipc_data_write_start(vfs_phone, pc, pc_len);
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		async_serialize_end();
+		futex_up(&vfs_phone_futex);
+		free(pa);
 		return (int) rc;
 	}
@@ -336,4 +413,5 @@
 	async_serialize_end();
 	futex_up(&vfs_phone_futex);
+	free(pa);
 	return EOK; 
 }
@@ -345,20 +423,31 @@
 	aid_t req;
 	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	if (vfs_phone < 0) {
-		res = vfs_connect();
-		if (res < 0) {
-			async_serialize_end();
-			futex_up(&vfs_phone_futex);
+	char *pa = absolutize(path);
+	if (!pa)
+		return ENOMEM;
+	size_t pc_len;
+	char *pc = canonify(pa, &pc_len);
+	if (!pc) {
+		free(pa);
+		return EINVAL;
+	}
+	futex_down(&vfs_phone_futex);
+	async_serialize_start();
+	if (vfs_phone < 0) {
+		res = vfs_connect();
+		if (res < 0) {
+			async_serialize_end();
+			futex_up(&vfs_phone_futex);
+			free(pa);
 			return res;
 		}
 	}
 	req = async_send_0(vfs_phone, VFS_UNLINK, NULL);
-	rc = ipc_data_write_start(vfs_phone, path, strlen(path));
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		futex_up(&vfs_phone_futex);
+	rc = ipc_data_write_start(vfs_phone, pc, pc_len);
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		async_serialize_end();
+		futex_up(&vfs_phone_futex);
+		free(pa);
 		return (int) rc;
 	}
@@ -366,4 +455,5 @@
 	async_serialize_end();
 	futex_up(&vfs_phone_futex);
+	free(pa);
 	return EOK; 
 }
@@ -377,4 +467,50 @@
 {
 	return _unlink(path, L_DIRECTORY);
+}
+
+int chdir(const char *path)
+{
+	char *pa = absolutize(path);
+	if (!pa)
+		return ENOMEM;
+	size_t pc_len;
+	char *pc = canonify(pa, &pc_len);
+	if (!pc) {
+		free(pa);
+		return ENOENT;
+	}
+
+	DIR *d = opendir(pc);
+	if (!d) {
+		free(pa);
+		return ENOENT;
+	}
+
+	futex_down(&cwd_futex);
+	if (cwd_dir) {
+		closedir(cwd_dir);
+		cwd_dir = NULL;
+		free(cwd_path);	
+		cwd_path = NULL;
+		cwd_len = 0;
+	}
+	cwd_dir = d;
+	cwd_path = pc;
+	cwd_len = pc_len;
+	futex_up(&cwd_futex);
+}
+
+char *getcwd(char *buf, size_t size)
+{
+	if (!size)
+		return NULL;
+	futex_down(&cwd_futex);
+	if (size < cwd_len + 1) {
+		futex_up(&cwd_futex);
+		return NULL;
+	}
+	strcpy(buf, cwd_path);
+	futex_up(&cwd_futex);
+	return buf;
 }
 
Index: uspace/lib/libc/include/errno.h
===================================================================
--- uspace/lib/libc/include/errno.h	(revision 1526594cecdc714a8d598f097949f6f2939ec9fb)
+++ uspace/lib/libc/include/errno.h	(revision 5fec3551570815cfdb659a817d2ec7cc52c981d4)
@@ -45,4 +45,5 @@
 #define ENOTEMPTY	(-261)
 #define EBADF		(-262)
+#define ERANGE		(-263)
 
 #endif
Index: uspace/lib/libc/include/unistd.h
===================================================================
--- uspace/lib/libc/include/unistd.h	(revision 1526594cecdc714a8d598f097949f6f2939ec9fb)
+++ uspace/lib/libc/include/unistd.h	(revision 5fec3551570815cfdb659a817d2ec7cc52c981d4)
@@ -53,4 +53,6 @@
 extern int unlink(const char *);
 extern int rmdir(const char *);
+extern int chdir(const char *);
+extern char *getcwd(char *buf, size_t);
 
 extern void _exit(int status);
Index: uspace/lib/libc/include/vfs.h
===================================================================
--- uspace/lib/libc/include/vfs.h	(revision 1526594cecdc714a8d598f097949f6f2939ec9fb)
+++ 	(revision )
@@ -1,43 +1,0 @@
-/*
- * Copyright (c) 2007 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_VFS_H_
-#define LIBC_VFS_H_
-
-extern int mount(const char *, const char *, const char *);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/libc/include/vfs/canonify.h
===================================================================
--- uspace/lib/libc/include/vfs/canonify.h	(revision 1526594cecdc714a8d598f097949f6f2939ec9fb)
+++ uspace/lib/libc/include/vfs/canonify.h	(revision 5fec3551570815cfdb659a817d2ec7cc52c981d4)
@@ -36,4 +36,6 @@
 #define LIBC_VFS_CANONIFY_H_
 
+#include <sys/types.h>
+
 extern char *canonify(char *, size_t *);
 
Index: uspace/lib/libc/include/vfs/vfs.h
===================================================================
--- uspace/lib/libc/include/vfs/vfs.h	(revision 5fec3551570815cfdb659a817d2ec7cc52c981d4)
+++ uspace/lib/libc/include/vfs/vfs.h	(revision 5fec3551570815cfdb659a817d2ec7cc52c981d4)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_VFS_H_
+#define LIBC_VFS_H_
+
+extern int mount(const char *, const char *, const char *);
+
+#endif
+
+/** @}
+ */
