Fossil SCM

fossil-scm / win / include / dirent.h
Source Blame History 1160 lines
f460839… jan.nijtmans 1 /*
dd498bb… jan.nijtmans 2 * Dirent interface for Microsoft Visual Studio
398a90c… jan.nijtmans 3 * Version 1.23.1
f460839… jan.nijtmans 4 *
f460839… jan.nijtmans 5 * Copyright (C) 2006-2012 Toni Ronkko
dd498bb… jan.nijtmans 6 * This file is part of dirent. Dirent may be freely distributed
dd498bb… jan.nijtmans 7 * under the MIT license. For all details and documentation, see
dd498bb… jan.nijtmans 8 * https://github.com/tronkko/dirent
a374824… jan.nijtmans 9 */
3564af0… drh 10 #ifndef DIRENT_H
3564af0… drh 11 #define DIRENT_H
3564af0… drh 12
a374824… jan.nijtmans 13 /*
b66b99c… jan.nijtmans 14 * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
b66b99c… jan.nijtmans 15 * Windows Sockets 2.0.
a374824… jan.nijtmans 16 */
b66b99c… jan.nijtmans 17 #ifndef WIN32_LEAN_AND_MEAN
b66b99c… jan.nijtmans 18 # define WIN32_LEAN_AND_MEAN
f460839… jan.nijtmans 19 #endif
b66b99c… jan.nijtmans 20 #include <windows.h>
ed544f3… mistachkin 21
f460839… jan.nijtmans 22 #include <stdio.h>
f460839… jan.nijtmans 23 #include <stdarg.h>
f460839… jan.nijtmans 24 #include <wchar.h>
3564af0… drh 25 #include <string.h>
fb07d86… jan.nijtmans 26 #include <stdlib.h>
8e50ff0… jan.nijtmans 27 #include <malloc.h>
fb07d86… jan.nijtmans 28 #include <sys/types.h>
fb07d86… jan.nijtmans 29 #include <sys/stat.h>
fb07d86… jan.nijtmans 30 #include <errno.h>
fb07d86… jan.nijtmans 31
8e50ff0… jan.nijtmans 32 /* Indicates that d_type field is available in dirent structure */
8e50ff0… jan.nijtmans 33 #define _DIRENT_HAVE_D_TYPE
8e50ff0… jan.nijtmans 34
8e50ff0… jan.nijtmans 35 /* Indicates that d_namlen field is available in dirent structure */
8e50ff0… jan.nijtmans 36 #define _DIRENT_HAVE_D_NAMLEN
f460839… jan.nijtmans 37
f460839… jan.nijtmans 38 /* Entries missing from MSVC 6.0 */
f460839… jan.nijtmans 39 #if !defined(FILE_ATTRIBUTE_DEVICE)
8e50ff0… jan.nijtmans 40 # define FILE_ATTRIBUTE_DEVICE 0x40
8e50ff0… jan.nijtmans 41 #endif
8e50ff0… jan.nijtmans 42
dd498bb… jan.nijtmans 43 /* File type and permission flags for stat(), general mask */
8e50ff0… jan.nijtmans 44 #if !defined(S_IFMT)
dd498bb… jan.nijtmans 45 # define S_IFMT _S_IFMT
8e50ff0… jan.nijtmans 46 #endif
dd498bb… jan.nijtmans 47
dd498bb… jan.nijtmans 48 /* Directory bit */
8e50ff0… jan.nijtmans 49 #if !defined(S_IFDIR)
dd498bb… jan.nijtmans 50 # define S_IFDIR _S_IFDIR
8e50ff0… jan.nijtmans 51 #endif
dd498bb… jan.nijtmans 52
dd498bb… jan.nijtmans 53 /* Character device bit */
8e50ff0… jan.nijtmans 54 #if !defined(S_IFCHR)
dd498bb… jan.nijtmans 55 # define S_IFCHR _S_IFCHR
8e50ff0… jan.nijtmans 56 #endif
dd498bb… jan.nijtmans 57
dd498bb… jan.nijtmans 58 /* Pipe bit */
8e50ff0… jan.nijtmans 59 #if !defined(S_IFFIFO)
dd498bb… jan.nijtmans 60 # define S_IFFIFO _S_IFFIFO
8e50ff0… jan.nijtmans 61 #endif
dd498bb… jan.nijtmans 62
dd498bb… jan.nijtmans 63 /* Regular file bit */
8e50ff0… jan.nijtmans 64 #if !defined(S_IFREG)
dd498bb… jan.nijtmans 65 # define S_IFREG _S_IFREG
8e50ff0… jan.nijtmans 66 #endif
dd498bb… jan.nijtmans 67
dd498bb… jan.nijtmans 68 /* Read permission */
8e50ff0… jan.nijtmans 69 #if !defined(S_IREAD)
dd498bb… jan.nijtmans 70 # define S_IREAD _S_IREAD
8e50ff0… jan.nijtmans 71 #endif
dd498bb… jan.nijtmans 72
dd498bb… jan.nijtmans 73 /* Write permission */
8e50ff0… jan.nijtmans 74 #if !defined(S_IWRITE)
dd498bb… jan.nijtmans 75 # define S_IWRITE _S_IWRITE
8e50ff0… jan.nijtmans 76 #endif
dd498bb… jan.nijtmans 77
dd498bb… jan.nijtmans 78 /* Execute permission */
8e50ff0… jan.nijtmans 79 #if !defined(S_IEXEC)
dd498bb… jan.nijtmans 80 # define S_IEXEC _S_IEXEC
8e50ff0… jan.nijtmans 81 #endif
dd498bb… jan.nijtmans 82
dd498bb… jan.nijtmans 83 /* Pipe */
8e50ff0… jan.nijtmans 84 #if !defined(S_IFIFO)
dd498bb… jan.nijtmans 85 # define S_IFIFO _S_IFIFO
8e50ff0… jan.nijtmans 86 #endif
dd498bb… jan.nijtmans 87
dd498bb… jan.nijtmans 88 /* Block device */
8e50ff0… jan.nijtmans 89 #if !defined(S_IFBLK)
dd498bb… jan.nijtmans 90 # define S_IFBLK 0
8e50ff0… jan.nijtmans 91 #endif
dd498bb… jan.nijtmans 92
dd498bb… jan.nijtmans 93 /* Link */
8e50ff0… jan.nijtmans 94 #if !defined(S_IFLNK)
dd498bb… jan.nijtmans 95 # define S_IFLNK 0
8e50ff0… jan.nijtmans 96 #endif
dd498bb… jan.nijtmans 97
dd498bb… jan.nijtmans 98 /* Socket */
8e50ff0… jan.nijtmans 99 #if !defined(S_IFSOCK)
dd498bb… jan.nijtmans 100 # define S_IFSOCK 0
dd498bb… jan.nijtmans 101 #endif
dd498bb… jan.nijtmans 102
dd498bb… jan.nijtmans 103 /* Read user permission */
dd498bb… jan.nijtmans 104 #if !defined(S_IRUSR)
dd498bb… jan.nijtmans 105 # define S_IRUSR S_IREAD
dd498bb… jan.nijtmans 106 #endif
dd498bb… jan.nijtmans 107
dd498bb… jan.nijtmans 108 /* Write user permission */
dd498bb… jan.nijtmans 109 #if !defined(S_IWUSR)
dd498bb… jan.nijtmans 110 # define S_IWUSR S_IWRITE
dd498bb… jan.nijtmans 111 #endif
dd498bb… jan.nijtmans 112
dd498bb… jan.nijtmans 113 /* Execute user permission */
dd498bb… jan.nijtmans 114 #if !defined(S_IXUSR)
dd498bb… jan.nijtmans 115 # define S_IXUSR 0
dd498bb… jan.nijtmans 116 #endif
dd498bb… jan.nijtmans 117
dd498bb… jan.nijtmans 118 /* Read group permission */
dd498bb… jan.nijtmans 119 #if !defined(S_IRGRP)
dd498bb… jan.nijtmans 120 # define S_IRGRP 0
dd498bb… jan.nijtmans 121 #endif
dd498bb… jan.nijtmans 122
dd498bb… jan.nijtmans 123 /* Write group permission */
dd498bb… jan.nijtmans 124 #if !defined(S_IWGRP)
dd498bb… jan.nijtmans 125 # define S_IWGRP 0
dd498bb… jan.nijtmans 126 #endif
dd498bb… jan.nijtmans 127
dd498bb… jan.nijtmans 128 /* Execute group permission */
dd498bb… jan.nijtmans 129 #if !defined(S_IXGRP)
dd498bb… jan.nijtmans 130 # define S_IXGRP 0
dd498bb… jan.nijtmans 131 #endif
dd498bb… jan.nijtmans 132
dd498bb… jan.nijtmans 133 /* Read others permission */
dd498bb… jan.nijtmans 134 #if !defined(S_IROTH)
dd498bb… jan.nijtmans 135 # define S_IROTH 0
dd498bb… jan.nijtmans 136 #endif
dd498bb… jan.nijtmans 137
dd498bb… jan.nijtmans 138 /* Write others permission */
dd498bb… jan.nijtmans 139 #if !defined(S_IWOTH)
dd498bb… jan.nijtmans 140 # define S_IWOTH 0
8e50ff0… jan.nijtmans 141 #endif
8e50ff0… jan.nijtmans 142
dd498bb… jan.nijtmans 143 /* Execute others permission */
dd498bb… jan.nijtmans 144 #if !defined(S_IXOTH)
dd498bb… jan.nijtmans 145 # define S_IXOTH 0
8e50ff0… jan.nijtmans 146 #endif
8e50ff0… jan.nijtmans 147
8e50ff0… jan.nijtmans 148 /* Maximum length of file name */
8e50ff0… jan.nijtmans 149 #if !defined(PATH_MAX)
8e50ff0… jan.nijtmans 150 # define PATH_MAX MAX_PATH
8e50ff0… jan.nijtmans 151 #endif
8e50ff0… jan.nijtmans 152 #if !defined(FILENAME_MAX)
8e50ff0… jan.nijtmans 153 # define FILENAME_MAX MAX_PATH
8e50ff0… jan.nijtmans 154 #endif
8e50ff0… jan.nijtmans 155 #if !defined(NAME_MAX)
8e50ff0… jan.nijtmans 156 # define NAME_MAX FILENAME_MAX
8e50ff0… jan.nijtmans 157 #endif
f460839… jan.nijtmans 158
fb07d86… jan.nijtmans 159 /* File type flags for d_type */
dd498bb… jan.nijtmans 160 #define DT_UNKNOWN 0
dd498bb… jan.nijtmans 161 #define DT_REG S_IFREG
dd498bb… jan.nijtmans 162 #define DT_DIR S_IFDIR
dd498bb… jan.nijtmans 163 #define DT_FIFO S_IFIFO
dd498bb… jan.nijtmans 164 #define DT_SOCK S_IFSOCK
dd498bb… jan.nijtmans 165 #define DT_CHR S_IFCHR
dd498bb… jan.nijtmans 166 #define DT_BLK S_IFBLK
dd498bb… jan.nijtmans 167 #define DT_LNK S_IFLNK
fb07d86… jan.nijtmans 168
fb07d86… jan.nijtmans 169 /* Macros for converting between st_mode and d_type */
fb07d86… jan.nijtmans 170 #define IFTODT(mode) ((mode) & S_IFMT)
fb07d86… jan.nijtmans 171 #define DTTOIF(type) (type)
fb07d86… jan.nijtmans 172
fb07d86… jan.nijtmans 173 /*
fb07d86… jan.nijtmans 174 * File type macros. Note that block devices, sockets and links cannot be
fb07d86… jan.nijtmans 175 * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
fb07d86… jan.nijtmans 176 * only defined for compatibility. These macros should always return false
fb07d86… jan.nijtmans 177 * on Windows.
fb07d86… jan.nijtmans 178 */
dd498bb… jan.nijtmans 179 #if !defined(S_ISFIFO)
dd498bb… jan.nijtmans 180 # define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
dd498bb… jan.nijtmans 181 #endif
dd498bb… jan.nijtmans 182 #if !defined(S_ISDIR)
dd498bb… jan.nijtmans 183 # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
dd498bb… jan.nijtmans 184 #endif
dd498bb… jan.nijtmans 185 #if !defined(S_ISREG)
dd498bb… jan.nijtmans 186 # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
dd498bb… jan.nijtmans 187 #endif
dd498bb… jan.nijtmans 188 #if !defined(S_ISLNK)
dd498bb… jan.nijtmans 189 # define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
dd498bb… jan.nijtmans 190 #endif
dd498bb… jan.nijtmans 191 #if !defined(S_ISSOCK)
dd498bb… jan.nijtmans 192 # define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
dd498bb… jan.nijtmans 193 #endif
dd498bb… jan.nijtmans 194 #if !defined(S_ISCHR)
dd498bb… jan.nijtmans 195 # define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
dd498bb… jan.nijtmans 196 #endif
dd498bb… jan.nijtmans 197 #if !defined(S_ISBLK)
dd498bb… jan.nijtmans 198 # define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
dd498bb… jan.nijtmans 199 #endif
dd498bb… jan.nijtmans 200
ade4a65… jan.nijtmans 201 /* Return the exact length of the file name without zero terminator */
8e50ff0… jan.nijtmans 202 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
8e50ff0… jan.nijtmans 203
ade4a65… jan.nijtmans 204 /* Return the maximum size of a file name */
ade4a65… jan.nijtmans 205 #define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1)
8e50ff0… jan.nijtmans 206
fb07d86… jan.nijtmans 207
fb07d86… jan.nijtmans 208 #ifdef __cplusplus
fb07d86… jan.nijtmans 209 extern "C" {
3564af0… drh 210 #endif
3564af0… drh 211
8e50ff0… jan.nijtmans 212
8e50ff0… jan.nijtmans 213 /* Wide-character version */
f460839… jan.nijtmans 214 struct _wdirent {
dd498bb… jan.nijtmans 215 /* Always zero */
dd498bb… jan.nijtmans 216 long d_ino;
dd498bb… jan.nijtmans 217
ade4a65… jan.nijtmans 218 /* File position within stream */
ade4a65… jan.nijtmans 219 long d_off;
ade4a65… jan.nijtmans 220
dd498bb… jan.nijtmans 221 /* Structure size */
dd498bb… jan.nijtmans 222 unsigned short d_reclen;
dd498bb… jan.nijtmans 223
dd498bb… jan.nijtmans 224 /* Length of name without \0 */
dd498bb… jan.nijtmans 225 size_t d_namlen;
dd498bb… jan.nijtmans 226
dd498bb… jan.nijtmans 227 /* File type */
dd498bb… jan.nijtmans 228 int d_type;
dd498bb… jan.nijtmans 229
dd498bb… jan.nijtmans 230 /* File name */
ade4a65… jan.nijtmans 231 wchar_t d_name[PATH_MAX+1];
f460839… jan.nijtmans 232 };
f460839… jan.nijtmans 233 typedef struct _wdirent _wdirent;
f460839… jan.nijtmans 234
f460839… jan.nijtmans 235 struct _WDIR {
dd498bb… jan.nijtmans 236 /* Current directory entry */
dd498bb… jan.nijtmans 237 struct _wdirent ent;
dd498bb… jan.nijtmans 238
dd498bb… jan.nijtmans 239 /* Private file data */
dd498bb… jan.nijtmans 240 WIN32_FIND_DATAW data;
dd498bb… jan.nijtmans 241
dd498bb… jan.nijtmans 242 /* True if data is valid */
dd498bb… jan.nijtmans 243 int cached;
dd498bb… jan.nijtmans 244
dd498bb… jan.nijtmans 245 /* Win32 search handle */
dd498bb… jan.nijtmans 246 HANDLE handle;
dd498bb… jan.nijtmans 247
dd498bb… jan.nijtmans 248 /* Initial directory name */
dd498bb… jan.nijtmans 249 wchar_t *patt;
f460839… jan.nijtmans 250 };
f460839… jan.nijtmans 251 typedef struct _WDIR _WDIR;
f460839… jan.nijtmans 252
ade4a65… jan.nijtmans 253 /* Multi-byte character version */
8e50ff0… jan.nijtmans 254 struct dirent {
dd498bb… jan.nijtmans 255 /* Always zero */
dd498bb… jan.nijtmans 256 long d_ino;
ade4a65… jan.nijtmans 257
ade4a65… jan.nijtmans 258 /* File position within stream */
ade4a65… jan.nijtmans 259 long d_off;
dd498bb… jan.nijtmans 260
dd498bb… jan.nijtmans 261 /* Structure size */
dd498bb… jan.nijtmans 262 unsigned short d_reclen;
dd498bb… jan.nijtmans 263
dd498bb… jan.nijtmans 264 /* Length of name without \0 */
dd498bb… jan.nijtmans 265 size_t d_namlen;
dd498bb… jan.nijtmans 266
dd498bb… jan.nijtmans 267 /* File type */
dd498bb… jan.nijtmans 268 int d_type;
dd498bb… jan.nijtmans 269
dd498bb… jan.nijtmans 270 /* File name */
ade4a65… jan.nijtmans 271 char d_name[PATH_MAX+1];
8e50ff0… jan.nijtmans 272 };
8e50ff0… jan.nijtmans 273 typedef struct dirent dirent;
8e50ff0… jan.nijtmans 274
8e50ff0… jan.nijtmans 275 struct DIR {
8e50ff0… jan.nijtmans 276 struct dirent ent;
8e50ff0… jan.nijtmans 277 struct _WDIR *wdirp;
8e50ff0… jan.nijtmans 278 };
8e50ff0… jan.nijtmans 279 typedef struct DIR DIR;
8e50ff0… jan.nijtmans 280
ade4a65… jan.nijtmans 281
ade4a65… jan.nijtmans 282 /* Dirent functions */
8e50ff0… jan.nijtmans 283 static DIR *opendir (const char *dirname);
ade4a65… jan.nijtmans 284 static _WDIR *_wopendir (const wchar_t *dirname);
ade4a65… jan.nijtmans 285
8e50ff0… jan.nijtmans 286 static struct dirent *readdir (DIR *dirp);
ade4a65… jan.nijtmans 287 static struct _wdirent *_wreaddir (_WDIR *dirp);
ade4a65… jan.nijtmans 288
ade4a65… jan.nijtmans 289 static int readdir_r(
ade4a65… jan.nijtmans 290 DIR *dirp, struct dirent *entry, struct dirent **result);
ade4a65… jan.nijtmans 291 static int _wreaddir_r(
ade4a65… jan.nijtmans 292 _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result);
ade4a65… jan.nijtmans 293
8e50ff0… jan.nijtmans 294 static int closedir (DIR *dirp);
ade4a65… jan.nijtmans 295 static int _wclosedir (_WDIR *dirp);
ade4a65… jan.nijtmans 296
8e50ff0… jan.nijtmans 297 static void rewinddir (DIR* dirp);
ade4a65… jan.nijtmans 298 static void _wrewinddir (_WDIR* dirp);
ade4a65… jan.nijtmans 299
ade4a65… jan.nijtmans 300 static int scandir (const char *dirname, struct dirent ***namelist,
ade4a65… jan.nijtmans 301 int (*filter)(const struct dirent*),
1eee6c7… jan.nijtmans 302 int (*compare)(const struct dirent**, const struct dirent**));
ade4a65… jan.nijtmans 303
ade4a65… jan.nijtmans 304 static int alphasort (const struct dirent **a, const struct dirent **b);
ade4a65… jan.nijtmans 305
ade4a65… jan.nijtmans 306 static int versionsort (const struct dirent **a, const struct dirent **b);
ade4a65… jan.nijtmans 307
ade4a65… jan.nijtmans 308
ade4a65… jan.nijtmans 309 /* For compatibility with Symbian */
ade4a65… jan.nijtmans 310 #define wdirent _wdirent
ade4a65… jan.nijtmans 311 #define WDIR _WDIR
ade4a65… jan.nijtmans 312 #define wopendir _wopendir
ade4a65… jan.nijtmans 313 #define wreaddir _wreaddir
ade4a65… jan.nijtmans 314 #define wclosedir _wclosedir
ade4a65… jan.nijtmans 315 #define wrewinddir _wrewinddir
f460839… jan.nijtmans 316
f460839… jan.nijtmans 317
8e50ff0… jan.nijtmans 318 /* Internal utility functions */
8e50ff0… jan.nijtmans 319 static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
8e50ff0… jan.nijtmans 320 static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
8e50ff0… jan.nijtmans 321
8e50ff0… jan.nijtmans 322 static int dirent_mbstowcs_s(
8e50ff0… jan.nijtmans 323 size_t *pReturnValue,
8e50ff0… jan.nijtmans 324 wchar_t *wcstr,
8e50ff0… jan.nijtmans 325 size_t sizeInWords,
8e50ff0… jan.nijtmans 326 const char *mbstr,
8e50ff0… jan.nijtmans 327 size_t count);
8e50ff0… jan.nijtmans 328
8e50ff0… jan.nijtmans 329 static int dirent_wcstombs_s(
8e50ff0… jan.nijtmans 330 size_t *pReturnValue,
8e50ff0… jan.nijtmans 331 char *mbstr,
8e50ff0… jan.nijtmans 332 size_t sizeInBytes,
8e50ff0… jan.nijtmans 333 const wchar_t *wcstr,
8e50ff0… jan.nijtmans 334 size_t count);
8e50ff0… jan.nijtmans 335
8e50ff0… jan.nijtmans 336 static void dirent_set_errno (int error);
ade4a65… jan.nijtmans 337
f460839… jan.nijtmans 338
f460839… jan.nijtmans 339 /*
3564af0… drh 340 * Open directory stream DIRNAME for read and return a pointer to the
3564af0… drh 341 * internal working area that is used to retrieve individual directory
3564af0… drh 342 * entries.
3564af0… drh 343 */
f460839… jan.nijtmans 344 static _WDIR*
f460839… jan.nijtmans 345 _wopendir(
f460839… jan.nijtmans 346 const wchar_t *dirname)
f460839… jan.nijtmans 347 {
f460839… jan.nijtmans 348 _WDIR *dirp = NULL;
8e50ff0… jan.nijtmans 349 int error;
8e50ff0… jan.nijtmans 350
8e50ff0… jan.nijtmans 351 /* Must have directory name */
8e50ff0… jan.nijtmans 352 if (dirname == NULL || dirname[0] == '\0') {
8e50ff0… jan.nijtmans 353 dirent_set_errno (ENOENT);
8e50ff0… jan.nijtmans 354 return NULL;
8e50ff0… jan.nijtmans 355 }
f460839… jan.nijtmans 356
f460839… jan.nijtmans 357 /* Allocate new _WDIR structure */
f460839… jan.nijtmans 358 dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
f460839… jan.nijtmans 359 if (dirp != NULL) {
f460839… jan.nijtmans 360 DWORD n;
f460839… jan.nijtmans 361
f460839… jan.nijtmans 362 /* Reset _WDIR structure */
f460839… jan.nijtmans 363 dirp->handle = INVALID_HANDLE_VALUE;
f460839… jan.nijtmans 364 dirp->patt = NULL;
8e50ff0… jan.nijtmans 365 dirp->cached = 0;
f460839… jan.nijtmans 366
b66b99c… jan.nijtmans 367 /* Compute the length of full path plus zero terminator
ade4a65… jan.nijtmans 368 *
b66b99c… jan.nijtmans 369 * Note that on WinRT there's no way to convert relative paths
1eee6c7… jan.nijtmans 370 * into absolute paths, so just assume it is an absolute path.
b66b99c… jan.nijtmans 371 */
b66b99c… jan.nijtmans 372 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
b66b99c… jan.nijtmans 373 n = wcslen(dirname);
b66b99c… jan.nijtmans 374 # else
b66b99c… jan.nijtmans 375 n = GetFullPathNameW (dirname, 0, NULL, NULL);
b66b99c… jan.nijtmans 376 # endif
f460839… jan.nijtmans 377
8e50ff0… jan.nijtmans 378 /* Allocate room for absolute directory name and search pattern */
f460839… jan.nijtmans 379 dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
f460839… jan.nijtmans 380 if (dirp->patt) {
f460839… jan.nijtmans 381
f460839… jan.nijtmans 382 /*
f460839… jan.nijtmans 383 * Convert relative directory name to an absolute one. This
8e50ff0… jan.nijtmans 384 * allows rewinddir() to function correctly even when current
f460839… jan.nijtmans 385 * working directory is changed between opendir() and rewinddir().
ade4a65… jan.nijtmans 386 *
b66b99c… jan.nijtmans 387 * Note that on WinRT there's no way to convert relative paths
1eee6c7… jan.nijtmans 388 * into absolute paths, so just assume it is an absolute path.
f460839… jan.nijtmans 389 */
b66b99c… jan.nijtmans 390 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
b66b99c… jan.nijtmans 391 wcsncpy_s(dirp->patt, n+1, dirname, n);
b66b99c… jan.nijtmans 392 # else
b66b99c… jan.nijtmans 393 n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
b66b99c… jan.nijtmans 394 # endif
f460839… jan.nijtmans 395 if (n > 0) {
f460839… jan.nijtmans 396 wchar_t *p;
f460839… jan.nijtmans 397
f460839… jan.nijtmans 398 /* Append search pattern \* to the directory name */
f460839… jan.nijtmans 399 p = dirp->patt + n;
f460839… jan.nijtmans 400 if (dirp->patt < p) {
f460839… jan.nijtmans 401 switch (p[-1]) {
f460839… jan.nijtmans 402 case '\\':
f460839… jan.nijtmans 403 case '/':
f460839… jan.nijtmans 404 case ':':
f460839… jan.nijtmans 405 /* Directory ends in path separator, e.g. c:\temp\ */
f460839… jan.nijtmans 406 /*NOP*/;
f460839… jan.nijtmans 407 break;
f460839… jan.nijtmans 408
f460839… jan.nijtmans 409 default:
f460839… jan.nijtmans 410 /* Directory name doesn't end in path separator */
f460839… jan.nijtmans 411 *p++ = '\\';
f460839… jan.nijtmans 412 }
f460839… jan.nijtmans 413 }
f460839… jan.nijtmans 414 *p++ = '*';
f460839… jan.nijtmans 415 *p = '\0';
f460839… jan.nijtmans 416
f460839… jan.nijtmans 417 /* Open directory stream and retrieve the first entry */
8e50ff0… jan.nijtmans 418 if (dirent_first (dirp)) {
8e50ff0… jan.nijtmans 419 /* Directory stream opened successfully */
8e50ff0… jan.nijtmans 420 error = 0;
f460839… jan.nijtmans 421 } else {
8e50ff0… jan.nijtmans 422 /* Cannot retrieve first entry */
f460839… jan.nijtmans 423 error = 1;
8e50ff0… jan.nijtmans 424 dirent_set_errno (ENOENT);
f460839… jan.nijtmans 425 }
f460839… jan.nijtmans 426
f460839… jan.nijtmans 427 } else {
8e50ff0… jan.nijtmans 428 /* Cannot retrieve full path name */
8e50ff0… jan.nijtmans 429 dirent_set_errno (ENOENT);
f460839… jan.nijtmans 430 error = 1;
f460839… jan.nijtmans 431 }
f460839… jan.nijtmans 432
f460839… jan.nijtmans 433 } else {
f460839… jan.nijtmans 434 /* Cannot allocate memory for search pattern */
f460839… jan.nijtmans 435 error = 1;
f460839… jan.nijtmans 436 }
f460839… jan.nijtmans 437
f460839… jan.nijtmans 438 } else {
f460839… jan.nijtmans 439 /* Cannot allocate _WDIR structure */
f460839… jan.nijtmans 440 error = 1;
f460839… jan.nijtmans 441 }
f460839… jan.nijtmans 442
f460839… jan.nijtmans 443 /* Clean up in case of error */
f460839… jan.nijtmans 444 if (error && dirp) {
f460839… jan.nijtmans 445 _wclosedir (dirp);
f460839… jan.nijtmans 446 dirp = NULL;
f460839… jan.nijtmans 447 }
f460839… jan.nijtmans 448
f460839… jan.nijtmans 449 return dirp;
f460839… jan.nijtmans 450 }
f460839… jan.nijtmans 451
f460839… jan.nijtmans 452 /*
ade4a65… jan.nijtmans 453 * Read next directory entry.
ade4a65… jan.nijtmans 454 *
1eee6c7… jan.nijtmans 455 * Returns pointer to static directory entry which may be overwritten by
ade4a65… jan.nijtmans 456 * subsequent calls to _wreaddir().
f460839… jan.nijtmans 457 */
f460839… jan.nijtmans 458 static struct _wdirent*
f460839… jan.nijtmans 459 _wreaddir(
f460839… jan.nijtmans 460 _WDIR *dirp)
f460839… jan.nijtmans 461 {
ade4a65… jan.nijtmans 462 struct _wdirent *entry;
ade4a65… jan.nijtmans 463
ade4a65… jan.nijtmans 464 /*
ade4a65… jan.nijtmans 465 * Read directory entry to buffer. We can safely ignore the return value
ade4a65… jan.nijtmans 466 * as entry will be set to NULL in case of error.
ade4a65… jan.nijtmans 467 */
ade4a65… jan.nijtmans 468 (void) _wreaddir_r (dirp, &dirp->ent, &entry);
ade4a65… jan.nijtmans 469
ade4a65… jan.nijtmans 470 /* Return pointer to statically allocated directory entry */
ade4a65… jan.nijtmans 471 return entry;
ade4a65… jan.nijtmans 472 }
ade4a65… jan.nijtmans 473
ade4a65… jan.nijtmans 474 /*
ade4a65… jan.nijtmans 475 * Read next directory entry.
ade4a65… jan.nijtmans 476 *
ade4a65… jan.nijtmans 477 * Returns zero on success. If end of directory stream is reached, then sets
ade4a65… jan.nijtmans 478 * result to NULL and returns zero.
ade4a65… jan.nijtmans 479 */
ade4a65… jan.nijtmans 480 static int
ade4a65… jan.nijtmans 481 _wreaddir_r(
ade4a65… jan.nijtmans 482 _WDIR *dirp,
ade4a65… jan.nijtmans 483 struct _wdirent *entry,
ade4a65… jan.nijtmans 484 struct _wdirent **result)
ade4a65… jan.nijtmans 485 {
8e50ff0… jan.nijtmans 486 WIN32_FIND_DATAW *datap;
8e50ff0… jan.nijtmans 487
8e50ff0… jan.nijtmans 488 /* Read next directory entry */
8e50ff0… jan.nijtmans 489 datap = dirent_next (dirp);
8e50ff0… jan.nijtmans 490 if (datap) {
8e50ff0… jan.nijtmans 491 size_t n;
8e50ff0… jan.nijtmans 492 DWORD attr;
8e50ff0… jan.nijtmans 493
ade4a65… jan.nijtmans 494 /*
8e50ff0… jan.nijtmans 495 * Copy file name as wide-character string. If the file name is too
8e50ff0… jan.nijtmans 496 * long to fit in to the destination buffer, then truncate file name
8e50ff0… jan.nijtmans 497 * to PATH_MAX characters and zero-terminate the buffer.
8e50ff0… jan.nijtmans 498 */
8e50ff0… jan.nijtmans 499 n = 0;
ade4a65… jan.nijtmans 500 while (n < PATH_MAX && datap->cFileName[n] != 0) {
ade4a65… jan.nijtmans 501 entry->d_name[n] = datap->cFileName[n];
8e50ff0… jan.nijtmans 502 n++;
8e50ff0… jan.nijtmans 503 }
ade4a65… jan.nijtmans 504 entry->d_name[n] = 0;
8e50ff0… jan.nijtmans 505
8e50ff0… jan.nijtmans 506 /* Length of file name excluding zero terminator */
ade4a65… jan.nijtmans 507 entry->d_namlen = n;
8e50ff0… jan.nijtmans 508
8e50ff0… jan.nijtmans 509 /* File type */
8e50ff0… jan.nijtmans 510 attr = datap->dwFileAttributes;
f460839… jan.nijtmans 511 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
ade4a65… jan.nijtmans 512 entry->d_type = DT_CHR;
f460839… jan.nijtmans 513 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
ade4a65… jan.nijtmans 514 entry->d_type = DT_DIR;
f460839… jan.nijtmans 515 } else {
ade4a65… jan.nijtmans 516 entry->d_type = DT_REG;
f460839… jan.nijtmans 517 }
f460839… jan.nijtmans 518
f460839… jan.nijtmans 519 /* Reset dummy fields */
ade4a65… jan.nijtmans 520 entry->d_ino = 0;
ade4a65… jan.nijtmans 521 entry->d_off = 0;
ade4a65… jan.nijtmans 522 entry->d_reclen = sizeof (struct _wdirent);
ade4a65… jan.nijtmans 523
ade4a65… jan.nijtmans 524 /* Set result address */
ade4a65… jan.nijtmans 525 *result = entry;
f460839… jan.nijtmans 526
f460839… jan.nijtmans 527 } else {
f460839… jan.nijtmans 528
ade4a65… jan.nijtmans 529 /* Return NULL to indicate end of directory */
ade4a65… jan.nijtmans 530 *result = NULL;
8e50ff0… jan.nijtmans 531
f460839… jan.nijtmans 532 }
f460839… jan.nijtmans 533
ade4a65… jan.nijtmans 534 return /*OK*/0;
f460839… jan.nijtmans 535 }
f460839… jan.nijtmans 536
f460839… jan.nijtmans 537 /*
f460839… jan.nijtmans 538 * Close directory stream opened by opendir() function. This invalidates the
f460839… jan.nijtmans 539 * DIR structure as well as any directory entry read previously by
f460839… jan.nijtmans 540 * _wreaddir().
f460839… jan.nijtmans 541 */
f460839… jan.nijtmans 542 static int
f460839… jan.nijtmans 543 _wclosedir(
f460839… jan.nijtmans 544 _WDIR *dirp)
f460839… jan.nijtmans 545 {
f460839… jan.nijtmans 546 int ok;
f460839… jan.nijtmans 547 if (dirp) {
f460839… jan.nijtmans 548
f460839… jan.nijtmans 549 /* Release search handle */
f460839… jan.nijtmans 550 if (dirp->handle != INVALID_HANDLE_VALUE) {
f460839… jan.nijtmans 551 FindClose (dirp->handle);
f460839… jan.nijtmans 552 dirp->handle = INVALID_HANDLE_VALUE;
f460839… jan.nijtmans 553 }
f460839… jan.nijtmans 554
f460839… jan.nijtmans 555 /* Release search pattern */
f460839… jan.nijtmans 556 if (dirp->patt) {
f460839… jan.nijtmans 557 free (dirp->patt);
f460839… jan.nijtmans 558 dirp->patt = NULL;
f460839… jan.nijtmans 559 }
f460839… jan.nijtmans 560
f460839… jan.nijtmans 561 /* Release directory structure */
f460839… jan.nijtmans 562 free (dirp);
f460839… jan.nijtmans 563 ok = /*success*/0;
f460839… jan.nijtmans 564
f460839… jan.nijtmans 565 } else {
ade4a65… jan.nijtmans 566
f460839… jan.nijtmans 567 /* Invalid directory stream */
8e50ff0… jan.nijtmans 568 dirent_set_errno (EBADF);
f460839… jan.nijtmans 569 ok = /*failure*/-1;
ade4a65… jan.nijtmans 570
f460839… jan.nijtmans 571 }
f460839… jan.nijtmans 572 return ok;
f460839… jan.nijtmans 573 }
f460839… jan.nijtmans 574
f460839… jan.nijtmans 575 /*
f460839… jan.nijtmans 576 * Rewind directory stream such that _wreaddir() returns the very first
f460839… jan.nijtmans 577 * file name again.
f460839… jan.nijtmans 578 */
f460839… jan.nijtmans 579 static void
f460839… jan.nijtmans 580 _wrewinddir(
f460839… jan.nijtmans 581 _WDIR* dirp)
f460839… jan.nijtmans 582 {
8e50ff0… jan.nijtmans 583 if (dirp) {
8e50ff0… jan.nijtmans 584 /* Release existing search handle */
f460839… jan.nijtmans 585 if (dirp->handle != INVALID_HANDLE_VALUE) {
f460839… jan.nijtmans 586 FindClose (dirp->handle);
f460839… jan.nijtmans 587 }
f460839… jan.nijtmans 588
8e50ff0… jan.nijtmans 589 /* Open new search handle */
8e50ff0… jan.nijtmans 590 dirent_first (dirp);
8e50ff0… jan.nijtmans 591 }
8e50ff0… jan.nijtmans 592 }
8e50ff0… jan.nijtmans 593
8e50ff0… jan.nijtmans 594 /* Get first directory entry (internal) */
8e50ff0… jan.nijtmans 595 static WIN32_FIND_DATAW*
8e50ff0… jan.nijtmans 596 dirent_first(
8e50ff0… jan.nijtmans 597 _WDIR *dirp)
8e50ff0… jan.nijtmans 598 {
8e50ff0… jan.nijtmans 599 WIN32_FIND_DATAW *datap;
8e50ff0… jan.nijtmans 600
8e50ff0… jan.nijtmans 601 /* Open directory and retrieve the first entry */
b66b99c… jan.nijtmans 602 dirp->handle = FindFirstFileExW(
b66b99c… jan.nijtmans 603 dirp->patt, FindExInfoStandard, &dirp->data,
b66b99c… jan.nijtmans 604 FindExSearchNameMatch, NULL, 0);
8e50ff0… jan.nijtmans 605 if (dirp->handle != INVALID_HANDLE_VALUE) {
8e50ff0… jan.nijtmans 606
8e50ff0… jan.nijtmans 607 /* a directory entry is now waiting in memory */
8e50ff0… jan.nijtmans 608 datap = &dirp->data;
8e50ff0… jan.nijtmans 609 dirp->cached = 1;
8e50ff0… jan.nijtmans 610
8e50ff0… jan.nijtmans 611 } else {
8e50ff0… jan.nijtmans 612
8e50ff0… jan.nijtmans 613 /* Failed to re-open directory: no directory entry in memory */
8e50ff0… jan.nijtmans 614 dirp->cached = 0;
8e50ff0… jan.nijtmans 615 datap = NULL;
8e50ff0… jan.nijtmans 616
8e50ff0… jan.nijtmans 617 }
8e50ff0… jan.nijtmans 618 return datap;
8e50ff0… jan.nijtmans 619 }
8e50ff0… jan.nijtmans 620
ade4a65… jan.nijtmans 621 /*
ade4a65… jan.nijtmans 622 * Get next directory entry (internal).
ade4a65… jan.nijtmans 623 *
ade4a65… jan.nijtmans 624 * Returns
ade4a65… jan.nijtmans 625 */
8e50ff0… jan.nijtmans 626 static WIN32_FIND_DATAW*
8e50ff0… jan.nijtmans 627 dirent_next(
8e50ff0… jan.nijtmans 628 _WDIR *dirp)
8e50ff0… jan.nijtmans 629 {
8e50ff0… jan.nijtmans 630 WIN32_FIND_DATAW *p;
8e50ff0… jan.nijtmans 631
8e50ff0… jan.nijtmans 632 /* Get next directory entry */
8e50ff0… jan.nijtmans 633 if (dirp->cached != 0) {
8e50ff0… jan.nijtmans 634
8e50ff0… jan.nijtmans 635 /* A valid directory entry already in memory */
8e50ff0… jan.nijtmans 636 p = &dirp->data;
8e50ff0… jan.nijtmans 637 dirp->cached = 0;
8e50ff0… jan.nijtmans 638
8e50ff0… jan.nijtmans 639 } else if (dirp->handle != INVALID_HANDLE_VALUE) {
8e50ff0… jan.nijtmans 640
8e50ff0… jan.nijtmans 641 /* Get the next directory entry from stream */
8e50ff0… jan.nijtmans 642 if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
8e50ff0… jan.nijtmans 643 /* Got a file */
8e50ff0… jan.nijtmans 644 p = &dirp->data;
f460839… jan.nijtmans 645 } else {
1eee6c7… jan.nijtmans 646 /* The very last entry has been processed or an error occurred */
8e50ff0… jan.nijtmans 647 FindClose (dirp->handle);
8e50ff0… jan.nijtmans 648 dirp->handle = INVALID_HANDLE_VALUE;
8e50ff0… jan.nijtmans 649 p = NULL;
f460839… jan.nijtmans 650 }
8e50ff0… jan.nijtmans 651
8e50ff0… jan.nijtmans 652 } else {
8e50ff0… jan.nijtmans 653
8e50ff0… jan.nijtmans 654 /* End of directory stream reached */
8e50ff0… jan.nijtmans 655 p = NULL;
8e50ff0… jan.nijtmans 656
f460839… jan.nijtmans 657 }
8e50ff0… jan.nijtmans 658
8e50ff0… jan.nijtmans 659 return p;
f460839… jan.nijtmans 660 }
f460839… jan.nijtmans 661
ade4a65… jan.nijtmans 662 /*
f460839… jan.nijtmans 663 * Open directory stream using plain old C-string.
f460839… jan.nijtmans 664 */
f460839… jan.nijtmans 665 static DIR*
f460839… jan.nijtmans 666 opendir(
f460839… jan.nijtmans 667 const char *dirname)
f460839… jan.nijtmans 668 {
f460839… jan.nijtmans 669 struct DIR *dirp;
8e50ff0… jan.nijtmans 670 int error;
f460839… jan.nijtmans 671
f460839… jan.nijtmans 672 /* Must have directory name */
8e50ff0… jan.nijtmans 673 if (dirname == NULL || dirname[0] == '\0') {
8e50ff0… jan.nijtmans 674 dirent_set_errno (ENOENT);
f460839… jan.nijtmans 675 return NULL;
f460839… jan.nijtmans 676 }
f460839… jan.nijtmans 677
8e50ff0… jan.nijtmans 678 /* Allocate memory for DIR structure */
f460839… jan.nijtmans 679 dirp = (DIR*) malloc (sizeof (struct DIR));
f460839… jan.nijtmans 680 if (dirp) {
ade4a65… jan.nijtmans 681 wchar_t wname[PATH_MAX + 1];
f460839… jan.nijtmans 682 size_t n;
f460839… jan.nijtmans 683
8e50ff0… jan.nijtmans 684 /* Convert directory name to wide-character string */
ade4a65… jan.nijtmans 685 error = dirent_mbstowcs_s(
ade4a65… jan.nijtmans 686 &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
8e50ff0… jan.nijtmans 687 if (!error) {
8e50ff0… jan.nijtmans 688
8e50ff0… jan.nijtmans 689 /* Open directory stream using wide-character name */
f460839… jan.nijtmans 690 dirp->wdirp = _wopendir (wname);
f460839… jan.nijtmans 691 if (dirp->wdirp) {
8e50ff0… jan.nijtmans 692 /* Directory stream opened */
8e50ff0… jan.nijtmans 693 error = 0;
f460839… jan.nijtmans 694 } else {
f460839… jan.nijtmans 695 /* Failed to open directory stream */
f460839… jan.nijtmans 696 error = 1;
f460839… jan.nijtmans 697 }
f460839… jan.nijtmans 698
f460839… jan.nijtmans 699 } else {
ade4a65… jan.nijtmans 700 /*
f460839… jan.nijtmans 701 * Cannot convert file name to wide-character string. This
f460839… jan.nijtmans 702 * occurs if the string contains invalid multi-byte sequences or
f460839… jan.nijtmans 703 * the output buffer is too small to contain the resulting
f460839… jan.nijtmans 704 * string.
f460839… jan.nijtmans 705 */
f460839… jan.nijtmans 706 error = 1;
f460839… jan.nijtmans 707 }
f460839… jan.nijtmans 708
f460839… jan.nijtmans 709 } else {
f460839… jan.nijtmans 710 /* Cannot allocate DIR structure */
f460839… jan.nijtmans 711 error = 1;
f460839… jan.nijtmans 712 }
f460839… jan.nijtmans 713
f460839… jan.nijtmans 714 /* Clean up in case of error */
f460839… jan.nijtmans 715 if (error && dirp) {
f460839… jan.nijtmans 716 free (dirp);
f460839… jan.nijtmans 717 dirp = NULL;
f460839… jan.nijtmans 718 }
f460839… jan.nijtmans 719
f460839… jan.nijtmans 720 return dirp;
f460839… jan.nijtmans 721 }
f460839… jan.nijtmans 722
f460839… jan.nijtmans 723 /*
f460839… jan.nijtmans 724 * Read next directory entry.
8e50ff0… jan.nijtmans 725 */
8e50ff0… jan.nijtmans 726 static struct dirent*
8e50ff0… jan.nijtmans 727 readdir(
ade4a65… jan.nijtmans 728 DIR *dirp)
ade4a65… jan.nijtmans 729 {
ade4a65… jan.nijtmans 730 struct dirent *entry;
ade4a65… jan.nijtmans 731
ade4a65… jan.nijtmans 732 /*
ade4a65… jan.nijtmans 733 * Read directory entry to buffer. We can safely ignore the return value
ade4a65… jan.nijtmans 734 * as entry will be set to NULL in case of error.
ade4a65… jan.nijtmans 735 */
ade4a65… jan.nijtmans 736 (void) readdir_r (dirp, &dirp->ent, &entry);
ade4a65… jan.nijtmans 737
ade4a65… jan.nijtmans 738 /* Return pointer to statically allocated directory entry */
ade4a65… jan.nijtmans 739 return entry;
ade4a65… jan.nijtmans 740 }
ade4a65… jan.nijtmans 741
ade4a65… jan.nijtmans 742 /*
ade4a65… jan.nijtmans 743 * Read next directory entry into called-allocated buffer.
ade4a65… jan.nijtmans 744 *
1eee6c7… jan.nijtmans 745 * Returns zero on success. If the end of directory stream is reached, then
ade4a65… jan.nijtmans 746 * sets result to NULL and returns zero.
ade4a65… jan.nijtmans 747 */
ade4a65… jan.nijtmans 748 static int
ade4a65… jan.nijtmans 749 readdir_r(
ade4a65… jan.nijtmans 750 DIR *dirp,
ade4a65… jan.nijtmans 751 struct dirent *entry,
ade4a65… jan.nijtmans 752 struct dirent **result)
8e50ff0… jan.nijtmans 753 {
8e50ff0… jan.nijtmans 754 WIN32_FIND_DATAW *datap;
8e50ff0… jan.nijtmans 755
8e50ff0… jan.nijtmans 756 /* Read next directory entry */
8e50ff0… jan.nijtmans 757 datap = dirent_next (dirp->wdirp);
8e50ff0… jan.nijtmans 758 if (datap) {
8e50ff0… jan.nijtmans 759 size_t n;
8e50ff0… jan.nijtmans 760 int error;
8e50ff0… jan.nijtmans 761
8e50ff0… jan.nijtmans 762 /* Attempt to convert file name to multi-byte string */
8e50ff0… jan.nijtmans 763 error = dirent_wcstombs_s(
ade4a65… jan.nijtmans 764 &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1);
8e50ff0… jan.nijtmans 765
ade4a65… jan.nijtmans 766 /*
8e50ff0… jan.nijtmans 767 * If the file name cannot be represented by a multi-byte string,
8e50ff0… jan.nijtmans 768 * then attempt to use old 8+3 file name. This allows traditional
8e50ff0… jan.nijtmans 769 * Unix-code to access some file names despite of unicode
8e50ff0… jan.nijtmans 770 * characters, although file names may seem unfamiliar to the user.
8e50ff0… jan.nijtmans 771 *
8e50ff0… jan.nijtmans 772 * Be ware that the code below cannot come up with a short file
8e50ff0… jan.nijtmans 773 * name unless the file system provides one. At least
8e50ff0… jan.nijtmans 774 * VirtualBox shared folders fail to do this.
8e50ff0… jan.nijtmans 775 */
8e50ff0… jan.nijtmans 776 if (error && datap->cAlternateFileName[0] != '\0') {
8e50ff0… jan.nijtmans 777 error = dirent_wcstombs_s(
ade4a65… jan.nijtmans 778 &n, entry->d_name, PATH_MAX + 1,
ade4a65… jan.nijtmans 779 datap->cAlternateFileName, PATH_MAX + 1);
8e50ff0… jan.nijtmans 780 }
8e50ff0… jan.nijtmans 781
8e50ff0… jan.nijtmans 782 if (!error) {
8e50ff0… jan.nijtmans 783 DWORD attr;
8e50ff0… jan.nijtmans 784
8e50ff0… jan.nijtmans 785 /* Length of file name excluding zero terminator */
ade4a65… jan.nijtmans 786 entry->d_namlen = n - 1;
8e50ff0… jan.nijtmans 787
8e50ff0… jan.nijtmans 788 /* File attributes */
8e50ff0… jan.nijtmans 789 attr = datap->dwFileAttributes;
8e50ff0… jan.nijtmans 790 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
ade4a65… jan.nijtmans 791 entry->d_type = DT_CHR;
8e50ff0… jan.nijtmans 792 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
ade4a65… jan.nijtmans 793 entry->d_type = DT_DIR;
8e50ff0… jan.nijtmans 794 } else {
ade4a65… jan.nijtmans 795 entry->d_type = DT_REG;
8e50ff0… jan.nijtmans 796 }
8e50ff0… jan.nijtmans 797
8e50ff0… jan.nijtmans 798 /* Reset dummy fields */
ade4a65… jan.nijtmans 799 entry->d_ino = 0;
ade4a65… jan.nijtmans 800 entry->d_off = 0;
ade4a65… jan.nijtmans 801 entry->d_reclen = sizeof (struct dirent);
8e50ff0… jan.nijtmans 802
8e50ff0… jan.nijtmans 803 } else {
ade4a65… jan.nijtmans 804
ade4a65… jan.nijtmans 805 /*
8e50ff0… jan.nijtmans 806 * Cannot convert file name to multi-byte string so construct
1eee6c7… jan.nijtmans 807 * an erroneous directory entry and return that. Note that
8e50ff0… jan.nijtmans 808 * we cannot return NULL as that would stop the processing
8e50ff0… jan.nijtmans 809 * of directory entries completely.
8e50ff0… jan.nijtmans 810 */
ade4a65… jan.nijtmans 811 entry->d_name[0] = '?';
ade4a65… jan.nijtmans 812 entry->d_name[1] = '\0';
ade4a65… jan.nijtmans 813 entry->d_namlen = 1;
ade4a65… jan.nijtmans 814 entry->d_type = DT_UNKNOWN;
ade4a65… jan.nijtmans 815 entry->d_ino = 0;
ade4a65… jan.nijtmans 816 entry->d_off = -1;
ade4a65… jan.nijtmans 817 entry->d_reclen = 0;
ade4a65… jan.nijtmans 818
ade4a65… jan.nijtmans 819 }
ade4a65… jan.nijtmans 820
ade4a65… jan.nijtmans 821 /* Return pointer to directory entry */
ade4a65… jan.nijtmans 822 *result = entry;
8e50ff0… jan.nijtmans 823
8e50ff0… jan.nijtmans 824 } else {
ade4a65… jan.nijtmans 825
8e50ff0… jan.nijtmans 826 /* No more directory entries */
ade4a65… jan.nijtmans 827 *result = NULL;
ade4a65… jan.nijtmans 828
8e50ff0… jan.nijtmans 829 }
8e50ff0… jan.nijtmans 830
ade4a65… jan.nijtmans 831 return /*OK*/0;
f460839… jan.nijtmans 832 }
f460839… jan.nijtmans 833
f460839… jan.nijtmans 834 /*
f460839… jan.nijtmans 835 * Close directory stream.
f460839… jan.nijtmans 836 */
f460839… jan.nijtmans 837 static int
f460839… jan.nijtmans 838 closedir(
ade4a65… jan.nijtmans 839 DIR *dirp)
f460839… jan.nijtmans 840 {
f460839… jan.nijtmans 841 int ok;
f460839… jan.nijtmans 842 if (dirp) {
f460839… jan.nijtmans 843
f460839… jan.nijtmans 844 /* Close wide-character directory stream */
f460839… jan.nijtmans 845 ok = _wclosedir (dirp->wdirp);
f460839… jan.nijtmans 846 dirp->wdirp = NULL;
f460839… jan.nijtmans 847
f460839… jan.nijtmans 848 /* Release multi-byte character version */
f460839… jan.nijtmans 849 free (dirp);
f460839… jan.nijtmans 850
f460839… jan.nijtmans 851 } else {
8e50ff0… jan.nijtmans 852
f460839… jan.nijtmans 853 /* Invalid directory stream */
8e50ff0… jan.nijtmans 854 dirent_set_errno (EBADF);
f460839… jan.nijtmans 855 ok = /*failure*/-1;
8e50ff0… jan.nijtmans 856
f460839… jan.nijtmans 857 }
f460839… jan.nijtmans 858 return ok;
f460839… jan.nijtmans 859 }
f460839… jan.nijtmans 860
f460839… jan.nijtmans 861 /*
f460839… jan.nijtmans 862 * Rewind directory stream to beginning.
f460839… jan.nijtmans 863 */
f460839… jan.nijtmans 864 static void
f460839… jan.nijtmans 865 rewinddir(
ade4a65… jan.nijtmans 866 DIR* dirp)
f460839… jan.nijtmans 867 {
f460839… jan.nijtmans 868 /* Rewind wide-character string directory stream */
f460839… jan.nijtmans 869 _wrewinddir (dirp->wdirp);
8e50ff0… jan.nijtmans 870 }
ade4a65… jan.nijtmans 871
ade4a65… jan.nijtmans 872 /*
ade4a65… jan.nijtmans 873 * Scan directory for entries.
ade4a65… jan.nijtmans 874 */
ade4a65… jan.nijtmans 875 static int
ade4a65… jan.nijtmans 876 scandir(
ade4a65… jan.nijtmans 877 const char *dirname,
ade4a65… jan.nijtmans 878 struct dirent ***namelist,
ade4a65… jan.nijtmans 879 int (*filter)(const struct dirent*),
1eee6c7… jan.nijtmans 880 int (*compare)(const struct dirent**, const struct dirent**))
ade4a65… jan.nijtmans 881 {
ade4a65… jan.nijtmans 882 struct dirent **files = NULL;
ade4a65… jan.nijtmans 883 size_t size = 0;
ade4a65… jan.nijtmans 884 size_t allocated = 0;
ade4a65… jan.nijtmans 885 const size_t init_size = 1;
ade4a65… jan.nijtmans 886 DIR *dir = NULL;
ade4a65… jan.nijtmans 887 struct dirent *entry;
ade4a65… jan.nijtmans 888 struct dirent *tmp = NULL;
ade4a65… jan.nijtmans 889 size_t i;
ade4a65… jan.nijtmans 890 int result = 0;
ade4a65… jan.nijtmans 891
ade4a65… jan.nijtmans 892 /* Open directory stream */
ade4a65… jan.nijtmans 893 dir = opendir (dirname);
ade4a65… jan.nijtmans 894 if (dir) {
ade4a65… jan.nijtmans 895
ade4a65… jan.nijtmans 896 /* Read directory entries to memory */
ade4a65… jan.nijtmans 897 while (1) {
ade4a65… jan.nijtmans 898
ade4a65… jan.nijtmans 899 /* Enlarge pointer table to make room for another pointer */
ade4a65… jan.nijtmans 900 if (size >= allocated) {
ade4a65… jan.nijtmans 901 void *p;
ade4a65… jan.nijtmans 902 size_t num_entries;
ade4a65… jan.nijtmans 903
ade4a65… jan.nijtmans 904 /* Compute number of entries in the enlarged pointer table */
ade4a65… jan.nijtmans 905 if (size < init_size) {
ade4a65… jan.nijtmans 906 /* Allocate initial pointer table */
ade4a65… jan.nijtmans 907 num_entries = init_size;
ade4a65… jan.nijtmans 908 } else {
ade4a65… jan.nijtmans 909 /* Double the size */
ade4a65… jan.nijtmans 910 num_entries = size * 2;
ade4a65… jan.nijtmans 911 }
ade4a65… jan.nijtmans 912
ade4a65… jan.nijtmans 913 /* Allocate first pointer table or enlarge existing table */
ade4a65… jan.nijtmans 914 p = realloc (files, sizeof (void*) * num_entries);
ade4a65… jan.nijtmans 915 if (p != NULL) {
ade4a65… jan.nijtmans 916 /* Got the memory */
398a90c… jan.nijtmans 917 files = (dirent**) p;
ade4a65… jan.nijtmans 918 allocated = num_entries;
ade4a65… jan.nijtmans 919 } else {
ade4a65… jan.nijtmans 920 /* Out of memory */
ade4a65… jan.nijtmans 921 result = -1;
ade4a65… jan.nijtmans 922 break;
ade4a65… jan.nijtmans 923 }
ade4a65… jan.nijtmans 924
ade4a65… jan.nijtmans 925 }
ade4a65… jan.nijtmans 926
ade4a65… jan.nijtmans 927 /* Allocate room for temporary directory entry */
ade4a65… jan.nijtmans 928 if (tmp == NULL) {
ade4a65… jan.nijtmans 929 tmp = (struct dirent*) malloc (sizeof (struct dirent));
ade4a65… jan.nijtmans 930 if (tmp == NULL) {
ade4a65… jan.nijtmans 931 /* Cannot allocate temporary directory entry */
ade4a65… jan.nijtmans 932 result = -1;
ade4a65… jan.nijtmans 933 break;
ade4a65… jan.nijtmans 934 }
ade4a65… jan.nijtmans 935 }
ade4a65… jan.nijtmans 936
ade4a65… jan.nijtmans 937 /* Read directory entry to temporary area */
ade4a65… jan.nijtmans 938 if (readdir_r (dir, tmp, &entry) == /*OK*/0) {
ade4a65… jan.nijtmans 939
1eee6c7… jan.nijtmans 940 /* Did we get an entry? */
ade4a65… jan.nijtmans 941 if (entry != NULL) {
ade4a65… jan.nijtmans 942 int pass;
ade4a65… jan.nijtmans 943
ade4a65… jan.nijtmans 944 /* Determine whether to include the entry in result */
ade4a65… jan.nijtmans 945 if (filter) {
ade4a65… jan.nijtmans 946 /* Let the filter function decide */
ade4a65… jan.nijtmans 947 pass = filter (tmp);
ade4a65… jan.nijtmans 948 } else {
ade4a65… jan.nijtmans 949 /* No filter function, include everything */
ade4a65… jan.nijtmans 950 pass = 1;
ade4a65… jan.nijtmans 951 }
ade4a65… jan.nijtmans 952
ade4a65… jan.nijtmans 953 if (pass) {
ade4a65… jan.nijtmans 954 /* Store the temporary entry to pointer table */
ade4a65… jan.nijtmans 955 files[size++] = tmp;
ade4a65… jan.nijtmans 956 tmp = NULL;
ade4a65… jan.nijtmans 957
ade4a65… jan.nijtmans 958 /* Keep up with the number of files */
ade4a65… jan.nijtmans 959 result++;
ade4a65… jan.nijtmans 960 }
ade4a65… jan.nijtmans 961
ade4a65… jan.nijtmans 962 } else {
ade4a65… jan.nijtmans 963
ade4a65… jan.nijtmans 964 /*
ade4a65… jan.nijtmans 965 * End of directory stream reached => sort entries and
ade4a65… jan.nijtmans 966 * exit.
ade4a65… jan.nijtmans 967 */
1eee6c7… jan.nijtmans 968 qsort (files, size, sizeof (void*),
1eee6c7… jan.nijtmans 969 (int (*) (const void*, const void*)) compare);
ade4a65… jan.nijtmans 970 break;
ade4a65… jan.nijtmans 971
ade4a65… jan.nijtmans 972 }
ade4a65… jan.nijtmans 973
ade4a65… jan.nijtmans 974 } else {
ade4a65… jan.nijtmans 975 /* Error reading directory entry */
ade4a65… jan.nijtmans 976 result = /*Error*/ -1;
ade4a65… jan.nijtmans 977 break;
ade4a65… jan.nijtmans 978 }
ade4a65… jan.nijtmans 979
ade4a65… jan.nijtmans 980 }
ade4a65… jan.nijtmans 981
ade4a65… jan.nijtmans 982 } else {
ade4a65… jan.nijtmans 983 /* Cannot open directory */
ade4a65… jan.nijtmans 984 result = /*Error*/ -1;
ade4a65… jan.nijtmans 985 }
ade4a65… jan.nijtmans 986
ade4a65… jan.nijtmans 987 /* Release temporary directory entry */
ade4a65… jan.nijtmans 988 if (tmp) {
ade4a65… jan.nijtmans 989 free (tmp);
ade4a65… jan.nijtmans 990 }
ade4a65… jan.nijtmans 991
ade4a65… jan.nijtmans 992 /* Release allocated memory on error */
ade4a65… jan.nijtmans 993 if (result < 0) {
ade4a65… jan.nijtmans 994 for (i = 0; i < size; i++) {
ade4a65… jan.nijtmans 995 free (files[i]);
ade4a65… jan.nijtmans 996 }
ade4a65… jan.nijtmans 997 free (files);
ade4a65… jan.nijtmans 998 files = NULL;
ade4a65… jan.nijtmans 999 }
ade4a65… jan.nijtmans 1000
ade4a65… jan.nijtmans 1001 /* Close directory stream */
ade4a65… jan.nijtmans 1002 if (dir) {
ade4a65… jan.nijtmans 1003 closedir (dir);
ade4a65… jan.nijtmans 1004 }
ade4a65… jan.nijtmans 1005
ade4a65… jan.nijtmans 1006 /* Pass pointer table to caller */
ade4a65… jan.nijtmans 1007 if (namelist) {
ade4a65… jan.nijtmans 1008 *namelist = files;
ade4a65… jan.nijtmans 1009 }
ade4a65… jan.nijtmans 1010 return result;
ade4a65… jan.nijtmans 1011 }
ade4a65… jan.nijtmans 1012
ade4a65… jan.nijtmans 1013 /* Alphabetical sorting */
ade4a65… jan.nijtmans 1014 static int
ade4a65… jan.nijtmans 1015 alphasort(
ade4a65… jan.nijtmans 1016 const struct dirent **a, const struct dirent **b)
ade4a65… jan.nijtmans 1017 {
ade4a65… jan.nijtmans 1018 return strcoll ((*a)->d_name, (*b)->d_name);
ade4a65… jan.nijtmans 1019 }
ade4a65… jan.nijtmans 1020
ade4a65… jan.nijtmans 1021 /* Sort versions */
ade4a65… jan.nijtmans 1022 static int
ade4a65… jan.nijtmans 1023 versionsort(
ade4a65… jan.nijtmans 1024 const struct dirent **a, const struct dirent **b)
ade4a65… jan.nijtmans 1025 {
ade4a65… jan.nijtmans 1026 /* FIXME: implement strverscmp and use that */
ade4a65… jan.nijtmans 1027 return alphasort (a, b);
ade4a65… jan.nijtmans 1028 }
ade4a65… jan.nijtmans 1029
8e50ff0… jan.nijtmans 1030
8e50ff0… jan.nijtmans 1031 /* Convert multi-byte string to wide character string */
8e50ff0… jan.nijtmans 1032 static int
8e50ff0… jan.nijtmans 1033 dirent_mbstowcs_s(
8e50ff0… jan.nijtmans 1034 size_t *pReturnValue,
8e50ff0… jan.nijtmans 1035 wchar_t *wcstr,
8e50ff0… jan.nijtmans 1036 size_t sizeInWords,
8e50ff0… jan.nijtmans 1037 const char *mbstr,
8e50ff0… jan.nijtmans 1038 size_t count)
8e50ff0… jan.nijtmans 1039 {
8e50ff0… jan.nijtmans 1040 int error;
8e50ff0… jan.nijtmans 1041
8e50ff0… jan.nijtmans 1042 #if defined(_MSC_VER) && _MSC_VER >= 1400
8e50ff0… jan.nijtmans 1043
8e50ff0… jan.nijtmans 1044 /* Microsoft Visual Studio 2005 or later */
8e50ff0… jan.nijtmans 1045 error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
8e50ff0… jan.nijtmans 1046
8e50ff0… jan.nijtmans 1047 #else
8e50ff0… jan.nijtmans 1048
8e50ff0… jan.nijtmans 1049 /* Older Visual Studio or non-Microsoft compiler */
8e50ff0… jan.nijtmans 1050 size_t n;
8e50ff0… jan.nijtmans 1051
a374824… jan.nijtmans 1052 /* Convert to wide-character string (or count characters) */
a374824… jan.nijtmans 1053 n = mbstowcs (wcstr, mbstr, sizeInWords);
a374824… jan.nijtmans 1054 if (!wcstr || n < count) {
8e50ff0… jan.nijtmans 1055
8e50ff0… jan.nijtmans 1056 /* Zero-terminate output buffer */
a374824… jan.nijtmans 1057 if (wcstr && sizeInWords) {
a374824… jan.nijtmans 1058 if (n >= sizeInWords) {
a374824… jan.nijtmans 1059 n = sizeInWords - 1;
a374824… jan.nijtmans 1060 }
8e50ff0… jan.nijtmans 1061 wcstr[n] = 0;
8e50ff0… jan.nijtmans 1062 }
8e50ff0… jan.nijtmans 1063
1eee6c7… jan.nijtmans 1064 /* Length of resulting multi-byte string WITH zero terminator */
8e50ff0… jan.nijtmans 1065 if (pReturnValue) {
8e50ff0… jan.nijtmans 1066 *pReturnValue = n + 1;
8e50ff0… jan.nijtmans 1067 }
8e50ff0… jan.nijtmans 1068
8e50ff0… jan.nijtmans 1069 /* Success */
8e50ff0… jan.nijtmans 1070 error = 0;
8e50ff0… jan.nijtmans 1071
8e50ff0… jan.nijtmans 1072 } else {
8e50ff0… jan.nijtmans 1073
8e50ff0… jan.nijtmans 1074 /* Could not convert string */
8e50ff0… jan.nijtmans 1075 error = 1;
8e50ff0… jan.nijtmans 1076
8e50ff0… jan.nijtmans 1077 }
8e50ff0… jan.nijtmans 1078
8e50ff0… jan.nijtmans 1079 #endif
8e50ff0… jan.nijtmans 1080
8e50ff0… jan.nijtmans 1081 return error;
8e50ff0… jan.nijtmans 1082 }
8e50ff0… jan.nijtmans 1083
8e50ff0… jan.nijtmans 1084 /* Convert wide-character string to multi-byte string */
8e50ff0… jan.nijtmans 1085 static int
8e50ff0… jan.nijtmans 1086 dirent_wcstombs_s(
8e50ff0… jan.nijtmans 1087 size_t *pReturnValue,
8e50ff0… jan.nijtmans 1088 char *mbstr,
a374824… jan.nijtmans 1089 size_t sizeInBytes, /* max size of mbstr */
8e50ff0… jan.nijtmans 1090 const wchar_t *wcstr,
8e50ff0… jan.nijtmans 1091 size_t count)
8e50ff0… jan.nijtmans 1092 {
8e50ff0… jan.nijtmans 1093 int error;
8e50ff0… jan.nijtmans 1094
8e50ff0… jan.nijtmans 1095 #if defined(_MSC_VER) && _MSC_VER >= 1400
8e50ff0… jan.nijtmans 1096
8e50ff0… jan.nijtmans 1097 /* Microsoft Visual Studio 2005 or later */
8e50ff0… jan.nijtmans 1098 error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
8e50ff0… jan.nijtmans 1099
8e50ff0… jan.nijtmans 1100 #else
8e50ff0… jan.nijtmans 1101
8e50ff0… jan.nijtmans 1102 /* Older Visual Studio or non-Microsoft compiler */
8e50ff0… jan.nijtmans 1103 size_t n;
8e50ff0… jan.nijtmans 1104
a374824… jan.nijtmans 1105 /* Convert to multi-byte string (or count the number of bytes needed) */
a374824… jan.nijtmans 1106 n = wcstombs (mbstr, wcstr, sizeInBytes);
a374824… jan.nijtmans 1107 if (!mbstr || n < count) {
8e50ff0… jan.nijtmans 1108
8e50ff0… jan.nijtmans 1109 /* Zero-terminate output buffer */
a374824… jan.nijtmans 1110 if (mbstr && sizeInBytes) {
a374824… jan.nijtmans 1111 if (n >= sizeInBytes) {
a374824… jan.nijtmans 1112 n = sizeInBytes - 1;
a374824… jan.nijtmans 1113 }
8e50ff0… jan.nijtmans 1114 mbstr[n] = '\0';
8e50ff0… jan.nijtmans 1115 }
8e50ff0… jan.nijtmans 1116
b66b99c… jan.nijtmans 1117 /* Length of resulting multi-bytes string WITH zero-terminator */
8e50ff0… jan.nijtmans 1118 if (pReturnValue) {
8e50ff0… jan.nijtmans 1119 *pReturnValue = n + 1;
8e50ff0… jan.nijtmans 1120 }
8e50ff0… jan.nijtmans 1121
8e50ff0… jan.nijtmans 1122 /* Success */
8e50ff0… jan.nijtmans 1123 error = 0;
8e50ff0… jan.nijtmans 1124
8e50ff0… jan.nijtmans 1125 } else {
8e50ff0… jan.nijtmans 1126
8e50ff0… jan.nijtmans 1127 /* Cannot convert string */
8e50ff0… jan.nijtmans 1128 error = 1;
8e50ff0… jan.nijtmans 1129
8e50ff0… jan.nijtmans 1130 }
8e50ff0… jan.nijtmans 1131
8e50ff0… jan.nijtmans 1132 #endif
8e50ff0… jan.nijtmans 1133
8e50ff0… jan.nijtmans 1134 return error;
8e50ff0… jan.nijtmans 1135 }
8e50ff0… jan.nijtmans 1136
8e50ff0… jan.nijtmans 1137 /* Set errno variable */
8e50ff0… jan.nijtmans 1138 static void
8e50ff0… jan.nijtmans 1139 dirent_set_errno(
8e50ff0… jan.nijtmans 1140 int error)
8e50ff0… jan.nijtmans 1141 {
a374824… jan.nijtmans 1142 #if defined(_MSC_VER) && _MSC_VER >= 1400
8e50ff0… jan.nijtmans 1143
b9f0c78… jan.nijtmans 1144 /* Microsoft Visual Studio 2005 and later */
8e50ff0… jan.nijtmans 1145 _set_errno (error);
8e50ff0… jan.nijtmans 1146
8e50ff0… jan.nijtmans 1147 #else
8e50ff0… jan.nijtmans 1148
b9f0c78… jan.nijtmans 1149 /* Non-Microsoft compiler or older Microsoft compiler */
8e50ff0… jan.nijtmans 1150 errno = error;
8e50ff0… jan.nijtmans 1151
8e50ff0… jan.nijtmans 1152 #endif
f460839… jan.nijtmans 1153 }
f460839… jan.nijtmans 1154
fb07d86… jan.nijtmans 1155
fb07d86… jan.nijtmans 1156 #ifdef __cplusplus
fb07d86… jan.nijtmans 1157 }
fb07d86… jan.nijtmans 1158 #endif
fb07d86… jan.nijtmans 1159 #endif /*DIRENT_H*/
f460839… jan.nijtmans 1160

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button