diff --git a/Userspace/libc/include/dirent.h b/Userspace/libc/include/dirent.h index b47a0138..e1825fd6 100644 --- a/Userspace/libc/include/dirent.h +++ b/Userspace/libc/include/dirent.h @@ -58,16 +58,16 @@ extern "C" #define DT_SHM #define DT_TMO - int alphasort(const struct dirent **, const struct dirent **); + int alphasort(const struct dirent **d1, const struct dirent **d2); int closedir(DIR *dirp); int dirfd(DIR *dirp); - DIR *fdopendir(int); - DIR *opendir(const char *); - ssize_t posix_getdents(int, void *, size_t, int); - struct dirent *readdir(DIR *); + DIR *fdopendir(int fd); + DIR *opendir(const char *dirname); + ssize_t posix_getdents(int fildes, void *buf, size_t nbyte, int flags); + struct dirent *readdir(DIR *dirp); int readdir_r(DIR *restrict, struct dirent *restrict, struct dirent **restrict); void rewinddir(DIR *); - int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **)); + int scandir(const char *dir, struct dirent ***namelist, int (*sel)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **)); void seekdir(DIR *, long); long telldir(DIR *); diff --git a/Userspace/libc/src/std/dirent.c b/Userspace/libc/src/std/dirent.c index 6351e906..74046f16 100644 --- a/Userspace/libc/src/std/dirent.c +++ b/Userspace/libc/src/std/dirent.c @@ -20,8 +20,13 @@ #include #include #include +#include +#include -export int alphasort(const struct dirent **, const struct dirent **); +export int alphasort(const struct dirent **d1, const struct dirent **d2) +{ + return strcoll((*d1)->d_name, (*d2)->d_name); +} export int closedir(DIR *dirp) { @@ -52,12 +57,122 @@ export int dirfd(DIR *dirp) return __check_errno(-ENOSYS, -1); } -export DIR *fdopendir(int); -export DIR *opendir(const char *); -export ssize_t posix_getdents(int, void *, size_t, int); -export struct dirent *readdir(DIR *); +export DIR *fdopendir(int fd) +{ + DIR *dirp = malloc(sizeof(DIR)); + if (dirp == NULL) + return NULL; + + dirp->__fd = fd; + return dirp; +} + +export DIR *opendir(const char *dirname) +{ + DIR *dirp = malloc(sizeof(DIR)); + if (dirp == NULL) + return NULL; + + dirp->__fd = open(dirname, O_RDONLY); + if (dirp->__fd == -1) + { + free(dirp); + return NULL; + } + + return dirp; +} + +export ssize_t posix_getdents(int fildes, void *buf, size_t nbyte, int flags) +{ + printf("posix_getdents() is unimplemented\n"); + return __check_errno(-ENOSYS, -1); +} + +export struct dirent *readdir(DIR *dirp) +{ + if (!dirp) + { + errno = EBADF; + return NULL; + } + + struct dirent *entry = malloc(sizeof(struct dirent)); + if (entry == NULL) + return NULL; + + ssize_t bytes = posix_getdents(dirp->__fd, entry, sizeof(struct dirent), 0); + if (bytes == -1) + { + free(entry); + return NULL; + } + + return entry; +} + export int readdir_r(DIR *restrict, struct dirent *restrict, struct dirent **restrict); export void rewinddir(DIR *); -export int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **)); + +export int scandir(const char *dir, struct dirent ***namelist, int (*sel)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **)) +{ + struct dirent **entry_list = NULL; + struct dirent *entry; + DIR *dp; + int count = 0; + int capacity = 10; + + dp = opendir(dir); + if (dp == NULL) + return -1; + + entry_list = malloc(capacity * sizeof(struct dirent *)); + if (entry_list == NULL) + { + closedir(dp); + return -1; + } + + while ((entry = readdir(dp)) != NULL) + { + if (sel == NULL || sel(entry)) + { + if (count >= capacity) + { + capacity *= 2; + struct dirent **new_list = realloc(entry_list, capacity * sizeof(struct dirent *)); + if (new_list == NULL) + { + for (int i = 0; i < count; i++) + free(entry_list[i]); + free(entry_list); + closedir(dp); + return -1; + } + entry_list = new_list; + } + entry_list[count] = malloc(sizeof(struct dirent)); + if (entry_list[count] == NULL) + { + for (int i = 0; i < count; i++) + free(entry_list[i]); + free(entry_list); + closedir(dp); + return -1; + } + memcpy(entry_list[count], entry, sizeof(struct dirent)); + count++; + } + } + + closedir(dp); + + if (count > 0) + qsort(entry_list, count, sizeof(struct dirent *), (int (*)(const void *, const void *))compar); + + *namelist = entry_list; + return count; +} + export void seekdir(DIR *, long); export long telldir(DIR *);