Index: uspace/app/bdsh/cmds/builtins/cd/cd.c
===================================================================
--- uspace/app/bdsh/cmds/builtins/cd/cd.c	(revision 6bb169b5888edb060801d4ac1ed89a86670dd67a)
+++ uspace/app/bdsh/cmds/builtins/cd/cd.c	(revision 089385e85736c570d8465ad6e30a5f309db8738e)
@@ -63,4 +63,13 @@
 	argc = cli_count_args(argv);
 
+	/* Handle cd -- -. Override to switch to a directory named '-' */
+	bool hyphen_override = false;
+	if (argc == 3) {
+		if(!str_cmp(argv[1], "--")) {
+			hyphen_override = true;
+			argc--;
+		}
+	}
+
 	/* We don't yet play nice with whitespace, a getopt implementation should
 	 * protect "quoted\ destination" as a single argument. Its not our job to
@@ -79,8 +88,32 @@
 	}
 
-	/* We have the correct # of arguments
-     * TODO: handle tidle (~) expansion? */
+	/* We have the correct # of arguments */
+	// TODO: handle tidle (~) expansion? */
 
-	rc = chdir(argv[1]);
+	/* Handle 'cd -' first. */
+	if (!str_cmp(argv[1], "-") && !hyphen_override) {
+		char *buffer = (char *) malloc(PATH_MAX);
+		if (!buffer) {
+			cli_error(CL_ENOMEM, "Cannot switch to previous directory");
+			return CMD_FAILURE;
+		}
+		memset(buffer, 0, PATH_MAX);
+		getprevwd(buffer, PATH_MAX);
+		if (*buffer == '\0') {
+			cli_error(CL_EFAIL, "No previous directory to switch to");
+			free(buffer);
+			return CMD_FAILURE;
+		} else {
+			rc = chdir(buffer);
+			free(buffer);
+		}
+	} else if (hyphen_override) {
+		/* Handles 'cd -- <dirname>'.
+		 * Override for directory named '-'.
+		 */
+		rc = chdir(argv[2]);
+	} else {
+		rc = chdir(argv[1]);
+	}
 
 	if (rc == 0) {
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision 6bb169b5888edb060801d4ac1ed89a86670dd67a)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision 089385e85736c570d8465ad6e30a5f309db8738e)
@@ -58,9 +58,16 @@
 static async_sess_t *vfs_sess = NULL;
 
+/* Current (working) directory. */
 static FIBRIL_MUTEX_INITIALIZE(cwd_mutex);
-
 static int cwd_fd = -1;
 static char *cwd_path = NULL;
 static size_t cwd_size = 0;
+
+/* Previous directory. */
+static FIBRIL_MUTEX_INITIALIZE(pwd_mutex);
+static int pwd_fd = -1;
+static char *pwd_path = NULL;
+static size_t pwd_size = 0;
+
 
 /** Start an async exchange on the VFS session.
@@ -751,11 +758,21 @@
 	fibril_mutex_lock(&cwd_mutex);
 	
-	if (cwd_fd >= 0)
-		close(cwd_fd);
-	
-	
-	if (cwd_path)
-		free(cwd_path);
-	
+
+	fibril_mutex_lock(&pwd_mutex);
+
+	if (pwd_fd >= 0)
+		close(pwd_fd);
+
+
+	if (pwd_path)
+		free(pwd_path);
+
+
+	pwd_fd = cwd_fd;
+	pwd_path = cwd_path;
+	pwd_size = cwd_size;
+
+	fibril_mutex_unlock(&pwd_mutex);
+
 	cwd_fd = fd;
 	cwd_path = abs;
@@ -781,4 +798,23 @@
 	fibril_mutex_unlock(&cwd_mutex);
 	
+	return buf;
+}
+
+
+char *getprevwd(char *buf, size_t size)
+{
+	if (size == 0)
+		return NULL;
+
+	fibril_mutex_lock(&pwd_mutex);
+
+	if ((pwd_size == 0) || (size < pwd_size + 1)) {
+		fibril_mutex_unlock(&pwd_mutex);
+		return NULL;
+	}
+
+	str_cpy(buf, size, pwd_path);
+	fibril_mutex_unlock(&pwd_mutex);
+
 	return buf;
 }
Index: uspace/lib/c/include/unistd.h
===================================================================
--- uspace/lib/c/include/unistd.h	(revision 6bb169b5888edb060801d4ac1ed89a86670dd67a)
+++ uspace/lib/c/include/unistd.h	(revision 089385e85736c570d8465ad6e30a5f309db8738e)
@@ -74,4 +74,5 @@
 
 extern char *getcwd(char *buf, size_t);
+extern char *getprevwd(char *, size_t);
 extern int rmdir(const char *);
 extern int chdir(const char *);
