1 // Copyright 2021 Alexey Kutepov <reximkut@gmail.com> 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining 4 // a copy of this software and associated documentation files (the 5 // "Software"), to deal in the Software without restriction, including 6 // without limitation the rights to use, copy, modify, merge, publish, 7 // distribute, sublicense, and/or sell copies of the Software, and to 8 // permit persons to whom the Software is furnished to do so, subject to 9 // the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be 12 // included in all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 // 22 // ============================================================ 23 // 24 // minirent — 0.0.1 — A subset of dirent interface for Windows. 25 // 26 // https://github.com/tsoding/minirent 27 // 28 // ============================================================ 29 // 30 // ChangeLog (https://semver.org/ is implied) 31 // 32 // 0.0.1 First Official Release 33 34 #ifndef MINIRENT_H_ 35 #define MINIRENT_H_ 36 37 #define WIN32_LEAN_AND_MEAN 38 #include "windows.h" 39 40 struct dirent 41 { 42 char d_name[MAX_PATH+1]; 43 }; 44 45 typedef struct DIR DIR; 46 47 DIR *opendir(const char *dirpath); 48 struct dirent *readdir(DIR *dirp); 49 int closedir(DIR *dirp); 50 51 #endif // MINIRENT_H_ 52 53 #ifdef MINIRENT_IMPLEMENTATION 54 55 struct DIR 56 { 57 HANDLE hFind; 58 WIN32_FIND_DATA data; 59 struct dirent *dirent; 60 }; 61 62 DIR *opendir(const char *dirpath) 63 { 64 assert(dirpath); 65 66 char buffer[MAX_PATH]; 67 snprintf(buffer, MAX_PATH, "%s\\*", dirpath); 68 69 DIR *dir = (DIR*)calloc(1, sizeof(DIR)); 70 71 dir->hFind = FindFirstFile(buffer, &dir->data); 72 if (dir->hFind == INVALID_HANDLE_VALUE) { 73 // TODO: opendir should set errno accordingly on FindFirstFile fail 74 // https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror 75 errno = ENOSYS; 76 goto fail; 77 } 78 79 return dir; 80 81 fail: 82 if (dir) { 83 free(dir); 84 } 85 86 return NULL; 87 } 88 89 struct dirent *readdir(DIR *dirp) 90 { 91 assert(dirp); 92 93 if (dirp->dirent == NULL) { 94 dirp->dirent = (struct dirent*)calloc(1, sizeof(struct dirent)); 95 } else { 96 if(!FindNextFile(dirp->hFind, &dirp->data)) { 97 if (GetLastError() != ERROR_NO_MORE_FILES) { 98 // TODO: readdir should set errno accordingly on FindNextFile fail 99 // https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror 100 errno = ENOSYS; 101 } 102 103 return NULL; 104 } 105 } 106 107 memset(dirp->dirent->d_name, 0, sizeof(dirp->dirent->d_name)); 108 109 strncpy( 110 dirp->dirent->d_name, 111 dirp->data.cFileName, 112 sizeof(dirp->dirent->d_name) - 1); 113 114 return dirp->dirent; 115 } 116 117 int closedir(DIR *dirp) 118 { 119 assert(dirp); 120 121 if(!FindClose(dirp->hFind)) { 122 // TODO: closedir should set errno accordingly on FindClose fail 123 // https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror 124 errno = ENOSYS; 125 return -1; 126 } 127 128 if (dirp->dirent) { 129 free(dirp->dirent); 130 } 131 free(dirp); 132 133 return 0; 134 } 135 136 #endif // MINIRENT_IMPLEMENTATION
