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