diff --git a/Source/DrangPlatform/Source/linux/fs/dir.c b/Source/DrangPlatform/Source/linux/fs/dir.c new file mode 100644 index 0000000..e039d0a --- /dev/null +++ b/Source/DrangPlatform/Source/linux/fs/dir.c @@ -0,0 +1,160 @@ +#include "drang/alloc.h" +#include "errno_convert.h" +#include "internal.h" +#include +#include +#include +#include +#include +#include + +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() +} \ No newline at end of file diff --git a/Source/DrangPlatform/Source/linux/fs/internal.h b/Source/DrangPlatform/Source/linux/fs/internal.h index dad7663..d43fd4f 100644 --- a/Source/DrangPlatform/Source/linux/fs/internal.h +++ b/Source/DrangPlatform/Source/linux/fs/internal.h @@ -2,7 +2,7 @@ #include "linux/sync/internal.h" #include #include - +#include #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; +}; \ No newline at end of file