libc: Implement a basic subset of dirent.h

This commit is contained in:
apio 2022-10-23 14:41:45 +02:00
parent 32db366781
commit 8bf2904d74
6 changed files with 112 additions and 17 deletions

View File

@ -1,28 +1,22 @@
#include <dirent.h>
#include <fcntl.h>
#include <luna/dirent.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
int dirfd = open("/bin", O_RDONLY);
if (dirfd < 0)
DIR* dp = opendir("/bin");
if (!dp)
{
perror("open");
perror("opendir");
return 1;
}
struct luna_dirent dirent[5];
ssize_t nread;
do {
nread = getdents(dirfd, dirent, 5);
if (nread < 0)
{
perror("getdents");
return 1;
}
for (int i = 0; i < nread; i++) { printf("%s\n", dirent[i].name); }
} while (nread == 5);
struct dirent* ent = readdir(dp);
if (!ent) break;
printf("%s\n", ent->d_name);
} while (1);
close(dirfd);
closedir(dp);
return 0;
}

View File

@ -10,6 +10,8 @@ typedef long ssize_t;
#define VFS_MOUNTPOINT 0x1
#define NAME_MAX 64
namespace VFS
{
struct Node;
@ -23,7 +25,7 @@ namespace VFS
struct Node
{
char name[64];
char name[NAME_MAX];
uint64_t inode;
uint64_t length;
int type;

View File

@ -0,0 +1,43 @@
#ifndef _DIRENT_H
#define _DIRENT_H
#include <luna/os-limits.h>
#include <sys/types.h>
struct dirent
{
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[NAME_MAX];
};
typedef struct
{
int d_dirfd;
} DIR;
#ifdef __cplusplus
extern "C"
{
#endif
/* Opens the directory at path and returns a handle to it, or NULL on error. */
DIR* opendir(const char* path);
/* Returns a new directory handle associated with the file descriptor fd. */
DIR* fdopendir(int fd);
/* Closes the directory stream. */
int closedir(DIR* stream);
/* Reads an entry from the directory stream. The contents of the pointer returned may be overwritten by subsequent
* calls to readdir(). */
struct dirent* readdir(DIR* stream);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,12 +1,13 @@
#ifndef _LUNA_DIRENT_H
#define _LUNA_DIRENT_H
#include <luna/os-limits.h>
#include <sys/types.h>
struct luna_dirent
{
ino_t inode;
char name[64];
char name[NAME_MAX];
size_t total;
off_t offset;
};

View File

@ -4,6 +4,8 @@
#define OPEN_MAX 32
#define ATEXIT_MAX 32
#define NAME_MAX 64
#define PAGESIZE 4096
#define PAGE_SIZE 4096

53
libs/libc/src/dirent.cpp Normal file
View File

@ -0,0 +1,53 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <luna/dirent.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
extern "C"
{
DIR* opendir(const char* path)
{
int dirfd = open(path, O_RDONLY); // FIXME: Implement O_DIRECTORY and use that.
if (dirfd < 0) return NULL;
return fdopendir(dirfd);
}
DIR* fdopendir(int fd)
{
if (fd < 0) return NULL;
DIR* result = (DIR*)malloc(sizeof(DIR));
if (!result) return NULL;
result->d_dirfd = fd;
return result;
}
int closedir(DIR* stream)
{
int status = close(stream->d_dirfd);
if (status < 0)
{
int savederr = errno;
free(stream);
errno = savederr; // free might reset errno. We don't want that.
}
else { free(stream); }
return status;
}
struct dirent* readdir(DIR* stream)
{
static struct dirent result;
struct luna_dirent ent;
ssize_t nread = getdents(stream->d_dirfd, &ent, 1); // FIXME: Use a buffer to avoid too many system calls.
if (nread <= 0) return NULL; // Either EOF or error.
result.d_ino = ent.inode;
result.d_reclen = sizeof(result);
result.d_off = ent.offset;
result.d_type = 0;
strlcpy(result.d_name, ent.name, NAME_MAX);
return &result;
}
}