Luna/libc/src/dirent.cpp
2023-07-31 10:58:06 +02:00

77 lines
1.4 KiB
C++

#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; }
int fd = open(path, O_RDONLY | O_DIRECTORY);
if (fd < 0)
{
free(dp);
return nullptr;
}
fcntl(fd, F_SETFD, FD_CLOEXEC);
dp->_fd = fd;
return dp;
}
DIR* fdopendir(int fd)
{
DIR* dp = (DIR*)malloc(sizeof(DIR));
if (!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 = (int)-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;
}
int dirfd(DIR* stream)
{
return stream->_fd;
}
void rewinddir(DIR* stream)
{
lseek(stream->_fd, 0, SEEK_SET);
}
}