From c423164066a4566eee78ba3db09321ccfd051cc7 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 11 Jun 2023 00:19:20 +0300 Subject: [PATCH] LibC: Implement basic dirent functionality We don't currently support seeking --- libc/CMakeLists.txt | 1 + libc/dirent.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++ libc/include/dirent.h | 4 +- 3 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 libc/dirent.cpp diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 8717a5c627..f7ba67e087 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -5,6 +5,7 @@ project(libc CXX ASM) set(LIBC_SOURCES assert.cpp ctype.cpp + dirent.cpp fcntl.cpp printf_impl.cpp stdio.cpp diff --git a/libc/dirent.cpp b/libc/dirent.cpp new file mode 100644 index 0000000000..16f9f6ede1 --- /dev/null +++ b/libc/dirent.cpp @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include + +#include + +struct __DIR +{ + int fd { -1 }; + size_t entry_index { 0 }; + Kernel::API::DirectoryEntry* current { nullptr }; + + size_t buffer_size { 0 }; + Kernel::API::DirectoryEntryList buffer[]; +}; + +int closedir(DIR* dirp) +{ + if (dirp == nullptr || dirp->fd == -1) + { + errno = EBADF; + return -1; + } + + close(dirp->fd); + dirp->fd = -1; + free(dirp); + + return 0; +} + +int dirfd(DIR* dirp) +{ + if (dirp == nullptr || dirp->fd == -1) + { + errno = EINVAL; + return -1; + } + + return dirp->fd; +} + +DIR* fdopendir(int fd) +{ + DIR* dirp = (DIR*)malloc(sizeof(DIR) + 4096); + if (dirp == nullptr) + return nullptr; + + dirp->fd = fd; + dirp->current = nullptr; + dirp->buffer_size = 4096; + + return dirp; +} + +DIR* opendir(const char* dirname) +{ + int fd = open(dirname, O_SEARCH); + if (fd == -1) + return nullptr; + return fdopendir(fd); +} + +struct dirent* readdir(DIR* dirp) +{ + if (dirp == nullptr || dirp->fd == -1) + { + errno = EBADF; + return nullptr; + } + + dirp->entry_index++; + if (dirp->current && dirp->entry_index < dirp->buffer->entry_count) + { + dirp->current = dirp->current->next(); + return &dirp->current->dirent; + } + + if (syscall(SYS_READ_DIR_ENTRIES, dirp->fd, dirp->buffer, dirp->buffer_size) == -1) + return nullptr; + + if (dirp->buffer->entry_count == 0) + return nullptr; + + dirp->entry_index = 0; + dirp->current = dirp->buffer->array; + + return &dirp->current->dirent; +} diff --git a/libc/include/dirent.h b/libc/include/dirent.h index dbb4af0c0c..1ea2f25397 100644 --- a/libc/include/dirent.h +++ b/libc/include/dirent.h @@ -10,8 +10,8 @@ __BEGIN_DECLS #define __need_ino_t #include -struct DIR; -typedef struct DIR DIR; +struct __DIR; +typedef struct __DIR DIR; struct dirent {