feature: implement linux directory handling functions

This commit is contained in:
MechSlayer 2025-09-09 19:52:16 +02:00
parent d56466526b
commit 05f5933111
2 changed files with 167 additions and 1 deletions

View file

@ -0,0 +1,160 @@
#include "drang/alloc.h"
#include "errno_convert.h"
#include "internal.h"
#include <drang/error.h>
#include <drang/fs.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
int drang_fs_mkdir(const char *path, drang_fs_permissions_t permissions)
{
DRANG_BEGIN_TRY()
DRANG_FAIL_IF_NULL(path, DRANG_EINVAL);
int mode = 0;
if (permissions & DRANG_FS_PERM_USER_READ)
mode |= S_IRUSR;
if (permissions & DRANG_FS_PERM_USER_WRITE)
mode |= S_IWUSR;
if (permissions & DRANG_FS_PERM_USER_EXEC)
mode |= S_IXUSR;
if (permissions & DRANG_FS_PERM_GROUP_READ)
mode |= S_IRGRP;
if (permissions & DRANG_FS_PERM_GROUP_WRITE)
mode |= S_IWGRP;
if (permissions & DRANG_FS_PERM_GROUP_EXEC)
mode |= S_IXGRP;
if (permissions & DRANG_FS_PERM_OTHER_READ)
mode |= S_IROTH;
if (permissions & DRANG_FS_PERM_OTHER_WRITE)
mode |= S_IWOTH;
if (permissions & DRANG_FS_PERM_OTHER_EXEC)
mode |= S_IXOTH;
if (mkdir(path, mode) != 0) {
DRANG_FAIL(drang_errno_to_error(errno));
}
DRANG_END_TRY_IGNORE()
}
int drang_fs_rmdir(const char *path)
{
DRANG_BEGIN_TRY()
DRANG_FAIL_IF_NULL(path, DRANG_EINVAL);
if (rmdir(path) != 0) {
DRANG_FAIL(drang_errno_to_error(errno));
}
DRANG_END_TRY_IGNORE()
}
int drang_fs_opendir(const char *path, drang_fs_directory_t **out_directory)
{
struct drang_fs_directory *fs_dir = NULL;
DIR *dir = NULL;
DRANG_BEGIN_TRY()
DRANG_FAIL_IF_NULL(path, DRANG_EINVAL);
DRANG_FAIL_IF_NULL(out_directory, DRANG_EINVAL);
dir = opendir(path);
if (!dir) {
DRANG_FAIL(drang_errno_to_error(errno));
}
fs_dir = DRANG_TRY_ALLOC_T(struct drang_fs_directory);
fs_dir->dir = dir;
DRANG_RETURN_IN(out_directory, fs_dir);
DRANG_CATCH(_)
{
if (dir) {
closedir(dir);
}
drang_free(fs_dir);
}
DRANG_END_TRY()
}
int drang_fs_readdir(drang_fs_directory_t *directory, drang_fs_dir_entry_t *out_entry)
{
struct dirent *entry = NULL;
DRANG_BEGIN_TRY()
entry = readdir(directory->dir);
DRANG_CHECK(entry != NULL, DRANG_ENOENT);
while (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
entry = readdir(directory->dir);
DRANG_CHECK(entry != NULL, DRANG_ENOENT);
}
strncpy(out_entry->name, entry->d_name, DRANG_FS_MAX_REL_PATH_SIZE);
out_entry->name[DRANG_FS_MAX_REL_PATH_SIZE - 1] = '\0';
switch (entry->d_type) {
case DT_REG:
out_entry->type = drang_fs_type_file;
break;
case DT_DIR:
out_entry->type = drang_fs_type_directory;
break;
case DT_LNK:
out_entry->type = drang_fs_type_symlink;
break;
default:
out_entry->type = drang_fs_type_unknown;
break;
}
DRANG_END_TRY_IGNORE()
}
int drang_fs_closedir(drang_fs_directory_t *directory)
{
DRANG_BEGIN_TRY()
DRANG_FAIL_IF_NULL(directory, DRANG_EINVAL);
if (closedir(directory->dir) != 0) {
DRANG_FAIL(drang_errno_to_error(errno));
}
drang_free(directory);
DRANG_END_TRY_IGNORE()
}
int drang_fs_get_cwd(char *buffer, size_t size, size_t *out_size)
{
DRANG_BEGIN_TRY()
DRANG_FAIL_IF_NULL(buffer, DRANG_EINVAL);
if (getcwd(buffer, size) != NULL) {
DRANG_RETURN_IN(out_size, strlen(buffer));
}
if (errno == ERANGE) {
if (out_size) {
long required_size = pathconf(".", _PC_PATH_MAX);
*out_size = required_size;
}
DRANG_FAIL(DRANG_ENOMEM);
}
DRANG_FAIL(drang_errno_to_error(errno));
DRANG_END_TRY_IGNORE()
}
int drang_fs_set_cwd(const char *path)
{
DRANG_BEGIN_TRY()
if (chdir(path) != 0) {
DRANG_FAIL(drang_errno_to_error(errno));
}
DRANG_END_TRY_IGNORE()
}

View file

@ -2,7 +2,7 @@
#include "linux/sync/internal.h"
#include <drang/fs.h>
#include <unistd.h>
#include <dirent.h>
#define DRANG_LINUX_FS_BUFFER_SIZE (4096)
struct drang_fs_file
@ -11,3 +11,9 @@ struct drang_fs_file
drang_fs_mode_t mode;
struct drang_rwlock lock;
};
struct drang_fs_directory
{
DIR* dir;
};