Mercurial > molko
changeset 572:f7dcad94b7cf
util: add Windows support in dir
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 09 Mar 2023 23:07:31 +0100 |
parents | cba66f7d8a53 |
children | f3d9e10bcaf8 |
files | libmlk-util/mlk/util/dir.c |
diffstat | 1 files changed, 98 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/libmlk-util/mlk/util/dir.c Thu Mar 09 22:33:46 2023 +0100 +++ b/libmlk-util/mlk/util/dir.c Thu Mar 09 23:07:31 2023 +0100 @@ -95,13 +95,105 @@ /* }}} */ +#elif defined(_WIN32) + +/* {{{ Native Windows implementation. */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <windows.h> + +struct self { + WIN32_FIND_DATA data; + HANDLE handle; + int cached; +}; + +static inline int +skip(const struct self *self) +{ + return strcmp(self->data.cFileName, ".") == 0 || + strcmp(self->data.cFileName, "..") == 0; +} + +static void +handle_finish(struct mlk_dir_iter *iter) +{ + struct self *self = iter->handle; + + if (self) { + FindClose(self->handle); + free(self); + } + + iter->entry = NULL; + iter->handle = NULL; +} + +static int +handle_open(struct mlk_dir_iter *iter, const char *path) +{ + struct self *self; + char directory[MAX_PATH]; + BOOL ret = TRUE; + + snprintf(directory, sizeof (directory), "%s\\*", path); + + if (!(self = calloc(1, sizeof (*self)))) + return -1; + if ((self->handle = FindFirstFileA(directory, &self->data)) == INVALID_HANDLE_VALUE) { + free(self); + return -1; + } + + /* Skip . and .. */ + while (skip(self) && (ret = FindNextFileA(self->handle, &self->data))) + continue; + + /* Something failed. */ + if (!ret) { + handle_finish(iter); + return -1; + } + + self->cached = 1; + iter->entry = self->data.cFileName; + iter->handle = self; + + return 0; +} + +static int +handle_next(struct mlk_dir_iter *iter) +{ + struct self *self = iter->handle; + BOOL ret = TRUE; + + /* Returning the first entry on open. */ + if (self->cached) + self->cached = 0; + else { + /* The . and .. can still appear now. */ + while ((ret = FindNextFileA(self->handle, &self->data)) && skip(self)) + continue; + + if (!ret) + handle_finish(iter); + } + + return iter->entry != NULL; +} + +/* }}} */ + #else /* {{{ No-op implementation */ #include <stddef.h> -int +static int handle_open(struct mlk_dir_iter *iter, const char *path) { (void)path; @@ -112,7 +204,7 @@ return -1; } -int +static int handle_next(struct mlk_dir_iter *iter) { (void)iter; @@ -120,7 +212,7 @@ return 0; } -void +static void handle_finish(struct mlk_dir_iter *iter) { (void)iter; @@ -135,6 +227,9 @@ { assert(path); + iter->entry = NULL; + iter->handle = NULL; + return handle_open(iter, path); }