diff options
Diffstat (limited to 'src/dirent')
-rw-r--r-- | src/dirent/_dirent.h | 11 | ||||
-rw-r--r-- | src/dirent/closedir.c | 17 | ||||
-rw-r--r-- | src/dirent/opendir.c | 30 | ||||
-rw-r--r-- | src/dirent/readdir.c | 49 | ||||
-rw-r--r-- | src/dirent/rewinddir.c | 5 |
5 files changed, 100 insertions, 12 deletions
diff --git a/src/dirent/_dirent.h b/src/dirent/_dirent.h new file mode 100644 index 00000000..14af64ff --- /dev/null +++ b/src/dirent/_dirent.h @@ -0,0 +1,11 @@ +#ifndef ___DIRENT_H__ +#define ___DIRENT_H__ + +#include <dirent.h> + +struct __DIR { + int fd; + struct dirent de; +}; + +#endif diff --git a/src/dirent/closedir.c b/src/dirent/closedir.c index c12abfff..24cf31dd 100644 --- a/src/dirent/closedir.c +++ b/src/dirent/closedir.c @@ -1,14 +1,19 @@ #include <dirent.h> -#include "nonstd/assert.h" -#include "../_syscall.h" +#include "sys/types.h" +#include "unistd.h" +#include "stdlib.h" +#include "../_assert.h" +#include "_dirent.h" int closedir(DIR *dirp) { - /* + int ret = -1; ASSERT_NONNULL(dirp); - SYSCALL(closedir, int, -1, dirp, 0, 0, 0, 0, 0); - */ - return -1; + ret = close(dirp->fd); + if (ret != -1) { + free(dirp); + } + return ret; } /* POSIX(1) diff --git a/src/dirent/opendir.c b/src/dirent/opendir.c index 3e1d1c87..98a5df54 100644 --- a/src/dirent/opendir.c +++ b/src/dirent/opendir.c @@ -1,10 +1,34 @@ #include <dirent.h> -#include "stddef.h" +#include "errno.h" +#include "sys/types.h" +#include "stdlib.h" +#include "fcntl.h" +#include "_dirent.h" + +#ifndef O_DIRECTORY +#define O_DIRECTORY O_RDONLY +#endif + +#ifndef O_SEARCH +#define O_SEARCH O_RDONLY +#endif DIR * opendir(const char * dirname) { - (void)dirname; - return NULL; + DIR *dir = malloc(sizeof(*dir)); + if (dir == NULL) { + errno = ENOMEM; + return NULL; + } + + dir->fd = open(dirname, O_DIRECTORY | O_SEARCH); + if (dir->fd == -1) { + free(dir); + return NULL; + } + fcntl(dir->fd, F_SETFD, FD_CLOEXEC); + + return dir; } /* diff --git a/src/dirent/readdir.c b/src/dirent/readdir.c index 0e079f82..f8198169 100644 --- a/src/dirent/readdir.c +++ b/src/dirent/readdir.c @@ -1,10 +1,55 @@ #include <dirent.h> +#include "limits.h" +#include "errno.h" +#include "sys/types.h" #include "stddef.h" +#include "_dirent.h" +#include "unistd.h" +#include "../_syscall.h" + +#ifndef NAME_MAX +#define NAME_MAX _POSIX_NAME_MAX +#endif struct dirent * readdir(DIR * dirp) { - (void)dirp; - return NULL; + struct { + unsigned long inode; + unsigned long offset; + unsigned short length; + } kernel_de = { 0, 0, 0 }; + if (read(dirp->fd, &kernel_de, sizeof(kernel_de)) == -1) { + if (errno == EISDIR) { + struct { + long inode; + off_t offset; + unsigned short reclen; + char name[NAME_MAX + 1]; + } linux = { 0, 0, 0, "" }; + long ret = __syscall(__syscall_lookup(getdents), dirp->fd, &linux, sizeof(linux)); + if (ret < 0) { + errno = -ret; + return NULL; + } + + #ifdef _XOPEN_SOURCE + dirp->de.d_ino = linux.inode; + #endif + strcpy(dirp->de.d_name, linux.name); + return &dirp->de; + } + return NULL; + } + + #ifdef _XOPEN_SOURCE + dirp->de.d_ino = inode; + #endif + + if (read(dirp->fd, &dirp->de.d_name, kernel_de.length) == -1) { + return NULL; + } + + return &dirp->de; } /* diff --git a/src/dirent/rewinddir.c b/src/dirent/rewinddir.c index 0b53d783..f87f3e61 100644 --- a/src/dirent/rewinddir.c +++ b/src/dirent/rewinddir.c @@ -1,8 +1,11 @@ #include <dirent.h> +#include "sys/types.h" +#include "unistd.h" +#include "_dirent.h" void rewinddir(DIR * dirp) { - (void)dirp; + lseek(dirp->fd, 0, SEEK_SET); } /* |