My Project
dirent.h
1 #ifdef _WIN32
2 /*
3  * Dirent interface for Microsoft Visual Studio
4  * Version 1.21
5  *
6  * Copyright (C) 2006-2012 Toni Ronkko
7  * This file is part of dirent. Dirent may be freely distributed
8  * under the MIT license. For all details and documentation, see
9  * https://github.com/tronkko/dirent
10  */
11 #ifndef DIRENT_H
12 #define DIRENT_H
13 
14 /*
15  * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
16  * Windows Sockets 2.0.
17  */
18 #ifndef WIN32_LEAN_AND_MEAN
19 # define WIN32_LEAN_AND_MEAN
20 #endif
21 #include <windows.h>
22 
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <wchar.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <malloc.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <errno.h>
32 
33 /* Indicates that d_type field is available in dirent structure */
34 #define _DIRENT_HAVE_D_TYPE
35 
36 /* Indicates that d_namlen field is available in dirent structure */
37 #define _DIRENT_HAVE_D_NAMLEN
38 
39 /* Entries missing from MSVC 6.0 */
40 #if !defined(FILE_ATTRIBUTE_DEVICE)
41 # define FILE_ATTRIBUTE_DEVICE 0x40
42 #endif
43 
44 /* File type and permission flags for stat(), general mask */
45 #if !defined(S_IFMT)
46 # define S_IFMT _S_IFMT
47 #endif
48 
49 /* Directory bit */
50 #if !defined(S_IFDIR)
51 # define S_IFDIR _S_IFDIR
52 #endif
53 
54 /* Character device bit */
55 #if !defined(S_IFCHR)
56 # define S_IFCHR _S_IFCHR
57 #endif
58 
59 /* Pipe bit */
60 #if !defined(S_IFFIFO)
61 # define S_IFFIFO _S_IFFIFO
62 #endif
63 
64 /* Regular file bit */
65 #if !defined(S_IFREG)
66 # define S_IFREG _S_IFREG
67 #endif
68 
69 /* Read permission */
70 #if !defined(S_IREAD)
71 # define S_IREAD _S_IREAD
72 #endif
73 
74 /* Write permission */
75 #if !defined(S_IWRITE)
76 # define S_IWRITE _S_IWRITE
77 #endif
78 
79 /* Execute permission */
80 #if !defined(S_IEXEC)
81 # define S_IEXEC _S_IEXEC
82 #endif
83 
84 /* Pipe */
85 #if !defined(S_IFIFO)
86 # define S_IFIFO _S_IFIFO
87 #endif
88 
89 /* Block device */
90 #if !defined(S_IFBLK)
91 # define S_IFBLK 0
92 #endif
93 
94 /* Link */
95 #if !defined(S_IFLNK)
96 # define S_IFLNK 0
97 #endif
98 
99 /* Socket */
100 #if !defined(S_IFSOCK)
101 # define S_IFSOCK 0
102 #endif
103 
104 /* Read user permission */
105 #if !defined(S_IRUSR)
106 # define S_IRUSR S_IREAD
107 #endif
108 
109 /* Write user permission */
110 #if !defined(S_IWUSR)
111 # define S_IWUSR S_IWRITE
112 #endif
113 
114 /* Execute user permission */
115 #if !defined(S_IXUSR)
116 # define S_IXUSR 0
117 #endif
118 
119 /* Read group permission */
120 #if !defined(S_IRGRP)
121 # define S_IRGRP 0
122 #endif
123 
124 /* Write group permission */
125 #if !defined(S_IWGRP)
126 # define S_IWGRP 0
127 #endif
128 
129 /* Execute group permission */
130 #if !defined(S_IXGRP)
131 # define S_IXGRP 0
132 #endif
133 
134 /* Read others permission */
135 #if !defined(S_IROTH)
136 # define S_IROTH 0
137 #endif
138 
139 /* Write others permission */
140 #if !defined(S_IWOTH)
141 # define S_IWOTH 0
142 #endif
143 
144 /* Execute others permission */
145 #if !defined(S_IXOTH)
146 # define S_IXOTH 0
147 #endif
148 
149 /* Maximum length of file name */
150 #if !defined(PATH_MAX)
151 # define PATH_MAX MAX_PATH
152 #endif
153 #if !defined(FILENAME_MAX)
154 # define FILENAME_MAX MAX_PATH
155 #endif
156 #if !defined(NAME_MAX)
157 # define NAME_MAX FILENAME_MAX
158 #endif
159 
160 /* File type flags for d_type */
161 #define DT_UNKNOWN 0
162 #define DT_REG S_IFREG
163 #define DT_DIR S_IFDIR
164 #define DT_FIFO S_IFIFO
165 #define DT_SOCK S_IFSOCK
166 #define DT_CHR S_IFCHR
167 #define DT_BLK S_IFBLK
168 #define DT_LNK S_IFLNK
169 
170 /* Macros for converting between st_mode and d_type */
171 #define IFTODT(mode) ((mode) & S_IFMT)
172 #define DTTOIF(type) (type)
173 
174 /*
175  * File type macros. Note that block devices, sockets and links cannot be
176  * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
177  * only defined for compatibility. These macros should always return false
178  * on Windows.
179  */
180 #if !defined(S_ISFIFO)
181 # define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
182 #endif
183 #if !defined(S_ISDIR)
184 # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
185 #endif
186 #if !defined(S_ISREG)
187 # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
188 #endif
189 #if !defined(S_ISLNK)
190 # define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
191 #endif
192 #if !defined(S_ISSOCK)
193 # define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
194 #endif
195 #if !defined(S_ISCHR)
196 # define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
197 #endif
198 #if !defined(S_ISBLK)
199 # define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
200 #endif
201 
202 /* Return the exact length of d_namlen without zero terminator */
203 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
204 
205 /* Return number of bytes needed to store d_namlen */
206 #define _D_ALLOC_NAMLEN(p) (PATH_MAX)
207 
208 
209 #ifdef __cplusplus
210 extern "C" {
211 #endif
212 
213 
214 /* Wide-character version */
215 struct _wdirent {
216  /* Always zero */
217  long d_ino;
218 
219  /* Structure size */
220  unsigned short d_reclen;
221 
222  /* Length of name without \0 */
223  size_t d_namlen;
224 
225  /* File type */
226  int d_type;
227 
228  /* File name */
229  wchar_t d_name[PATH_MAX];
230 };
231 typedef struct _wdirent _wdirent;
232 
233 struct _WDIR {
234  /* Current directory entry */
235  struct _wdirent ent;
236 
237  /* Private file data */
238  WIN32_FIND_DATAW data;
239 
240  /* True if data is valid */
241  int cached;
242 
243  /* Win32 search handle */
244  HANDLE handle;
245 
246  /* Initial directory name */
247  wchar_t *patt;
248 };
249 typedef struct _WDIR _WDIR;
250 
251 static _WDIR *_wopendir (const wchar_t *dirname);
252 static struct _wdirent *_wreaddir (_WDIR *dirp);
253 static int _wclosedir (_WDIR *dirp);
254 static void _wrewinddir (_WDIR* dirp);
255 
256 
257 /* For compatibility with Symbian */
258 #define wdirent _wdirent
259 #define WDIR _WDIR
260 #define wopendir _wopendir
261 #define wreaddir _wreaddir
262 #define wclosedir _wclosedir
263 #define wrewinddir _wrewinddir
264 
265 
266 /* Multi-byte character versions */
267 struct dirent {
268  /* Always zero */
269  long d_ino;
270 
271  /* Structure size */
272  unsigned short d_reclen;
273 
274  /* Length of name without \0 */
275  size_t d_namlen;
276 
277  /* File type */
278  int d_type;
279 
280  /* File name */
281  char d_name[PATH_MAX];
282 };
283 typedef struct dirent dirent;
284 
285 struct DIR {
286  struct dirent ent;
287  struct _WDIR *wdirp;
288 };
289 typedef struct DIR DIR;
290 
291 static DIR *opendir (const char *dirname);
292 static struct dirent *readdir (DIR *dirp);
293 static int closedir (DIR *dirp);
294 static void rewinddir (DIR* dirp);
295 
296 
297 /* Internal utility functions */
298 static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
299 static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
300 
301 static int dirent_mbstowcs_s(
302  size_t *pReturnValue,
303  wchar_t *wcstr,
304  size_t sizeInWords,
305  const char *mbstr,
306  size_t count);
307 
308 static int dirent_wcstombs_s(
309  size_t *pReturnValue,
310  char *mbstr,
311  size_t sizeInBytes,
312  const wchar_t *wcstr,
313  size_t count);
314 
315 static void dirent_set_errno (int error);
316 
317 /*
318  * Open directory stream DIRNAME for read and return a pointer to the
319  * internal working area that is used to retrieve individual directory
320  * entries.
321  */
322 static _WDIR*
323 _wopendir(
324  const wchar_t *dirname)
325 {
326  _WDIR *dirp = NULL;
327  int error;
328 
329  /* Must have directory name */
330  if (dirname == NULL || dirname[0] == '\0') {
331  dirent_set_errno (ENOENT);
332  return NULL;
333  }
334 
335  /* Allocate new _WDIR structure */
336  dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
337  if (dirp != NULL) {
338  DWORD n;
339 
340  /* Reset _WDIR structure */
341  dirp->handle = INVALID_HANDLE_VALUE;
342  dirp->patt = NULL;
343  dirp->cached = 0;
344 
345  /* Compute the length of full path plus zero terminator
346  *
347  * Note that on WinRT there's no way to convert relative paths
348  * into absolute paths, so just assume its an absolute path.
349  */
350 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
351  n = wcslen(dirname);
352 # else
353  n = GetFullPathNameW (dirname, 0, NULL, NULL);
354 # endif
355 
356  /* Allocate room for absolute directory name and search pattern */
357  dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
358  if (dirp->patt) {
359 
360  /*
361  * Convert relative directory name to an absolute one. This
362  * allows rewinddir() to function correctly even when current
363  * working directory is changed between opendir() and rewinddir().
364  *
365  * Note that on WinRT there's no way to convert relative paths
366  * into absolute paths, so just assume its an absolute path.
367  */
368 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
369  wcsncpy_s(dirp->patt, n+1, dirname, n);
370 # else
371  n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
372 # endif
373  if (n > 0) {
374  wchar_t *p;
375 
376  /* Append search pattern \* to the directory name */
377  p = dirp->patt + n;
378  if (dirp->patt < p) {
379  switch (p[-1]) {
380  case '\\':
381  case '/':
382  case ':':
383  /* Directory ends in path separator, e.g. c:\temp\ */
384  /*NOP*/;
385  break;
386 
387  default:
388  /* Directory name doesn't end in path separator */
389  *p++ = '\\';
390  }
391  }
392  *p++ = '*';
393  *p = '\0';
394 
395  /* Open directory stream and retrieve the first entry */
396  if (dirent_first (dirp)) {
397  /* Directory stream opened successfully */
398  error = 0;
399  } else {
400  /* Cannot retrieve first entry */
401  error = 1;
402  dirent_set_errno (ENOENT);
403  }
404 
405  } else {
406  /* Cannot retrieve full path name */
407  dirent_set_errno (ENOENT);
408  error = 1;
409  }
410 
411  } else {
412  /* Cannot allocate memory for search pattern */
413  error = 1;
414  }
415 
416  } else {
417  /* Cannot allocate _WDIR structure */
418  error = 1;
419  }
420 
421  /* Clean up in case of error */
422  if (error && dirp) {
423  _wclosedir (dirp);
424  dirp = NULL;
425  }
426 
427  return dirp;
428 }
429 
430 /*
431  * Read next directory entry. The directory entry is returned in dirent
432  * structure in the d_name field. Individual directory entries returned by
433  * this function include regular files, sub-directories, pseudo-directories
434  * "." and ".." as well as volume labels, hidden files and system files.
435  */
436 static struct _wdirent*
437 _wreaddir(
438  _WDIR *dirp)
439 {
440  WIN32_FIND_DATAW *datap;
441  struct _wdirent *entp;
442 
443  /* Read next directory entry */
444  datap = dirent_next (dirp);
445  if (datap) {
446  size_t n;
447  DWORD attr;
448 
449  /* Pointer to directory entry to return */
450  entp = &dirp->ent;
451 
452  /*
453  * Copy file name as wide-character string. If the file name is too
454  * long to fit in to the destination buffer, then truncate file name
455  * to PATH_MAX characters and zero-terminate the buffer.
456  */
457  n = 0;
458  while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) {
459  entp->d_name[n] = datap->cFileName[n];
460  n++;
461  }
462  dirp->ent.d_name[n] = 0;
463 
464  /* Length of file name excluding zero terminator */
465  entp->d_namlen = n;
466 
467  /* File type */
468  attr = datap->dwFileAttributes;
469  if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
470  entp->d_type = DT_CHR;
471  } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
472  entp->d_type = DT_DIR;
473  } else {
474  entp->d_type = DT_REG;
475  }
476 
477  /* Reset dummy fields */
478  entp->d_ino = 0;
479  entp->d_reclen = sizeof (struct _wdirent);
480 
481  } else {
482 
483  /* Last directory entry read */
484  entp = NULL;
485 
486  }
487 
488  return entp;
489 }
490 
491 /*
492  * Close directory stream opened by opendir() function. This invalidates the
493  * DIR structure as well as any directory entry read previously by
494  * _wreaddir().
495  */
496 static int
497 _wclosedir(
498  _WDIR *dirp)
499 {
500  int ok;
501  if (dirp) {
502 
503  /* Release search handle */
504  if (dirp->handle != INVALID_HANDLE_VALUE) {
505  FindClose (dirp->handle);
506  dirp->handle = INVALID_HANDLE_VALUE;
507  }
508 
509  /* Release search pattern */
510  if (dirp->patt) {
511  free (dirp->patt);
512  dirp->patt = NULL;
513  }
514 
515  /* Release directory structure */
516  free (dirp);
517  ok = /*success*/0;
518 
519  } else {
520  /* Invalid directory stream */
521  dirent_set_errno (EBADF);
522  ok = /*failure*/-1;
523  }
524  return ok;
525 }
526 
527 /*
528  * Rewind directory stream such that _wreaddir() returns the very first
529  * file name again.
530  */
531 static void
532 _wrewinddir(
533  _WDIR* dirp)
534 {
535  if (dirp) {
536  /* Release existing search handle */
537  if (dirp->handle != INVALID_HANDLE_VALUE) {
538  FindClose (dirp->handle);
539  }
540 
541  /* Open new search handle */
542  dirent_first (dirp);
543  }
544 }
545 
546 /* Get first directory entry (internal) */
547 static WIN32_FIND_DATAW*
548 dirent_first(
549  _WDIR *dirp)
550 {
551  WIN32_FIND_DATAW *datap;
552 
553  /* Open directory and retrieve the first entry */
554  dirp->handle = FindFirstFileExW(
555  dirp->patt, FindExInfoStandard, &dirp->data,
556  FindExSearchNameMatch, NULL, 0);
557  if (dirp->handle != INVALID_HANDLE_VALUE) {
558 
559  /* a directory entry is now waiting in memory */
560  datap = &dirp->data;
561  dirp->cached = 1;
562 
563  } else {
564 
565  /* Failed to re-open directory: no directory entry in memory */
566  dirp->cached = 0;
567  datap = NULL;
568 
569  }
570  return datap;
571 }
572 
573 /* Get next directory entry (internal) */
574 static WIN32_FIND_DATAW*
575 dirent_next(
576  _WDIR *dirp)
577 {
578  WIN32_FIND_DATAW *p;
579 
580  /* Get next directory entry */
581  if (dirp->cached != 0) {
582 
583  /* A valid directory entry already in memory */
584  p = &dirp->data;
585  dirp->cached = 0;
586 
587  } else if (dirp->handle != INVALID_HANDLE_VALUE) {
588 
589  /* Get the next directory entry from stream */
590  if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
591  /* Got a file */
592  p = &dirp->data;
593  } else {
594  /* The very last entry has been processed or an error occured */
595  FindClose (dirp->handle);
596  dirp->handle = INVALID_HANDLE_VALUE;
597  p = NULL;
598  }
599 
600  } else {
601 
602  /* End of directory stream reached */
603  p = NULL;
604 
605  }
606 
607  return p;
608 }
609 
610 /*
611  * Open directory stream using plain old C-string.
612  */
613 static DIR*
614 opendir(
615  const char *dirname)
616 {
617  struct DIR *dirp;
618  int error;
619 
620  /* Must have directory name */
621  if (dirname == NULL || dirname[0] == '\0') {
622  dirent_set_errno (ENOENT);
623  return NULL;
624  }
625 
626  /* Allocate memory for DIR structure */
627  dirp = (DIR*) malloc (sizeof (struct DIR));
628  if (dirp) {
629  wchar_t wname[PATH_MAX];
630  size_t n;
631 
632  /* Convert directory name to wide-character string */
633  error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);
634  if (!error) {
635 
636  /* Open directory stream using wide-character name */
637  dirp->wdirp = _wopendir (wname);
638  if (dirp->wdirp) {
639  /* Directory stream opened */
640  error = 0;
641  } else {
642  /* Failed to open directory stream */
643  error = 1;
644  }
645 
646  } else {
647  /*
648  * Cannot convert file name to wide-character string. This
649  * occurs if the string contains invalid multi-byte sequences or
650  * the output buffer is too small to contain the resulting
651  * string.
652  */
653  error = 1;
654  }
655 
656  } else {
657  /* Cannot allocate DIR structure */
658  error = 1;
659  }
660 
661  /* Clean up in case of error */
662  if (error && dirp) {
663  free (dirp);
664  dirp = NULL;
665  }
666 
667  return dirp;
668 }
669 
670 /*
671  * Read next directory entry.
672  *
673  * When working with text consoles, please note that file names returned by
674  * readdir() are represented in the default ANSI code page while any output to
675  * console is typically formatted on another code page. Thus, non-ASCII
676  * characters in file names will not usually display correctly on console. The
677  * problem can be fixed in two ways: (1) change the character set of console
678  * to 1252 using chcp utility and use Lucida Console font, or (2) use
679  * _cprintf function when writing to console. The _cprinf() will re-encode
680  * ANSI strings to the console code page so many non-ASCII characters will
681  * display correcly.
682  */
683 static struct dirent*
684 readdir(
685  DIR *dirp)
686 {
687  WIN32_FIND_DATAW *datap;
688  struct dirent *entp;
689 
690  /* Read next directory entry */
691  datap = dirent_next (dirp->wdirp);
692  if (datap) {
693  size_t n;
694  int error;
695 
696  /* Attempt to convert file name to multi-byte string */
697  error = dirent_wcstombs_s(
698  &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
699 
700  /*
701  * If the file name cannot be represented by a multi-byte string,
702  * then attempt to use old 8+3 file name. This allows traditional
703  * Unix-code to access some file names despite of unicode
704  * characters, although file names may seem unfamiliar to the user.
705  *
706  * Be ware that the code below cannot come up with a short file
707  * name unless the file system provides one. At least
708  * VirtualBox shared folders fail to do this.
709  */
710  if (error && datap->cAlternateFileName[0] != '\0') {
711  error = dirent_wcstombs_s(
712  &n, dirp->ent.d_name, PATH_MAX,
713  datap->cAlternateFileName, PATH_MAX);
714  }
715 
716  if (!error) {
717  DWORD attr;
718 
719  /* Initialize directory entry for return */
720  entp = &dirp->ent;
721 
722  /* Length of file name excluding zero terminator */
723  entp->d_namlen = n - 1;
724 
725  /* File attributes */
726  attr = datap->dwFileAttributes;
727  if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
728  entp->d_type = DT_CHR;
729  } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
730  entp->d_type = DT_DIR;
731  } else {
732  entp->d_type = DT_REG;
733  }
734 
735  /* Reset dummy fields */
736  entp->d_ino = 0;
737  entp->d_reclen = sizeof (struct dirent);
738 
739  } else {
740  /*
741  * Cannot convert file name to multi-byte string so construct
742  * an errornous directory entry and return that. Note that
743  * we cannot return NULL as that would stop the processing
744  * of directory entries completely.
745  */
746  entp = &dirp->ent;
747  entp->d_name[0] = '?';
748  entp->d_name[1] = '\0';
749  entp->d_namlen = 1;
750  entp->d_type = DT_UNKNOWN;
751  entp->d_ino = 0;
752  entp->d_reclen = 0;
753  }
754 
755  } else {
756  /* No more directory entries */
757  entp = NULL;
758  }
759 
760  return entp;
761 }
762 
763 /*
764  * Close directory stream.
765  */
766 static int
767 closedir(
768  DIR *dirp)
769 {
770  int ok;
771  if (dirp) {
772 
773  /* Close wide-character directory stream */
774  ok = _wclosedir (dirp->wdirp);
775  dirp->wdirp = NULL;
776 
777  /* Release multi-byte character version */
778  free (dirp);
779 
780  } else {
781 
782  /* Invalid directory stream */
783  dirent_set_errno (EBADF);
784  ok = /*failure*/-1;
785 
786  }
787  return ok;
788 }
789 
790 /*
791  * Rewind directory stream to beginning.
792  */
793 static void
794 rewinddir(
795  DIR* dirp)
796 {
797  /* Rewind wide-character string directory stream */
798  _wrewinddir (dirp->wdirp);
799 }
800 
801 /* Convert multi-byte string to wide character string */
802 static int
803 dirent_mbstowcs_s(
804  size_t *pReturnValue,
805  wchar_t *wcstr,
806  size_t sizeInWords,
807  const char *mbstr,
808  size_t count)
809 {
810  int error;
811 
812 #if defined(_MSC_VER) && _MSC_VER >= 1400
813 
814  /* Microsoft Visual Studio 2005 or later */
815  error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
816 
817 #else
818 
819  /* Older Visual Studio or non-Microsoft compiler */
820  size_t n;
821 
822  /* Convert to wide-character string (or count characters) */
823  n = mbstowcs (wcstr, mbstr, sizeInWords);
824  if (!wcstr || n < count) {
825 
826  /* Zero-terminate output buffer */
827  if (wcstr && sizeInWords) {
828  if (n >= sizeInWords) {
829  n = sizeInWords - 1;
830  }
831  wcstr[n] = 0;
832  }
833 
834  /* Length of resuting multi-byte string WITH zero terminator */
835  if (pReturnValue) {
836  *pReturnValue = n + 1;
837  }
838 
839  /* Success */
840  error = 0;
841 
842  } else {
843 
844  /* Could not convert string */
845  error = 1;
846 
847  }
848 
849 #endif
850 
851  return error;
852 }
853 
854 /* Convert wide-character string to multi-byte string */
855 static int
856 dirent_wcstombs_s(
857  size_t *pReturnValue,
858  char *mbstr,
859  size_t sizeInBytes, /* max size of mbstr */
860  const wchar_t *wcstr,
861  size_t count)
862 {
863  int error;
864 
865 #if defined(_MSC_VER) && _MSC_VER >= 1400
866 
867  /* Microsoft Visual Studio 2005 or later */
868  error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
869 
870 #else
871 
872  /* Older Visual Studio or non-Microsoft compiler */
873  size_t n;
874 
875  /* Convert to multi-byte string (or count the number of bytes needed) */
876  n = wcstombs (mbstr, wcstr, sizeInBytes);
877  if (!mbstr || n < count) {
878 
879  /* Zero-terminate output buffer */
880  if (mbstr && sizeInBytes) {
881  if (n >= sizeInBytes) {
882  n = sizeInBytes - 1;
883  }
884  mbstr[n] = '\0';
885  }
886 
887  /* Length of resulting multi-bytes string WITH zero-terminator */
888  if (pReturnValue) {
889  *pReturnValue = n + 1;
890  }
891 
892  /* Success */
893  error = 0;
894 
895  } else {
896 
897  /* Cannot convert string */
898  error = 1;
899 
900  }
901 
902 #endif
903 
904  return error;
905 }
906 
907 /* Set errno variable */
908 static void
909 dirent_set_errno(
910  int error)
911 {
912 #if defined(_MSC_VER) && _MSC_VER >= 1400
913 
914  /* Microsoft Visual Studio 2005 and later */
915  _set_errno (error);
916 
917 #else
918 
919  /* Non-Microsoft compiler or older Microsoft compiler */
920  errno = error;
921 
922 #endif
923 }
924 
925 
926 #ifdef __cplusplus
927 }
928 #endif
929 #endif /*DIRENT_H*/
930 #endif /*_WIN32*/