dirent.h (5184B)
1 /**************************************************************************** 2 3 Declaration of POSIX directory browsing functions and types for Win32. 4 5 Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com) 6 History: Created March 1997. Updated June 2003. 7 Reviewed by Ramon Santamaria for raylib on January 2020. 8 9 Copyright Kevlin Henney, 1997, 2003. All rights reserved. 10 11 Permission to use, copy, modify, and distribute this software and its 12 documentation for any purpose is hereby granted without fee, provided 13 that this copyright and permissions notice appear in all copies and 14 derivatives. 15 16 This software is supplied "as is" without express or implied warranty. 17 18 But that said, if there are any problems please get in touch. 19 20 ****************************************************************************/ 21 22 #ifndef DIRENT_H 23 #define DIRENT_H 24 25 // Allow custom memory allocators 26 #ifndef DIRENT_MALLOC 27 #define DIRENT_MALLOC(sz) malloc(sz) 28 #endif 29 #ifndef DIRENT_FREE 30 #define DIRENT_FREE(p) free(p) 31 #endif 32 33 //---------------------------------------------------------------------------------- 34 // Types and Structures Definition 35 //---------------------------------------------------------------------------------- 36 37 // Fordward declaration of DIR, implementation below 38 typedef struct DIR DIR; 39 40 struct dirent { 41 char *d_name; 42 }; 43 44 #ifdef __cplusplus 45 extern "C" { 46 #endif 47 48 //------------------------------------------------------------------------------------ 49 // Functions Declaration 50 //------------------------------------------------------------------------------------ 51 DIR *opendir(const char *name); 52 int closedir(DIR *dir); 53 struct dirent *readdir(DIR *dir); 54 void rewinddir(DIR *dir); 55 56 #ifdef __cplusplus 57 } 58 #endif 59 60 #endif // DIRENT_H 61 62 /**************************************************************************** 63 64 Implementation of POSIX directory browsing functions and types for Win32. 65 66 Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com) 67 History: Created March 1997. Updated June 2003. 68 Reviewed by Ramon Santamaria for raylib on January 2020. 69 70 Copyright Kevlin Henney, 1997, 2003. All rights reserved. 71 72 Permission to use, copy, modify, and distribute this software and its 73 documentation for any purpose is hereby granted without fee, provided 74 that this copyright and permissions notice appear in all copies and 75 derivatives. 76 77 This software is supplied "as is" without express or implied warranty. 78 79 But that said, if there are any problems please get in touch. 80 81 ****************************************************************************/ 82 83 #include <io.h> // _findfirst and _findnext set errno iff they return -1 84 #include <stdlib.h> 85 #include <string.h> 86 #include <errno.h> 87 88 //---------------------------------------------------------------------------------- 89 // Types and Structures Definition 90 //---------------------------------------------------------------------------------- 91 typedef ptrdiff_t handle_type; // C99's intptr_t not sufficiently portable 92 93 struct DIR { 94 handle_type handle; // -1 for failed rewind 95 struct _finddata_t info; 96 struct dirent result; // d_name null iff first time 97 char *name; // null-terminated char string 98 }; 99 100 DIR *opendir(const char *name) 101 { 102 DIR *dir = 0; 103 104 if (name && name[0]) 105 { 106 size_t base_length = strlen(name); 107 108 // Search pattern must end with suitable wildcard 109 const char *all = strchr("/\\", name[base_length - 1]) ? "*" : "/*"; 110 111 if ((dir = (DIR *)DIRENT_MALLOC(sizeof *dir)) != 0 && 112 (dir->name = (char *)DIRENT_MALLOC(base_length + strlen(all) + 1)) != 0) 113 { 114 strcat(strcpy(dir->name, name), all); 115 116 if ((dir->handle = (handle_type) _findfirst(dir->name, &dir->info)) != -1) 117 { 118 dir->result.d_name = 0; 119 } 120 else // rollback 121 { 122 DIRENT_FREE(dir->name); 123 DIRENT_FREE(dir); 124 dir = 0; 125 } 126 } 127 else // rollback 128 { 129 DIRENT_FREE(dir); 130 dir = 0; 131 errno = ENOMEM; 132 } 133 } 134 else errno = EINVAL; 135 136 return dir; 137 } 138 139 int closedir(DIR *dir) 140 { 141 int result = -1; 142 143 if (dir) 144 { 145 if (dir->handle != -1) result = _findclose(dir->handle); 146 147 DIRENT_FREE(dir->name); 148 DIRENT_FREE(dir); 149 } 150 151 // NOTE: All errors ampped to EBADF 152 if (result == -1) errno = EBADF; 153 154 return result; 155 } 156 157 struct dirent *readdir(DIR *dir) 158 { 159 struct dirent *result = 0; 160 161 if (dir && dir->handle != -1) 162 { 163 if (!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) 164 { 165 result = &dir->result; 166 result->d_name = dir->info.name; 167 } 168 } 169 else errno = EBADF; 170 171 return result; 172 } 173 174 void rewinddir(DIR *dir) 175 { 176 if (dir && dir->handle != -1) 177 { 178 _findclose(dir->handle); 179 dir->handle = (handle_type) _findfirst(dir->name, &dir->info); 180 dir->result.d_name = 0; 181 } 182 else errno = EBADF; 183 }