Fossil SCM

Update dirent to version 1.23. See [https://github.com/tronkko/dirent/releases]

jan.nijtmans 2017-08-28 14:04 trunk
Commit ade4a657dc852f4b992dfbec48dfc26d6922ffd12f7a9cc5fe8aff302506e6ce
1 file changed +318 -88
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -1,8 +1,8 @@
11
/*
22
* Dirent interface for Microsoft Visual Studio
3
- * Version 1.22
3
+ * Version 1.23
44
*
55
* Copyright (C) 2006-2012 Toni Ronkko
66
* This file is part of dirent. Dirent may be freely distributed
77
* under the MIT license. For all details and documentation, see
88
* https://github.com/tronkko/dirent
@@ -196,15 +196,15 @@
196196
#endif
197197
#if !defined(S_ISBLK)
198198
# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
199199
#endif
200200
201
-/* Return the exact length of d_namlen without zero terminator */
201
+/* Return the exact length of the file name without zero terminator */
202202
#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
203203
204
-/* Return number of bytes needed to store d_namlen */
205
-#define _D_ALLOC_NAMLEN(p) (PATH_MAX)
204
+/* Return the maximum size of a file name */
205
+#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1)
206206
207207
208208
#ifdef __cplusplus
209209
extern "C" {
210210
#endif
@@ -212,10 +212,13 @@
212212
213213
/* Wide-character version */
214214
struct _wdirent {
215215
/* Always zero */
216216
long d_ino;
217
+
218
+ /* File position within stream */
219
+ long d_off;
217220
218221
/* Structure size */
219222
unsigned short d_reclen;
220223
221224
/* Length of name without \0 */
@@ -223,11 +226,11 @@
223226
224227
/* File type */
225228
int d_type;
226229
227230
/* File name */
228
- wchar_t d_name[PATH_MAX];
231
+ wchar_t d_name[PATH_MAX+1];
229232
};
230233
typedef struct _wdirent _wdirent;
231234
232235
struct _WDIR {
233236
/* Current directory entry */
@@ -245,29 +248,17 @@
245248
/* Initial directory name */
246249
wchar_t *patt;
247250
};
248251
typedef struct _WDIR _WDIR;
249252
250
-static _WDIR *_wopendir (const wchar_t *dirname);
251
-static struct _wdirent *_wreaddir (_WDIR *dirp);
252
-static int _wclosedir (_WDIR *dirp);
253
-static void _wrewinddir (_WDIR* dirp);
254
-
255
-
256
-/* For compatibility with Symbian */
257
-#define wdirent _wdirent
258
-#define WDIR _WDIR
259
-#define wopendir _wopendir
260
-#define wreaddir _wreaddir
261
-#define wclosedir _wclosedir
262
-#define wrewinddir _wrewinddir
263
-
264
-
265
-/* Multi-byte character versions */
253
+/* Multi-byte character version */
266254
struct dirent {
267255
/* Always zero */
268256
long d_ino;
257
+
258
+ /* File position within stream */
259
+ long d_off;
269260
270261
/* Structure size */
271262
unsigned short d_reclen;
272263
273264
/* Length of name without \0 */
@@ -275,24 +266,55 @@
275266
276267
/* File type */
277268
int d_type;
278269
279270
/* File name */
280
- char d_name[PATH_MAX];
271
+ char d_name[PATH_MAX+1];
281272
};
282273
typedef struct dirent dirent;
283274
284275
struct DIR {
285276
struct dirent ent;
286277
struct _WDIR *wdirp;
287278
};
288279
typedef struct DIR DIR;
289280
281
+
282
+/* Dirent functions */
290283
static DIR *opendir (const char *dirname);
284
+static _WDIR *_wopendir (const wchar_t *dirname);
285
+
291286
static struct dirent *readdir (DIR *dirp);
287
+static struct _wdirent *_wreaddir (_WDIR *dirp);
288
+
289
+static int readdir_r(
290
+ DIR *dirp, struct dirent *entry, struct dirent **result);
291
+static int _wreaddir_r(
292
+ _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result);
293
+
292294
static int closedir (DIR *dirp);
295
+static int _wclosedir (_WDIR *dirp);
296
+
293297
static void rewinddir (DIR* dirp);
298
+static void _wrewinddir (_WDIR* dirp);
299
+
300
+static int scandir (const char *dirname, struct dirent ***namelist,
301
+ int (*filter)(const struct dirent*),
302
+ int (*compare)(const void *, const void *));
303
+
304
+static int alphasort (const struct dirent **a, const struct dirent **b);
305
+
306
+static int versionsort (const struct dirent **a, const struct dirent **b);
307
+
308
+
309
+/* For compatibility with Symbian */
310
+#define wdirent _wdirent
311
+#define WDIR _WDIR
312
+#define wopendir _wopendir
313
+#define wreaddir _wreaddir
314
+#define wclosedir _wclosedir
315
+#define wrewinddir _wrewinddir
294316
295317
296318
/* Internal utility functions */
297319
static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
298320
static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
@@ -310,10 +332,11 @@
310332
size_t sizeInBytes,
311333
const wchar_t *wcstr,
312334
size_t count);
313335
314336
static void dirent_set_errno (int error);
337
+
315338
316339
/*
317340
* Open directory stream DIRNAME for read and return a pointer to the
318341
* internal working area that is used to retrieve individual directory
319342
* entries.
@@ -340,11 +363,11 @@
340363
dirp->handle = INVALID_HANDLE_VALUE;
341364
dirp->patt = NULL;
342365
dirp->cached = 0;
343366
344367
/* Compute the length of full path plus zero terminator
345
- *
368
+ *
346369
* Note that on WinRT there's no way to convert relative paths
347370
* into absolute paths, so just assume its an absolute path.
348371
*/
349372
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
350373
n = wcslen(dirname);
@@ -358,11 +381,11 @@
358381
359382
/*
360383
* Convert relative directory name to an absolute one. This
361384
* allows rewinddir() to function correctly even when current
362385
* working directory is changed between opendir() and rewinddir().
363
- *
386
+ *
364387
* Note that on WinRT there's no way to convert relative paths
365388
* into absolute paths, so just assume its an absolute path.
366389
*/
367390
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
368391
wcsncpy_s(dirp->patt, n+1, dirname, n);
@@ -425,68 +448,92 @@
425448
426449
return dirp;
427450
}
428451
429452
/*
430
- * Read next directory entry. The directory entry is returned in dirent
431
- * structure in the d_name field. Individual directory entries returned by
432
- * this function include regular files, sub-directories, pseudo-directories
433
- * "." and ".." as well as volume labels, hidden files and system files.
453
+ * Read next directory entry.
454
+ *
455
+ * Returns pointer to static directory entry which may be overwritted by
456
+ * subsequent calls to _wreaddir().
434457
*/
435458
static struct _wdirent*
436459
_wreaddir(
437460
_WDIR *dirp)
438461
{
462
+ struct _wdirent *entry;
463
+
464
+ /*
465
+ * Read directory entry to buffer. We can safely ignore the return value
466
+ * as entry will be set to NULL in case of error.
467
+ */
468
+ (void) _wreaddir_r (dirp, &dirp->ent, &entry);
469
+
470
+ /* Return pointer to statically allocated directory entry */
471
+ return entry;
472
+}
473
+
474
+/*
475
+ * Read next directory entry.
476
+ *
477
+ * Returns zero on success. If end of directory stream is reached, then sets
478
+ * result to NULL and returns zero.
479
+ */
480
+static int
481
+_wreaddir_r(
482
+ _WDIR *dirp,
483
+ struct _wdirent *entry,
484
+ struct _wdirent **result)
485
+{
439486
WIN32_FIND_DATAW *datap;
440
- struct _wdirent *entp;
441487
442488
/* Read next directory entry */
443489
datap = dirent_next (dirp);
444490
if (datap) {
445491
size_t n;
446492
DWORD attr;
447
-
448
- /* Pointer to directory entry to return */
449
- entp = &dirp->ent;
450493
451
- /*
494
+ /*
452495
* Copy file name as wide-character string. If the file name is too
453496
* long to fit in to the destination buffer, then truncate file name
454497
* to PATH_MAX characters and zero-terminate the buffer.
455498
*/
456499
n = 0;
457
- while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) {
458
- entp->d_name[n] = datap->cFileName[n];
500
+ while (n < PATH_MAX && datap->cFileName[n] != 0) {
501
+ entry->d_name[n] = datap->cFileName[n];
459502
n++;
460503
}
461
- dirp->ent.d_name[n] = 0;
504
+ entry->d_name[n] = 0;
462505
463506
/* Length of file name excluding zero terminator */
464
- entp->d_namlen = n;
507
+ entry->d_namlen = n;
465508
466509
/* File type */
467510
attr = datap->dwFileAttributes;
468511
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
469
- entp->d_type = DT_CHR;
512
+ entry->d_type = DT_CHR;
470513
} else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
471
- entp->d_type = DT_DIR;
514
+ entry->d_type = DT_DIR;
472515
} else {
473
- entp->d_type = DT_REG;
516
+ entry->d_type = DT_REG;
474517
}
475518
476519
/* Reset dummy fields */
477
- entp->d_ino = 0;
478
- entp->d_reclen = sizeof (struct _wdirent);
520
+ entry->d_ino = 0;
521
+ entry->d_off = 0;
522
+ entry->d_reclen = sizeof (struct _wdirent);
523
+
524
+ /* Set result address */
525
+ *result = entry;
479526
480527
} else {
481528
482
- /* Last directory entry read */
483
- entp = NULL;
529
+ /* Return NULL to indicate end of directory */
530
+ *result = NULL;
484531
485532
}
486533
487
- return entp;
534
+ return /*OK*/0;
488535
}
489536
490537
/*
491538
* Close directory stream opened by opendir() function. This invalidates the
492539
* DIR structure as well as any directory entry read previously by
@@ -514,13 +561,15 @@
514561
/* Release directory structure */
515562
free (dirp);
516563
ok = /*success*/0;
517564
518565
} else {
566
+
519567
/* Invalid directory stream */
520568
dirent_set_errno (EBADF);
521569
ok = /*failure*/-1;
570
+
522571
}
523572
return ok;
524573
}
525574
526575
/*
@@ -567,11 +616,15 @@
567616
568617
}
569618
return datap;
570619
}
571620
572
-/* Get next directory entry (internal) */
621
+/*
622
+ * Get next directory entry (internal).
623
+ *
624
+ * Returns
625
+ */
573626
static WIN32_FIND_DATAW*
574627
dirent_next(
575628
_WDIR *dirp)
576629
{
577630
WIN32_FIND_DATAW *p;
@@ -604,11 +657,11 @@
604657
}
605658
606659
return p;
607660
}
608661
609
-/*
662
+/*
610663
* Open directory stream using plain old C-string.
611664
*/
612665
static DIR*
613666
opendir(
614667
const char *dirname)
@@ -623,15 +676,16 @@
623676
}
624677
625678
/* Allocate memory for DIR structure */
626679
dirp = (DIR*) malloc (sizeof (struct DIR));
627680
if (dirp) {
628
- wchar_t wname[PATH_MAX];
681
+ wchar_t wname[PATH_MAX + 1];
629682
size_t n;
630683
631684
/* Convert directory name to wide-character string */
632
- error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);
685
+ error = dirent_mbstowcs_s(
686
+ &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
633687
if (!error) {
634688
635689
/* Open directory stream using wide-character name */
636690
dirp->wdirp = _wopendir (wname);
637691
if (dirp->wdirp) {
@@ -641,11 +695,11 @@
641695
/* Failed to open directory stream */
642696
error = 1;
643697
}
644698
645699
} else {
646
- /*
700
+ /*
647701
* Cannot convert file name to wide-character string. This
648702
* occurs if the string contains invalid multi-byte sequences or
649703
* the output buffer is too small to contain the resulting
650704
* string.
651705
*/
@@ -666,39 +720,52 @@
666720
return dirp;
667721
}
668722
669723
/*
670724
* Read next directory entry.
671
- *
672
- * When working with text consoles, please note that file names returned by
673
- * readdir() are represented in the default ANSI code page while any output to
674
- * console is typically formatted on another code page. Thus, non-ASCII
675
- * characters in file names will not usually display correctly on console. The
676
- * problem can be fixed in two ways: (1) change the character set of console
677
- * to 1252 using chcp utility and use Lucida Console font, or (2) use
678
- * _cprintf function when writing to console. The _cprinf() will re-encode
679
- * ANSI strings to the console code page so many non-ASCII characters will
680
- * display correcly.
681725
*/
682726
static struct dirent*
683727
readdir(
684
- DIR *dirp)
728
+ DIR *dirp)
729
+{
730
+ struct dirent *entry;
731
+
732
+ /*
733
+ * Read directory entry to buffer. We can safely ignore the return value
734
+ * as entry will be set to NULL in case of error.
735
+ */
736
+ (void) readdir_r (dirp, &dirp->ent, &entry);
737
+
738
+ /* Return pointer to statically allocated directory entry */
739
+ return entry;
740
+}
741
+
742
+/*
743
+ * Read next directory entry into called-allocated buffer.
744
+ *
745
+ * Returns zero on sucess. If the end of directory stream is reached, then
746
+ * sets result to NULL and returns zero.
747
+ */
748
+static int
749
+readdir_r(
750
+ DIR *dirp,
751
+ struct dirent *entry,
752
+ struct dirent **result)
685753
{
686754
WIN32_FIND_DATAW *datap;
687
- struct dirent *entp;
688755
689756
/* Read next directory entry */
690757
datap = dirent_next (dirp->wdirp);
691758
if (datap) {
692759
size_t n;
693760
int error;
694761
695762
/* Attempt to convert file name to multi-byte string */
696763
error = dirent_wcstombs_s(
697
- &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
764
+ &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1);
698765
699
- /*
766
+ /*
700767
* If the file name cannot be represented by a multi-byte string,
701768
* then attempt to use old 8+3 file name. This allows traditional
702769
* Unix-code to access some file names despite of unicode
703770
* characters, although file names may seem unfamiliar to the user.
704771
*
@@ -706,67 +773,72 @@
706773
* name unless the file system provides one. At least
707774
* VirtualBox shared folders fail to do this.
708775
*/
709776
if (error && datap->cAlternateFileName[0] != '\0') {
710777
error = dirent_wcstombs_s(
711
- &n, dirp->ent.d_name, PATH_MAX,
712
- datap->cAlternateFileName, PATH_MAX);
778
+ &n, entry->d_name, PATH_MAX + 1,
779
+ datap->cAlternateFileName, PATH_MAX + 1);
713780
}
714781
715782
if (!error) {
716783
DWORD attr;
717784
718
- /* Initialize directory entry for return */
719
- entp = &dirp->ent;
720
-
721785
/* Length of file name excluding zero terminator */
722
- entp->d_namlen = n - 1;
786
+ entry->d_namlen = n - 1;
723787
724788
/* File attributes */
725789
attr = datap->dwFileAttributes;
726790
if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
727
- entp->d_type = DT_CHR;
791
+ entry->d_type = DT_CHR;
728792
} else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
729
- entp->d_type = DT_DIR;
793
+ entry->d_type = DT_DIR;
730794
} else {
731
- entp->d_type = DT_REG;
795
+ entry->d_type = DT_REG;
732796
}
733797
734798
/* Reset dummy fields */
735
- entp->d_ino = 0;
736
- entp->d_reclen = sizeof (struct dirent);
799
+ entry->d_ino = 0;
800
+ entry->d_off = 0;
801
+ entry->d_reclen = sizeof (struct dirent);
737802
738803
} else {
739
- /*
804
+
805
+ /*
740806
* Cannot convert file name to multi-byte string so construct
741807
* an errornous directory entry and return that. Note that
742808
* we cannot return NULL as that would stop the processing
743809
* of directory entries completely.
744810
*/
745
- entp = &dirp->ent;
746
- entp->d_name[0] = '?';
747
- entp->d_name[1] = '\0';
748
- entp->d_namlen = 1;
749
- entp->d_type = DT_UNKNOWN;
750
- entp->d_ino = 0;
751
- entp->d_reclen = 0;
752
- }
811
+ entry->d_name[0] = '?';
812
+ entry->d_name[1] = '\0';
813
+ entry->d_namlen = 1;
814
+ entry->d_type = DT_UNKNOWN;
815
+ entry->d_ino = 0;
816
+ entry->d_off = -1;
817
+ entry->d_reclen = 0;
818
+
819
+ }
820
+
821
+ /* Return pointer to directory entry */
822
+ *result = entry;
753823
754824
} else {
825
+
755826
/* No more directory entries */
756
- entp = NULL;
827
+ *result = NULL;
828
+
757829
}
758830
759
- return entp;
831
+ return /*OK*/0;
760832
}
761833
762834
/*
763835
* Close directory stream.
764836
*/
765837
static int
766838
closedir(
767
- DIR *dirp)
839
+ DIR *dirp)
768840
{
769841
int ok;
770842
if (dirp) {
771843
772844
/* Close wide-character directory stream */
@@ -789,15 +861,173 @@
789861
/*
790862
* Rewind directory stream to beginning.
791863
*/
792864
static void
793865
rewinddir(
794
- DIR* dirp)
866
+ DIR* dirp)
795867
{
796868
/* Rewind wide-character string directory stream */
797869
_wrewinddir (dirp->wdirp);
798870
}
871
+
872
+/*
873
+ * Scan directory for entries.
874
+ */
875
+static int
876
+scandir(
877
+ const char *dirname,
878
+ struct dirent ***namelist,
879
+ int (*filter)(const struct dirent*),
880
+ int (*compare)(const void*, const void*))
881
+{
882
+ struct dirent **files = NULL;
883
+ size_t size = 0;
884
+ size_t allocated = 0;
885
+ const size_t init_size = 1;
886
+ DIR *dir = NULL;
887
+ struct dirent *entry;
888
+ struct dirent *tmp = NULL;
889
+ size_t i;
890
+ int result = 0;
891
+
892
+ /* Open directory stream */
893
+ dir = opendir (dirname);
894
+ if (dir) {
895
+
896
+ /* Read directory entries to memory */
897
+ while (1) {
898
+
899
+ /* Enlarge pointer table to make room for another pointer */
900
+ if (size >= allocated) {
901
+ void *p;
902
+ size_t num_entries;
903
+
904
+ /* Compute number of entries in the enlarged pointer table */
905
+ if (size < init_size) {
906
+ /* Allocate initial pointer table */
907
+ num_entries = init_size;
908
+ } else {
909
+ /* Double the size */
910
+ num_entries = size * 2;
911
+ }
912
+
913
+ /* Allocate first pointer table or enlarge existing table */
914
+ p = realloc (files, sizeof (void*) * num_entries);
915
+ if (p != NULL) {
916
+ /* Got the memory */
917
+ files = p;
918
+ allocated = num_entries;
919
+ } else {
920
+ /* Out of memory */
921
+ result = -1;
922
+ break;
923
+ }
924
+
925
+ }
926
+
927
+ /* Allocate room for temporary directory entry */
928
+ if (tmp == NULL) {
929
+ tmp = (struct dirent*) malloc (sizeof (struct dirent));
930
+ if (tmp == NULL) {
931
+ /* Cannot allocate temporary directory entry */
932
+ result = -1;
933
+ break;
934
+ }
935
+ }
936
+
937
+ /* Read directory entry to temporary area */
938
+ if (readdir_r (dir, tmp, &entry) == /*OK*/0) {
939
+
940
+ /* Did we got an entry? */
941
+ if (entry != NULL) {
942
+ int pass;
943
+
944
+ /* Determine whether to include the entry in result */
945
+ if (filter) {
946
+ /* Let the filter function decide */
947
+ pass = filter (tmp);
948
+ } else {
949
+ /* No filter function, include everything */
950
+ pass = 1;
951
+ }
952
+
953
+ if (pass) {
954
+ /* Store the temporary entry to pointer table */
955
+ files[size++] = tmp;
956
+ tmp = NULL;
957
+
958
+ /* Keep up with the number of files */
959
+ result++;
960
+ }
961
+
962
+ } else {
963
+
964
+ /*
965
+ * End of directory stream reached => sort entries and
966
+ * exit.
967
+ */
968
+ qsort (files, size, sizeof (void*), (void*) compare);
969
+ break;
970
+
971
+ }
972
+
973
+ } else {
974
+ /* Error reading directory entry */
975
+ result = /*Error*/ -1;
976
+ break;
977
+ }
978
+
979
+ }
980
+
981
+ } else {
982
+ /* Cannot open directory */
983
+ result = /*Error*/ -1;
984
+ }
985
+
986
+ /* Release temporary directory entry */
987
+ if (tmp) {
988
+ free (tmp);
989
+ }
990
+
991
+ /* Release allocated memory on error */
992
+ if (result < 0) {
993
+ for (i = 0; i < size; i++) {
994
+ free (files[i]);
995
+ }
996
+ free (files);
997
+ files = NULL;
998
+ }
999
+
1000
+ /* Close directory stream */
1001
+ if (dir) {
1002
+ closedir (dir);
1003
+ }
1004
+
1005
+ /* Pass pointer table to caller */
1006
+ if (namelist) {
1007
+ *namelist = files;
1008
+ }
1009
+ return result;
1010
+}
1011
+
1012
+/* Alphabetical sorting */
1013
+static int
1014
+alphasort(
1015
+ const struct dirent **a, const struct dirent **b)
1016
+{
1017
+ return strcoll ((*a)->d_name, (*b)->d_name);
1018
+}
1019
+
1020
+/* Sort versions */
1021
+static int
1022
+versionsort(
1023
+ const struct dirent **a, const struct dirent **b)
1024
+{
1025
+ /* FIXME: implement strverscmp and use that */
1026
+ return alphasort (a, b);
1027
+}
1028
+
7991029
8001030
/* Convert multi-byte string to wide character string */
8011031
static int
8021032
dirent_mbstowcs_s(
8031033
size_t *pReturnValue,
8041034
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -1,8 +1,8 @@
1 /*
2 * Dirent interface for Microsoft Visual Studio
3 * Version 1.22
4 *
5 * Copyright (C) 2006-2012 Toni Ronkko
6 * This file is part of dirent. Dirent may be freely distributed
7 * under the MIT license. For all details and documentation, see
8 * https://github.com/tronkko/dirent
@@ -196,15 +196,15 @@
196 #endif
197 #if !defined(S_ISBLK)
198 # define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
199 #endif
200
201 /* Return the exact length of d_namlen without zero terminator */
202 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
203
204 /* Return number of bytes needed to store d_namlen */
205 #define _D_ALLOC_NAMLEN(p) (PATH_MAX)
206
207
208 #ifdef __cplusplus
209 extern "C" {
210 #endif
@@ -212,10 +212,13 @@
212
213 /* Wide-character version */
214 struct _wdirent {
215 /* Always zero */
216 long d_ino;
 
 
 
217
218 /* Structure size */
219 unsigned short d_reclen;
220
221 /* Length of name without \0 */
@@ -223,11 +226,11 @@
223
224 /* File type */
225 int d_type;
226
227 /* File name */
228 wchar_t d_name[PATH_MAX];
229 };
230 typedef struct _wdirent _wdirent;
231
232 struct _WDIR {
233 /* Current directory entry */
@@ -245,29 +248,17 @@
245 /* Initial directory name */
246 wchar_t *patt;
247 };
248 typedef struct _WDIR _WDIR;
249
250 static _WDIR *_wopendir (const wchar_t *dirname);
251 static struct _wdirent *_wreaddir (_WDIR *dirp);
252 static int _wclosedir (_WDIR *dirp);
253 static void _wrewinddir (_WDIR* dirp);
254
255
256 /* For compatibility with Symbian */
257 #define wdirent _wdirent
258 #define WDIR _WDIR
259 #define wopendir _wopendir
260 #define wreaddir _wreaddir
261 #define wclosedir _wclosedir
262 #define wrewinddir _wrewinddir
263
264
265 /* Multi-byte character versions */
266 struct dirent {
267 /* Always zero */
268 long d_ino;
 
 
 
269
270 /* Structure size */
271 unsigned short d_reclen;
272
273 /* Length of name without \0 */
@@ -275,24 +266,55 @@
275
276 /* File type */
277 int d_type;
278
279 /* File name */
280 char d_name[PATH_MAX];
281 };
282 typedef struct dirent dirent;
283
284 struct DIR {
285 struct dirent ent;
286 struct _WDIR *wdirp;
287 };
288 typedef struct DIR DIR;
289
 
 
290 static DIR *opendir (const char *dirname);
 
 
291 static struct dirent *readdir (DIR *dirp);
 
 
 
 
 
 
 
292 static int closedir (DIR *dirp);
 
 
293 static void rewinddir (DIR* dirp);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
295
296 /* Internal utility functions */
297 static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
298 static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
@@ -310,10 +332,11 @@
310 size_t sizeInBytes,
311 const wchar_t *wcstr,
312 size_t count);
313
314 static void dirent_set_errno (int error);
 
315
316 /*
317 * Open directory stream DIRNAME for read and return a pointer to the
318 * internal working area that is used to retrieve individual directory
319 * entries.
@@ -340,11 +363,11 @@
340 dirp->handle = INVALID_HANDLE_VALUE;
341 dirp->patt = NULL;
342 dirp->cached = 0;
343
344 /* Compute the length of full path plus zero terminator
345 *
346 * Note that on WinRT there's no way to convert relative paths
347 * into absolute paths, so just assume its an absolute path.
348 */
349 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
350 n = wcslen(dirname);
@@ -358,11 +381,11 @@
358
359 /*
360 * Convert relative directory name to an absolute one. This
361 * allows rewinddir() to function correctly even when current
362 * working directory is changed between opendir() and rewinddir().
363 *
364 * Note that on WinRT there's no way to convert relative paths
365 * into absolute paths, so just assume its an absolute path.
366 */
367 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
368 wcsncpy_s(dirp->patt, n+1, dirname, n);
@@ -425,68 +448,92 @@
425
426 return dirp;
427 }
428
429 /*
430 * Read next directory entry. The directory entry is returned in dirent
431 * structure in the d_name field. Individual directory entries returned by
432 * this function include regular files, sub-directories, pseudo-directories
433 * "." and ".." as well as volume labels, hidden files and system files.
434 */
435 static struct _wdirent*
436 _wreaddir(
437 _WDIR *dirp)
438 {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
439 WIN32_FIND_DATAW *datap;
440 struct _wdirent *entp;
441
442 /* Read next directory entry */
443 datap = dirent_next (dirp);
444 if (datap) {
445 size_t n;
446 DWORD attr;
447
448 /* Pointer to directory entry to return */
449 entp = &dirp->ent;
450
451 /*
452 * Copy file name as wide-character string. If the file name is too
453 * long to fit in to the destination buffer, then truncate file name
454 * to PATH_MAX characters and zero-terminate the buffer.
455 */
456 n = 0;
457 while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) {
458 entp->d_name[n] = datap->cFileName[n];
459 n++;
460 }
461 dirp->ent.d_name[n] = 0;
462
463 /* Length of file name excluding zero terminator */
464 entp->d_namlen = n;
465
466 /* File type */
467 attr = datap->dwFileAttributes;
468 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
469 entp->d_type = DT_CHR;
470 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
471 entp->d_type = DT_DIR;
472 } else {
473 entp->d_type = DT_REG;
474 }
475
476 /* Reset dummy fields */
477 entp->d_ino = 0;
478 entp->d_reclen = sizeof (struct _wdirent);
 
 
 
 
479
480 } else {
481
482 /* Last directory entry read */
483 entp = NULL;
484
485 }
486
487 return entp;
488 }
489
490 /*
491 * Close directory stream opened by opendir() function. This invalidates the
492 * DIR structure as well as any directory entry read previously by
@@ -514,13 +561,15 @@
514 /* Release directory structure */
515 free (dirp);
516 ok = /*success*/0;
517
518 } else {
 
519 /* Invalid directory stream */
520 dirent_set_errno (EBADF);
521 ok = /*failure*/-1;
 
522 }
523 return ok;
524 }
525
526 /*
@@ -567,11 +616,15 @@
567
568 }
569 return datap;
570 }
571
572 /* Get next directory entry (internal) */
 
 
 
 
573 static WIN32_FIND_DATAW*
574 dirent_next(
575 _WDIR *dirp)
576 {
577 WIN32_FIND_DATAW *p;
@@ -604,11 +657,11 @@
604 }
605
606 return p;
607 }
608
609 /*
610 * Open directory stream using plain old C-string.
611 */
612 static DIR*
613 opendir(
614 const char *dirname)
@@ -623,15 +676,16 @@
623 }
624
625 /* Allocate memory for DIR structure */
626 dirp = (DIR*) malloc (sizeof (struct DIR));
627 if (dirp) {
628 wchar_t wname[PATH_MAX];
629 size_t n;
630
631 /* Convert directory name to wide-character string */
632 error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);
 
633 if (!error) {
634
635 /* Open directory stream using wide-character name */
636 dirp->wdirp = _wopendir (wname);
637 if (dirp->wdirp) {
@@ -641,11 +695,11 @@
641 /* Failed to open directory stream */
642 error = 1;
643 }
644
645 } else {
646 /*
647 * Cannot convert file name to wide-character string. This
648 * occurs if the string contains invalid multi-byte sequences or
649 * the output buffer is too small to contain the resulting
650 * string.
651 */
@@ -666,39 +720,52 @@
666 return dirp;
667 }
668
669 /*
670 * Read next directory entry.
671 *
672 * When working with text consoles, please note that file names returned by
673 * readdir() are represented in the default ANSI code page while any output to
674 * console is typically formatted on another code page. Thus, non-ASCII
675 * characters in file names will not usually display correctly on console. The
676 * problem can be fixed in two ways: (1) change the character set of console
677 * to 1252 using chcp utility and use Lucida Console font, or (2) use
678 * _cprintf function when writing to console. The _cprinf() will re-encode
679 * ANSI strings to the console code page so many non-ASCII characters will
680 * display correcly.
681 */
682 static struct dirent*
683 readdir(
684 DIR *dirp)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
685 {
686 WIN32_FIND_DATAW *datap;
687 struct dirent *entp;
688
689 /* Read next directory entry */
690 datap = dirent_next (dirp->wdirp);
691 if (datap) {
692 size_t n;
693 int error;
694
695 /* Attempt to convert file name to multi-byte string */
696 error = dirent_wcstombs_s(
697 &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
698
699 /*
700 * If the file name cannot be represented by a multi-byte string,
701 * then attempt to use old 8+3 file name. This allows traditional
702 * Unix-code to access some file names despite of unicode
703 * characters, although file names may seem unfamiliar to the user.
704 *
@@ -706,67 +773,72 @@
706 * name unless the file system provides one. At least
707 * VirtualBox shared folders fail to do this.
708 */
709 if (error && datap->cAlternateFileName[0] != '\0') {
710 error = dirent_wcstombs_s(
711 &n, dirp->ent.d_name, PATH_MAX,
712 datap->cAlternateFileName, PATH_MAX);
713 }
714
715 if (!error) {
716 DWORD attr;
717
718 /* Initialize directory entry for return */
719 entp = &dirp->ent;
720
721 /* Length of file name excluding zero terminator */
722 entp->d_namlen = n - 1;
723
724 /* File attributes */
725 attr = datap->dwFileAttributes;
726 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
727 entp->d_type = DT_CHR;
728 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
729 entp->d_type = DT_DIR;
730 } else {
731 entp->d_type = DT_REG;
732 }
733
734 /* Reset dummy fields */
735 entp->d_ino = 0;
736 entp->d_reclen = sizeof (struct dirent);
 
737
738 } else {
739 /*
 
740 * Cannot convert file name to multi-byte string so construct
741 * an errornous directory entry and return that. Note that
742 * we cannot return NULL as that would stop the processing
743 * of directory entries completely.
744 */
745 entp = &dirp->ent;
746 entp->d_name[0] = '?';
747 entp->d_name[1] = '\0';
748 entp->d_namlen = 1;
749 entp->d_type = DT_UNKNOWN;
750 entp->d_ino = 0;
751 entp->d_reclen = 0;
752 }
 
 
 
 
753
754 } else {
 
755 /* No more directory entries */
756 entp = NULL;
 
757 }
758
759 return entp;
760 }
761
762 /*
763 * Close directory stream.
764 */
765 static int
766 closedir(
767 DIR *dirp)
768 {
769 int ok;
770 if (dirp) {
771
772 /* Close wide-character directory stream */
@@ -789,15 +861,173 @@
789 /*
790 * Rewind directory stream to beginning.
791 */
792 static void
793 rewinddir(
794 DIR* dirp)
795 {
796 /* Rewind wide-character string directory stream */
797 _wrewinddir (dirp->wdirp);
798 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
799
800 /* Convert multi-byte string to wide character string */
801 static int
802 dirent_mbstowcs_s(
803 size_t *pReturnValue,
804
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -1,8 +1,8 @@
1 /*
2 * Dirent interface for Microsoft Visual Studio
3 * Version 1.23
4 *
5 * Copyright (C) 2006-2012 Toni Ronkko
6 * This file is part of dirent. Dirent may be freely distributed
7 * under the MIT license. For all details and documentation, see
8 * https://github.com/tronkko/dirent
@@ -196,15 +196,15 @@
196 #endif
197 #if !defined(S_ISBLK)
198 # define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
199 #endif
200
201 /* Return the exact length of the file name without zero terminator */
202 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
203
204 /* Return the maximum size of a file name */
205 #define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1)
206
207
208 #ifdef __cplusplus
209 extern "C" {
210 #endif
@@ -212,10 +212,13 @@
212
213 /* Wide-character version */
214 struct _wdirent {
215 /* Always zero */
216 long d_ino;
217
218 /* File position within stream */
219 long d_off;
220
221 /* Structure size */
222 unsigned short d_reclen;
223
224 /* Length of name without \0 */
@@ -223,11 +226,11 @@
226
227 /* File type */
228 int d_type;
229
230 /* File name */
231 wchar_t d_name[PATH_MAX+1];
232 };
233 typedef struct _wdirent _wdirent;
234
235 struct _WDIR {
236 /* Current directory entry */
@@ -245,29 +248,17 @@
248 /* Initial directory name */
249 wchar_t *patt;
250 };
251 typedef struct _WDIR _WDIR;
252
253 /* Multi-byte character version */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254 struct dirent {
255 /* Always zero */
256 long d_ino;
257
258 /* File position within stream */
259 long d_off;
260
261 /* Structure size */
262 unsigned short d_reclen;
263
264 /* Length of name without \0 */
@@ -275,24 +266,55 @@
266
267 /* File type */
268 int d_type;
269
270 /* File name */
271 char d_name[PATH_MAX+1];
272 };
273 typedef struct dirent dirent;
274
275 struct DIR {
276 struct dirent ent;
277 struct _WDIR *wdirp;
278 };
279 typedef struct DIR DIR;
280
281
282 /* Dirent functions */
283 static DIR *opendir (const char *dirname);
284 static _WDIR *_wopendir (const wchar_t *dirname);
285
286 static struct dirent *readdir (DIR *dirp);
287 static struct _wdirent *_wreaddir (_WDIR *dirp);
288
289 static int readdir_r(
290 DIR *dirp, struct dirent *entry, struct dirent **result);
291 static int _wreaddir_r(
292 _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result);
293
294 static int closedir (DIR *dirp);
295 static int _wclosedir (_WDIR *dirp);
296
297 static void rewinddir (DIR* dirp);
298 static void _wrewinddir (_WDIR* dirp);
299
300 static int scandir (const char *dirname, struct dirent ***namelist,
301 int (*filter)(const struct dirent*),
302 int (*compare)(const void *, const void *));
303
304 static int alphasort (const struct dirent **a, const struct dirent **b);
305
306 static int versionsort (const struct dirent **a, const struct dirent **b);
307
308
309 /* For compatibility with Symbian */
310 #define wdirent _wdirent
311 #define WDIR _WDIR
312 #define wopendir _wopendir
313 #define wreaddir _wreaddir
314 #define wclosedir _wclosedir
315 #define wrewinddir _wrewinddir
316
317
318 /* Internal utility functions */
319 static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
320 static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
@@ -310,10 +332,11 @@
332 size_t sizeInBytes,
333 const wchar_t *wcstr,
334 size_t count);
335
336 static void dirent_set_errno (int error);
337
338
339 /*
340 * Open directory stream DIRNAME for read and return a pointer to the
341 * internal working area that is used to retrieve individual directory
342 * entries.
@@ -340,11 +363,11 @@
363 dirp->handle = INVALID_HANDLE_VALUE;
364 dirp->patt = NULL;
365 dirp->cached = 0;
366
367 /* Compute the length of full path plus zero terminator
368 *
369 * Note that on WinRT there's no way to convert relative paths
370 * into absolute paths, so just assume its an absolute path.
371 */
372 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
373 n = wcslen(dirname);
@@ -358,11 +381,11 @@
381
382 /*
383 * Convert relative directory name to an absolute one. This
384 * allows rewinddir() to function correctly even when current
385 * working directory is changed between opendir() and rewinddir().
386 *
387 * Note that on WinRT there's no way to convert relative paths
388 * into absolute paths, so just assume its an absolute path.
389 */
390 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
391 wcsncpy_s(dirp->patt, n+1, dirname, n);
@@ -425,68 +448,92 @@
448
449 return dirp;
450 }
451
452 /*
453 * Read next directory entry.
454 *
455 * Returns pointer to static directory entry which may be overwritted by
456 * subsequent calls to _wreaddir().
457 */
458 static struct _wdirent*
459 _wreaddir(
460 _WDIR *dirp)
461 {
462 struct _wdirent *entry;
463
464 /*
465 * Read directory entry to buffer. We can safely ignore the return value
466 * as entry will be set to NULL in case of error.
467 */
468 (void) _wreaddir_r (dirp, &dirp->ent, &entry);
469
470 /* Return pointer to statically allocated directory entry */
471 return entry;
472 }
473
474 /*
475 * Read next directory entry.
476 *
477 * Returns zero on success. If end of directory stream is reached, then sets
478 * result to NULL and returns zero.
479 */
480 static int
481 _wreaddir_r(
482 _WDIR *dirp,
483 struct _wdirent *entry,
484 struct _wdirent **result)
485 {
486 WIN32_FIND_DATAW *datap;
 
487
488 /* Read next directory entry */
489 datap = dirent_next (dirp);
490 if (datap) {
491 size_t n;
492 DWORD attr;
 
 
 
493
494 /*
495 * Copy file name as wide-character string. If the file name is too
496 * long to fit in to the destination buffer, then truncate file name
497 * to PATH_MAX characters and zero-terminate the buffer.
498 */
499 n = 0;
500 while (n < PATH_MAX && datap->cFileName[n] != 0) {
501 entry->d_name[n] = datap->cFileName[n];
502 n++;
503 }
504 entry->d_name[n] = 0;
505
506 /* Length of file name excluding zero terminator */
507 entry->d_namlen = n;
508
509 /* File type */
510 attr = datap->dwFileAttributes;
511 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
512 entry->d_type = DT_CHR;
513 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
514 entry->d_type = DT_DIR;
515 } else {
516 entry->d_type = DT_REG;
517 }
518
519 /* Reset dummy fields */
520 entry->d_ino = 0;
521 entry->d_off = 0;
522 entry->d_reclen = sizeof (struct _wdirent);
523
524 /* Set result address */
525 *result = entry;
526
527 } else {
528
529 /* Return NULL to indicate end of directory */
530 *result = NULL;
531
532 }
533
534 return /*OK*/0;
535 }
536
537 /*
538 * Close directory stream opened by opendir() function. This invalidates the
539 * DIR structure as well as any directory entry read previously by
@@ -514,13 +561,15 @@
561 /* Release directory structure */
562 free (dirp);
563 ok = /*success*/0;
564
565 } else {
566
567 /* Invalid directory stream */
568 dirent_set_errno (EBADF);
569 ok = /*failure*/-1;
570
571 }
572 return ok;
573 }
574
575 /*
@@ -567,11 +616,15 @@
616
617 }
618 return datap;
619 }
620
621 /*
622 * Get next directory entry (internal).
623 *
624 * Returns
625 */
626 static WIN32_FIND_DATAW*
627 dirent_next(
628 _WDIR *dirp)
629 {
630 WIN32_FIND_DATAW *p;
@@ -604,11 +657,11 @@
657 }
658
659 return p;
660 }
661
662 /*
663 * Open directory stream using plain old C-string.
664 */
665 static DIR*
666 opendir(
667 const char *dirname)
@@ -623,15 +676,16 @@
676 }
677
678 /* Allocate memory for DIR structure */
679 dirp = (DIR*) malloc (sizeof (struct DIR));
680 if (dirp) {
681 wchar_t wname[PATH_MAX + 1];
682 size_t n;
683
684 /* Convert directory name to wide-character string */
685 error = dirent_mbstowcs_s(
686 &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
687 if (!error) {
688
689 /* Open directory stream using wide-character name */
690 dirp->wdirp = _wopendir (wname);
691 if (dirp->wdirp) {
@@ -641,11 +695,11 @@
695 /* Failed to open directory stream */
696 error = 1;
697 }
698
699 } else {
700 /*
701 * Cannot convert file name to wide-character string. This
702 * occurs if the string contains invalid multi-byte sequences or
703 * the output buffer is too small to contain the resulting
704 * string.
705 */
@@ -666,39 +720,52 @@
720 return dirp;
721 }
722
723 /*
724 * Read next directory entry.
 
 
 
 
 
 
 
 
 
 
725 */
726 static struct dirent*
727 readdir(
728 DIR *dirp)
729 {
730 struct dirent *entry;
731
732 /*
733 * Read directory entry to buffer. We can safely ignore the return value
734 * as entry will be set to NULL in case of error.
735 */
736 (void) readdir_r (dirp, &dirp->ent, &entry);
737
738 /* Return pointer to statically allocated directory entry */
739 return entry;
740 }
741
742 /*
743 * Read next directory entry into called-allocated buffer.
744 *
745 * Returns zero on sucess. If the end of directory stream is reached, then
746 * sets result to NULL and returns zero.
747 */
748 static int
749 readdir_r(
750 DIR *dirp,
751 struct dirent *entry,
752 struct dirent **result)
753 {
754 WIN32_FIND_DATAW *datap;
 
755
756 /* Read next directory entry */
757 datap = dirent_next (dirp->wdirp);
758 if (datap) {
759 size_t n;
760 int error;
761
762 /* Attempt to convert file name to multi-byte string */
763 error = dirent_wcstombs_s(
764 &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1);
765
766 /*
767 * If the file name cannot be represented by a multi-byte string,
768 * then attempt to use old 8+3 file name. This allows traditional
769 * Unix-code to access some file names despite of unicode
770 * characters, although file names may seem unfamiliar to the user.
771 *
@@ -706,67 +773,72 @@
773 * name unless the file system provides one. At least
774 * VirtualBox shared folders fail to do this.
775 */
776 if (error && datap->cAlternateFileName[0] != '\0') {
777 error = dirent_wcstombs_s(
778 &n, entry->d_name, PATH_MAX + 1,
779 datap->cAlternateFileName, PATH_MAX + 1);
780 }
781
782 if (!error) {
783 DWORD attr;
784
 
 
 
785 /* Length of file name excluding zero terminator */
786 entry->d_namlen = n - 1;
787
788 /* File attributes */
789 attr = datap->dwFileAttributes;
790 if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
791 entry->d_type = DT_CHR;
792 } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
793 entry->d_type = DT_DIR;
794 } else {
795 entry->d_type = DT_REG;
796 }
797
798 /* Reset dummy fields */
799 entry->d_ino = 0;
800 entry->d_off = 0;
801 entry->d_reclen = sizeof (struct dirent);
802
803 } else {
804
805 /*
806 * Cannot convert file name to multi-byte string so construct
807 * an errornous directory entry and return that. Note that
808 * we cannot return NULL as that would stop the processing
809 * of directory entries completely.
810 */
811 entry->d_name[0] = '?';
812 entry->d_name[1] = '\0';
813 entry->d_namlen = 1;
814 entry->d_type = DT_UNKNOWN;
815 entry->d_ino = 0;
816 entry->d_off = -1;
817 entry->d_reclen = 0;
818
819 }
820
821 /* Return pointer to directory entry */
822 *result = entry;
823
824 } else {
825
826 /* No more directory entries */
827 *result = NULL;
828
829 }
830
831 return /*OK*/0;
832 }
833
834 /*
835 * Close directory stream.
836 */
837 static int
838 closedir(
839 DIR *dirp)
840 {
841 int ok;
842 if (dirp) {
843
844 /* Close wide-character directory stream */
@@ -789,15 +861,173 @@
861 /*
862 * Rewind directory stream to beginning.
863 */
864 static void
865 rewinddir(
866 DIR* dirp)
867 {
868 /* Rewind wide-character string directory stream */
869 _wrewinddir (dirp->wdirp);
870 }
871
872 /*
873 * Scan directory for entries.
874 */
875 static int
876 scandir(
877 const char *dirname,
878 struct dirent ***namelist,
879 int (*filter)(const struct dirent*),
880 int (*compare)(const void*, const void*))
881 {
882 struct dirent **files = NULL;
883 size_t size = 0;
884 size_t allocated = 0;
885 const size_t init_size = 1;
886 DIR *dir = NULL;
887 struct dirent *entry;
888 struct dirent *tmp = NULL;
889 size_t i;
890 int result = 0;
891
892 /* Open directory stream */
893 dir = opendir (dirname);
894 if (dir) {
895
896 /* Read directory entries to memory */
897 while (1) {
898
899 /* Enlarge pointer table to make room for another pointer */
900 if (size >= allocated) {
901 void *p;
902 size_t num_entries;
903
904 /* Compute number of entries in the enlarged pointer table */
905 if (size < init_size) {
906 /* Allocate initial pointer table */
907 num_entries = init_size;
908 } else {
909 /* Double the size */
910 num_entries = size * 2;
911 }
912
913 /* Allocate first pointer table or enlarge existing table */
914 p = realloc (files, sizeof (void*) * num_entries);
915 if (p != NULL) {
916 /* Got the memory */
917 files = p;
918 allocated = num_entries;
919 } else {
920 /* Out of memory */
921 result = -1;
922 break;
923 }
924
925 }
926
927 /* Allocate room for temporary directory entry */
928 if (tmp == NULL) {
929 tmp = (struct dirent*) malloc (sizeof (struct dirent));
930 if (tmp == NULL) {
931 /* Cannot allocate temporary directory entry */
932 result = -1;
933 break;
934 }
935 }
936
937 /* Read directory entry to temporary area */
938 if (readdir_r (dir, tmp, &entry) == /*OK*/0) {
939
940 /* Did we got an entry? */
941 if (entry != NULL) {
942 int pass;
943
944 /* Determine whether to include the entry in result */
945 if (filter) {
946 /* Let the filter function decide */
947 pass = filter (tmp);
948 } else {
949 /* No filter function, include everything */
950 pass = 1;
951 }
952
953 if (pass) {
954 /* Store the temporary entry to pointer table */
955 files[size++] = tmp;
956 tmp = NULL;
957
958 /* Keep up with the number of files */
959 result++;
960 }
961
962 } else {
963
964 /*
965 * End of directory stream reached => sort entries and
966 * exit.
967 */
968 qsort (files, size, sizeof (void*), (void*) compare);
969 break;
970
971 }
972
973 } else {
974 /* Error reading directory entry */
975 result = /*Error*/ -1;
976 break;
977 }
978
979 }
980
981 } else {
982 /* Cannot open directory */
983 result = /*Error*/ -1;
984 }
985
986 /* Release temporary directory entry */
987 if (tmp) {
988 free (tmp);
989 }
990
991 /* Release allocated memory on error */
992 if (result < 0) {
993 for (i = 0; i < size; i++) {
994 free (files[i]);
995 }
996 free (files);
997 files = NULL;
998 }
999
1000 /* Close directory stream */
1001 if (dir) {
1002 closedir (dir);
1003 }
1004
1005 /* Pass pointer table to caller */
1006 if (namelist) {
1007 *namelist = files;
1008 }
1009 return result;
1010 }
1011
1012 /* Alphabetical sorting */
1013 static int
1014 alphasort(
1015 const struct dirent **a, const struct dirent **b)
1016 {
1017 return strcoll ((*a)->d_name, (*b)->d_name);
1018 }
1019
1020 /* Sort versions */
1021 static int
1022 versionsort(
1023 const struct dirent **a, const struct dirent **b)
1024 {
1025 /* FIXME: implement strverscmp and use that */
1026 return alphasort (a, b);
1027 }
1028
1029
1030 /* Convert multi-byte string to wide character string */
1031 static int
1032 dirent_mbstowcs_s(
1033 size_t *pReturnValue,
1034

Keyboard Shortcuts

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