From 0b44a0315b47dd8eced9f3b7f31580cf14bbfc01 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 12 Feb 2011 00:22:29 -0500 Subject: initial check-in, version 0.5.0 --- src/dirent/__dirent.h | 9 +++++++++ src/dirent/__getdents.c | 12 ++++++++++++ src/dirent/alphasort.c | 10 ++++++++++ src/dirent/closedir.c | 11 +++++++++++ src/dirent/dirfd.c | 7 +++++++ src/dirent/fdopendir.c | 26 +++++++++++++++++++++++++ src/dirent/opendir.c | 25 +++++++++++++++++++++++++ src/dirent/readdir.c | 32 +++++++++++++++++++++++++++++++ src/dirent/readdir_r.c | 30 +++++++++++++++++++++++++++++ src/dirent/rewinddir.c | 13 +++++++++++++ src/dirent/scandir.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ src/dirent/seekdir.c | 12 ++++++++++++ src/dirent/telldir.c | 7 +++++++ 13 files changed, 244 insertions(+) create mode 100644 src/dirent/__dirent.h create mode 100644 src/dirent/__getdents.c create mode 100644 src/dirent/alphasort.c create mode 100644 src/dirent/closedir.c create mode 100644 src/dirent/dirfd.c create mode 100644 src/dirent/fdopendir.c create mode 100644 src/dirent/opendir.c create mode 100644 src/dirent/readdir.c create mode 100644 src/dirent/readdir_r.c create mode 100644 src/dirent/rewinddir.c create mode 100644 src/dirent/scandir.c create mode 100644 src/dirent/seekdir.c create mode 100644 src/dirent/telldir.c (limited to 'src/dirent') diff --git a/src/dirent/__dirent.h b/src/dirent/__dirent.h new file mode 100644 index 00000000..07b3ee68 --- /dev/null +++ b/src/dirent/__dirent.h @@ -0,0 +1,9 @@ +struct __DIR_s +{ + int lock; + int fd; + off_t tell; + int buf_pos; + int buf_end; + char buf[2048]; +}; diff --git a/src/dirent/__getdents.c b/src/dirent/__getdents.c new file mode 100644 index 00000000..4195430b --- /dev/null +++ b/src/dirent/__getdents.c @@ -0,0 +1,12 @@ +#include +#include "syscall.h" +#include "libc.h" + +int __getdents(int fd, struct dirent *buf, size_t len) +{ + return syscall3(__NR_getdents64, fd, (long)buf, len); +} + +weak_alias(__getdents, getdents); + +LFS64(getdents); diff --git a/src/dirent/alphasort.c b/src/dirent/alphasort.c new file mode 100644 index 00000000..42050fb7 --- /dev/null +++ b/src/dirent/alphasort.c @@ -0,0 +1,10 @@ +#include +#include +#include "libc.h" + +int alphasort(const struct dirent **a, const struct dirent **b) +{ + return strcoll((*a)->d_name, (*b)->d_name); +} + +LFS64(alphasort); diff --git a/src/dirent/closedir.c b/src/dirent/closedir.c new file mode 100644 index 00000000..81e9591c --- /dev/null +++ b/src/dirent/closedir.c @@ -0,0 +1,11 @@ +#include +#include +#include "__dirent.h" +#include "libc.h" + +int closedir(DIR *dir) +{ + int ret = close(dir->fd); + free(dir); + return ret; +} diff --git a/src/dirent/dirfd.c b/src/dirent/dirfd.c new file mode 100644 index 00000000..6c860073 --- /dev/null +++ b/src/dirent/dirfd.c @@ -0,0 +1,7 @@ +#include +#include "__dirent.h" + +int dirfd(DIR *d) +{ + return d->fd; +} diff --git a/src/dirent/fdopendir.c b/src/dirent/fdopendir.c new file mode 100644 index 00000000..c4b8e61d --- /dev/null +++ b/src/dirent/fdopendir.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include +#include +#include +#include "__dirent.h" + +DIR *fdopendir(int fd) +{ + DIR *dir; + struct stat st; + + if (fstat(fd, &st) < 0 || !S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + return 0; + } + if (!(dir = calloc(1, sizeof *dir))) { + return 0; + } + + fcntl(fd, F_SETFD, FD_CLOEXEC); + dir->fd = fd; + return dir; +} diff --git a/src/dirent/opendir.c b/src/dirent/opendir.c new file mode 100644 index 00000000..cefe6ce7 --- /dev/null +++ b/src/dirent/opendir.c @@ -0,0 +1,25 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include "__dirent.h" + +DIR *opendir(const char *name) +{ + int fd; + DIR *dir; + + if ((fd = open(name, O_RDONLY|O_DIRECTORY)) < 0) + return 0; + fcntl(fd, F_SETFD, FD_CLOEXEC); + if (!(dir = calloc(1, sizeof *dir))) { + close(fd); + return 0; + } + dir->fd = fd; + return dir; +} diff --git a/src/dirent/readdir.c b/src/dirent/readdir.c new file mode 100644 index 00000000..1aeb25a5 --- /dev/null +++ b/src/dirent/readdir.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include +#include "__dirent.h" +#include "syscall.h" +#include "libc.h" + +int __getdents(int, struct dirent *, size_t); + +struct dirent *readdir(DIR *dir) +{ + struct dirent *de; + + if (dir->buf_pos >= dir->buf_end) { + int len = __getdents(dir->fd, (void *)dir->buf, sizeof dir->buf); + if (len < 0) { + dir->lock = 0; + return NULL; + } else if (len == 0) return 0; + dir->buf_end = len; + dir->buf_pos = 0; + } + de = (void *)(dir->buf + dir->buf_pos); + dir->buf_pos += de->d_reclen; + dir->tell = de->d_off; + return de; +} + +LFS64(readdir); diff --git a/src/dirent/readdir_r.c b/src/dirent/readdir_r.c new file mode 100644 index 00000000..58f60325 --- /dev/null +++ b/src/dirent/readdir_r.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include "__dirent.h" +#include "libc.h" + +int readdir_r(DIR *dir, struct dirent *buf, struct dirent **result) +{ + struct dirent *de; + int errno_save = errno; + int ret; + + LOCK(&dir->lock); + errno = 0; + de = readdir(dir); + if ((ret = errno)) { + UNLOCK(&dir->lock); + return ret; + } + errno = errno_save; + if (de) memcpy(buf, de, de->d_reclen); + else buf = NULL; + + UNLOCK(&dir->lock); + *result = buf; + return 0; +} + +LFS64_2(readdir_r, readdir64_r); diff --git a/src/dirent/rewinddir.c b/src/dirent/rewinddir.c new file mode 100644 index 00000000..c6138f7c --- /dev/null +++ b/src/dirent/rewinddir.c @@ -0,0 +1,13 @@ +#include +#include +#include "__dirent.h" +#include "libc.h" + +void rewinddir(DIR *dir) +{ + LOCK(&dir->lock); + lseek(dir->fd, 0, SEEK_SET); + dir->buf_pos = dir->buf_end = 0; + dir->tell = 0; + UNLOCK(&dir->lock); +} diff --git a/src/dirent/scandir.c b/src/dirent/scandir.c new file mode 100644 index 00000000..6a0a9993 --- /dev/null +++ b/src/dirent/scandir.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include +#include + +int scandir(const char *path, struct dirent ***res, + int (*sel)(const struct dirent *), + int (*cmp)(const struct dirent **, const struct dirent **)) +{ + DIR *d = opendir(path); + struct dirent *de, **names=0, **tmp; + size_t cnt=0, len=0, size; + int old_errno = errno; + + if (!d) return -1; + + while ((errno=0), (de = readdir(d))) { + if (sel && !sel(de)) continue; + if (cnt >= len) { + len = 2*len+1; + if (len > SIZE_MAX/sizeof *names) break; + tmp = realloc(names, len * sizeof *names); + if (!tmp) break; + names = tmp; + } + size = offsetof(struct dirent,d_name) + strlen(de->d_name) + 1; + names[cnt] = malloc(size); + if (!names[cnt]) break; + memcpy(names[cnt++], de, size); + } + + closedir(d); + + if (errno) { + old_errno = errno; + if (names) while (cnt-->0) free(names[cnt]); + free(names); + errno = old_errno; + return -1; + } + + if (cmp) qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *))cmp); + *res = names; + return cnt; +} + +LFS64(scandir); diff --git a/src/dirent/seekdir.c b/src/dirent/seekdir.c new file mode 100644 index 00000000..81a0e331 --- /dev/null +++ b/src/dirent/seekdir.c @@ -0,0 +1,12 @@ +#include +#include +#include "__dirent.h" +#include "libc.h" + +void seekdir(DIR *dir, long off) +{ + LOCK(&dir->lock); + dir->tell = lseek(dir->fd, off, SEEK_SET); + dir->buf_pos = dir->buf_end = 0; + UNLOCK(&dir->lock); +} diff --git a/src/dirent/telldir.c b/src/dirent/telldir.c new file mode 100644 index 00000000..cf25acff --- /dev/null +++ b/src/dirent/telldir.c @@ -0,0 +1,7 @@ +#include +#include "__dirent.h" + +long telldir(DIR *dir) +{ + return dir->tell; +} -- cgit v1.2.1