feature: implement Win32 directory handling functions including mkdir, rmdir, opendir, readdir, closedir, getcwd, and setcwd
This commit is contained in:
parent
c43748d1d4
commit
f766cdb21e
2 changed files with 161 additions and 0 deletions
154
Source/DrangPlatform/Source/win32/fs/dir.c
Normal file
154
Source/DrangPlatform/Source/win32/fs/dir.c
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
#include "internal.h"
|
||||
#include "win32/common.h"
|
||||
#include <drang/alloc.h>
|
||||
#include <drang/error.h>
|
||||
#include <drang/fs.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int drang_fs_mkdir(const char *path, drang_fs_permissions_t permissions)
|
||||
{
|
||||
DRANG_BEGIN_TRY()
|
||||
DRANG_UNUSED(permissions); // Permissions are not used on Windows
|
||||
|
||||
if (!CreateDirectoryA(path, NULL)) {
|
||||
DRANG_FAIL(win32_error_to_drang(GetLastError()));
|
||||
}
|
||||
|
||||
DRANG_END_TRY_IGNORE()
|
||||
}
|
||||
|
||||
int drang_fs_rmdir(const char *path)
|
||||
{
|
||||
DRANG_BEGIN_TRY()
|
||||
if (!RemoveDirectoryA(path)) {
|
||||
DRANG_FAIL(win32_error_to_drang(GetLastError()));
|
||||
}
|
||||
DRANG_END_TRY_IGNORE()
|
||||
}
|
||||
|
||||
int drang_fs_opendir(const char *path, drang_fs_directory_t **out_directory)
|
||||
{
|
||||
struct drang_fs_directory *fs_dir = NULL;
|
||||
char search_path[MAX_PATH];
|
||||
DRANG_BEGIN_TRY()
|
||||
DRANG_FAIL_IF_NULL(path, DRANG_EINVAL);
|
||||
DRANG_FAIL_IF_NULL(out_directory, DRANG_EINVAL);
|
||||
|
||||
fs_dir = DRANG_TRY_CALLOC_T(struct drang_fs_directory);
|
||||
snprintf(search_path, MAX_PATH, "%s\\*", path);
|
||||
fs_dir->handle = FindFirstFileA(search_path, &fs_dir->find_data);
|
||||
if (fs_dir->handle == INVALID_HANDLE_VALUE) {
|
||||
DRANG_FAIL(win32_error_to_drang(GetLastError()));
|
||||
}
|
||||
fs_dir->first_entry = true;
|
||||
DRANG_RETURN_IN(out_directory, fs_dir);
|
||||
|
||||
DRANG_CATCH(_)
|
||||
{
|
||||
if (fs_dir) {
|
||||
if (fs_dir->handle != INVALID_HANDLE_VALUE) {
|
||||
FindClose(fs_dir->handle);
|
||||
}
|
||||
drang_free(fs_dir);
|
||||
}
|
||||
}
|
||||
|
||||
DRANG_END_TRY()
|
||||
}
|
||||
|
||||
static int skip_invalid_entries(struct drang_fs_directory *dir)
|
||||
{
|
||||
DRANG_BEGIN_TRY()
|
||||
|
||||
while (strcmp(dir->find_data.cFileName, ".") == 0 || strcmp(dir->find_data.cFileName, "..") == 0) {
|
||||
if (!FindNextFileA(dir->handle, &dir->find_data)) {
|
||||
const DWORD err = GetLastError();
|
||||
if (err == ERROR_NO_MORE_FILES) {
|
||||
DRANG_FAIL(DRANG_ENOENT);
|
||||
}
|
||||
DRANG_FAIL(win32_error_to_drang(err));
|
||||
}
|
||||
}
|
||||
|
||||
DRANG_END_TRY_IGNORE()
|
||||
}
|
||||
|
||||
int drang_fs_readdir(drang_fs_directory_t *directory, drang_fs_dir_entry_t *out_entry)
|
||||
{
|
||||
DRANG_BEGIN_TRY()
|
||||
DRANG_FAIL_IF_NULL(directory, DRANG_EINVAL);
|
||||
DRANG_FAIL_IF_NULL(out_entry, DRANG_EINVAL);
|
||||
|
||||
if (directory->first_entry) {
|
||||
directory->first_entry = false;
|
||||
DRANG_TRY(skip_invalid_entries(directory));
|
||||
} else {
|
||||
if (!FindNextFileA(directory->handle, &directory->find_data)) {
|
||||
const DWORD err = GetLastError();
|
||||
if (err == ERROR_NO_MORE_FILES) {
|
||||
DRANG_FAIL(DRANG_ENOENT);
|
||||
}
|
||||
DRANG_FAIL(win32_error_to_drang(err));
|
||||
}
|
||||
|
||||
DRANG_TRY(skip_invalid_entries(directory));
|
||||
}
|
||||
|
||||
strncpy(out_entry->name, directory->find_data.cFileName, DRANG_FS_MAX_REL_PATH_SIZE);
|
||||
out_entry->name[DRANG_FS_MAX_REL_PATH_SIZE - 1] = '\0';
|
||||
if (directory->find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
out_entry->type = drang_fs_type_directory;
|
||||
} else if (directory->find_data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
out_entry->type = drang_fs_type_symlink;
|
||||
} else {
|
||||
out_entry->type = drang_fs_type_file;
|
||||
}
|
||||
|
||||
DRANG_END_TRY_IGNORE()
|
||||
}
|
||||
|
||||
int drang_fs_closedir(drang_fs_directory_t *directory)
|
||||
{
|
||||
DRANG_BEGIN_TRY()
|
||||
if (directory) {
|
||||
if (directory->handle != INVALID_HANDLE_VALUE) {
|
||||
if (!FindClose(directory->handle)) {
|
||||
DRANG_FAIL(win32_error_to_drang(GetLastError()));
|
||||
}
|
||||
}
|
||||
drang_free(directory);
|
||||
}
|
||||
DRANG_END_TRY_IGNORE()
|
||||
}
|
||||
|
||||
int drang_fs_get_cwd(char *buffer, size_t size, size_t *out_size)
|
||||
{
|
||||
DWORD length = 0;
|
||||
DRANG_BEGIN_TRY()
|
||||
DRANG_FAIL_IF_NULL(buffer, DRANG_EINVAL);
|
||||
|
||||
length = GetCurrentDirectoryA((DWORD) size, buffer);
|
||||
if (length == 0) {
|
||||
DRANG_FAIL(win32_error_to_drang(GetLastError()));
|
||||
}
|
||||
|
||||
if (out_size) {
|
||||
*out_size = length;
|
||||
}
|
||||
|
||||
DRANG_CHECK(length < size, DRANG_ENOMEM);
|
||||
|
||||
DRANG_END_TRY_IGNORE()
|
||||
}
|
||||
|
||||
int drang_fs_set_cwd(const char *path)
|
||||
{
|
||||
DRANG_BEGIN_TRY()
|
||||
DRANG_FAIL_IF_NULL(path, DRANG_EINVAL);
|
||||
|
||||
if (!SetCurrentDirectoryA(path)) {
|
||||
DRANG_FAIL(win32_error_to_drang(GetLastError()));
|
||||
}
|
||||
|
||||
DRANG_END_TRY_IGNORE()
|
||||
}
|
||||
|
|
@ -11,3 +11,10 @@ struct drang_fs_file
|
|||
drang_fs_mode_t mode;
|
||||
struct drang_rwlock lock;
|
||||
};
|
||||
|
||||
struct drang_fs_directory
|
||||
{
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATAA find_data;
|
||||
bool first_entry;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue