diff options
author | alexv-smirnov <alex@ydb.tech> | 2022-12-20 00:50:48 +0300 |
---|---|---|
committer | alexv-smirnov <alex@ydb.tech> | 2022-12-20 00:50:48 +0300 |
commit | 84f2cfa253cc618438ed6e9d68b33fa7c0d88cb9 (patch) | |
tree | f0cf2236e0aafb3e437199f1ac7b559e7fad554a /util/folder/dirent_win.c | |
parent | bde6febc1ad3b826e72746de21d7250803e8e0b5 (diff) | |
download | ydb-84f2cfa253cc618438ed6e9d68b33fa7c0d88cb9.tar.gz |
add windows platform to ydb github export
Diffstat (limited to 'util/folder/dirent_win.c')
-rw-r--r-- | util/folder/dirent_win.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/util/folder/dirent_win.c b/util/folder/dirent_win.c new file mode 100644 index 0000000000..7e6db74ce5 --- /dev/null +++ b/util/folder/dirent_win.c @@ -0,0 +1,125 @@ +#include <util/system/defaults.h> + +#ifdef _win_ + + #include <stdio.h> + #include "dirent_win.h" + + #if defined(_MSC_VER) && (_MSC_VER < 1900) +void __cdecl _dosmaperr(unsigned long); + +static void SetErrno() { + _dosmaperr(GetLastError()); +} + #else +void __cdecl __acrt_errno_map_os_error(unsigned long const oserrno); + +static void SetErrno() { + __acrt_errno_map_os_error(GetLastError()); +} + #endif + +struct DIR* opendir(const char* dirname) { + struct DIR* dir = (struct DIR*)malloc(sizeof(struct DIR)); + if (!dir) { + return NULL; + } + dir->sh = INVALID_HANDLE_VALUE; + dir->fff_templ = NULL; + dir->file_no = 0; + dir->readdir_buf = NULL; + + int len = strlen(dirname); + //Remove trailing slashes + while (len && (dirname[len - 1] == '\\' || dirname[len - 1] == '/')) { + --len; + } + int len_converted = MultiByteToWideChar(CP_UTF8, 0, dirname, len, 0, 0); + if (len_converted == 0) { + closedir(dir); + return NULL; + } + dir->fff_templ = (WCHAR*)malloc((len_converted + 5) * sizeof(WCHAR)); + if (!dir->fff_templ) { + closedir(dir); + return NULL; + } + MultiByteToWideChar(CP_UTF8, 0, dirname, len, dir->fff_templ, len_converted); + + WCHAR append[] = {'\\', '*', '.', '*', 0}; + memcpy(dir->fff_templ + len_converted, append, sizeof(append)); + dir->sh = FindFirstFileW(dir->fff_templ, &dir->wfd); + if (dir->sh == INVALID_HANDLE_VALUE) { + SetErrno(); + closedir(dir); + return NULL; + } + + return dir; +} + +int closedir(struct DIR* dir) { + if (dir->sh != INVALID_HANDLE_VALUE) + FindClose(dir->sh); + free(dir->fff_templ); + free(dir->readdir_buf); + free(dir); + return 0; +} + +int readdir_r(struct DIR* dir, struct dirent* entry, struct dirent** result) { + if (!FindNextFileW(dir->sh, &dir->wfd)) { + int err = GetLastError(); + *result = 0; + if (err == ERROR_NO_MORE_FILES) { + SetLastError(0); + return 0; + } else { + return err; + } + } + entry->d_fileno = dir->file_no++; + entry->d_reclen = sizeof(struct dirent); + if (dir->wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && + (dir->wfd.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT || dir->wfd.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) + { + entry->d_type = DT_LNK; + } else if (dir->wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + entry->d_type = DT_DIR; + } else { + entry->d_type = DT_REG; + } + int len = lstrlenW(dir->wfd.cFileName); + int conv_len = WideCharToMultiByte(CP_UTF8, 0, dir->wfd.cFileName, len, 0, 0, 0, 0); + if (conv_len == 0) { + return -1; + } + if (conv_len > sizeof(entry->d_name) - 1) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return ERROR_INSUFFICIENT_BUFFER; + } + entry->d_namlen = conv_len; + WideCharToMultiByte(CP_UTF8, 0, dir->wfd.cFileName, len, entry->d_name, conv_len, 0, 0); + entry->d_name[conv_len] = 0; + *result = entry; + return 0; +} + +struct dirent* readdir(struct DIR* dir) { + struct dirent* res; + if (!dir->readdir_buf) { + dir->readdir_buf = (struct dirent*)malloc(sizeof(struct dirent)); + if (dir->readdir_buf == 0) + return 0; + } + readdir_r(dir, dir->readdir_buf, &res); + return res; +} + +void rewinddir(struct DIR* dir) { + FindClose(dir->sh); + dir->sh = FindFirstFileW(dir->fff_templ, &dir->wfd); + dir->file_no = 0; +} + +#endif //_win_ |