]>
git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/lib/librte_eal/windows/include/dirent.h
1 /* SPDX-License-Identifier: MIT
2 * Dirent interface for Microsoft Visual Studio
4 * Copyright (C) 2006-2012 Toni Ronkko
5 * https://github.com/tronkko/dirent
12 * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
13 * Windows Sockets 2.0.
15 #ifndef WIN32_LEAN_AND_MEAN
16 # define WIN32_LEAN_AND_MEAN
27 #include <sys/types.h>
31 /* Maximum length of file name */
32 #if !defined(PATH_MAX)
33 # define PATH_MAX MAX_PATH
36 /* File type flags for d_type */
38 #define DT_REG S_IFREG
39 #define DT_DIR S_IFDIR
40 #define DT_CHR S_IFCHR
43 * File type macros. Note that block devices, sockets and links cannot be
44 * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
45 * only defined for compatibility. These macros should always return false
49 # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
52 # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
55 /* Wide-character version */
61 unsigned short d_reclen
;
63 /* Length of name without \0 */
70 wchar_t d_name
[PATH_MAX
];
72 typedef struct _wdirent _wdirent
;
75 /* Current directory entry */
78 /* Private file data */
79 WIN32_FIND_DATAW data
;
81 /* True if data is valid */
84 /* Win32 search handle */
87 /* Initial directory name */
90 typedef struct _WDIR _WDIR
;
92 static _WDIR
*_wopendir(const wchar_t *dirname
);
93 static int _wclosedir(_WDIR
*dirp
);
95 /* For compatibility with Symbian */
96 #define wdirent _wdirent
98 #define wopendir _wopendir
99 #define wclosedir _wclosedir
101 /* Multi-byte character versions */
107 unsigned short d_reclen
;
109 /* Length of name without \0 */
116 char d_name
[PATH_MAX
];
118 typedef struct dirent dirent
;
124 typedef struct DIR DIR;
126 static DIR *opendir(const char *dirname
);
127 static struct dirent
*readdir(DIR *dirp
);
128 static int closedir(DIR *dirp
);
130 /* Internal utility functions */
131 static WIN32_FIND_DATAW
*dirent_first(_WDIR
*dirp
);
132 static WIN32_FIND_DATAW
*dirent_next(_WDIR
*dirp
);
134 static int dirent_mbstowcs_s(
135 size_t *pReturnValue
,
141 static int dirent_wcstombs_s(
142 size_t *pReturnValue
,
145 const wchar_t *wcstr
,
148 static void dirent_set_errno(int error
);
151 * Open directory stream DIRNAME for read and return a pointer to the
152 * internal working area that is used to retrieve individual directory
156 _wopendir(const wchar_t *dirname
)
161 /* Must have directory name */
162 if (dirname
== NULL
|| dirname
[0] == '\0') {
163 dirent_set_errno(ENOENT
);
167 /* Allocate new _WDIR structure */
168 dirp
= (_WDIR
*)malloc(sizeof(struct _WDIR
));
172 /* Reset _WDIR structure */
173 dirp
->handle
= INVALID_HANDLE_VALUE
;
177 /* Compute the length of full path plus zero terminator
179 * Note that on WinRT there's no way to convert relative paths
180 * into absolute paths, so just assume its an absolute path.
182 #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
185 n
= GetFullPathNameW(dirname
, 0, NULL
, NULL
);
188 /* Allocate room for absolute directory name and search
191 dirp
->patt
= (wchar_t *)malloc(sizeof(wchar_t) * n
+ 16);
193 /* Convert relative directory name to an
194 * absolute one. This allows rewinddir() to
195 * function correctly even when current working
196 * directory is changed between opendir()
199 * Note that on WinRT there's no way to convert
200 * relative paths into absolute paths, so just
201 * assume its an absolute path.
203 #if defined(WINAPI_FAMILY) && \
204 (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
205 wcsncpy_s(dirp
->patt
, n
+ 1, dirname
, n
);
207 n
= GetFullPathNameW(dirname
, n
, dirp
->patt
, NULL
);
212 /* Append search pattern \* to the directory
216 if (dirp
->patt
< p
) {
221 /* Directory ends in path separator,
228 /* Directory name doesn't end in path
237 /* Open directory stream and retrieve the first
240 if (dirent_first(dirp
)) {
241 /* Directory stream opened successfully */
244 /* Cannot retrieve first entry */
246 dirent_set_errno(ENOENT
);
250 /* Cannot retrieve full path name */
251 dirent_set_errno(ENOENT
);
256 /* Cannot allocate memory for search pattern */
261 /* Cannot allocate _WDIR structure */
265 /* Clean up in case of error */
275 * Close directory stream opened by opendir() function.
276 * This invalidates the DIR structure as well as any directory
277 * entry read previously by _wreaddir().
280 _wclosedir(_WDIR
*dirp
)
285 /* Release search handle */
286 if (dirp
->handle
!= INVALID_HANDLE_VALUE
) {
287 FindClose(dirp
->handle
);
288 dirp
->handle
= INVALID_HANDLE_VALUE
;
291 /* Release search pattern */
297 /* Release directory structure */
302 /* Invalid directory stream */
303 dirent_set_errno(EBADF
);
309 /* Get first directory entry (internal) */
310 static WIN32_FIND_DATAW
*
311 dirent_first(_WDIR
*dirp
)
313 WIN32_FIND_DATAW
*datap
;
315 /* Open directory and retrieve the first entry */
316 dirp
->handle
= FindFirstFileExW(
317 dirp
->patt
, FindExInfoStandard
, &dirp
->data
,
318 FindExSearchNameMatch
, NULL
, 0);
319 if (dirp
->handle
!= INVALID_HANDLE_VALUE
) {
321 /* a directory entry is now waiting in memory */
327 /* Failed to re-open directory: no directory entry in memory */
335 /* Get next directory entry (internal) */
336 static WIN32_FIND_DATAW
*
337 dirent_next(_WDIR
*dirp
)
341 /* Get next directory entry */
342 if (dirp
->cached
!= 0) {
344 /* A valid directory entry already in memory */
348 } else if (dirp
->handle
!= INVALID_HANDLE_VALUE
) {
350 /* Get the next directory entry from stream */
351 if (FindNextFileW(dirp
->handle
, &dirp
->data
) != FALSE
) {
355 /* The very last entry has been processed
356 *or an error occurred
358 FindClose(dirp
->handle
);
359 dirp
->handle
= INVALID_HANDLE_VALUE
;
365 /* End of directory stream reached */
374 * Open directory stream using plain old C-string.
377 opendir(const char *dirname
)
382 /* Must have directory name */
383 if (dirname
== NULL
|| dirname
[0] == '\0') {
384 dirent_set_errno(ENOENT
);
388 /* Allocate memory for DIR structure */
389 dirp
= (DIR *)malloc(sizeof(struct DIR));
391 wchar_t wname
[PATH_MAX
];
394 /* Convert directory name to wide-character string */
395 error
= dirent_mbstowcs_s(&n
, wname
, PATH_MAX
,
399 /* Open directory stream using wide-character name */
400 dirp
->wdirp
= _wopendir(wname
);
402 /* Directory stream opened */
405 /* Failed to open directory stream */
411 * Cannot convert file name to wide-character string.
412 * This occurs if the string contains invalid multi-byte
413 * sequences or the output buffer is too small to
414 * contain the resulting string.
420 /* Cannot allocate DIR structure */
424 /* Clean up in case of error */
434 * Read next directory entry.
436 * When working with text consoles, please note that file names
437 * returned by readdir() are represented in the default ANSI code
438 * page while any output toconsole is typically formatted on another
439 * code page. Thus, non-ASCII characters in file names will not usually
440 * display correctly on console. The problem can be fixed in two ways:
441 * (1) change the character set of console to 1252 using chcp utility
442 * and use Lucida Console font, or (2) use _cprintf function when
443 * writing to console. The _cprinf() will re-encode ANSI strings to the
444 * console code page so many non-ASCII characters will display correctly.
446 static struct dirent
*
449 WIN32_FIND_DATAW
*datap
;
452 /* Read next directory entry */
453 datap
= dirent_next(dirp
->wdirp
);
458 /* Attempt to convert file name to multi-byte string */
459 error
= dirent_wcstombs_s(&n
, dirp
->ent
.d_name
,
460 PATH_MAX
, datap
->cFileName
, PATH_MAX
);
463 * If the file name cannot be represented by a multi-byte
464 * string, then attempt to use old 8+3 file name.
465 * This allows traditional Unix-code to access some file
466 * names despite of unicode characters, although file names
467 * may seem unfamiliar to the user.
469 * Be ware that the code below cannot come up with a short
470 * file name unless the file system provides one. At least
471 * VirtualBox shared folders fail to do this.
473 if (error
&& datap
->cAlternateFileName
[0] != '\0') {
474 error
= dirent_wcstombs_s(
475 &n
, dirp
->ent
.d_name
, PATH_MAX
,
476 datap
->cAlternateFileName
, PATH_MAX
);
482 /* Initialize directory entry for return */
485 /* Length of file name excluding zero terminator */
486 entp
->d_namlen
= n
- 1;
488 /* File attributes */
489 attr
= datap
->dwFileAttributes
;
490 if ((attr
& FILE_ATTRIBUTE_DEVICE
) != 0)
491 entp
->d_type
= DT_CHR
;
492 else if ((attr
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
493 entp
->d_type
= DT_DIR
;
495 entp
->d_type
= DT_REG
;
497 /* Reset dummy fields */
499 entp
->d_reclen
= sizeof(struct dirent
);
503 * Cannot convert file name to multi-byte string so
504 * construct an erroneous directory entry and return
505 * that. Note that we cannot return NULL as that would
506 * stop the processing of directory entries completely.
509 entp
->d_name
[0] = '?';
510 entp
->d_name
[1] = '\0';
512 entp
->d_type
= DT_UNKNOWN
;
518 /* No more directory entries */
526 * Close directory stream.
534 /* Close wide-character directory stream */
535 ok
= _wclosedir(dirp
->wdirp
);
538 /* Release multi-byte character version */
543 /* Invalid directory stream */
544 dirent_set_errno(EBADF
);
551 /* Convert multi-byte string to wide character string */
554 size_t *pReturnValue
,
562 #if defined(_MSC_VER) && _MSC_VER >= 1400
563 /* Microsoft Visual Studio 2005 or later */
564 error
= mbstowcs_s(pReturnValue
, wcstr
,
565 sizeInWords
, mbstr
, count
);
568 /* Older Visual Studio or non-Microsoft compiler */
571 /* Convert to wide-character string (or count characters) */
572 n
= mbstowcs(wcstr
, mbstr
, sizeInWords
);
573 if (!wcstr
|| n
< count
) {
575 /* Zero-terminate output buffer */
576 if (wcstr
&& sizeInWords
) {
577 if (n
>= sizeInWords
)
582 /* Length of resuting multi-byte string WITH zero
586 *pReturnValue
= n
+ 1;
593 /* Could not convert string */
602 /* Convert wide-character string to multi-byte string */
605 size_t *pReturnValue
,
607 size_t sizeInBytes
, /* max size of mbstr */
608 const wchar_t *wcstr
,
613 #if defined(_MSC_VER) && _MSC_VER >= 1400
614 /* Microsoft Visual Studio 2005 or later */
615 error
= wcstombs_s(pReturnValue
, mbstr
, sizeInBytes
, wcstr
, count
);
617 /* Older Visual Studio or non-Microsoft compiler */
620 /* Convert to multi-byte string
621 * (or count the number of bytes needed)
623 n
= wcstombs(mbstr
, wcstr
, sizeInBytes
);
624 if (!mbstr
|| n
< count
) {
625 /* Zero-terminate output buffer */
626 if (mbstr
&& sizeInBytes
) {
627 if (n
>= sizeInBytes
)
631 /* Length of resulting multi-bytes string WITH
635 *pReturnValue
= n
+ 1;
639 /* Cannot convert string */
647 /* Set errno variable */
649 dirent_set_errno(int error
)
651 #if defined(_MSC_VER) && _MSC_VER >= 1400
652 /* Microsoft Visual Studio 2005 and later */
656 /* Non-Microsoft compiler or older Microsoft compiler */