Merge pull request #26337 from luzpaz/typos-addon
[xbmc.git] / xbmc / platform / win32 / dirent.h
blob20e38d8d5c7f087aebc9e2e3867f731c55f4693c
1 /*
2 * dirent.h - dirent API for Microsoft Visual Studio
4 * Copyright (C) 2006-2012 Toni Ronkko
6 * SPDX-License-Identifier: MIT
7 * See LICENSES/README.md for more information.
9 * Version 1.13, Dec 12 2012, Toni Ronkko
10 * Use traditional 8+3 file name if the name cannot be represented in the
11 * default ANSI code page. Now compiles again with MSVC 6.0. Thanks to
12 * Konstantin Khomoutov for testing.
14 * Version 1.12.1, Oct 1 2012, Toni Ronkko
15 * Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with
16 * capital W) in order to maintain compatibility with MingW.
18 * Version 1.12, Sep 30 2012, Toni Ronkko
19 * Define PATH_MAX and NAME_MAX. Added wide-character variants _wDIR,
20 * _wdirent, _wopendir(), _wreaddir(), _wclosedir() and _wrewinddir().
21 * Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code.
23 * Do not include windows.h. This allows dirent.h to be integrated more
24 * easily into programs using winsock. Thanks to Fernando Azaldegui.
26 * Version 1.11, Mar 15, 2011, Toni Ronkko
27 * Defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0.
29 * Version 1.10, Aug 11, 2010, Toni Ronkko
30 * Added d_type and d_namlen fields to dirent structure. The former is
31 * especially useful for determining whether directory entry represents a
32 * file or a directory. For more information, see
33 * http://www.delorie.com/gnu/docs/glibc/libc_270.html
35 * Improved conformance to the standards. For example, errno is now set
36 * properly on failure and assert() is never used. Thanks to Peter Brockam
37 * for suggestions.
39 * Fixed a bug in rewinddir(): when using relative directory names, change
40 * of working directory no longer causes rewinddir() to fail.
42 * Version 1.9, Dec 15, 2009, John Cunningham
43 * Added rewinddir member function
45 * Version 1.8, Jan 18, 2008, Toni Ronkko
46 * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
47 * between multi-byte and unicode representations. This makes the
48 * code simpler and also allows the code to be compiled under MingW. Thanks
49 * to Azriel Fasten for the suggestion.
51 * Mar 4, 2007, Toni Ronkko
52 * Bug fix: due to the strncpy_s() function this file only compiled in
53 * Visual Studio 2005. Using the new string functions only when the
54 * compiler version allows.
56 * Nov 2, 2006, Toni Ronkko
57 * Major update: removed support for Watcom C, MS-DOS and Turbo C to
58 * simplify the file, updated the code to compile cleanly on Visual
59 * Studio 2005 with both unicode and multi-byte character strings,
60 * removed rewinddir() as it had a bug.
62 * Aug 20, 2006, Toni Ronkko
63 * Removed all remarks about MSVC 1.0, which is antiqued now. Simplified
64 * comments by removing SGML tags.
66 * May 14 2002, Toni Ronkko
67 * Embedded the function definitions directly to the header so that no
68 * source modules need to be included in the Visual Studio project. Removed
69 * all the dependencies to other projects so that this header file can be
70 * used independently.
72 * May 28 1998, Toni Ronkko
73 * First version.
76 #pragma once
78 #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
79 # define _X86_
80 #endif
81 #include <stdio.h>
82 #include <stdarg.h>
83 #include <windef.h>
84 #include <winbase.h>
85 #include <wchar.h>
86 #include <string.h>
87 #include <stdlib.h>
88 #include <malloc.h>
89 #include <sys/types.h>
90 #include <sys/stat.h>
91 #include <errno.h>
93 /* Indicates that d_type field is available in dirent structure */
94 #define _DIRENT_HAVE_D_TYPE
96 /* Indicates that d_namlen field is available in dirent structure */
97 #define _DIRENT_HAVE_D_NAMLEN
99 /* Entries missing from MSVC 6.0 */
100 #if !defined(FILE_ATTRIBUTE_DEVICE)
101 # define FILE_ATTRIBUTE_DEVICE 0x40
102 #endif
104 /* File type and permission flags for stat() */
105 #if !defined(S_IFMT)
106 # define S_IFMT _S_IFMT /* File type mask */
107 #endif
108 #if !defined(S_IFDIR)
109 # define S_IFDIR _S_IFDIR /* Directory */
110 #endif
111 #if !defined(S_IFCHR)
112 # define S_IFCHR _S_IFCHR /* Character device */
113 #endif
114 #if !defined(S_IFFIFO)
115 # define S_IFFIFO _S_IFFIFO /* Pipe */
116 #endif
117 #if !defined(S_IFREG)
118 # define S_IFREG _S_IFREG /* Regular file */
119 #endif
120 #if !defined(S_IREAD)
121 # define S_IREAD _S_IREAD /* Read permission */
122 #endif
123 #if !defined(S_IWRITE)
124 # define S_IWRITE _S_IWRITE /* Write permission */
125 #endif
126 #if !defined(S_IEXEC)
127 # define S_IEXEC _S_IEXEC /* Execute permission */
128 #endif
129 #if !defined(S_IFIFO)
130 # define S_IFIFO _S_IFIFO /* Pipe */
131 #endif
132 #if !defined(S_IFBLK)
133 # define S_IFBLK 0 /* Block device */
134 #endif
135 #if !defined(S_IFLNK)
136 # define S_IFLNK 0 /* Link */
137 #endif
138 #if !defined(S_IFSOCK)
139 # define S_IFSOCK 0 /* Socket */
140 #endif
142 #if defined(_MSC_VER)
143 # define S_IRUSR S_IREAD /* Read user */
144 # define S_IWUSR S_IWRITE /* Write user */
145 # define S_IXUSR 0 /* Execute user */
146 # define S_IRGRP 0 /* Read group */
147 # define S_IWGRP 0 /* Write group */
148 # define S_IXGRP 0 /* Execute group */
149 # define S_IROTH 0 /* Read others */
150 # define S_IWOTH 0 /* Write others */
151 # define S_IXOTH 0 /* Execute others */
152 #endif
154 /* Maximum length of file name */
155 #if !defined(PATH_MAX)
156 # define PATH_MAX MAX_PATH
157 #endif
158 #if !defined(FILENAME_MAX)
159 # define FILENAME_MAX MAX_PATH
160 #endif
161 #if !defined(NAME_MAX)
162 # define NAME_MAX FILENAME_MAX
163 #endif
165 /* File type flags for d_type */
166 #define DT_UNKNOWN 0
167 #define DT_REG S_IFREG
168 #define DT_DIR S_IFDIR
169 #define DT_FIFO S_IFIFO
170 #define DT_SOCK S_IFSOCK
171 #define DT_CHR S_IFCHR
172 #define DT_BLK S_IFBLK
174 /* Macros for converting between st_mode and d_type */
175 #define IFTODT(mode) ((mode) & S_IFMT)
176 #define DTTOIF(type) (type)
179 * File type macros. Note that block devices, sockets and links cannot be
180 * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
181 * only defined for compatibility. These macros should always return false
182 * on Windows.
184 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
185 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
186 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
187 #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
188 #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
189 #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
190 #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
192 /* Return the exact length of d_namlen without zero terminator */
193 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
195 /* Return number of bytes needed to store d_namlen */
196 #define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1)
199 #ifdef __cplusplus
200 extern "C" {
201 #endif
204 /* Wide-character version */
205 struct _wdirent {
206 long d_ino; /* Always zero */
207 unsigned short d_reclen; /* Structure size */
208 size_t d_namlen; /* Length of name without \0 */
209 int d_type; /* File type */
210 wchar_t d_name[PATH_MAX + 1]; /* File name */
212 typedef struct _wdirent _wdirent;
214 struct _WDIR {
215 struct _wdirent ent; /* Current directory entry */
216 WIN32_FIND_DATAW data; /* Private file data */
217 int cached; /* True if data is valid */
218 HANDLE handle; /* Win32 search handle */
219 wchar_t *patt; /* Initial directory name */
221 typedef struct _WDIR _WDIR;
223 static _WDIR *_wopendir (const wchar_t *dirname);
224 static struct _wdirent *_wreaddir (_WDIR *dirp);
225 static int _wclosedir (_WDIR *dirp);
226 static void _wrewinddir (_WDIR* dirp);
229 /* For compatibility with Symbian */
230 #define wdirent _wdirent
231 #define WDIR _WDIR
232 #define wopendir _wopendir
233 #define wreaddir _wreaddir
234 #define wclosedir _wclosedir
235 #define wrewinddir _wrewinddir
238 /* Multi-byte character versions */
239 struct dirent {
240 long d_ino; /* Always zero */
241 unsigned short d_reclen; /* Structure size */
242 size_t d_namlen; /* Length of name without \0 */
243 int d_type; /* File type */
244 char d_name[PATH_MAX + 1]; /* File name */
246 typedef struct dirent dirent;
248 struct DIR {
249 struct dirent ent;
250 struct _WDIR *wdirp;
252 typedef struct DIR DIR;
254 static DIR *opendir (const char *dirname);
255 static struct dirent *readdir (DIR *dirp);
256 static int closedir (DIR *dirp);
257 static void rewinddir (DIR* dirp);
260 /* Internal utility functions */
261 static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
262 static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
264 static int dirent_mbstowcs_s(
265 size_t *pReturnValue,
266 wchar_t *wcstr,
267 size_t sizeInWords,
268 const char *mbstr,
269 size_t count);
271 static int dirent_wcstombs_s(
272 size_t *pReturnValue,
273 char *mbstr,
274 size_t sizeInBytes,
275 const wchar_t *wcstr,
276 size_t count);
278 static void dirent_set_errno (int error);
281 * Open directory stream DIRNAME for read and return a pointer to the
282 * internal working area that is used to retrieve individual directory
283 * entries.
285 static _WDIR*
286 _wopendir(
287 const wchar_t *dirname)
289 _WDIR *dirp = NULL;
290 int error;
292 /* Must have directory name */
293 if (dirname == NULL || dirname[0] == '\0') {
294 dirent_set_errno (ENOENT);
295 return NULL;
298 /* Allocate new _WDIR structure */
299 dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
300 if (dirp != NULL) {
301 DWORD n;
303 /* Reset _WDIR structure */
304 dirp->handle = INVALID_HANDLE_VALUE;
305 dirp->patt = NULL;
306 dirp->cached = 0;
308 /* Compute the length of full path plus zero terminator */
309 n = GetFullPathNameW (dirname, 0, NULL, NULL);
311 /* Allocate room for absolute directory name and search pattern */
312 dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
313 if (dirp->patt) {
316 * Convert relative directory name to an absolute one. This
317 * allows rewinddir() to function correctly even when current
318 * working directory is changed between opendir() and rewinddir().
320 n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
321 if (n > 0) {
322 wchar_t *p;
324 /* Append search pattern \* to the directory name */
325 p = dirp->patt + n;
326 if (dirp->patt < p) {
327 switch (p[-1]) {
328 case '\\':
329 case '/':
330 case ':':
331 /* Directory ends in path separator, e.g. c:\temp\ */
332 /*NOP*/;
333 break;
335 default:
336 /* Directory name doesn't end in path separator */
337 *p++ = '\\';
340 *p++ = '*';
341 *p = '\0';
343 /* Open directory stream and retrieve the first entry */
344 if (dirent_first (dirp)) {
345 /* Directory stream opened successfully */
346 error = 0;
347 } else {
348 /* Cannot retrieve first entry */
349 error = 1;
350 dirent_set_errno (ENOENT);
353 } else {
354 /* Cannot retrieve full path name */
355 dirent_set_errno (ENOENT);
356 error = 1;
359 } else {
360 /* Cannot allocate memory for search pattern */
361 error = 1;
364 } else {
365 /* Cannot allocate _WDIR structure */
366 error = 1;
369 /* Clean up in case of error */
370 if (error && dirp) {
371 _wclosedir (dirp);
372 dirp = NULL;
375 return dirp;
379 * Read next directory entry. The directory entry is returned in dirent
380 * structure in the d_name field. Individual directory entries returned by
381 * this function include regular files, sub-directories, pseudo-directories
382 * "." and ".." as well as volume labels, hidden files and system files.
384 static struct _wdirent*
385 _wreaddir(
386 _WDIR *dirp)
388 WIN32_FIND_DATAW *datap;
389 struct _wdirent *entp;
391 /* Read next directory entry */
392 datap = dirent_next (dirp);
393 if (datap) {
394 size_t n;
395 DWORD attr;
397 /* Pointer to directory entry to return */
398 entp = &dirp->ent;
401 * Copy file name as wide-character string. If the file name is too
402 * long to fit in to the destination buffer, then truncate file name
403 * to PATH_MAX characters and zero-terminate the buffer.
405 n = 0;
406 while (n < PATH_MAX && datap->cFileName[n] != 0) {
407 entp->d_name[n] = datap->cFileName[n];
408 n++;
410 dirp->ent.d_name[n] = 0;
412 /* Length of file name excluding zero terminator */
413 entp->d_namlen = n;
415 /* File type */
416 attr = datap->dwFileAttributes;
417 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
418 entp->d_type = DT_CHR;
419 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
420 entp->d_type = DT_DIR;
421 } else {
422 entp->d_type = DT_REG;
425 /* Reset dummy fields */
426 entp->d_ino = 0;
427 entp->d_reclen = sizeof (struct _wdirent);
429 } else {
431 /* Last directory entry read */
432 entp = NULL;
436 return entp;
440 * Close directory stream opened by opendir() function. This invalidates the
441 * DIR structure as well as any directory entry read previously by
442 * _wreaddir().
444 static int
445 _wclosedir(
446 _WDIR *dirp)
448 int ok;
449 if (dirp) {
451 /* Release search handle */
452 if (dirp->handle != INVALID_HANDLE_VALUE) {
453 FindClose (dirp->handle);
454 dirp->handle = INVALID_HANDLE_VALUE;
457 /* Release search pattern */
458 if (dirp->patt) {
459 free (dirp->patt);
460 dirp->patt = NULL;
463 /* Release directory structure */
464 free (dirp);
465 ok = /*success*/0;
467 } else {
468 /* Invalid directory stream */
469 dirent_set_errno (EBADF);
470 ok = /*failure*/-1;
472 return ok;
476 * Rewind directory stream such that _wreaddir() returns the very first
477 * file name again.
479 static void
480 _wrewinddir(
481 _WDIR* dirp)
483 if (dirp) {
484 /* Release existing search handle */
485 if (dirp->handle != INVALID_HANDLE_VALUE) {
486 FindClose (dirp->handle);
489 /* Open new search handle */
490 dirent_first (dirp);
494 /* Get first directory entry (internal) */
495 static WIN32_FIND_DATAW*
496 dirent_first(
497 _WDIR *dirp)
499 WIN32_FIND_DATAW *datap;
501 /* Open directory and retrieve the first entry */
502 dirp->handle = FindFirstFileW (dirp->patt, &dirp->data);
503 if (dirp->handle != INVALID_HANDLE_VALUE) {
505 /* a directory entry is now waiting in memory */
506 datap = &dirp->data;
507 dirp->cached = 1;
509 } else {
511 /* Failed to re-open directory: no directory entry in memory */
512 dirp->cached = 0;
513 datap = NULL;
516 return datap;
519 /* Get next directory entry (internal) */
520 static WIN32_FIND_DATAW*
521 dirent_next(
522 _WDIR *dirp)
524 WIN32_FIND_DATAW *p;
526 /* Get next directory entry */
527 if (dirp->cached != 0) {
529 /* A valid directory entry already in memory */
530 p = &dirp->data;
531 dirp->cached = 0;
533 } else if (dirp->handle != INVALID_HANDLE_VALUE) {
535 /* Get the next directory entry from stream */
536 if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
537 /* Got a file */
538 p = &dirp->data;
539 } else {
540 /* The very last entry has been processed or an error occurred */
541 FindClose (dirp->handle);
542 dirp->handle = INVALID_HANDLE_VALUE;
543 p = NULL;
546 } else {
548 /* End of directory stream reached */
549 p = NULL;
553 return p;
557 * Open directory stream using plain old C-string.
559 static DIR*
560 opendir(
561 const char *dirname)
563 struct DIR *dirp;
564 int error;
566 /* Must have directory name */
567 if (dirname == NULL || dirname[0] == '\0') {
568 dirent_set_errno (ENOENT);
569 return NULL;
572 /* Allocate memory for DIR structure */
573 dirp = (DIR*) malloc (sizeof (struct DIR));
574 if (dirp) {
575 wchar_t wname[PATH_MAX + 1];
576 size_t n;
578 /* Convert directory name to wide-character string */
579 error = dirent_mbstowcs_s(
580 &n, wname, PATH_MAX + 1, dirname, PATH_MAX);
581 if (!error) {
583 /* Open directory stream using wide-character name */
584 dirp->wdirp = _wopendir (wname);
585 if (dirp->wdirp) {
586 /* Directory stream opened */
587 error = 0;
588 } else {
589 /* Failed to open directory stream */
590 error = 1;
593 } else {
595 * Cannot convert file name to wide-character string. This
596 * occurs if the string contains invalid multi-byte sequences or
597 * the output buffer is too small to contain the resulting
598 * string.
600 error = 1;
603 } else {
604 /* Cannot allocate DIR structure */
605 error = 1;
608 /* Clean up in case of error */
609 if (error && dirp) {
610 free (dirp);
611 dirp = NULL;
614 return dirp;
618 * Read next directory entry.
620 * When working with text consoles, please note that file names returned by
621 * readdir() are represented in the default ANSI code page while any output to
622 * console is typically formatted on another code page. Thus, non-ASCII
623 * characters in file names will not usually display correctly on console. The
624 * problem can be fixed in two ways: (1) change the character set of console
625 * to 1252 using chcp utility and use Lucida Console font, or (2) use
626 * _cprintf function when writing to console. The _cprinf() will re-encode
627 * ANSI strings to the console code page so many non-ASCII characters will
628 * display correctly.
630 static struct dirent*
631 readdir(
632 DIR *dirp)
634 WIN32_FIND_DATAW *datap;
635 struct dirent *entp;
637 /* Read next directory entry */
638 datap = dirent_next (dirp->wdirp);
639 if (datap) {
640 size_t n;
641 int error;
643 /* Attempt to convert file name to multi-byte string */
644 error = dirent_wcstombs_s(
645 &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);
648 * If the file name cannot be represented by a multi-byte string,
649 * then attempt to use old 8+3 file name. This allows traditional
650 * Unix-code to access some file names despite of unicode
651 * characters, although file names may seem unfamiliar to the user.
653 * Be ware that the code below cannot come up with a short file
654 * name unless the file system provides one. At least
655 * VirtualBox shared folders fail to do this.
657 if (error && datap->cAlternateFileName[0] != '\0') {
658 error = dirent_wcstombs_s(
659 &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
660 sizeof (datap->cAlternateFileName) /
661 sizeof (datap->cAlternateFileName[0]));
664 if (!error) {
665 DWORD attr;
667 /* Initialize directory entry for return */
668 entp = &dirp->ent;
670 /* Length of file name excluding zero terminator */
671 entp->d_namlen = n - 1;
673 /* File attributes */
674 attr = datap->dwFileAttributes;
675 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
676 entp->d_type = DT_CHR;
677 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
678 entp->d_type = DT_DIR;
679 } else {
680 entp->d_type = DT_REG;
683 /* Reset dummy fields */
684 entp->d_ino = 0;
685 entp->d_reclen = sizeof (struct dirent);
687 } else {
689 * Cannot convert file name to multi-byte string so construct
690 * an erroneous directory entry and return that. Note that
691 * we cannot return NULL as that would stop the processing
692 * of directory entries completely.
694 entp = &dirp->ent;
695 entp->d_name[0] = '?';
696 entp->d_name[1] = '\0';
697 entp->d_namlen = 1;
698 entp->d_type = DT_UNKNOWN;
699 entp->d_ino = 0;
700 entp->d_reclen = 0;
703 } else {
704 /* No more directory entries */
705 entp = NULL;
708 return entp;
712 * Close directory stream.
714 static int
715 closedir(
716 DIR *dirp)
718 int ok;
719 if (dirp) {
721 /* Close wide-character directory stream */
722 ok = _wclosedir (dirp->wdirp);
723 dirp->wdirp = NULL;
725 /* Release multi-byte character version */
726 free (dirp);
728 } else {
730 /* Invalid directory stream */
731 dirent_set_errno (EBADF);
732 ok = /*failure*/-1;
735 return ok;
739 * Rewind directory stream to beginning.
741 static void
742 rewinddir(
743 DIR* dirp)
745 /* Rewind wide-character string directory stream */
746 _wrewinddir (dirp->wdirp);
749 /* Convert multi-byte string to wide character string */
750 static int
751 dirent_mbstowcs_s(
752 size_t *pReturnValue,
753 wchar_t *wcstr,
754 size_t sizeInWords,
755 const char *mbstr,
756 size_t count)
758 int error;
760 #if defined(_MSC_VER) && _MSC_VER >= 1400
762 /* Microsoft Visual Studio 2005 or later */
763 error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
765 #else
767 /* Older Visual Studio or non-Microsoft compiler */
768 size_t n;
770 /* Convert to wide-character string */
771 n = mbstowcs (wcstr, mbstr, count);
772 if (n < sizeInWords) {
774 /* Zero-terminate output buffer */
775 if (wcstr) {
776 wcstr[n] = 0;
779 /* Length of resulting multi-byte string WITH zero terminator */
780 if (pReturnValue) {
781 *pReturnValue = n + 1;
784 /* Success */
785 error = 0;
787 } else {
789 /* Could not convert string */
790 error = 1;
794 #endif
796 return error;
799 /* Convert wide-character string to multi-byte string */
800 static int
801 dirent_wcstombs_s(
802 size_t *pReturnValue,
803 char *mbstr,
804 size_t sizeInBytes,
805 const wchar_t *wcstr,
806 size_t count)
808 int error;
810 #if defined(_MSC_VER) && _MSC_VER >= 1400
812 /* Microsoft Visual Studio 2005 or later */
813 error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
815 #else
817 /* Older Visual Studio or non-Microsoft compiler */
818 size_t n;
820 /* Convert to multi-byte string */
821 n = wcstombs (mbstr, wcstr, count);
822 if (n < sizeInBytes) {
824 /* Zero-terminate output buffer */
825 if (mbstr) {
826 mbstr[n] = '\0';
829 /* Length of resulting multi-bytes string WITH zero-terminator */
830 if (pReturnValue) {
831 *pReturnValue = n + 1;
834 /* Success */
835 error = 0;
837 } else {
839 /* Cannot convert string */
840 error = 1;
844 #endif
846 return error;
849 /* Set errno variable */
850 static void
851 dirent_set_errno(
852 int error)
854 #if defined(_MSC_VER)
856 /* Microsoft Visual Studio */
857 _set_errno (error);
859 #else
861 /* Non-Microsoft compiler */
862 errno = error;
864 #endif
868 #ifdef __cplusplus
870 #endif