quickfix_ruby 1.14.3.1 → 1.15.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/ext/quickfix/Acceptor.h +2 -0
  3. data/ext/quickfix/AtomicCount.h +82 -12
  4. data/ext/quickfix/DOMDocument.h +9 -7
  5. data/ext/quickfix/DataDictionary.cpp +77 -14
  6. data/ext/quickfix/DataDictionary.h +90 -16
  7. data/ext/quickfix/Dictionary.cpp +1 -2
  8. data/ext/quickfix/Exceptions.h +3 -5
  9. data/ext/quickfix/Field.h +83 -32
  10. data/ext/quickfix/FieldConvertors.cpp +93 -0
  11. data/ext/quickfix/FieldConvertors.h +129 -275
  12. data/ext/quickfix/FieldMap.cpp +53 -13
  13. data/ext/quickfix/FieldMap.h +200 -62
  14. data/ext/quickfix/FieldTypes.cpp +10 -10
  15. data/ext/quickfix/FieldTypes.h +293 -44
  16. data/ext/quickfix/FileLog.cpp +6 -10
  17. data/ext/quickfix/FileLog.h +4 -10
  18. data/ext/quickfix/FileStore.cpp +19 -6
  19. data/ext/quickfix/FileStore.h +4 -0
  20. data/ext/quickfix/FixFieldNumbers.h +1462 -1461
  21. data/ext/quickfix/FixFields.h +1462 -1461
  22. data/ext/quickfix/FixValues.h +3230 -3227
  23. data/ext/quickfix/HttpConnection.cpp +1 -1
  24. data/ext/quickfix/Initiator.cpp +7 -1
  25. data/ext/quickfix/Initiator.h +2 -0
  26. data/ext/quickfix/Log.h +6 -12
  27. data/ext/quickfix/Message.cpp +186 -57
  28. data/ext/quickfix/Message.h +109 -47
  29. data/ext/quickfix/MySQLConnection.h +1 -1
  30. data/ext/quickfix/PostgreSQLConnection.h +1 -1
  31. data/ext/quickfix/QuickfixRuby.cpp +79141 -77959
  32. data/ext/quickfix/QuickfixRuby.h +1 -1
  33. data/ext/quickfix/SSLSocketAcceptor.cpp +410 -0
  34. data/ext/quickfix/SSLSocketAcceptor.h +185 -0
  35. data/ext/quickfix/SSLSocketConnection.cpp +427 -0
  36. data/ext/quickfix/SSLSocketConnection.h +206 -0
  37. data/ext/quickfix/SSLSocketInitiator.cpp +485 -0
  38. data/ext/quickfix/SSLSocketInitiator.h +196 -0
  39. data/ext/quickfix/Session.cpp +113 -20
  40. data/ext/quickfix/Session.h +18 -4
  41. data/ext/quickfix/SessionFactory.cpp +10 -3
  42. data/ext/quickfix/SessionSettings.cpp +5 -3
  43. data/ext/quickfix/SessionSettings.h +97 -5
  44. data/ext/quickfix/Settings.cpp +72 -2
  45. data/ext/quickfix/Settings.h +3 -0
  46. data/ext/quickfix/SharedArray.h +140 -6
  47. data/ext/quickfix/SocketConnection.cpp +2 -2
  48. data/ext/quickfix/SocketConnector.cpp +5 -2
  49. data/ext/quickfix/SocketConnector.h +3 -2
  50. data/ext/quickfix/SocketInitiator.cpp +28 -4
  51. data/ext/quickfix/SocketInitiator.h +1 -1
  52. data/ext/quickfix/SocketMonitor.cpp +5 -5
  53. data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +455 -0
  54. data/ext/quickfix/ThreadedSSLSocketAcceptor.h +217 -0
  55. data/ext/quickfix/ThreadedSSLSocketConnection.cpp +404 -0
  56. data/ext/quickfix/ThreadedSSLSocketConnection.h +189 -0
  57. data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +469 -0
  58. data/ext/quickfix/ThreadedSSLSocketInitiator.h +201 -0
  59. data/ext/quickfix/ThreadedSocketAcceptor.cpp +5 -1
  60. data/ext/quickfix/ThreadedSocketConnection.cpp +8 -2
  61. data/ext/quickfix/ThreadedSocketConnection.h +4 -1
  62. data/ext/quickfix/ThreadedSocketInitiator.cpp +24 -4
  63. data/ext/quickfix/ThreadedSocketInitiator.h +1 -1
  64. data/ext/quickfix/Utility.cpp +23 -1
  65. data/ext/quickfix/Utility.h +28 -2
  66. data/ext/quickfix/UtilitySSL.cpp +1733 -0
  67. data/ext/quickfix/UtilitySSL.h +277 -0
  68. data/ext/quickfix/config-all.h +10 -0
  69. data/ext/quickfix/dirent_windows.h +838 -0
  70. data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
  71. data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
  72. data/ext/quickfix/double-conversion/bignum.cc +766 -0
  73. data/ext/quickfix/double-conversion/bignum.h +144 -0
  74. data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
  75. data/ext/quickfix/double-conversion/cached-powers.h +64 -0
  76. data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
  77. data/ext/quickfix/double-conversion/diy-fp.h +118 -0
  78. data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
  79. data/ext/quickfix/double-conversion/double-conversion.h +543 -0
  80. data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
  81. data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
  82. data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
  83. data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
  84. data/ext/quickfix/double-conversion/ieee.h +402 -0
  85. data/ext/quickfix/double-conversion/strtod.cc +557 -0
  86. data/ext/quickfix/double-conversion/strtod.h +45 -0
  87. data/ext/quickfix/double-conversion/utils.h +372 -0
  88. data/ext/quickfix/stdint_msvc.h +254 -0
  89. data/lib/quickfix44.rb +3329 -10
  90. data/lib/quickfix50.rb +6649 -81
  91. data/lib/quickfix50sp1.rb +8054 -142
  92. data/lib/quickfix50sp2.rb +10900 -234
  93. data/lib/quickfix_fields.rb +7662 -7649
  94. data/spec/FIX40.xml +28 -28
  95. data/spec/FIX41.xml +29 -29
  96. data/spec/FIX42.xml +47 -47
  97. data/spec/FIX43.xml +148 -148
  98. data/spec/FIX44.xml +1078 -1081
  99. data/spec/FIX50.xml +1292 -1289
  100. data/spec/FIX50SP1.xml +1811 -1802
  101. data/spec/FIX50SP2.xml +1948 -1939
  102. data/spec/FIXT11.xml +5 -8
  103. data/test/test_FieldBaseTestCase.rb +1 -1
  104. data/test/test_MessageTestCase.rb +2 -2
  105. metadata +42 -6
@@ -0,0 +1,277 @@
1
+ /* Licensed to the Apache Software Foundation (ASF) under one or more
2
+ * contributor license agreements. See the NOTICE file distributed with
3
+ * this work for additional information regarding copyright ownership.
4
+ * The ASF licenses this file to You under the Apache License, Version 2.0
5
+ * (the "License"); you may not use this file except in compliance with
6
+ * the License. You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ /* ====================================================================
18
+ * Copyright (c) 1998-2006 Ralf S. Engelschall. All rights reserved.
19
+ *
20
+ * Redistribution and use in source and binary forms, with or without
21
+ * modification, are permitted provided that the following conditions
22
+ * are met:
23
+ *
24
+ * 1. Redistributions of source code must retain the above copyright
25
+ * notice, this list of conditions and the following disclaimer.
26
+ *
27
+ * 2. Redistributions in binary form must reproduce the above copyright
28
+ * notice, this list of conditions and the following
29
+ * disclaimer in the documentation and/or other materials
30
+ * provided with the distribution.
31
+ *
32
+ * 3. All advertising materials mentioning features or use of this
33
+ * software must display the following acknowledgment:
34
+ * "This product includes software developed by
35
+ * Ralf S. Engelschall <rse@engelschall.com> for use in the
36
+ * mod_ssl project (http://www.modssl.org/)."
37
+ *
38
+ * 4. The names "mod_ssl" must not be used to endorse or promote
39
+ * products derived from this software without prior written
40
+ * permission. For written permission, please contact
41
+ * rse@engelschall.com.
42
+ *
43
+ * 5. Products derived from this software may not be called "mod_ssl"
44
+ * nor may "mod_ssl" appear in their names without prior
45
+ * written permission of Ralf S. Engelschall.
46
+ *
47
+ * 6. Redistributions of any form whatsoever must retain the following
48
+ * acknowledgment:
49
+ * "This product includes software developed by
50
+ * Ralf S. Engelschall <rse@engelschall.com> for use in the
51
+ * mod_ssl project (http://www.modssl.org/)."
52
+ *
53
+ * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
54
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
57
+ * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
58
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
59
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
60
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
62
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
64
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
65
+ * ====================================================================
66
+ */
67
+
68
+ /* ====================================================================
69
+ * Copyright (c) 1995-1999 Ben Laurie. All rights reserved.
70
+ *
71
+ * Redistribution and use in source and binary forms, with or without
72
+ * modification, are permitted provided that the following conditions
73
+ * are met:
74
+ *
75
+ * 1. Redistributions of source code must retain the above copyright
76
+ * notice, this list of conditions and the following disclaimer.
77
+ *
78
+ * 2. Redistributions in binary form must reproduce the above copyright
79
+ * notice, this list of conditions and the following disclaimer in
80
+ * the documentation and/or other materials provided with the
81
+ * distribution.
82
+ *
83
+ * 3. All advertising materials mentioning features or use of this
84
+ * software must display the following acknowledgment:
85
+ * "This product includes software developed by Ben Laurie
86
+ * for use in the Apache-SSL HTTP server project."
87
+ *
88
+ * 4. The name "Apache-SSL Server" must not be used to
89
+ * endorse or promote products derived from this software without
90
+ * prior written permission.
91
+ *
92
+ * 5. Redistributions of any form whatsoever must retain the following
93
+ * acknowledgment:
94
+ * "This product includes software developed by Ben Laurie
95
+ * for use in the Apache-SSL HTTP server project."
96
+ *
97
+ * THIS SOFTWARE IS PROVIDED BY BEN LAURIE ``AS IS'' AND ANY
98
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
99
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
100
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BEN LAURIE OR
101
+ * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
102
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
103
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
104
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
105
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
106
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
107
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
108
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
109
+ * ====================================================================
110
+ */
111
+
112
+ #ifndef FIX_UTILITY_SSL_H
113
+ #define FIX_UTILITY_SSL_H
114
+
115
+ #if (HAVE_SSL > 0)
116
+
117
+ #include "Log.h"
118
+ #include "SessionSettings.h"
119
+ #include "Utility.h"
120
+
121
+ #ifndef _MSC_VER
122
+ #include <dirent.h>
123
+ #else
124
+ #ifndef HAVE_ACE_DIRENT
125
+ #include "dirent_windows.h"
126
+ #else
127
+ #include "ace/OS_NS_dirent.h"
128
+ #endif
129
+ #endif
130
+
131
+ #include "openssl/err.h"
132
+ #include "openssl/ssl.h" // SSL and SSL_CTX for SSL connections
133
+
134
+ namespace FIX
135
+ {
136
+
137
+ #if defined(_MSC_VER)
138
+
139
+ #define snprintf _snprintf
140
+
141
+ static const char *WSAErrString(int code)
142
+ /********************************************************************************
143
+ * Translate WSA error code to message string (abreviated)
144
+ * Returns: pointer to static string.
145
+ */
146
+ {
147
+ #define expand(x) \
148
+ { \
149
+ x, #x \
150
+ }
151
+ static struct
152
+ {
153
+ int code;
154
+ const char *s;
155
+ } tab[] = {expand(WSAEINTR), expand(WSAEBADF),
156
+ expand(WSAEACCES), expand(WSAEFAULT),
157
+ expand(WSAEINVAL), expand(WSAEMFILE),
158
+ expand(WSAEWOULDBLOCK), expand(WSAEINPROGRESS),
159
+ expand(WSAEALREADY), expand(WSAENOTSOCK),
160
+ expand(WSAEDESTADDRREQ), expand(WSAEMSGSIZE),
161
+ expand(WSAEPROTOTYPE), expand(WSAENOPROTOOPT),
162
+ expand(WSAEPROTONOSUPPORT), expand(WSAESOCKTNOSUPPORT),
163
+ expand(WSAEOPNOTSUPP), expand(WSAEPFNOSUPPORT),
164
+ expand(WSAEAFNOSUPPORT), expand(WSAEADDRINUSE),
165
+ expand(WSAEADDRNOTAVAIL), expand(WSAENETDOWN),
166
+ expand(WSAENETUNREACH), expand(WSAENETRESET),
167
+ expand(WSAECONNABORTED), expand(WSAECONNRESET),
168
+ expand(WSAENOBUFS), expand(WSAEISCONN),
169
+ expand(WSAENOTCONN), expand(WSAESHUTDOWN),
170
+ expand(WSAETOOMANYREFS), expand(WSAETIMEDOUT),
171
+ expand(WSAECONNREFUSED), expand(WSAELOOP),
172
+ expand(WSAENAMETOOLONG), expand(WSAEHOSTDOWN),
173
+ expand(WSAEHOSTUNREACH), expand(WSAENOTEMPTY),
174
+ expand(WSAEPROCLIM), expand(WSAEUSERS),
175
+ expand(WSAEDQUOT), expand(WSAESTALE),
176
+ expand(WSAEREMOTE), {-1, ""}};
177
+ int i;
178
+
179
+ for (i = 0; tab[i].code > 0; i++)
180
+ if (code == tab[i].code)
181
+ return tab[i].s;
182
+
183
+ return "Unknown error code";
184
+ }
185
+
186
+ #define SLASH "\\"
187
+ #define SUFFIX "*"
188
+
189
+ #else
190
+
191
+ #define SLASH "/"
192
+
193
+ #endif
194
+
195
+ // Callback functions
196
+ extern "C" {
197
+ typedef int (*passPhraseHandleCallbackType)(char *, int, int, void *);
198
+
199
+ int caListX509NameCmp(const X509_NAME *const *a, const X509_NAME *const *b);
200
+ STACK_OF(X509_NAME) * findCAList(const char *cpCAfile, const char *cpCApath);
201
+ int lookupX509Store(X509_STORE *pStore, int nType, X509_NAME *pName,
202
+ X509_OBJECT *pObj);
203
+ int callbackVerify(int ok, X509_STORE_CTX *ctx);
204
+ int callbackVerifyCRL(int ok, X509_STORE_CTX *ctx, X509_STORE *revStore);
205
+ X509_STORE *createX509Store(const char *cpFile, const char *cpPath);
206
+ X509 *readX509(FILE *fp, X509 **x509, passPhraseHandleCallbackType cb);
207
+ EVP_PKEY *readPrivateKey(FILE *fp, EVP_PKEY **key,
208
+ passPhraseHandleCallbackType cb);
209
+
210
+ char *strCat(const char *a, ...);
211
+ }
212
+
213
+ int setSocketNonBlocking(int pSocket);
214
+
215
+ // define certificate algorithm type
216
+ #define SSL_ALGO_UNKNOWN 0
217
+ #define SSL_ALGO_RSA 1
218
+ #define SSL_ALGO_DSA 2
219
+ #define SSL_ALGO_ALL (SSL_ALGO_RSA | SSL_ALGO_DSA)
220
+
221
+ /*
222
+ * Define the SSL Protocol options
223
+ */
224
+ #define SSL_PROTOCOL_NONE (0)
225
+ #define SSL_PROTOCOL_SSLV2 (1 << 0)
226
+ #define SSL_PROTOCOL_SSLV3 (1 << 1)
227
+ #define SSL_PROTOCOL_TLSV1 (1 << 2)
228
+ #define SSL_PROTOCOL_TLSV1_1 (1 << 3)
229
+ #define SSL_PROTOCOL_TLSV1_2 (1 << 4)
230
+ #define SSL_PROTOCOL_ALL \
231
+ (SSL_PROTOCOL_SSLV2 | SSL_PROTOCOL_SSLV3 | SSL_PROTOCOL_TLSV1 | \
232
+ SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2)
233
+
234
+ typedef enum {
235
+ SSL_CLIENT_VERIFY_NONE = 0,
236
+ SSL_CLIENT_VERIFY_REQUIRE = 1,
237
+ SSL_CLIENT_VERIFY_OPTIONAL = 2,
238
+ SSL_CLIENT_VERIFY_NOTSET = 3
239
+ } SSLVerifyClient;
240
+
241
+ // Should always call ssl_init/ssl_term.
242
+
243
+ void ssl_init();
244
+
245
+ void ssl_term();
246
+
247
+ void ssl_socket_close(int socket, SSL *ssl);
248
+
249
+ const char *socket_error(char *tempbuf, int buflen);
250
+
251
+ int typeofSSLAlgo(X509 *pCert, EVP_PKEY *pKey);
252
+
253
+ long protocolOptions(const char *opt);
254
+
255
+ void setCtxOptions(SSL_CTX *ctx, long options);
256
+
257
+ int enable_DH_ECDH(SSL_CTX *ctx, const char *certFile);
258
+
259
+ SSL_CTX *createSSLContext(bool server, const SessionSettings &settings,
260
+ std::string &errStr);
261
+
262
+ bool loadSSLCert(SSL_CTX *ctx, bool server, const SessionSettings &settings,
263
+ Log *log, passPhraseHandleCallbackType cb,
264
+ std::string &errStr);
265
+
266
+ bool loadCAInfo(SSL_CTX *ctx, bool server, const SessionSettings &settings,
267
+ Log *log, std::string &errStr, int &verifyLevel);
268
+
269
+ X509_STORE *loadCRLInfo(SSL_CTX *ctx, const SessionSettings &settings, Log *log,
270
+ std::string &errStr);
271
+
272
+ int acceptSSLConnection(int socket, SSL * ssl, Log * log, int verify);
273
+ }
274
+
275
+ #endif
276
+
277
+ #endif
@@ -0,0 +1,10 @@
1
+ #ifndef CONFIG_ALL_H
2
+ #define CONFIG_ALL_H
3
+
4
+ #if !defined(__x86_64) && !defined(_M_X64) && !defined(__i386) && !defined(_M_IX86)
5
+
6
+ #define NO_UNALIGNED_ACCESS 1
7
+
8
+ #endif
9
+
10
+ #endif
@@ -0,0 +1,838 @@
1
+ /*
2
+ * dirent.h - dirent API for Microsoft Visual Studio
3
+ *
4
+ * Copyright (C) 2006-2012 Toni Ronkko
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining
7
+ * a copy of this software and associated documentation files (the
8
+ * ``Software''), to deal in the Software without restriction, including
9
+ * without limitation the rights to use, copy, modify, merge, publish,
10
+ * distribute, sublicense, and/or sell copies of the Software, and to
11
+ * permit persons to whom the Software is furnished to do so, subject to
12
+ * the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
+ * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
21
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
+ * OTHER DEALINGS IN THE SOFTWARE.
24
+ *
25
+ * $Id: dirent.h,v 1.20 2014/03/19 17:52:23 tronkko Exp $
26
+ */
27
+ #ifndef DIRENT_H
28
+ #define DIRENT_H
29
+
30
+ /*
31
+ * Define architecture flags so we don't need to include windows.h.
32
+ * Avoiding windows.h makes it simpler to use windows sockets in conjunction
33
+ * with dirent.h.
34
+ */
35
+ #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
36
+ # define _X86_
37
+ #endif
38
+ #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64)
39
+ #define _AMD64_
40
+ #endif
41
+
42
+ #include <stdio.h>
43
+ #include <stdarg.h>
44
+ #include <windef.h>
45
+ #include <winbase.h>
46
+ #include <wchar.h>
47
+ #include <string.h>
48
+ #include <stdlib.h>
49
+ #include <malloc.h>
50
+ #include <sys/types.h>
51
+ #include <sys/stat.h>
52
+ #include <errno.h>
53
+
54
+ /* Indicates that d_type field is available in dirent structure */
55
+ #define _DIRENT_HAVE_D_TYPE
56
+
57
+ /* Indicates that d_namlen field is available in dirent structure */
58
+ #define _DIRENT_HAVE_D_NAMLEN
59
+
60
+ /* Entries missing from MSVC 6.0 */
61
+ #if !defined(FILE_ATTRIBUTE_DEVICE)
62
+ # define FILE_ATTRIBUTE_DEVICE 0x40
63
+ #endif
64
+
65
+ /* File type and permission flags for stat() */
66
+ #if !defined(S_IFMT)
67
+ # define S_IFMT _S_IFMT /* File type mask */
68
+ #endif
69
+ #if !defined(S_IFDIR)
70
+ # define S_IFDIR _S_IFDIR /* Directory */
71
+ #endif
72
+ #if !defined(S_IFCHR)
73
+ # define S_IFCHR _S_IFCHR /* Character device */
74
+ #endif
75
+ #if !defined(S_IFFIFO)
76
+ # define S_IFFIFO _S_IFFIFO /* Pipe */
77
+ #endif
78
+ #if !defined(S_IFREG)
79
+ # define S_IFREG _S_IFREG /* Regular file */
80
+ #endif
81
+ #if !defined(S_IREAD)
82
+ # define S_IREAD _S_IREAD /* Read permission */
83
+ #endif
84
+ #if !defined(S_IWRITE)
85
+ # define S_IWRITE _S_IWRITE /* Write permission */
86
+ #endif
87
+ #if !defined(S_IEXEC)
88
+ # define S_IEXEC _S_IEXEC /* Execute permission */
89
+ #endif
90
+ #if !defined(S_IFIFO)
91
+ # define S_IFIFO _S_IFIFO /* Pipe */
92
+ #endif
93
+ #if !defined(S_IFBLK)
94
+ # define S_IFBLK 0 /* Block device */
95
+ #endif
96
+ #if !defined(S_IFLNK)
97
+ # define S_IFLNK 0 /* Link */
98
+ #endif
99
+ #if !defined(S_IFSOCK)
100
+ # define S_IFSOCK 0 /* Socket */
101
+ #endif
102
+
103
+ #if defined(_MSC_VER)
104
+ # define S_IRUSR S_IREAD /* Read user */
105
+ # define S_IWUSR S_IWRITE /* Write user */
106
+ # define S_IXUSR 0 /* Execute user */
107
+ # define S_IRGRP 0 /* Read group */
108
+ # define S_IWGRP 0 /* Write group */
109
+ # define S_IXGRP 0 /* Execute group */
110
+ # define S_IROTH 0 /* Read others */
111
+ # define S_IWOTH 0 /* Write others */
112
+ # define S_IXOTH 0 /* Execute others */
113
+ #endif
114
+
115
+ /* Maximum length of file name */
116
+ #if !defined(PATH_MAX)
117
+ # define PATH_MAX MAX_PATH
118
+ #endif
119
+ #if !defined(FILENAME_MAX)
120
+ # define FILENAME_MAX MAX_PATH
121
+ #endif
122
+ #if !defined(NAME_MAX)
123
+ # define NAME_MAX FILENAME_MAX
124
+ #endif
125
+
126
+ /* File type flags for d_type */
127
+ #define DT_UNKNOWN 0
128
+ #define DT_REG S_IFREG
129
+ #define DT_DIR S_IFDIR
130
+ #define DT_FIFO S_IFIFO
131
+ #define DT_SOCK S_IFSOCK
132
+ #define DT_CHR S_IFCHR
133
+ #define DT_BLK S_IFBLK
134
+ #define DT_LNK S_IFLNK
135
+
136
+ /* Macros for converting between st_mode and d_type */
137
+ #define IFTODT(mode) ((mode) & S_IFMT)
138
+ #define DTTOIF(type) (type)
139
+
140
+ /*
141
+ * File type macros. Note that block devices, sockets and links cannot be
142
+ * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
143
+ * only defined for compatibility. These macros should always return false
144
+ * on Windows.
145
+ */
146
+ #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
147
+ #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
148
+ #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
149
+ #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
150
+ #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
151
+ #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
152
+ #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
153
+
154
+ /* Return the exact length of d_namlen without zero terminator */
155
+ #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
156
+
157
+ /* Return number of bytes needed to store d_namlen */
158
+ #define _D_ALLOC_NAMLEN(p) (PATH_MAX)
159
+
160
+
161
+ #ifdef __cplusplus
162
+ extern "C" {
163
+ #endif
164
+
165
+
166
+ /* Wide-character version */
167
+ struct _wdirent {
168
+ long d_ino; /* Always zero */
169
+ unsigned short d_reclen; /* Structure size */
170
+ size_t d_namlen; /* Length of name without \0 */
171
+ int d_type; /* File type */
172
+ wchar_t d_name[PATH_MAX]; /* File name */
173
+ };
174
+ typedef struct _wdirent _wdirent;
175
+
176
+ struct _WDIR {
177
+ struct _wdirent ent; /* Current directory entry */
178
+ WIN32_FIND_DATAW data; /* Private file data */
179
+ int cached; /* True if data is valid */
180
+ HANDLE handle; /* Win32 search handle */
181
+ wchar_t *patt; /* Initial directory name */
182
+ };
183
+ typedef struct _WDIR _WDIR;
184
+
185
+ static _WDIR *_wopendir (const wchar_t *dirname);
186
+ static struct _wdirent *_wreaddir (_WDIR *dirp);
187
+ static int _wclosedir (_WDIR *dirp);
188
+ static void _wrewinddir (_WDIR* dirp);
189
+
190
+
191
+ /* For compatibility with Symbian */
192
+ #define wdirent _wdirent
193
+ #define WDIR _WDIR
194
+ #define wopendir _wopendir
195
+ #define wreaddir _wreaddir
196
+ #define wclosedir _wclosedir
197
+ #define wrewinddir _wrewinddir
198
+
199
+
200
+ /* Multi-byte character versions */
201
+ struct dirent {
202
+ long d_ino; /* Always zero */
203
+ unsigned short d_reclen; /* Structure size */
204
+ size_t d_namlen; /* Length of name without \0 */
205
+ int d_type; /* File type */
206
+ char d_name[PATH_MAX]; /* File name */
207
+ };
208
+ typedef struct dirent dirent;
209
+
210
+ struct DIR {
211
+ struct dirent ent;
212
+ struct _WDIR *wdirp;
213
+ };
214
+ typedef struct DIR DIR;
215
+
216
+ static DIR *opendir (const char *dirname);
217
+ static struct dirent *readdir (DIR *dirp);
218
+ static int closedir (DIR *dirp);
219
+ static void rewinddir (DIR* dirp);
220
+
221
+
222
+ /* Internal utility functions */
223
+ static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
224
+ static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
225
+
226
+ static int dirent_mbstowcs_s(
227
+ size_t *pReturnValue,
228
+ wchar_t *wcstr,
229
+ size_t sizeInWords,
230
+ const char *mbstr,
231
+ size_t count);
232
+
233
+ static int dirent_wcstombs_s(
234
+ size_t *pReturnValue,
235
+ char *mbstr,
236
+ size_t sizeInBytes,
237
+ const wchar_t *wcstr,
238
+ size_t count);
239
+
240
+ static void dirent_set_errno (int error);
241
+
242
+ /*
243
+ * Open directory stream DIRNAME for read and return a pointer to the
244
+ * internal working area that is used to retrieve individual directory
245
+ * entries.
246
+ */
247
+ static _WDIR*
248
+ _wopendir(
249
+ const wchar_t *dirname)
250
+ {
251
+ _WDIR *dirp = NULL;
252
+ int error;
253
+
254
+ /* Must have directory name */
255
+ if (dirname == NULL || dirname[0] == '\0') {
256
+ dirent_set_errno (ENOENT);
257
+ return NULL;
258
+ }
259
+
260
+ /* Allocate new _WDIR structure */
261
+ dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
262
+ if (dirp != NULL) {
263
+ DWORD n;
264
+
265
+ /* Reset _WDIR structure */
266
+ dirp->handle = INVALID_HANDLE_VALUE;
267
+ dirp->patt = NULL;
268
+ dirp->cached = 0;
269
+
270
+ /* Compute the length of full path plus zero terminator */
271
+ n = GetFullPathNameW (dirname, 0, NULL, NULL);
272
+
273
+ /* Allocate room for absolute directory name and search pattern */
274
+ dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
275
+ if (dirp->patt) {
276
+
277
+ /*
278
+ * Convert relative directory name to an absolute one. This
279
+ * allows rewinddir() to function correctly even when current
280
+ * working directory is changed between opendir() and rewinddir().
281
+ */
282
+ n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
283
+ if (n > 0) {
284
+ wchar_t *p;
285
+
286
+ /* Append search pattern \* to the directory name */
287
+ p = dirp->patt + n;
288
+ if (dirp->patt < p) {
289
+ switch (p[-1]) {
290
+ case '\\':
291
+ case '/':
292
+ case ':':
293
+ /* Directory ends in path separator, e.g. c:\temp\ */
294
+ /*NOP*/;
295
+ break;
296
+
297
+ default:
298
+ /* Directory name doesn't end in path separator */
299
+ *p++ = '\\';
300
+ }
301
+ }
302
+ *p++ = '*';
303
+ *p = '\0';
304
+
305
+ /* Open directory stream and retrieve the first entry */
306
+ if (dirent_first (dirp)) {
307
+ /* Directory stream opened successfully */
308
+ error = 0;
309
+ } else {
310
+ /* Cannot retrieve first entry */
311
+ error = 1;
312
+ dirent_set_errno (ENOENT);
313
+ }
314
+
315
+ } else {
316
+ /* Cannot retrieve full path name */
317
+ dirent_set_errno (ENOENT);
318
+ error = 1;
319
+ }
320
+
321
+ } else {
322
+ /* Cannot allocate memory for search pattern */
323
+ error = 1;
324
+ }
325
+
326
+ } else {
327
+ /* Cannot allocate _WDIR structure */
328
+ error = 1;
329
+ }
330
+
331
+ /* Clean up in case of error */
332
+ if (error && dirp) {
333
+ _wclosedir (dirp);
334
+ dirp = NULL;
335
+ }
336
+
337
+ return dirp;
338
+ }
339
+
340
+ /*
341
+ * Read next directory entry. The directory entry is returned in dirent
342
+ * structure in the d_name field. Individual directory entries returned by
343
+ * this function include regular files, sub-directories, pseudo-directories
344
+ * "." and ".." as well as volume labels, hidden files and system files.
345
+ */
346
+ static struct _wdirent*
347
+ _wreaddir(
348
+ _WDIR *dirp)
349
+ {
350
+ WIN32_FIND_DATAW *datap;
351
+ struct _wdirent *entp;
352
+
353
+ /* Read next directory entry */
354
+ datap = dirent_next (dirp);
355
+ if (datap) {
356
+ size_t n;
357
+ DWORD attr;
358
+
359
+ /* Pointer to directory entry to return */
360
+ entp = &dirp->ent;
361
+
362
+ /*
363
+ * Copy file name as wide-character string. If the file name is too
364
+ * long to fit in to the destination buffer, then truncate file name
365
+ * to PATH_MAX characters and zero-terminate the buffer.
366
+ */
367
+ n = 0;
368
+ while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) {
369
+ entp->d_name[n] = datap->cFileName[n];
370
+ n++;
371
+ }
372
+ dirp->ent.d_name[n] = 0;
373
+
374
+ /* Length of file name excluding zero terminator */
375
+ entp->d_namlen = n;
376
+
377
+ /* File type */
378
+ attr = datap->dwFileAttributes;
379
+ if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
380
+ entp->d_type = DT_CHR;
381
+ } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
382
+ entp->d_type = DT_DIR;
383
+ } else {
384
+ entp->d_type = DT_REG;
385
+ }
386
+
387
+ /* Reset dummy fields */
388
+ entp->d_ino = 0;
389
+ entp->d_reclen = sizeof (struct _wdirent);
390
+
391
+ } else {
392
+
393
+ /* Last directory entry read */
394
+ entp = NULL;
395
+
396
+ }
397
+
398
+ return entp;
399
+ }
400
+
401
+ /*
402
+ * Close directory stream opened by opendir() function. This invalidates the
403
+ * DIR structure as well as any directory entry read previously by
404
+ * _wreaddir().
405
+ */
406
+ static int
407
+ _wclosedir(
408
+ _WDIR *dirp)
409
+ {
410
+ int ok;
411
+ if (dirp) {
412
+
413
+ /* Release search handle */
414
+ if (dirp->handle != INVALID_HANDLE_VALUE) {
415
+ FindClose (dirp->handle);
416
+ dirp->handle = INVALID_HANDLE_VALUE;
417
+ }
418
+
419
+ /* Release search pattern */
420
+ if (dirp->patt) {
421
+ free (dirp->patt);
422
+ dirp->patt = NULL;
423
+ }
424
+
425
+ /* Release directory structure */
426
+ free (dirp);
427
+ ok = /*success*/0;
428
+
429
+ } else {
430
+ /* Invalid directory stream */
431
+ dirent_set_errno (EBADF);
432
+ ok = /*failure*/-1;
433
+ }
434
+ return ok;
435
+ }
436
+
437
+ /*
438
+ * Rewind directory stream such that _wreaddir() returns the very first
439
+ * file name again.
440
+ */
441
+ static void
442
+ _wrewinddir(
443
+ _WDIR* dirp)
444
+ {
445
+ if (dirp) {
446
+ /* Release existing search handle */
447
+ if (dirp->handle != INVALID_HANDLE_VALUE) {
448
+ FindClose (dirp->handle);
449
+ }
450
+
451
+ /* Open new search handle */
452
+ dirent_first (dirp);
453
+ }
454
+ }
455
+
456
+ /* Get first directory entry (internal) */
457
+ static WIN32_FIND_DATAW*
458
+ dirent_first(
459
+ _WDIR *dirp)
460
+ {
461
+ WIN32_FIND_DATAW *datap;
462
+
463
+ /* Open directory and retrieve the first entry */
464
+ dirp->handle = FindFirstFileW (dirp->patt, &dirp->data);
465
+ if (dirp->handle != INVALID_HANDLE_VALUE) {
466
+
467
+ /* a directory entry is now waiting in memory */
468
+ datap = &dirp->data;
469
+ dirp->cached = 1;
470
+
471
+ } else {
472
+
473
+ /* Failed to re-open directory: no directory entry in memory */
474
+ dirp->cached = 0;
475
+ datap = NULL;
476
+
477
+ }
478
+ return datap;
479
+ }
480
+
481
+ /* Get next directory entry (internal) */
482
+ static WIN32_FIND_DATAW*
483
+ dirent_next(
484
+ _WDIR *dirp)
485
+ {
486
+ WIN32_FIND_DATAW *p;
487
+
488
+ /* Get next directory entry */
489
+ if (dirp->cached != 0) {
490
+
491
+ /* A valid directory entry already in memory */
492
+ p = &dirp->data;
493
+ dirp->cached = 0;
494
+
495
+ } else if (dirp->handle != INVALID_HANDLE_VALUE) {
496
+
497
+ /* Get the next directory entry from stream */
498
+ if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
499
+ /* Got a file */
500
+ p = &dirp->data;
501
+ } else {
502
+ /* The very last entry has been processed or an error occured */
503
+ FindClose (dirp->handle);
504
+ dirp->handle = INVALID_HANDLE_VALUE;
505
+ p = NULL;
506
+ }
507
+
508
+ } else {
509
+
510
+ /* End of directory stream reached */
511
+ p = NULL;
512
+
513
+ }
514
+
515
+ return p;
516
+ }
517
+
518
+ /*
519
+ * Open directory stream using plain old C-string.
520
+ */
521
+ static DIR*
522
+ opendir(
523
+ const char *dirname)
524
+ {
525
+ struct DIR *dirp;
526
+ int error;
527
+
528
+ /* Must have directory name */
529
+ if (dirname == NULL || dirname[0] == '\0') {
530
+ dirent_set_errno (ENOENT);
531
+ return NULL;
532
+ }
533
+
534
+ /* Allocate memory for DIR structure */
535
+ dirp = (DIR*) malloc (sizeof (struct DIR));
536
+ if (dirp) {
537
+ wchar_t wname[PATH_MAX];
538
+ size_t n;
539
+
540
+ /* Convert directory name to wide-character string */
541
+ error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);
542
+ if (!error) {
543
+
544
+ /* Open directory stream using wide-character name */
545
+ dirp->wdirp = _wopendir (wname);
546
+ if (dirp->wdirp) {
547
+ /* Directory stream opened */
548
+ error = 0;
549
+ } else {
550
+ /* Failed to open directory stream */
551
+ error = 1;
552
+ }
553
+
554
+ } else {
555
+ /*
556
+ * Cannot convert file name to wide-character string. This
557
+ * occurs if the string contains invalid multi-byte sequences or
558
+ * the output buffer is too small to contain the resulting
559
+ * string.
560
+ */
561
+ error = 1;
562
+ }
563
+
564
+ } else {
565
+ /* Cannot allocate DIR structure */
566
+ error = 1;
567
+ }
568
+
569
+ /* Clean up in case of error */
570
+ if (error && dirp) {
571
+ free (dirp);
572
+ dirp = NULL;
573
+ }
574
+
575
+ return dirp;
576
+ }
577
+
578
+ /*
579
+ * Read next directory entry.
580
+ *
581
+ * When working with text consoles, please note that file names returned by
582
+ * readdir() are represented in the default ANSI code page while any output to
583
+ * console is typically formatted on another code page. Thus, non-ASCII
584
+ * characters in file names will not usually display correctly on console. The
585
+ * problem can be fixed in two ways: (1) change the character set of console
586
+ * to 1252 using chcp utility and use Lucida Console font, or (2) use
587
+ * _cprintf function when writing to console. The _cprinf() will re-encode
588
+ * ANSI strings to the console code page so many non-ASCII characters will
589
+ * display correcly.
590
+ */
591
+ static struct dirent*
592
+ readdir(
593
+ DIR *dirp)
594
+ {
595
+ WIN32_FIND_DATAW *datap;
596
+ struct dirent *entp;
597
+
598
+ /* Read next directory entry */
599
+ datap = dirent_next (dirp->wdirp);
600
+ if (datap) {
601
+ size_t n;
602
+ int error;
603
+
604
+ /* Attempt to convert file name to multi-byte string */
605
+ error = dirent_wcstombs_s(
606
+ &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
607
+
608
+ /*
609
+ * If the file name cannot be represented by a multi-byte string,
610
+ * then attempt to use old 8+3 file name. This allows traditional
611
+ * Unix-code to access some file names despite of unicode
612
+ * characters, although file names may seem unfamiliar to the user.
613
+ *
614
+ * Be ware that the code below cannot come up with a short file
615
+ * name unless the file system provides one. At least
616
+ * VirtualBox shared folders fail to do this.
617
+ */
618
+ if (error && datap->cAlternateFileName[0] != '\0') {
619
+ error = dirent_wcstombs_s(
620
+ &n, dirp->ent.d_name, PATH_MAX,
621
+ datap->cAlternateFileName, PATH_MAX);
622
+ }
623
+
624
+ if (!error) {
625
+ DWORD attr;
626
+
627
+ /* Initialize directory entry for return */
628
+ entp = &dirp->ent;
629
+
630
+ /* Length of file name excluding zero terminator */
631
+ entp->d_namlen = n - 1;
632
+
633
+ /* File attributes */
634
+ attr = datap->dwFileAttributes;
635
+ if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
636
+ entp->d_type = DT_CHR;
637
+ } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
638
+ entp->d_type = DT_DIR;
639
+ } else {
640
+ entp->d_type = DT_REG;
641
+ }
642
+
643
+ /* Reset dummy fields */
644
+ entp->d_ino = 0;
645
+ entp->d_reclen = sizeof (struct dirent);
646
+
647
+ } else {
648
+ /*
649
+ * Cannot convert file name to multi-byte string so construct
650
+ * an errornous directory entry and return that. Note that
651
+ * we cannot return NULL as that would stop the processing
652
+ * of directory entries completely.
653
+ */
654
+ entp = &dirp->ent;
655
+ entp->d_name[0] = '?';
656
+ entp->d_name[1] = '\0';
657
+ entp->d_namlen = 1;
658
+ entp->d_type = DT_UNKNOWN;
659
+ entp->d_ino = 0;
660
+ entp->d_reclen = 0;
661
+ }
662
+
663
+ } else {
664
+ /* No more directory entries */
665
+ entp = NULL;
666
+ }
667
+
668
+ return entp;
669
+ }
670
+
671
+ /*
672
+ * Close directory stream.
673
+ */
674
+ static int
675
+ closedir(
676
+ DIR *dirp)
677
+ {
678
+ int ok;
679
+ if (dirp) {
680
+
681
+ /* Close wide-character directory stream */
682
+ ok = _wclosedir (dirp->wdirp);
683
+ dirp->wdirp = NULL;
684
+
685
+ /* Release multi-byte character version */
686
+ free (dirp);
687
+
688
+ } else {
689
+
690
+ /* Invalid directory stream */
691
+ dirent_set_errno (EBADF);
692
+ ok = /*failure*/-1;
693
+
694
+ }
695
+ return ok;
696
+ }
697
+
698
+ /*
699
+ * Rewind directory stream to beginning.
700
+ */
701
+ static void
702
+ rewinddir(
703
+ DIR* dirp)
704
+ {
705
+ /* Rewind wide-character string directory stream */
706
+ _wrewinddir (dirp->wdirp);
707
+ }
708
+
709
+ /* Convert multi-byte string to wide character string */
710
+ static int
711
+ dirent_mbstowcs_s(
712
+ size_t *pReturnValue,
713
+ wchar_t *wcstr,
714
+ size_t sizeInWords,
715
+ const char *mbstr,
716
+ size_t count)
717
+ {
718
+ int error;
719
+
720
+ #if defined(_MSC_VER) && _MSC_VER >= 1400
721
+
722
+ /* Microsoft Visual Studio 2005 or later */
723
+ error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
724
+
725
+ #else
726
+
727
+ /* Older Visual Studio or non-Microsoft compiler */
728
+ size_t n;
729
+
730
+ /* Convert to wide-character string (or count characters) */
731
+ n = mbstowcs (wcstr, mbstr, sizeInWords);
732
+ if (!wcstr || n < count) {
733
+
734
+ /* Zero-terminate output buffer */
735
+ if (wcstr && sizeInWords) {
736
+ if (n >= sizeInWords) {
737
+ n = sizeInWords - 1;
738
+ }
739
+ wcstr[n] = 0;
740
+ }
741
+
742
+ /* Length of resuting multi-byte string WITH zero terminator */
743
+ if (pReturnValue) {
744
+ *pReturnValue = n + 1;
745
+ }
746
+
747
+ /* Success */
748
+ error = 0;
749
+
750
+ } else {
751
+
752
+ /* Could not convert string */
753
+ error = 1;
754
+
755
+ }
756
+
757
+ #endif
758
+
759
+ return error;
760
+ }
761
+
762
+ /* Convert wide-character string to multi-byte string */
763
+ static int
764
+ dirent_wcstombs_s(
765
+ size_t *pReturnValue,
766
+ char *mbstr,
767
+ size_t sizeInBytes, /* max size of mbstr */
768
+ const wchar_t *wcstr,
769
+ size_t count)
770
+ {
771
+ int error;
772
+
773
+ #if defined(_MSC_VER) && _MSC_VER >= 1400
774
+
775
+ /* Microsoft Visual Studio 2005 or later */
776
+ error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
777
+
778
+ #else
779
+
780
+ /* Older Visual Studio or non-Microsoft compiler */
781
+ size_t n;
782
+
783
+ /* Convert to multi-byte string (or count the number of bytes needed) */
784
+ n = wcstombs (mbstr, wcstr, sizeInBytes);
785
+ if (!mbstr || n < count) {
786
+
787
+ /* Zero-terminate output buffer */
788
+ if (mbstr && sizeInBytes) {
789
+ if (n >= sizeInBytes) {
790
+ n = sizeInBytes - 1;
791
+ }
792
+ mbstr[n] = '\0';
793
+ }
794
+
795
+ /* Lenght of resulting multi-bytes string WITH zero-terminator */
796
+ if (pReturnValue) {
797
+ *pReturnValue = n + 1;
798
+ }
799
+
800
+ /* Success */
801
+ error = 0;
802
+
803
+ } else {
804
+
805
+ /* Cannot convert string */
806
+ error = 1;
807
+
808
+ }
809
+
810
+ #endif
811
+
812
+ return error;
813
+ }
814
+
815
+ /* Set errno variable */
816
+ static void
817
+ dirent_set_errno(
818
+ int error)
819
+ {
820
+ #if defined(_MSC_VER) && _MSC_VER >= 1400
821
+
822
+ /* Microsoft Visual Studio 2005 and later */
823
+ _set_errno (error);
824
+
825
+ #else
826
+
827
+ /* Non-Microsoft compiler or older Microsoft compiler */
828
+ errno = error;
829
+
830
+ #endif
831
+ }
832
+
833
+
834
+ #ifdef __cplusplus
835
+ }
836
+ #endif
837
+ #endif /*DIRENT_H*/
838
+