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")));