summaryrefslogtreecommitdiff
path: root/src/dirent
diff options
context:
space:
mode:
Diffstat (limited to 'src/dirent')
-rw-r--r--src/dirent/_dirent.h11
-rw-r--r--src/dirent/closedir.c17
-rw-r--r--src/dirent/opendir.c30
-rw-r--r--src/dirent/readdir.c49
-rw-r--r--src/dirent/rewinddir.c5
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);
}
/*