libc: Add opendir, readdir and closedir

This commit is contained in:
apio 2023-03-29 01:06:57 +02:00
parent 5623f3c699
commit 3e30f0a88c
Signed by: apio
GPG Key ID: B8A7D06E42258954
3 changed files with 88 additions and 0 deletions

View File

@ -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

32
libc/include/dirent.h Normal file
View File

@ -0,0 +1,32 @@
/* dirent.h: Directory streams interface. */
#ifndef _DIRENT_H
#define _DIRENT_H
#include <sys/types.h>
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

55
libc/src/dirent.cpp Normal file
View File

@ -0,0 +1,55 @@
#include <bits/getdents.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
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;
}
}