From 3e30f0a88c1cf2477524f0f853b8022e71a57633 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 29 Mar 2023 01:06:57 +0200 Subject: [PATCH] libc: Add opendir, readdir and closedir --- libc/CMakeLists.txt | 1 + libc/include/dirent.h | 32 +++++++++++++++++++++++++ libc/src/dirent.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 libc/include/dirent.h create mode 100644 libc/src/dirent.cpp diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index d9098584..85dd2249 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES src/ctype.cpp src/time.cpp src/init.cpp + src/dirent.cpp src/setjmp.cpp src/sys/stat.cpp src/sys/mman.cpp diff --git a/libc/include/dirent.h b/libc/include/dirent.h new file mode 100644 index 00000000..f2927430 --- /dev/null +++ b/libc/include/dirent.h @@ -0,0 +1,32 @@ +/* dirent.h: Directory streams interface. */ + +#ifndef _DIRENT_H +#define _DIRENT_H + +#include + +typedef struct +{ + int _fd; +} DIR; + +struct dirent +{ + ino_t d_ino; + char d_name[129]; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + + DIR* opendir(const char* path); + struct dirent* readdir(DIR* stream); + int closedir(DIR* stream); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/src/dirent.cpp b/libc/src/dirent.cpp new file mode 100644 index 00000000..650026fe --- /dev/null +++ b/libc/src/dirent.cpp @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include +#include + +extern "C" +{ + DIR* opendir(const char* path) + { + DIR* dp = (DIR*)malloc(sizeof(DIR)); + if (!dp) { return nullptr; } + + // FIXME: Use O_DIRECTORY (validate that path is actually a directory) + int fd = open(path, O_RDONLY); + if (fd < 0) + { + free(dp); + return nullptr; + } + + dp->_fd = fd; + + return dp; + } + + struct dirent* readdir(DIR* stream) + { + // FIXME: Very hackish, right now luna_dirent and dirent have the same layout. + static luna_dirent ent; + + long rc = syscall(SYS_getdents, stream->_fd, &ent, 1); + if (rc < 0) + { + errno = -rc; + return nullptr; + } + + // End-of-file (no more directory entries) + if (rc < 1) return nullptr; + + return (struct dirent*)&ent; + } + + int closedir(DIR* stream) + { + if (close(stream->_fd) < 0) return -1; + + free(stream); + + return 0; + } +}