diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc
index b4293d0bdc4ba8b64cd1b7689eec7625d27aeb3d..d134d44fb41686162b5d07975c58e3b3ca5c091e 100644
--- a/fs/vfs/main.cc
+++ b/fs/vfs/main.cc
@@ -526,31 +526,75 @@ TRACEPOINT(trace_vfs_readdir, "%d %p", int, dirent*);
 TRACEPOINT(trace_vfs_readdir_ret, "");
 TRACEPOINT(trace_vfs_readdir_err, "%d", int);
 
-extern "C"
-int
-ll_readdir(int fd, struct dirent *d)
+struct __DIR_s {
+    int fd;
+};
+
+DIR *opendir(const char *path)
+{
+    DIR *dir = new DIR;
+
+    if (!dir)
+        return libc_error_ptr<DIR>(ENOMEM);
+
+    dir->fd = open(path, O_RDONLY);
+    if (dir->fd < 0) {
+        delete dir;
+        return NULL;
+    }
+    return dir;
+}
+
+int closedir(DIR *dir)
+{
+    close(dir->fd);
+    delete dir;
+    return 0;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+    static __thread struct dirent entry, *result;
+    int ret;
+
+    ret = readdir_r(dir, &entry, &result);
+    if (ret)
+        return libc_error_ptr<struct dirent>(ret);
+
+    errno = 0;
+    return result;
+}
+
+int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result)
 {
     int error;
     struct file *fp;
 
-    trace_vfs_readdir(fd, d);
-    error = fget(fd, &fp);
+    trace_vfs_readdir(dir->fd, entry);
+    error = fget(dir->fd, &fp);
     if (error) {
         trace_vfs_readdir_err(error);
-        return error;
+    } else {
+        error = sys_readdir(fp, entry);
+        fdrop(fp);
+        if (error) {
+            trace_vfs_readdir_err(error);
+        } else {
+            trace_vfs_readdir_ret();
+        }
     }
 
-    error = sys_readdir(fp, d);
-    fdrop(fp);
     if (error) {
-        trace_vfs_readdir_err(error);
+        *result = NULL;
     } else {
-        trace_vfs_readdir_ret();
+        *result = entry;
     }
-
-    return error;
+    return error == ENOENT ? 0 : error;
 }
 
+#undef readdir64
+extern "C" struct dirent *readdir64(DIR *dir) __attribute__((alias("readdir")));
+
 #if 0
 static int
 fs_rewinddir(struct task *t, struct msg *msg)
diff --git a/libc/build.mk b/libc/build.mk
index 6c7fcb83866ace9ab61f992d0df46f2dc16c61c6..b8119ad00f778a96287d8943e1f505f60c19c6dd 100644
--- a/libc/build.mk
+++ b/libc/build.mk
@@ -631,7 +631,6 @@ libc += unistd/gethostname.o
 libc += unistd/sync.o
 
 libc += pthread.o
-libc += dir.o
 libc += libc.o
 libc += dlfcn.o
 libc += time.o
diff --git a/libc/dir.cc b/libc/dir.cc
deleted file mode 100644
index 05ff2821146895d0ba9a05786010789edb797483..0000000000000000000000000000000000000000
--- a/libc/dir.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2013 Cloudius Systems, Ltd.
- *
- * This work is open source software, licensed under the terms of the
- * BSD license as described in the LICENSE file in the top-level directory.
- */
-
-
-#include <fcntl.h>
-#include <string.h>
-#include <dirent.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include "libc.hh"
-
-// XXX: move to header
-extern "C" { int ll_readdir(int fd, struct dirent *d); }
-
-struct __dirstream {
-	int fd;
-};
-
-struct __DIR_s {
-    int fd;
-};
-
-
-DIR *opendir(const char *path)
-{
-	DIR *dir = new DIR;
-
-	if (!dir) 
-		return libc_error_ptr<DIR>(ENOMEM);
-
-
-	dir->fd = open(path, O_RDONLY);
-	if (dir->fd < 0) {
-		delete dir;
-		return NULL;
-	}
-	return dir;
-}
-
-int closedir(DIR *dir)
-{
-	close(dir->fd);
-	delete dir;
-	return 0;
-}
-
-struct dirent *readdir(DIR *dir)
-{
-	static __thread struct dirent entry, *result;
-	int ret;
-
-	ret = readdir_r(dir, &entry, &result);
-	if (ret)
-		return libc_error_ptr<struct dirent>(ret);
-
-	errno = 0;
-	return result;
-}
-
-int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result)
-{
-	int ret;
-
-	ret = ll_readdir(dir->fd, entry);
-	if (ret == 0)
-		*result = entry;
-	else
-		*result = NULL;
-	return ret == ENOENT ? 0 : ret;
-}
-
-// FIXME: in 64bit dirent64 and dirent are identical, so it's safe to alias
-extern "C" int readdir64_r(DIR *dir, struct dirent64 *entry,
-		struct dirent64 **result)
-		__attribute__((alias("readdir_r")));
-
-#undef readdir64
-extern "C" struct dirent *readdir64(DIR *dir) __attribute__((alias("readdir")));