/* * Copyright (c) 2014-2018 Cesanta Software Limited * All rights reserved * * Licensed under the Apache License, Version 2.0 (the ""License""); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an ""AS IS"" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef EXCLUDE_COMMON #include "mg_mem.h" #include "cs_dirent.h" /* * This file contains POSIX opendir/closedir/readdir API implementation * for systems which do not natively support it (e.g. Windows). */ #ifdef _WIN32 struct win32_dir { DIR d; HANDLE handle; WIN32_FIND_DATAW info; struct dirent result; }; DIR *opendir(const char *name) { struct win32_dir *dir = NULL; wchar_t wpath[MAX_PATH]; DWORD attrs; if (name == NULL) { SetLastError(ERROR_BAD_ARGUMENTS); } else if ((dir = (struct win32_dir *) MG_MALLOC(sizeof(*dir))) == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); } else { to_wchar(name, wpath, ARRAY_SIZE(wpath)); attrs = GetFileAttributesW(wpath); if (attrs != 0xFFFFFFFF && (attrs & FILE_ATTRIBUTE_DIRECTORY)) { (void) wcscat(wpath, L"\\*"); dir->handle = FindFirstFileW(wpath, &dir->info); dir->result.d_name[0] = '\0'; } else { MG_FREE(dir); dir = NULL; } } return (DIR *) dir; } int closedir(DIR *d) { struct win32_dir *dir = (struct win32_dir *) d; int result = 0; if (dir != NULL) { if (dir->handle != INVALID_HANDLE_VALUE) result = FindClose(dir->handle) ? 0 : -1; MG_FREE(dir); } else { result = -1; SetLastError(ERROR_BAD_ARGUMENTS); } return result; } struct dirent *readdir(DIR *d) { struct win32_dir *dir = (struct win32_dir *) d; struct dirent *result = NULL; if (dir) { memset(&dir->result, 0, sizeof(dir->result)); if (dir->handle != INVALID_HANDLE_VALUE) { result = &dir->result; (void) WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName, -1, result->d_name, sizeof(result->d_name), NULL, NULL); if (!FindNextFileW(dir->handle, &dir->info)) { (void) FindClose(dir->handle); dir->handle = INVALID_HANDLE_VALUE; } } else { SetLastError(ERROR_FILE_NOT_FOUND); } } else { SetLastError(ERROR_BAD_ARGUMENTS); } return result; } #endif #endif /* EXCLUDE_COMMON */ /* ISO C requires a translation unit to contain at least one declaration */ typedef int cs_dirent_dummy;