Fossil SCM

type integrate latest version of dirent.h

jan.nijtmans 2012-12-12 22:03 trunk
Commit 8e50ff0c303872249114df3fd71f4ac4f0256d48
2 files changed +1 -1 +398 -204
+1 -1
--- src/checkin.c
+++ src/checkin.c
@@ -1144,11 +1144,11 @@
11441144
}
11451145
11461146
/* So that older versions of Fossil (that do not understand delta-
11471147
** manifest) can continue to use this repository, do not create a new
11481148
** delta-manifest unless this repository already contains one or more
1149
- ** delta-manifets, or unless the delta-manifest is explicitly requested
1149
+ ** delta-manifests, or unless the delta-manifest is explicitly requested
11501150
** by the --delta option.
11511151
*/
11521152
if( !forceDelta && !db_get_boolean("seen-delta-manifest",0) ){
11531153
forceBaseline = 1;
11541154
}
11551155
--- src/checkin.c
+++ src/checkin.c
@@ -1144,11 +1144,11 @@
1144 }
1145
1146 /* So that older versions of Fossil (that do not understand delta-
1147 ** manifest) can continue to use this repository, do not create a new
1148 ** delta-manifest unless this repository already contains one or more
1149 ** delta-manifets, or unless the delta-manifest is explicitly requested
1150 ** by the --delta option.
1151 */
1152 if( !forceDelta && !db_get_boolean("seen-delta-manifest",0) ){
1153 forceBaseline = 1;
1154 }
1155
--- src/checkin.c
+++ src/checkin.c
@@ -1144,11 +1144,11 @@
1144 }
1145
1146 /* So that older versions of Fossil (that do not understand delta-
1147 ** manifest) can continue to use this repository, do not create a new
1148 ** delta-manifest unless this repository already contains one or more
1149 ** delta-manifests, or unless the delta-manifest is explicitly requested
1150 ** by the --delta option.
1151 */
1152 if( !forceDelta && !db_get_boolean("seen-delta-manifest",0) ){
1153 forceBaseline = 1;
1154 }
1155
+398 -204
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -20,21 +20,24 @@
2020
* IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
2121
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2222
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2323
* OTHER DEALINGS IN THE SOFTWARE.
2424
*
25
+ *
26
+ * Version 1.13, Dec 12 2012, Toni Ronkko
27
+ * Use traditional 8+3 file name if the name cannot be represented in the
28
+ * default ANSI code page. Now compiles again with MSVC 6.0. Thanks to
29
+ * Konstantin Khomoutov for testing.
2530
*
2631
* Version 1.12.1, Oct 1 2012, Toni Ronkko
2732
* Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with
2833
* capital W) in order to maintain compatibility with MingW.
2934
*
3035
* Version 1.12, Sep 30 2012, Toni Ronkko
31
- * Define PATH_MAX and NAME_MAX.
32
- *
33
- * Added wide-character variants _wDIR, _wdirent, _wopendir(),
34
- * _wreaddir(), _wclosedir() and _wrewinddir(). Thanks to Edgar Buerkle
35
- * and Jan Nijtmans for ideas and code.
36
+ * Define PATH_MAX and NAME_MAX. Added wide-character variants _wDIR,
37
+ * _wdirent, _wopendir(), _wreaddir(), _wclosedir() and _wrewinddir().
38
+ * Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code.
3639
*
3740
* Do not include windows.h. This allows dirent.h to be integrated more
3841
* easily into programs using winsock. Thanks to Fernando Azaldegui.
3942
*
4043
* Version 1.11, Mar 15, 2011, Toni Ronkko
@@ -88,48 +91,72 @@
8891
*****************************************************************************/
8992
#ifndef DIRENT_H
9093
#define DIRENT_H
9194
9295
#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
93
-#define _X86_
96
+# define _X86_
9497
#endif
9598
#include <stdio.h>
9699
#include <stdarg.h>
97100
#include <windef.h>
98101
#include <winbase.h>
99102
#include <wchar.h>
100
-#include <winnls.h>
101103
#include <string.h>
102104
#include <stdlib.h>
105
+#include <malloc.h>
103106
#include <sys/types.h>
104107
#include <sys/stat.h>
105108
#include <errno.h>
106109
107
-/* Windows 8 wide-character string functions */
108
-#if (_WIN32_WINNT >= 0x0602)
109
-# include <stringapiset.h>
110
-#endif
110
+/* Indicates that d_type field is available in dirent structure */
111
+#define _DIRENT_HAVE_D_TYPE
112
+
113
+/* Indicates that d_namlen field is available in dirent structure */
114
+#define _DIRENT_HAVE_D_NAMLEN
111115
112116
/* Entries missing from MSVC 6.0 */
113117
#if !defined(FILE_ATTRIBUTE_DEVICE)
114
-# define FILE_ATTRIBUTE_DEVICE 0x40
118
+# define FILE_ATTRIBUTE_DEVICE 0x40
115119
#endif
116120
117121
/* File type and permission flags for stat() */
118
-#if defined(_MSC_VER) && !defined(S_IREAD)
122
+#if !defined(S_IFMT)
119123
# define S_IFMT _S_IFMT /* File type mask */
124
+#endif
125
+#if !defined(S_IFDIR)
120126
# define S_IFDIR _S_IFDIR /* Directory */
127
+#endif
128
+#if !defined(S_IFCHR)
121129
# define S_IFCHR _S_IFCHR /* Character device */
130
+#endif
131
+#if !defined(S_IFFIFO)
122132
# define S_IFFIFO _S_IFFIFO /* Pipe */
133
+#endif
134
+#if !defined(S_IFREG)
123135
# define S_IFREG _S_IFREG /* Regular file */
136
+#endif
137
+#if !defined(S_IREAD)
124138
# define S_IREAD _S_IREAD /* Read permission */
139
+#endif
140
+#if !defined(S_IWRITE)
125141
# define S_IWRITE _S_IWRITE /* Write permission */
142
+#endif
143
+#if !defined(S_IEXEC)
126144
# define S_IEXEC _S_IEXEC /* Execute permission */
127145
#endif
128
-#define S_IFBLK 0 /* Block device */
129
-#define S_IFLNK 0 /* Link */
130
-#define S_IFSOCK 0 /* Socket */
146
+#if !defined(S_IFIFO)
147
+# define S_IFIFO _S_IFIFO /* Pipe */
148
+#endif
149
+#if !defined(S_IFBLK)
150
+# define S_IFBLK 0 /* Block device */
151
+#endif
152
+#if !defined(S_IFLNK)
153
+# define S_IFLNK 0 /* Link */
154
+#endif
155
+#if !defined(S_IFSOCK)
156
+# define S_IFSOCK 0 /* Socket */
157
+#endif
131158
132159
#if defined(_MSC_VER)
133160
# define S_IRUSR S_IREAD /* Read user */
134161
# define S_IWUSR S_IWRITE /* Write user */
135162
# define S_IXUSR 0 /* Execute user */
@@ -139,18 +166,26 @@
139166
# define S_IROTH 0 /* Read others */
140167
# define S_IWOTH 0 /* Write others */
141168
# define S_IXOTH 0 /* Execute others */
142169
#endif
143170
144
-/* Indicates that d_type field is available in dirent structure */
145
-#define _DIRENT_HAVE_D_TYPE
171
+/* Maximum length of file name */
172
+#if !defined(PATH_MAX)
173
+# define PATH_MAX MAX_PATH
174
+#endif
175
+#if !defined(FILENAME_MAX)
176
+# define FILENAME_MAX MAX_PATH
177
+#endif
178
+#if !defined(NAME_MAX)
179
+# define NAME_MAX FILENAME_MAX
180
+#endif
146181
147182
/* File type flags for d_type */
148183
#define DT_UNKNOWN 0
149184
#define DT_REG S_IFREG
150185
#define DT_DIR S_IFDIR
151
-#define DT_FIFO S_IFFIFO
186
+#define DT_FIFO S_IFIFO
152187
#define DT_SOCK S_IFSOCK
153188
#define DT_CHR S_IFCHR
154189
#define DT_BLK S_IFBLK
155190
156191
/* Macros for converting between st_mode and d_type */
@@ -161,41 +196,31 @@
161196
* File type macros. Note that block devices, sockets and links cannot be
162197
* distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
163198
* only defined for compatibility. These macros should always return false
164199
* on Windows.
165200
*/
166
-#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
201
+#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
167202
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
168203
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
169204
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
170205
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
171206
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
172207
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
173208
174
-/* For compatiblity with Unix */
175
-#if !defined(PATH_MAX)
176
-# define PATH_MAX MAX_PATH
177
-#endif
178
-#if !defined(FILENAME_MAX)
179
-# define FILENAME_MAX MAX_PATH
180
-#endif
181
-#if !defined(NAME_MAX)
182
-# define NAME_MAX FILENAME_MAX
183
-#endif
184
-
185
-/* Set errno variable */
186
-#if defined(_MSC_VER)
187
-#define DIRENT_SET_ERRNO(x) _set_errno (x)
188
-#else
189
-#define DIRENT_SET_ERRNO(x) (errno = (x))
190
-#endif
209
+/* Return the exact length of d_namlen without zero terminator */
210
+#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
211
+
212
+/* Return number of bytes needed to store d_namlen */
213
+#define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1)
214
+
191215
192216
#ifdef __cplusplus
193217
extern "C" {
194218
#endif
195219
196
-/* Wide-character versions */
220
+
221
+/* Wide-character version */
197222
struct _wdirent {
198223
long d_ino; /* Always zero */
199224
unsigned short d_reclen; /* Structure size */
200225
size_t d_namlen; /* Length of name without \0 */
201226
int d_type; /* File type */
@@ -203,11 +228,11 @@
203228
};
204229
typedef struct _wdirent _wdirent;
205230
206231
struct _WDIR {
207232
struct _wdirent ent; /* Current directory entry */
208
- WIN32_FIND_DATAW find_data; /* Private file data */
233
+ WIN32_FIND_DATAW data; /* Private file data */
209234
int cached; /* True if data is valid */
210235
HANDLE handle; /* Win32 search handle */
211236
wchar_t *patt; /* Initial directory name */
212237
};
213238
typedef struct _WDIR _WDIR;
@@ -214,10 +239,11 @@
214239
215240
static _WDIR *_wopendir (const wchar_t *dirname);
216241
static struct _wdirent *_wreaddir (_WDIR *dirp);
217242
static int _wclosedir (_WDIR *dirp);
218243
static void _wrewinddir (_WDIR* dirp);
244
+
219245
220246
/* For compatibility with Symbian */
221247
#define wdirent _wdirent
222248
#define WDIR _WDIR
223249
#define wopendir _wopendir
@@ -246,10 +272,30 @@
246272
static struct dirent *readdir (DIR *dirp);
247273
static int closedir (DIR *dirp);
248274
static void rewinddir (DIR* dirp);
249275
250276
277
+/* Internal utility functions */
278
+static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
279
+static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
280
+
281
+static int dirent_mbstowcs_s(
282
+ size_t *pReturnValue,
283
+ wchar_t *wcstr,
284
+ size_t sizeInWords,
285
+ const char *mbstr,
286
+ size_t count);
287
+
288
+static int dirent_wcstombs_s(
289
+ size_t *pReturnValue,
290
+ char *mbstr,
291
+ size_t sizeInBytes,
292
+ const wchar_t *wcstr,
293
+ size_t count);
294
+
295
+static void dirent_set_errno (int error);
296
+
251297
/*
252298
* Open directory stream DIRNAME for read and return a pointer to the
253299
* internal working area that is used to retrieve individual directory
254300
* entries.
255301
*/
@@ -256,31 +302,38 @@
256302
static _WDIR*
257303
_wopendir(
258304
const wchar_t *dirname)
259305
{
260306
_WDIR *dirp = NULL;
261
- int error = 0;
307
+ int error;
308
+
309
+ /* Must have directory name */
310
+ if (dirname == NULL || dirname[0] == '\0') {
311
+ dirent_set_errno (ENOENT);
312
+ return NULL;
313
+ }
262314
263315
/* Allocate new _WDIR structure */
264316
dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
265317
if (dirp != NULL) {
266318
DWORD n;
267319
268320
/* Reset _WDIR structure */
269321
dirp->handle = INVALID_HANDLE_VALUE;
270322
dirp->patt = NULL;
323
+ dirp->cached = 0;
271324
272325
/* Compute the length of full path plus zero terminator */
273326
n = GetFullPathNameW (dirname, 0, NULL, NULL);
274327
275
- /* Allocate room for full path and search patterns */
328
+ /* Allocate room for absolute directory name and search pattern */
276329
dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
277330
if (dirp->patt) {
278331
279332
/*
280333
* Convert relative directory name to an absolute one. This
281
- * allows rewinddir() to function correctly when the current
334
+ * allows rewinddir() to function correctly even when current
282335
* working directory is changed between opendir() and rewinddir().
283336
*/
284337
n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
285338
if (n > 0) {
286339
wchar_t *p;
@@ -303,25 +356,22 @@
303356
}
304357
*p++ = '*';
305358
*p = '\0';
306359
307360
/* Open directory stream and retrieve the first entry */
308
- dirp->handle = FindFirstFileW (dirp->patt, &dirp->find_data);
309
- if (dirp->handle != INVALID_HANDLE_VALUE) {
310
-
311
- /* Directory entry is now waiting in memory */
312
- dirp->cached = 1;
313
-
361
+ if (dirent_first (dirp)) {
362
+ /* Directory stream opened successfully */
363
+ error = 0;
314364
} else {
315
- /* Search pattern is not a directory name? */
316
- DIRENT_SET_ERRNO (ENOENT);
365
+ /* Cannot retrieve first entry */
317366
error = 1;
367
+ dirent_set_errno (ENOENT);
318368
}
319369
320370
} else {
321
- /* Cannot convert directory name to wide character string */
322
- DIRENT_SET_ERRNO (ENOENT);
371
+ /* Cannot retrieve full path name */
372
+ dirent_set_errno (ENOENT);
323373
error = 1;
324374
}
325375
326376
} else {
327377
/* Cannot allocate memory for search pattern */
@@ -350,70 +400,59 @@
350400
*/
351401
static struct _wdirent*
352402
_wreaddir(
353403
_WDIR *dirp)
354404
{
355
- DWORD attr;
356
- errno_t error;
357
-
358
- /* Get next directory entry */
359
- if (dirp->cached != 0) {
360
- /* A valid directory entry already in memory */
361
- dirp->cached = 0;
362
- } else {
363
- /* Get the next directory entry from stream */
364
- if (dirp->handle == INVALID_HANDLE_VALUE) {
365
- return NULL;
366
- }
367
- if (FindNextFileW (dirp->handle, &dirp->find_data) == FALSE) {
368
- /* The very last entry has been processed or an error occured */
369
- FindClose (dirp->handle);
370
- dirp->handle = INVALID_HANDLE_VALUE;
371
- return NULL;
372
- }
373
- }
374
-
375
- /* Copy file name as a wide-character string */
376
- error = wcsncpy_s(
377
- dirp->ent.d_name, /* Destination string */
378
- PATH_MAX, /* Size of dest in words */
379
- dirp->find_data.cFileName, /* Source string */
380
- PATH_MAX + 1); /* Max # of chars to copy */
381
- if (!error) {
382
-
383
- /* Compute the length of name */
384
- dirp->ent.d_namlen = wcsnlen (dirp->ent.d_name, PATH_MAX);
385
-
386
- /* Determine file type */
387
- attr = dirp->find_data.dwFileAttributes;
405
+ WIN32_FIND_DATAW *datap;
406
+ struct _wdirent *entp;
407
+
408
+ /* Read next directory entry */
409
+ datap = dirent_next (dirp);
410
+ if (datap) {
411
+ size_t n;
412
+ DWORD attr;
413
+
414
+ /* Pointer to directory entry to return */
415
+ entp = &dirp->ent;
416
+
417
+ /*
418
+ * Copy file name as wide-character string. If the file name is too
419
+ * long to fit in to the destination buffer, then truncate file name
420
+ * to PATH_MAX characters and zero-terminate the buffer.
421
+ */
422
+ n = 0;
423
+ while (n < PATH_MAX && datap->cFileName[n] != 0) {
424
+ entp->d_name[n] = datap->cFileName[n];
425
+ n++;
426
+ }
427
+ dirp->ent.d_name[n] = 0;
428
+
429
+ /* Length of file name excluding zero terminator */
430
+ entp->d_namlen = n;
431
+
432
+ /* File type */
433
+ attr = datap->dwFileAttributes;
388434
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
389
- dirp->ent.d_type = DT_CHR;
435
+ entp->d_type = DT_CHR;
390436
} else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
391
- dirp->ent.d_type = DT_DIR;
437
+ entp->d_type = DT_DIR;
392438
} else {
393
- dirp->ent.d_type = DT_REG;
439
+ entp->d_type = DT_REG;
394440
}
395441
396442
/* Reset dummy fields */
397
- dirp->ent.d_ino = 0;
398
- dirp->ent.d_reclen = sizeof (dirp->ent);
443
+ entp->d_ino = 0;
444
+ entp->d_reclen = sizeof (struct _wdirent);
399445
400446
} else {
401447
402
- /*
403
- * Cannot copy file name from find_data to ent. Construct a
404
- * dummy _wdirent structure to pass error to caller.
405
- */
406
- dirp->ent.d_name[0] = '?';
407
- dirp->ent.d_name[1] = '\0';
408
- dirp->ent.d_namlen = 1;
409
- dirp->ent.d_type = DT_UNKNOWN;
410
- dirp->ent.d_ino = 0;
411
- dirp->ent.d_reclen = 0;
448
+ /* Last directory entry read */
449
+ entp = NULL;
450
+
412451
}
413452
414
- return &dirp->ent;
453
+ return entp;
415454
}
416455
417456
/*
418457
* Close directory stream opened by opendir() function. This invalidates the
419458
* DIR structure as well as any directory entry read previously by
@@ -442,11 +481,11 @@
442481
free (dirp);
443482
ok = /*success*/0;
444483
445484
} else {
446485
/* Invalid directory stream */
447
- DIRENT_SET_ERRNO (EBADF);
486
+ dirent_set_errno (EBADF);
448487
ok = /*failure*/-1;
449488
}
450489
return ok;
451490
}
452491
@@ -456,26 +495,81 @@
456495
*/
457496
static void
458497
_wrewinddir(
459498
_WDIR* dirp)
460499
{
461
- if (dirp != NULL) {
462
- /* release search handle */
500
+ if (dirp) {
501
+ /* Release existing search handle */
463502
if (dirp->handle != INVALID_HANDLE_VALUE) {
464503
FindClose (dirp->handle);
465504
}
466505
467
- /* Open new search handle and retrieve the first directory entry */
468
- dirp->handle = FindFirstFileW (dirp->patt, &dirp->find_data);
469
- if (dirp->handle != INVALID_HANDLE_VALUE) {
470
- /* a directory entry is now waiting in memory */
471
- dirp->cached = 1;
506
+ /* Open new search handle */
507
+ dirent_first (dirp);
508
+ }
509
+}
510
+
511
+/* Get first directory entry (internal) */
512
+static WIN32_FIND_DATAW*
513
+dirent_first(
514
+ _WDIR *dirp)
515
+{
516
+ WIN32_FIND_DATAW *datap;
517
+
518
+ /* Open directory and retrieve the first entry */
519
+ dirp->handle = FindFirstFileW (dirp->patt, &dirp->data);
520
+ if (dirp->handle != INVALID_HANDLE_VALUE) {
521
+
522
+ /* a directory entry is now waiting in memory */
523
+ datap = &dirp->data;
524
+ dirp->cached = 1;
525
+
526
+ } else {
527
+
528
+ /* Failed to re-open directory: no directory entry in memory */
529
+ dirp->cached = 0;
530
+ datap = NULL;
531
+
532
+ }
533
+ return datap;
534
+}
535
+
536
+/* Get next directory entry (internal) */
537
+static WIN32_FIND_DATAW*
538
+dirent_next(
539
+ _WDIR *dirp)
540
+{
541
+ WIN32_FIND_DATAW *p;
542
+
543
+ /* Get next directory entry */
544
+ if (dirp->cached != 0) {
545
+
546
+ /* A valid directory entry already in memory */
547
+ p = &dirp->data;
548
+ dirp->cached = 0;
549
+
550
+ } else if (dirp->handle != INVALID_HANDLE_VALUE) {
551
+
552
+ /* Get the next directory entry from stream */
553
+ if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
554
+ /* Got a file */
555
+ p = &dirp->data;
472556
} else {
473
- /* Failed to re-open directory: no directory entry in memory */
474
- dirp->cached = 0;
557
+ /* The very last entry has been processed or an error occured */
558
+ FindClose (dirp->handle);
559
+ dirp->handle = INVALID_HANDLE_VALUE;
560
+ p = NULL;
475561
}
562
+
563
+ } else {
564
+
565
+ /* End of directory stream reached */
566
+ p = NULL;
567
+
476568
}
569
+
570
+ return p;
477571
}
478572
479573
/*
480574
* Open directory stream using plain old C-string.
481575
*/
@@ -482,58 +576,34 @@
482576
static DIR*
483577
opendir(
484578
const char *dirname)
485579
{
486580
struct DIR *dirp;
487
- errno_t error = 0;
581
+ int error;
488582
489583
/* Must have directory name */
490
- if (dirname == NULL) {
491
- DIRENT_SET_ERRNO (ENOENT);
584
+ if (dirname == NULL || dirname[0] == '\0') {
585
+ dirent_set_errno (ENOENT);
492586
return NULL;
493587
}
494588
495
- /* Allocate memory for multi-byte string directory structures */
589
+ /* Allocate memory for DIR structure */
496590
dirp = (DIR*) malloc (sizeof (struct DIR));
497591
if (dirp) {
498592
wchar_t wname[PATH_MAX + 1];
499593
size_t n;
500594
501
- /*
502
- * Convert directory name to wide-character string.
503
- *
504
- * Be ware of the return schemantics of MultiByteToWideChar() --
505
- * the function basically returns the number of characters written to
506
- * output buffer or zero if the conversion fails. However, the
507
- * function does not necessarily zero-terminate the output
508
- * buffer and may return 0xFFFD if the string contains invalid
509
- * characters!
510
- */
511
- n = MultiByteToWideChar(
512
- CP_ACP, /* Input code page */
513
- MB_PRECOMPOSED, /* Conversion flags */
514
- dirname, /* Input string */
515
- -1, /* Length of input string */
516
- wname, /* Output buffer */
517
- PATH_MAX); /* Size of output buffer */
518
- if (n > 0 && n < PATH_MAX) {
519
-
520
- /* Zero-terminate output buffer */
521
- wname[n] = '\0';
522
-
523
- /* Open directory stream with wide-character string file name */
595
+ /* Convert directory name to wide-character string */
596
+ error = dirent_mbstowcs_s(
597
+ &n, wname, PATH_MAX + 1, dirname, PATH_MAX);
598
+ if (!error) {
599
+
600
+ /* Open directory stream using wide-character name */
524601
dirp->wdirp = _wopendir (wname);
525602
if (dirp->wdirp) {
526
-
527
- /* Initialize directory structure */
528
- dirp->ent.d_name[0] = '\0';
529
- dirp->ent.d_namlen = 0;
530
- dirp->ent.d_type = 0;
531
- dirp->ent.d_ino = 0;
532
- dirp->ent.d_reclen = 0;
533
-
534
-
603
+ /* Directory stream opened */
604
+ error = 0;
535605
} else {
536606
/* Failed to open directory stream */
537607
error = 1;
538608
}
539609
@@ -562,95 +632,99 @@
562632
}
563633
564634
/*
565635
* Read next directory entry.
566636
*
567
- * When working with console, please note that file names returned by
568
- * readdir() are represented in the default ANSI code page while the
569
- * console typically runs on another code page. Thus, non-ASCII characters
570
- * will not usually display correctly. The problem can be fixed in two ways:
571
- * (1) change the character set of console to 1252 using chcp utility and use
572
- * Lucida Console font, or (2) always use _cprintf function when writing to
573
- * console. The _cprinf() will re-encode ANSI strings to the console code
574
- * page so non-ASCII characters will display correcly.
637
+ * When working with text consoles, please note that file names returned by
638
+ * readdir() are represented in the default ANSI code page while any output to
639
+ * console is typically formatted on another code page. Thus, non-ASCII
640
+ * characters in file names will not usually display correctly on console. The
641
+ * problem can be fixed in two ways: (1) change the character set of console
642
+ * to 1252 using chcp utility and use Lucida Console font, or (2) use
643
+ * _cprintf function when writing to console. The _cprinf() will re-encode
644
+ * ANSI strings to the console code page so many non-ASCII characters will
645
+ * display correcly.
575646
*/
576647
static struct dirent*
577648
readdir(
578649
DIR *dirp)
579650
{
580
- struct dirent *p;
581
- struct _wdirent *wp;
651
+ WIN32_FIND_DATAW *datap;
652
+ struct dirent *entp;
582653
583
- /* Read next directory entry using wide-character string functions */
584
- wp = _wreaddir (dirp->wdirp);
585
- if (wp) {
654
+ /* Read next directory entry */
655
+ datap = dirent_next (dirp->wdirp);
656
+ if (datap) {
586657
size_t n;
658
+ int error;
659
+
660
+ /* Attempt to convert file name to multi-byte string */
661
+ error = dirent_wcstombs_s(
662
+ &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);
587663
588664
/*
589
- * Convert file name to multi-byte string.
590
- *
591
- * Be ware of the return schemantics of WideCharToMultiByte() --
592
- * the function basically returns the number of bytes
593
- * written to output buffer or zero if the conversion fails.
594
- * However, the function does not necessarily zero-terminate the
595
- * buffer and it may even return 0xFFFD the string contains
596
- * invalid characters!
665
+ * If the file name cannot be represented by a multi-byte string,
666
+ * then attempt to use old 8+3 file name. This allows traditional
667
+ * Unix-code to access some file names despite of unicode
668
+ * characters, although file names may seem unfamiliar to the user.
669
+ *
670
+ * Be ware that the code below cannot come up with a short file
671
+ * name unless the file system provides one. At least
672
+ * VirtualBox shared folders fail to do this.
597673
*/
598
- n = WideCharToMultiByte(
599
- CP_ACP, /* Output code page */
600
- 0, /* Conversion flags */
601
- wp->d_name, /* Input string */
602
- wp->d_namlen, /* Length of input string */
603
- dirp->ent.d_name, /* Output buffer */
604
- PATH_MAX, /* Size of output buffer */
605
- NULL, /* Replacement character */
606
- NULL); /* If chars were replaced */
607
- if (n > 0 && n < PATH_MAX) {
608
-
609
- /* Zero-terminate buffer */
610
- dirp->ent.d_name[n] = '\0';
674
+ if (error && datap->cAlternateFileName[0] != '\0') {
675
+ error = dirent_wcstombs_s(
676
+ &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
677
+ sizeof (datap->cAlternateFileName) /
678
+ sizeof (datap->cAlternateFileName[0]));
679
+ }
680
+
681
+ if (!error) {
682
+ DWORD attr;
611683
612684
/* Initialize directory entry for return */
613
- p = &dirp->ent;
685
+ entp = &dirp->ent;
614686
615
- /* Compute length */
616
- p->d_namlen = strnlen (dirp->ent.d_name, PATH_MAX);
687
+ /* Length of file name excluding zero terminator */
688
+ entp->d_namlen = n - 1;
617689
618
- /* Copy file attributes */
619
- p->d_type = wp->d_type;
690
+ /* File attributes */
691
+ attr = datap->dwFileAttributes;
692
+ if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
693
+ entp->d_type = DT_CHR;
694
+ } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
695
+ entp->d_type = DT_DIR;
696
+ } else {
697
+ entp->d_type = DT_REG;
698
+ }
620699
621700
/* Reset dummy fields */
622
- p->d_ino = 0;
623
- p->d_reclen = sizeof (dirp->ent);
624
-
701
+ entp->d_ino = 0;
702
+ entp->d_reclen = sizeof (struct dirent);
625703
626704
} else {
627
-
628705
/*
629706
* Cannot convert file name to multi-byte string so construct
630707
* an errornous directory entry and return that. Note that
631708
* we cannot return NULL as that would stop the processing
632709
* of directory entries completely.
633710
*/
634
- p = &dirp->ent;
635
- p->d_name[0] = '?';
636
- p->d_name[1] = '\0';
637
- p->d_namlen = 1;
638
- p->d_type = DT_UNKNOWN;
639
- p->d_ino = 0;
640
- p->d_reclen = 0;
641
-
711
+ entp = &dirp->ent;
712
+ entp->d_name[0] = '?';
713
+ entp->d_name[1] = '\0';
714
+ entp->d_namlen = 1;
715
+ entp->d_type = DT_UNKNOWN;
716
+ entp->d_ino = 0;
717
+ entp->d_reclen = 0;
642718
}
643719
644720
} else {
645
-
646
- /* End of directory stream */
647
- p = NULL;
648
-
721
+ /* No more directory entries */
722
+ entp = NULL;
649723
}
650724
651
- return p;
725
+ return entp;
652726
}
653727
654728
/*
655729
* Close directory stream.
656730
*/
@@ -667,13 +741,15 @@
667741
668742
/* Release multi-byte character version */
669743
free (dirp);
670744
671745
} else {
746
+
672747
/* Invalid directory stream */
673
- DIRENT_SET_ERRNO (EBADF);
748
+ dirent_set_errno (EBADF);
674749
ok = /*failure*/-1;
750
+
675751
}
676752
return ok;
677753
}
678754
679755
/*
@@ -684,12 +760,130 @@
684760
DIR* dirp)
685761
{
686762
/* Rewind wide-character string directory stream */
687763
_wrewinddir (dirp->wdirp);
688764
}
765
+
766
+/* Convert multi-byte string to wide character string */
767
+static int
768
+dirent_mbstowcs_s(
769
+ size_t *pReturnValue,
770
+ wchar_t *wcstr,
771
+ size_t sizeInWords,
772
+ const char *mbstr,
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 = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
781
+
782
+#else
783
+
784
+ /* Older Visual Studio or non-Microsoft compiler */
785
+ size_t n;
786
+
787
+ /* Convert to wide-character string */
788
+ n = mbstowcs (wcstr, mbstr, count);
789
+ if (n < sizeInWords) {
790
+
791
+ /* Zero-terminate output buffer */
792
+ if (wcstr) {
793
+ wcstr[n] = 0;
794
+ }
795
+
796
+ /* Length of resuting multi-byte string WITH zero terminator */
797
+ if (pReturnValue) {
798
+ *pReturnValue = n + 1;
799
+ }
800
+
801
+ /* Success */
802
+ error = 0;
803
+
804
+ } else {
805
+
806
+ /* Could not convert string */
807
+ error = 1;
808
+
809
+ }
810
+
811
+#endif
812
+
813
+ return error;
814
+}
815
+
816
+/* Convert wide-character string to multi-byte string */
817
+static int
818
+dirent_wcstombs_s(
819
+ size_t *pReturnValue,
820
+ char *mbstr,
821
+ size_t sizeInBytes,
822
+ const wchar_t *wcstr,
823
+ size_t count)
824
+{
825
+ int error;
826
+
827
+#if defined(_MSC_VER) && _MSC_VER >= 1400
828
+
829
+ /* Microsoft Visual Studio 2005 or later */
830
+ error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
831
+
832
+#else
833
+
834
+ /* Older Visual Studio or non-Microsoft compiler */
835
+ size_t n;
836
+
837
+ /* Convert to multi-byte string */
838
+ n = wcstombs (mbstr, wcstr, count);
839
+ if (n < sizeInBytes) {
840
+
841
+ /* Zero-terminate output buffer */
842
+ if (mbstr) {
843
+ mbstr[n] = '\0';
844
+ }
845
+
846
+ /* Lenght of resulting multi-bytes string WITH zero-terminator */
847
+ if (pReturnValue) {
848
+ *pReturnValue = n + 1;
849
+ }
850
+
851
+ /* Success */
852
+ error = 0;
853
+
854
+ } else {
855
+
856
+ /* Cannot convert string */
857
+ error = 1;
858
+
859
+ }
860
+
861
+#endif
862
+
863
+ return error;
864
+}
865
+
866
+/* Set errno variable */
867
+static void
868
+dirent_set_errno(
869
+ int error)
870
+{
871
+#if defined(_MSC_VER)
872
+
873
+ /* Microsoft Visual Studio */
874
+ _set_errno (error);
875
+
876
+#else
877
+
878
+ /* Non-Microsoft compiler */
879
+ errno = error;
880
+
881
+#endif
882
+}
689883
690884
691885
#ifdef __cplusplus
692886
}
693887
#endif
694888
#endif /*DIRENT_H*/
695889
696890
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -20,21 +20,24 @@
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 *
26 * Version 1.12.1, Oct 1 2012, Toni Ronkko
27 * Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with
28 * capital W) in order to maintain compatibility with MingW.
29 *
30 * Version 1.12, Sep 30 2012, Toni Ronkko
31 * Define PATH_MAX and NAME_MAX.
32 *
33 * Added wide-character variants _wDIR, _wdirent, _wopendir(),
34 * _wreaddir(), _wclosedir() and _wrewinddir(). Thanks to Edgar Buerkle
35 * and Jan Nijtmans for ideas and code.
36 *
37 * Do not include windows.h. This allows dirent.h to be integrated more
38 * easily into programs using winsock. Thanks to Fernando Azaldegui.
39 *
40 * Version 1.11, Mar 15, 2011, Toni Ronkko
@@ -88,48 +91,72 @@
88 *****************************************************************************/
89 #ifndef DIRENT_H
90 #define DIRENT_H
91
92 #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
93 #define _X86_
94 #endif
95 #include <stdio.h>
96 #include <stdarg.h>
97 #include <windef.h>
98 #include <winbase.h>
99 #include <wchar.h>
100 #include <winnls.h>
101 #include <string.h>
102 #include <stdlib.h>
 
103 #include <sys/types.h>
104 #include <sys/stat.h>
105 #include <errno.h>
106
107 /* Windows 8 wide-character string functions */
108 #if (_WIN32_WINNT >= 0x0602)
109 # include <stringapiset.h>
110 #endif
 
111
112 /* Entries missing from MSVC 6.0 */
113 #if !defined(FILE_ATTRIBUTE_DEVICE)
114 # define FILE_ATTRIBUTE_DEVICE 0x40
115 #endif
116
117 /* File type and permission flags for stat() */
118 #if defined(_MSC_VER) && !defined(S_IREAD)
119 # define S_IFMT _S_IFMT /* File type mask */
 
 
120 # define S_IFDIR _S_IFDIR /* Directory */
 
 
121 # define S_IFCHR _S_IFCHR /* Character device */
 
 
122 # define S_IFFIFO _S_IFFIFO /* Pipe */
 
 
123 # define S_IFREG _S_IFREG /* Regular file */
 
 
124 # define S_IREAD _S_IREAD /* Read permission */
 
 
125 # define S_IWRITE _S_IWRITE /* Write permission */
 
 
126 # define S_IEXEC _S_IEXEC /* Execute permission */
127 #endif
128 #define S_IFBLK 0 /* Block device */
129 #define S_IFLNK 0 /* Link */
130 #define S_IFSOCK 0 /* Socket */
 
 
 
 
 
 
 
 
 
131
132 #if defined(_MSC_VER)
133 # define S_IRUSR S_IREAD /* Read user */
134 # define S_IWUSR S_IWRITE /* Write user */
135 # define S_IXUSR 0 /* Execute user */
@@ -139,18 +166,26 @@
139 # define S_IROTH 0 /* Read others */
140 # define S_IWOTH 0 /* Write others */
141 # define S_IXOTH 0 /* Execute others */
142 #endif
143
144 /* Indicates that d_type field is available in dirent structure */
145 #define _DIRENT_HAVE_D_TYPE
 
 
 
 
 
 
 
 
146
147 /* File type flags for d_type */
148 #define DT_UNKNOWN 0
149 #define DT_REG S_IFREG
150 #define DT_DIR S_IFDIR
151 #define DT_FIFO S_IFFIFO
152 #define DT_SOCK S_IFSOCK
153 #define DT_CHR S_IFCHR
154 #define DT_BLK S_IFBLK
155
156 /* Macros for converting between st_mode and d_type */
@@ -161,41 +196,31 @@
161 * File type macros. Note that block devices, sockets and links cannot be
162 * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
163 * only defined for compatibility. These macros should always return false
164 * on Windows.
165 */
166 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
167 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
168 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
169 #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
170 #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
171 #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
172 #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
173
174 /* For compatiblity with Unix */
175 #if !defined(PATH_MAX)
176 # define PATH_MAX MAX_PATH
177 #endif
178 #if !defined(FILENAME_MAX)
179 # define FILENAME_MAX MAX_PATH
180 #endif
181 #if !defined(NAME_MAX)
182 # define NAME_MAX FILENAME_MAX
183 #endif
184
185 /* Set errno variable */
186 #if defined(_MSC_VER)
187 #define DIRENT_SET_ERRNO(x) _set_errno (x)
188 #else
189 #define DIRENT_SET_ERRNO(x) (errno = (x))
190 #endif
191
192 #ifdef __cplusplus
193 extern "C" {
194 #endif
195
196 /* Wide-character versions */
 
197 struct _wdirent {
198 long d_ino; /* Always zero */
199 unsigned short d_reclen; /* Structure size */
200 size_t d_namlen; /* Length of name without \0 */
201 int d_type; /* File type */
@@ -203,11 +228,11 @@
203 };
204 typedef struct _wdirent _wdirent;
205
206 struct _WDIR {
207 struct _wdirent ent; /* Current directory entry */
208 WIN32_FIND_DATAW find_data; /* Private file data */
209 int cached; /* True if data is valid */
210 HANDLE handle; /* Win32 search handle */
211 wchar_t *patt; /* Initial directory name */
212 };
213 typedef struct _WDIR _WDIR;
@@ -214,10 +239,11 @@
214
215 static _WDIR *_wopendir (const wchar_t *dirname);
216 static struct _wdirent *_wreaddir (_WDIR *dirp);
217 static int _wclosedir (_WDIR *dirp);
218 static void _wrewinddir (_WDIR* dirp);
 
219
220 /* For compatibility with Symbian */
221 #define wdirent _wdirent
222 #define WDIR _WDIR
223 #define wopendir _wopendir
@@ -246,10 +272,30 @@
246 static struct dirent *readdir (DIR *dirp);
247 static int closedir (DIR *dirp);
248 static void rewinddir (DIR* dirp);
249
250
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251 /*
252 * Open directory stream DIRNAME for read and return a pointer to the
253 * internal working area that is used to retrieve individual directory
254 * entries.
255 */
@@ -256,31 +302,38 @@
256 static _WDIR*
257 _wopendir(
258 const wchar_t *dirname)
259 {
260 _WDIR *dirp = NULL;
261 int error = 0;
 
 
 
 
 
 
262
263 /* Allocate new _WDIR structure */
264 dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
265 if (dirp != NULL) {
266 DWORD n;
267
268 /* Reset _WDIR structure */
269 dirp->handle = INVALID_HANDLE_VALUE;
270 dirp->patt = NULL;
 
271
272 /* Compute the length of full path plus zero terminator */
273 n = GetFullPathNameW (dirname, 0, NULL, NULL);
274
275 /* Allocate room for full path and search patterns */
276 dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
277 if (dirp->patt) {
278
279 /*
280 * Convert relative directory name to an absolute one. This
281 * allows rewinddir() to function correctly when the current
282 * working directory is changed between opendir() and rewinddir().
283 */
284 n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
285 if (n > 0) {
286 wchar_t *p;
@@ -303,25 +356,22 @@
303 }
304 *p++ = '*';
305 *p = '\0';
306
307 /* Open directory stream and retrieve the first entry */
308 dirp->handle = FindFirstFileW (dirp->patt, &dirp->find_data);
309 if (dirp->handle != INVALID_HANDLE_VALUE) {
310
311 /* Directory entry is now waiting in memory */
312 dirp->cached = 1;
313
314 } else {
315 /* Search pattern is not a directory name? */
316 DIRENT_SET_ERRNO (ENOENT);
317 error = 1;
 
318 }
319
320 } else {
321 /* Cannot convert directory name to wide character string */
322 DIRENT_SET_ERRNO (ENOENT);
323 error = 1;
324 }
325
326 } else {
327 /* Cannot allocate memory for search pattern */
@@ -350,70 +400,59 @@
350 */
351 static struct _wdirent*
352 _wreaddir(
353 _WDIR *dirp)
354 {
355 DWORD attr;
356 errno_t error;
357
358 /* Get next directory entry */
359 if (dirp->cached != 0) {
360 /* A valid directory entry already in memory */
361 dirp->cached = 0;
362 } else {
363 /* Get the next directory entry from stream */
364 if (dirp->handle == INVALID_HANDLE_VALUE) {
365 return NULL;
366 }
367 if (FindNextFileW (dirp->handle, &dirp->find_data) == FALSE) {
368 /* The very last entry has been processed or an error occured */
369 FindClose (dirp->handle);
370 dirp->handle = INVALID_HANDLE_VALUE;
371 return NULL;
372 }
373 }
374
375 /* Copy file name as a wide-character string */
376 error = wcsncpy_s(
377 dirp->ent.d_name, /* Destination string */
378 PATH_MAX, /* Size of dest in words */
379 dirp->find_data.cFileName, /* Source string */
380 PATH_MAX + 1); /* Max # of chars to copy */
381 if (!error) {
382
383 /* Compute the length of name */
384 dirp->ent.d_namlen = wcsnlen (dirp->ent.d_name, PATH_MAX);
385
386 /* Determine file type */
387 attr = dirp->find_data.dwFileAttributes;
388 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
389 dirp->ent.d_type = DT_CHR;
390 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
391 dirp->ent.d_type = DT_DIR;
392 } else {
393 dirp->ent.d_type = DT_REG;
394 }
395
396 /* Reset dummy fields */
397 dirp->ent.d_ino = 0;
398 dirp->ent.d_reclen = sizeof (dirp->ent);
399
400 } else {
401
402 /*
403 * Cannot copy file name from find_data to ent. Construct a
404 * dummy _wdirent structure to pass error to caller.
405 */
406 dirp->ent.d_name[0] = '?';
407 dirp->ent.d_name[1] = '\0';
408 dirp->ent.d_namlen = 1;
409 dirp->ent.d_type = DT_UNKNOWN;
410 dirp->ent.d_ino = 0;
411 dirp->ent.d_reclen = 0;
412 }
413
414 return &dirp->ent;
415 }
416
417 /*
418 * Close directory stream opened by opendir() function. This invalidates the
419 * DIR structure as well as any directory entry read previously by
@@ -442,11 +481,11 @@
442 free (dirp);
443 ok = /*success*/0;
444
445 } else {
446 /* Invalid directory stream */
447 DIRENT_SET_ERRNO (EBADF);
448 ok = /*failure*/-1;
449 }
450 return ok;
451 }
452
@@ -456,26 +495,81 @@
456 */
457 static void
458 _wrewinddir(
459 _WDIR* dirp)
460 {
461 if (dirp != NULL) {
462 /* release search handle */
463 if (dirp->handle != INVALID_HANDLE_VALUE) {
464 FindClose (dirp->handle);
465 }
466
467 /* Open new search handle and retrieve the first directory entry */
468 dirp->handle = FindFirstFileW (dirp->patt, &dirp->find_data);
469 if (dirp->handle != INVALID_HANDLE_VALUE) {
470 /* a directory entry is now waiting in memory */
471 dirp->cached = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472 } else {
473 /* Failed to re-open directory: no directory entry in memory */
474 dirp->cached = 0;
 
 
475 }
 
 
 
 
 
 
476 }
 
 
477 }
478
479 /*
480 * Open directory stream using plain old C-string.
481 */
@@ -482,58 +576,34 @@
482 static DIR*
483 opendir(
484 const char *dirname)
485 {
486 struct DIR *dirp;
487 errno_t error = 0;
488
489 /* Must have directory name */
490 if (dirname == NULL) {
491 DIRENT_SET_ERRNO (ENOENT);
492 return NULL;
493 }
494
495 /* Allocate memory for multi-byte string directory structures */
496 dirp = (DIR*) malloc (sizeof (struct DIR));
497 if (dirp) {
498 wchar_t wname[PATH_MAX + 1];
499 size_t n;
500
501 /*
502 * Convert directory name to wide-character string.
503 *
504 * Be ware of the return schemantics of MultiByteToWideChar() --
505 * the function basically returns the number of characters written to
506 * output buffer or zero if the conversion fails. However, the
507 * function does not necessarily zero-terminate the output
508 * buffer and may return 0xFFFD if the string contains invalid
509 * characters!
510 */
511 n = MultiByteToWideChar(
512 CP_ACP, /* Input code page */
513 MB_PRECOMPOSED, /* Conversion flags */
514 dirname, /* Input string */
515 -1, /* Length of input string */
516 wname, /* Output buffer */
517 PATH_MAX); /* Size of output buffer */
518 if (n > 0 && n < PATH_MAX) {
519
520 /* Zero-terminate output buffer */
521 wname[n] = '\0';
522
523 /* Open directory stream with wide-character string file name */
524 dirp->wdirp = _wopendir (wname);
525 if (dirp->wdirp) {
526
527 /* Initialize directory structure */
528 dirp->ent.d_name[0] = '\0';
529 dirp->ent.d_namlen = 0;
530 dirp->ent.d_type = 0;
531 dirp->ent.d_ino = 0;
532 dirp->ent.d_reclen = 0;
533
534
535 } else {
536 /* Failed to open directory stream */
537 error = 1;
538 }
539
@@ -562,95 +632,99 @@
562 }
563
564 /*
565 * Read next directory entry.
566 *
567 * When working with console, please note that file names returned by
568 * readdir() are represented in the default ANSI code page while the
569 * console typically runs on another code page. Thus, non-ASCII characters
570 * will not usually display correctly. The problem can be fixed in two ways:
571 * (1) change the character set of console to 1252 using chcp utility and use
572 * Lucida Console font, or (2) always use _cprintf function when writing to
573 * console. The _cprinf() will re-encode ANSI strings to the console code
574 * page so non-ASCII characters will display correcly.
 
575 */
576 static struct dirent*
577 readdir(
578 DIR *dirp)
579 {
580 struct dirent *p;
581 struct _wdirent *wp;
582
583 /* Read next directory entry using wide-character string functions */
584 wp = _wreaddir (dirp->wdirp);
585 if (wp) {
586 size_t n;
 
 
 
 
 
587
588 /*
589 * Convert file name to multi-byte string.
590 *
591 * Be ware of the return schemantics of WideCharToMultiByte() --
592 * the function basically returns the number of bytes
593 * written to output buffer or zero if the conversion fails.
594 * However, the function does not necessarily zero-terminate the
595 * buffer and it may even return 0xFFFD the string contains
596 * invalid characters!
597 */
598 n = WideCharToMultiByte(
599 CP_ACP, /* Output code page */
600 0, /* Conversion flags */
601 wp->d_name, /* Input string */
602 wp->d_namlen, /* Length of input string */
603 dirp->ent.d_name, /* Output buffer */
604 PATH_MAX, /* Size of output buffer */
605 NULL, /* Replacement character */
606 NULL); /* If chars were replaced */
607 if (n > 0 && n < PATH_MAX) {
608
609 /* Zero-terminate buffer */
610 dirp->ent.d_name[n] = '\0';
611
612 /* Initialize directory entry for return */
613 p = &dirp->ent;
614
615 /* Compute length */
616 p->d_namlen = strnlen (dirp->ent.d_name, PATH_MAX);
617
618 /* Copy file attributes */
619 p->d_type = wp->d_type;
 
 
 
 
 
 
 
620
621 /* Reset dummy fields */
622 p->d_ino = 0;
623 p->d_reclen = sizeof (dirp->ent);
624
625
626 } else {
627
628 /*
629 * Cannot convert file name to multi-byte string so construct
630 * an errornous directory entry and return that. Note that
631 * we cannot return NULL as that would stop the processing
632 * of directory entries completely.
633 */
634 p = &dirp->ent;
635 p->d_name[0] = '?';
636 p->d_name[1] = '\0';
637 p->d_namlen = 1;
638 p->d_type = DT_UNKNOWN;
639 p->d_ino = 0;
640 p->d_reclen = 0;
641
642 }
643
644 } else {
645
646 /* End of directory stream */
647 p = NULL;
648
649 }
650
651 return p;
652 }
653
654 /*
655 * Close directory stream.
656 */
@@ -667,13 +741,15 @@
667
668 /* Release multi-byte character version */
669 free (dirp);
670
671 } else {
 
672 /* Invalid directory stream */
673 DIRENT_SET_ERRNO (EBADF);
674 ok = /*failure*/-1;
 
675 }
676 return ok;
677 }
678
679 /*
@@ -684,12 +760,130 @@
684 DIR* dirp)
685 {
686 /* Rewind wide-character string directory stream */
687 _wrewinddir (dirp->wdirp);
688 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
689
690
691 #ifdef __cplusplus
692 }
693 #endif
694 #endif /*DIRENT_H*/
695
696
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -20,21 +20,24 @@
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 *
26 * Version 1.13, Dec 12 2012, Toni Ronkko
27 * Use traditional 8+3 file name if the name cannot be represented in the
28 * default ANSI code page. Now compiles again with MSVC 6.0. Thanks to
29 * Konstantin Khomoutov for testing.
30 *
31 * Version 1.12.1, Oct 1 2012, Toni Ronkko
32 * Bug fix: renamed wide-character DIR structure _wDIR to _WDIR (with
33 * capital W) in order to maintain compatibility with MingW.
34 *
35 * Version 1.12, Sep 30 2012, Toni Ronkko
36 * Define PATH_MAX and NAME_MAX. Added wide-character variants _wDIR,
37 * _wdirent, _wopendir(), _wreaddir(), _wclosedir() and _wrewinddir().
38 * Thanks to Edgar Buerkle and Jan Nijtmans for ideas and code.
 
 
39 *
40 * Do not include windows.h. This allows dirent.h to be integrated more
41 * easily into programs using winsock. Thanks to Fernando Azaldegui.
42 *
43 * Version 1.11, Mar 15, 2011, Toni Ronkko
@@ -88,48 +91,72 @@
91 *****************************************************************************/
92 #ifndef DIRENT_H
93 #define DIRENT_H
94
95 #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
96 # define _X86_
97 #endif
98 #include <stdio.h>
99 #include <stdarg.h>
100 #include <windef.h>
101 #include <winbase.h>
102 #include <wchar.h>
 
103 #include <string.h>
104 #include <stdlib.h>
105 #include <malloc.h>
106 #include <sys/types.h>
107 #include <sys/stat.h>
108 #include <errno.h>
109
110 /* Indicates that d_type field is available in dirent structure */
111 #define _DIRENT_HAVE_D_TYPE
112
113 /* Indicates that d_namlen field is available in dirent structure */
114 #define _DIRENT_HAVE_D_NAMLEN
115
116 /* Entries missing from MSVC 6.0 */
117 #if !defined(FILE_ATTRIBUTE_DEVICE)
118 # define FILE_ATTRIBUTE_DEVICE 0x40
119 #endif
120
121 /* File type and permission flags for stat() */
122 #if !defined(S_IFMT)
123 # define S_IFMT _S_IFMT /* File type mask */
124 #endif
125 #if !defined(S_IFDIR)
126 # define S_IFDIR _S_IFDIR /* Directory */
127 #endif
128 #if !defined(S_IFCHR)
129 # define S_IFCHR _S_IFCHR /* Character device */
130 #endif
131 #if !defined(S_IFFIFO)
132 # define S_IFFIFO _S_IFFIFO /* Pipe */
133 #endif
134 #if !defined(S_IFREG)
135 # define S_IFREG _S_IFREG /* Regular file */
136 #endif
137 #if !defined(S_IREAD)
138 # define S_IREAD _S_IREAD /* Read permission */
139 #endif
140 #if !defined(S_IWRITE)
141 # define S_IWRITE _S_IWRITE /* Write permission */
142 #endif
143 #if !defined(S_IEXEC)
144 # define S_IEXEC _S_IEXEC /* Execute permission */
145 #endif
146 #if !defined(S_IFIFO)
147 # define S_IFIFO _S_IFIFO /* Pipe */
148 #endif
149 #if !defined(S_IFBLK)
150 # define S_IFBLK 0 /* Block device */
151 #endif
152 #if !defined(S_IFLNK)
153 # define S_IFLNK 0 /* Link */
154 #endif
155 #if !defined(S_IFSOCK)
156 # define S_IFSOCK 0 /* Socket */
157 #endif
158
159 #if defined(_MSC_VER)
160 # define S_IRUSR S_IREAD /* Read user */
161 # define S_IWUSR S_IWRITE /* Write user */
162 # define S_IXUSR 0 /* Execute user */
@@ -139,18 +166,26 @@
166 # define S_IROTH 0 /* Read others */
167 # define S_IWOTH 0 /* Write others */
168 # define S_IXOTH 0 /* Execute others */
169 #endif
170
171 /* Maximum length of file name */
172 #if !defined(PATH_MAX)
173 # define PATH_MAX MAX_PATH
174 #endif
175 #if !defined(FILENAME_MAX)
176 # define FILENAME_MAX MAX_PATH
177 #endif
178 #if !defined(NAME_MAX)
179 # define NAME_MAX FILENAME_MAX
180 #endif
181
182 /* File type flags for d_type */
183 #define DT_UNKNOWN 0
184 #define DT_REG S_IFREG
185 #define DT_DIR S_IFDIR
186 #define DT_FIFO S_IFIFO
187 #define DT_SOCK S_IFSOCK
188 #define DT_CHR S_IFCHR
189 #define DT_BLK S_IFBLK
190
191 /* Macros for converting between st_mode and d_type */
@@ -161,41 +196,31 @@
196 * File type macros. Note that block devices, sockets and links cannot be
197 * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
198 * only defined for compatibility. These macros should always return false
199 * on Windows.
200 */
201 #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
202 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
203 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
204 #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
205 #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
206 #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
207 #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
208
209 /* Return the exact length of d_namlen without zero terminator */
210 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
211
212 /* Return number of bytes needed to store d_namlen */
213 #define _D_ALLOC_NAMLEN(p) (PATH_MAX + 1)
214
 
 
 
 
 
 
 
 
 
 
 
215
216 #ifdef __cplusplus
217 extern "C" {
218 #endif
219
220
221 /* Wide-character version */
222 struct _wdirent {
223 long d_ino; /* Always zero */
224 unsigned short d_reclen; /* Structure size */
225 size_t d_namlen; /* Length of name without \0 */
226 int d_type; /* File type */
@@ -203,11 +228,11 @@
228 };
229 typedef struct _wdirent _wdirent;
230
231 struct _WDIR {
232 struct _wdirent ent; /* Current directory entry */
233 WIN32_FIND_DATAW data; /* Private file data */
234 int cached; /* True if data is valid */
235 HANDLE handle; /* Win32 search handle */
236 wchar_t *patt; /* Initial directory name */
237 };
238 typedef struct _WDIR _WDIR;
@@ -214,10 +239,11 @@
239
240 static _WDIR *_wopendir (const wchar_t *dirname);
241 static struct _wdirent *_wreaddir (_WDIR *dirp);
242 static int _wclosedir (_WDIR *dirp);
243 static void _wrewinddir (_WDIR* dirp);
244
245
246 /* For compatibility with Symbian */
247 #define wdirent _wdirent
248 #define WDIR _WDIR
249 #define wopendir _wopendir
@@ -246,10 +272,30 @@
272 static struct dirent *readdir (DIR *dirp);
273 static int closedir (DIR *dirp);
274 static void rewinddir (DIR* dirp);
275
276
277 /* Internal utility functions */
278 static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
279 static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
280
281 static int dirent_mbstowcs_s(
282 size_t *pReturnValue,
283 wchar_t *wcstr,
284 size_t sizeInWords,
285 const char *mbstr,
286 size_t count);
287
288 static int dirent_wcstombs_s(
289 size_t *pReturnValue,
290 char *mbstr,
291 size_t sizeInBytes,
292 const wchar_t *wcstr,
293 size_t count);
294
295 static void dirent_set_errno (int error);
296
297 /*
298 * Open directory stream DIRNAME for read and return a pointer to the
299 * internal working area that is used to retrieve individual directory
300 * entries.
301 */
@@ -256,31 +302,38 @@
302 static _WDIR*
303 _wopendir(
304 const wchar_t *dirname)
305 {
306 _WDIR *dirp = NULL;
307 int error;
308
309 /* Must have directory name */
310 if (dirname == NULL || dirname[0] == '\0') {
311 dirent_set_errno (ENOENT);
312 return NULL;
313 }
314
315 /* Allocate new _WDIR structure */
316 dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
317 if (dirp != NULL) {
318 DWORD n;
319
320 /* Reset _WDIR structure */
321 dirp->handle = INVALID_HANDLE_VALUE;
322 dirp->patt = NULL;
323 dirp->cached = 0;
324
325 /* Compute the length of full path plus zero terminator */
326 n = GetFullPathNameW (dirname, 0, NULL, NULL);
327
328 /* Allocate room for absolute directory name and search pattern */
329 dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
330 if (dirp->patt) {
331
332 /*
333 * Convert relative directory name to an absolute one. This
334 * allows rewinddir() to function correctly even when current
335 * working directory is changed between opendir() and rewinddir().
336 */
337 n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
338 if (n > 0) {
339 wchar_t *p;
@@ -303,25 +356,22 @@
356 }
357 *p++ = '*';
358 *p = '\0';
359
360 /* Open directory stream and retrieve the first entry */
361 if (dirent_first (dirp)) {
362 /* Directory stream opened successfully */
363 error = 0;
 
 
 
364 } else {
365 /* Cannot retrieve first entry */
 
366 error = 1;
367 dirent_set_errno (ENOENT);
368 }
369
370 } else {
371 /* Cannot retrieve full path name */
372 dirent_set_errno (ENOENT);
373 error = 1;
374 }
375
376 } else {
377 /* Cannot allocate memory for search pattern */
@@ -350,70 +400,59 @@
400 */
401 static struct _wdirent*
402 _wreaddir(
403 _WDIR *dirp)
404 {
405 WIN32_FIND_DATAW *datap;
406 struct _wdirent *entp;
407
408 /* Read next directory entry */
409 datap = dirent_next (dirp);
410 if (datap) {
411 size_t n;
412 DWORD attr;
413
414 /* Pointer to directory entry to return */
415 entp = &dirp->ent;
416
417 /*
418 * Copy file name as wide-character string. If the file name is too
419 * long to fit in to the destination buffer, then truncate file name
420 * to PATH_MAX characters and zero-terminate the buffer.
421 */
422 n = 0;
423 while (n < PATH_MAX && datap->cFileName[n] != 0) {
424 entp->d_name[n] = datap->cFileName[n];
425 n++;
426 }
427 dirp->ent.d_name[n] = 0;
428
429 /* Length of file name excluding zero terminator */
430 entp->d_namlen = n;
431
432 /* File type */
433 attr = datap->dwFileAttributes;
 
 
 
 
434 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
435 entp->d_type = DT_CHR;
436 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
437 entp->d_type = DT_DIR;
438 } else {
439 entp->d_type = DT_REG;
440 }
441
442 /* Reset dummy fields */
443 entp->d_ino = 0;
444 entp->d_reclen = sizeof (struct _wdirent);
445
446 } else {
447
448 /* Last directory entry read */
449 entp = NULL;
450
 
 
 
 
 
 
 
451 }
452
453 return entp;
454 }
455
456 /*
457 * Close directory stream opened by opendir() function. This invalidates the
458 * DIR structure as well as any directory entry read previously by
@@ -442,11 +481,11 @@
481 free (dirp);
482 ok = /*success*/0;
483
484 } else {
485 /* Invalid directory stream */
486 dirent_set_errno (EBADF);
487 ok = /*failure*/-1;
488 }
489 return ok;
490 }
491
@@ -456,26 +495,81 @@
495 */
496 static void
497 _wrewinddir(
498 _WDIR* dirp)
499 {
500 if (dirp) {
501 /* Release existing search handle */
502 if (dirp->handle != INVALID_HANDLE_VALUE) {
503 FindClose (dirp->handle);
504 }
505
506 /* Open new search handle */
507 dirent_first (dirp);
508 }
509 }
510
511 /* Get first directory entry (internal) */
512 static WIN32_FIND_DATAW*
513 dirent_first(
514 _WDIR *dirp)
515 {
516 WIN32_FIND_DATAW *datap;
517
518 /* Open directory and retrieve the first entry */
519 dirp->handle = FindFirstFileW (dirp->patt, &dirp->data);
520 if (dirp->handle != INVALID_HANDLE_VALUE) {
521
522 /* a directory entry is now waiting in memory */
523 datap = &dirp->data;
524 dirp->cached = 1;
525
526 } else {
527
528 /* Failed to re-open directory: no directory entry in memory */
529 dirp->cached = 0;
530 datap = NULL;
531
532 }
533 return datap;
534 }
535
536 /* Get next directory entry (internal) */
537 static WIN32_FIND_DATAW*
538 dirent_next(
539 _WDIR *dirp)
540 {
541 WIN32_FIND_DATAW *p;
542
543 /* Get next directory entry */
544 if (dirp->cached != 0) {
545
546 /* A valid directory entry already in memory */
547 p = &dirp->data;
548 dirp->cached = 0;
549
550 } else if (dirp->handle != INVALID_HANDLE_VALUE) {
551
552 /* Get the next directory entry from stream */
553 if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
554 /* Got a file */
555 p = &dirp->data;
556 } else {
557 /* The very last entry has been processed or an error occured */
558 FindClose (dirp->handle);
559 dirp->handle = INVALID_HANDLE_VALUE;
560 p = NULL;
561 }
562
563 } else {
564
565 /* End of directory stream reached */
566 p = NULL;
567
568 }
569
570 return p;
571 }
572
573 /*
574 * Open directory stream using plain old C-string.
575 */
@@ -482,58 +576,34 @@
576 static DIR*
577 opendir(
578 const char *dirname)
579 {
580 struct DIR *dirp;
581 int error;
582
583 /* Must have directory name */
584 if (dirname == NULL || dirname[0] == '\0') {
585 dirent_set_errno (ENOENT);
586 return NULL;
587 }
588
589 /* Allocate memory for DIR structure */
590 dirp = (DIR*) malloc (sizeof (struct DIR));
591 if (dirp) {
592 wchar_t wname[PATH_MAX + 1];
593 size_t n;
594
595 /* Convert directory name to wide-character string */
596 error = dirent_mbstowcs_s(
597 &n, wname, PATH_MAX + 1, dirname, PATH_MAX);
598 if (!error) {
599
600 /* Open directory stream using wide-character name */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
601 dirp->wdirp = _wopendir (wname);
602 if (dirp->wdirp) {
603 /* Directory stream opened */
604 error = 0;
 
 
 
 
 
 
 
605 } else {
606 /* Failed to open directory stream */
607 error = 1;
608 }
609
@@ -562,95 +632,99 @@
632 }
633
634 /*
635 * Read next directory entry.
636 *
637 * When working with text consoles, please note that file names returned by
638 * readdir() are represented in the default ANSI code page while any output to
639 * console is typically formatted on another code page. Thus, non-ASCII
640 * characters in file names will not usually display correctly on console. The
641 * problem can be fixed in two ways: (1) change the character set of console
642 * to 1252 using chcp utility and use Lucida Console font, or (2) use
643 * _cprintf function when writing to console. The _cprinf() will re-encode
644 * ANSI strings to the console code page so many non-ASCII characters will
645 * display correcly.
646 */
647 static struct dirent*
648 readdir(
649 DIR *dirp)
650 {
651 WIN32_FIND_DATAW *datap;
652 struct dirent *entp;
653
654 /* Read next directory entry */
655 datap = dirent_next (dirp->wdirp);
656 if (datap) {
657 size_t n;
658 int error;
659
660 /* Attempt to convert file name to multi-byte string */
661 error = dirent_wcstombs_s(
662 &n, dirp->ent.d_name, MAX_PATH + 1, datap->cFileName, MAX_PATH);
663
664 /*
665 * If the file name cannot be represented by a multi-byte string,
666 * then attempt to use old 8+3 file name. This allows traditional
667 * Unix-code to access some file names despite of unicode
668 * characters, although file names may seem unfamiliar to the user.
669 *
670 * Be ware that the code below cannot come up with a short file
671 * name unless the file system provides one. At least
672 * VirtualBox shared folders fail to do this.
673 */
674 if (error && datap->cAlternateFileName[0] != '\0') {
675 error = dirent_wcstombs_s(
676 &n, dirp->ent.d_name, MAX_PATH + 1, datap->cAlternateFileName,
677 sizeof (datap->cAlternateFileName) /
678 sizeof (datap->cAlternateFileName[0]));
679 }
680
681 if (!error) {
682 DWORD attr;
 
 
 
 
683
684 /* Initialize directory entry for return */
685 entp = &dirp->ent;
686
687 /* Length of file name excluding zero terminator */
688 entp->d_namlen = n - 1;
689
690 /* File attributes */
691 attr = datap->dwFileAttributes;
692 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
693 entp->d_type = DT_CHR;
694 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
695 entp->d_type = DT_DIR;
696 } else {
697 entp->d_type = DT_REG;
698 }
699
700 /* Reset dummy fields */
701 entp->d_ino = 0;
702 entp->d_reclen = sizeof (struct dirent);
 
703
704 } else {
 
705 /*
706 * Cannot convert file name to multi-byte string so construct
707 * an errornous directory entry and return that. Note that
708 * we cannot return NULL as that would stop the processing
709 * of directory entries completely.
710 */
711 entp = &dirp->ent;
712 entp->d_name[0] = '?';
713 entp->d_name[1] = '\0';
714 entp->d_namlen = 1;
715 entp->d_type = DT_UNKNOWN;
716 entp->d_ino = 0;
717 entp->d_reclen = 0;
 
718 }
719
720 } else {
721 /* No more directory entries */
722 entp = NULL;
 
 
723 }
724
725 return entp;
726 }
727
728 /*
729 * Close directory stream.
730 */
@@ -667,13 +741,15 @@
741
742 /* Release multi-byte character version */
743 free (dirp);
744
745 } else {
746
747 /* Invalid directory stream */
748 dirent_set_errno (EBADF);
749 ok = /*failure*/-1;
750
751 }
752 return ok;
753 }
754
755 /*
@@ -684,12 +760,130 @@
760 DIR* dirp)
761 {
762 /* Rewind wide-character string directory stream */
763 _wrewinddir (dirp->wdirp);
764 }
765
766 /* Convert multi-byte string to wide character string */
767 static int
768 dirent_mbstowcs_s(
769 size_t *pReturnValue,
770 wchar_t *wcstr,
771 size_t sizeInWords,
772 const char *mbstr,
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 = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
781
782 #else
783
784 /* Older Visual Studio or non-Microsoft compiler */
785 size_t n;
786
787 /* Convert to wide-character string */
788 n = mbstowcs (wcstr, mbstr, count);
789 if (n < sizeInWords) {
790
791 /* Zero-terminate output buffer */
792 if (wcstr) {
793 wcstr[n] = 0;
794 }
795
796 /* Length of resuting multi-byte string WITH zero terminator */
797 if (pReturnValue) {
798 *pReturnValue = n + 1;
799 }
800
801 /* Success */
802 error = 0;
803
804 } else {
805
806 /* Could not convert string */
807 error = 1;
808
809 }
810
811 #endif
812
813 return error;
814 }
815
816 /* Convert wide-character string to multi-byte string */
817 static int
818 dirent_wcstombs_s(
819 size_t *pReturnValue,
820 char *mbstr,
821 size_t sizeInBytes,
822 const wchar_t *wcstr,
823 size_t count)
824 {
825 int error;
826
827 #if defined(_MSC_VER) && _MSC_VER >= 1400
828
829 /* Microsoft Visual Studio 2005 or later */
830 error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
831
832 #else
833
834 /* Older Visual Studio or non-Microsoft compiler */
835 size_t n;
836
837 /* Convert to multi-byte string */
838 n = wcstombs (mbstr, wcstr, count);
839 if (n < sizeInBytes) {
840
841 /* Zero-terminate output buffer */
842 if (mbstr) {
843 mbstr[n] = '\0';
844 }
845
846 /* Lenght of resulting multi-bytes string WITH zero-terminator */
847 if (pReturnValue) {
848 *pReturnValue = n + 1;
849 }
850
851 /* Success */
852 error = 0;
853
854 } else {
855
856 /* Cannot convert string */
857 error = 1;
858
859 }
860
861 #endif
862
863 return error;
864 }
865
866 /* Set errno variable */
867 static void
868 dirent_set_errno(
869 int error)
870 {
871 #if defined(_MSC_VER)
872
873 /* Microsoft Visual Studio */
874 _set_errno (error);
875
876 #else
877
878 /* Non-Microsoft compiler */
879 errno = error;
880
881 #endif
882 }
883
884
885 #ifdef __cplusplus
886 }
887 #endif
888 #endif /*DIRENT_H*/
889
890

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button