"Fossies" - the Fresh Open Source Software Archive

Member "rrdtool-1.7.2/win32/dirent.h" (4 Feb 2019, 27350 Bytes) of package /linux/misc/rrdtool-1.7.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dirent.h" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Dirent interface for Microsoft Visual Studio
    3  * Version 1.23.1
    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
    9  */
   10 #ifndef DIRENT_H
   11 #define DIRENT_H
   12 
   13 /*
   14  * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
   15  * Windows Sockets 2.0.
   16  */
   17 #ifndef WIN32_LEAN_AND_MEAN
   18 #   define WIN32_LEAN_AND_MEAN
   19 #endif
   20 #include <windows.h>
   21 
   22 #include <stdio.h>
   23 #include <stdarg.h>
   24 #include <wchar.h>
   25 #include <string.h>
   26 #include <stdlib.h>
   27 #include <malloc.h>
   28 #include <sys/types.h>
   29 #include <sys/stat.h>
   30 #include <errno.h>
   31 
   32 /* Indicates that d_type field is available in dirent structure */
   33 #define _DIRENT_HAVE_D_TYPE
   34 
   35 /* Indicates that d_namlen field is available in dirent structure */
   36 #define _DIRENT_HAVE_D_NAMLEN
   37 
   38 /* Entries missing from MSVC 6.0 */
   39 #if !defined(FILE_ATTRIBUTE_DEVICE)
   40 #   define FILE_ATTRIBUTE_DEVICE 0x40
   41 #endif
   42 
   43 /* File type and permission flags for stat(), general mask */
   44 #if !defined(S_IFMT)
   45 #   define S_IFMT _S_IFMT
   46 #endif
   47 
   48 /* Directory bit */
   49 #if !defined(S_IFDIR)
   50 #   define S_IFDIR _S_IFDIR
   51 #endif
   52 
   53 /* Character device bit */
   54 #if !defined(S_IFCHR)
   55 #   define S_IFCHR _S_IFCHR
   56 #endif
   57 
   58 /* Pipe bit */
   59 #if !defined(S_IFFIFO)
   60 #   define S_IFFIFO _S_IFFIFO
   61 #endif
   62 
   63 /* Regular file bit */
   64 #if !defined(S_IFREG)
   65 #   define S_IFREG _S_IFREG
   66 #endif
   67 
   68 /* Read permission */
   69 #if !defined(S_IREAD)
   70 #   define S_IREAD _S_IREAD
   71 #endif
   72 
   73 /* Write permission */
   74 #if !defined(S_IWRITE)
   75 #   define S_IWRITE _S_IWRITE
   76 #endif
   77 
   78 /* Execute permission */
   79 #if !defined(S_IEXEC)
   80 #   define S_IEXEC _S_IEXEC
   81 #endif
   82 
   83 /* Pipe */
   84 #if !defined(S_IFIFO)
   85 #   define S_IFIFO _S_IFIFO
   86 #endif
   87 
   88 /* Block device */
   89 #if !defined(S_IFBLK)
   90 #   define S_IFBLK 0
   91 #endif
   92 
   93 /* Link */
   94 #if !defined(S_IFLNK)
   95 #   define S_IFLNK 0
   96 #endif
   97 
   98 /* Socket */
   99 #if !defined(S_IFSOCK)
  100 #   define S_IFSOCK 0
  101 #endif
  102 
  103 /* Read user permission */
  104 #if !defined(S_IRUSR)
  105 #   define S_IRUSR S_IREAD
  106 #endif
  107 
  108 /* Write user permission */
  109 #if !defined(S_IWUSR)
  110 #   define S_IWUSR S_IWRITE
  111 #endif
  112 
  113 /* Execute user permission */
  114 #if !defined(S_IXUSR)
  115 #   define S_IXUSR 0
  116 #endif
  117 
  118 /* Read group permission */
  119 #if !defined(S_IRGRP)
  120 #   define S_IRGRP 0
  121 #endif
  122 
  123 /* Write group permission */
  124 #if !defined(S_IWGRP)
  125 #   define S_IWGRP 0
  126 #endif
  127 
  128 /* Execute group permission */
  129 #if !defined(S_IXGRP)
  130 #   define S_IXGRP 0
  131 #endif
  132 
  133 /* Read others permission */
  134 #if !defined(S_IROTH)
  135 #   define S_IROTH 0
  136 #endif
  137 
  138 /* Write others permission */
  139 #if !defined(S_IWOTH)
  140 #   define S_IWOTH 0
  141 #endif
  142 
  143 /* Execute others permission */
  144 #if !defined(S_IXOTH)
  145 #   define S_IXOTH 0
  146 #endif
  147 
  148 /* Maximum length of file name */
  149 #if !defined(PATH_MAX)
  150 #   define PATH_MAX MAX_PATH
  151 #endif
  152 #if !defined(FILENAME_MAX)
  153 #   define FILENAME_MAX MAX_PATH
  154 #endif
  155 #if !defined(NAME_MAX)
  156 #   define NAME_MAX FILENAME_MAX
  157 #endif
  158 
  159 /* File type flags for d_type */
  160 #define DT_UNKNOWN 0
  161 #define DT_REG S_IFREG
  162 #define DT_DIR S_IFDIR
  163 #define DT_FIFO S_IFIFO
  164 #define DT_SOCK S_IFSOCK
  165 #define DT_CHR S_IFCHR
  166 #define DT_BLK S_IFBLK
  167 #define DT_LNK S_IFLNK
  168 
  169 /* Macros for converting between st_mode and d_type */
  170 #define IFTODT(mode) ((mode) & S_IFMT)
  171 #define DTTOIF(type) (type)
  172 
  173 /*
  174  * File type macros.  Note that block devices, sockets and links cannot be
  175  * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
  176  * only defined for compatibility.  These macros should always return false
  177  * on Windows.
  178  */
  179 #if !defined(S_ISFIFO)
  180 #   define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
  181 #endif
  182 #if !defined(S_ISDIR)
  183 #   define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
  184 #endif
  185 #if !defined(S_ISREG)
  186 #   define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
  187 #endif
  188 #if !defined(S_ISLNK)
  189 #   define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
  190 #endif
  191 #if !defined(S_ISSOCK)
  192 #   define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
  193 #endif
  194 #if !defined(S_ISCHR)
  195 #   define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
  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
  211 
  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 */
  225     size_t d_namlen;
  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 */
  237     struct _wdirent ent;
  238 
  239     /* Private file data */
  240     WIN32_FIND_DATAW data;
  241 
  242     /* True if data is valid */
  243     int cached;
  244 
  245     /* Win32 search handle */
  246     HANDLE handle;
  247 
  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 */
  265     size_t d_namlen;
  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);
  321 
  322 static int dirent_mbstowcs_s(
  323     size_t *pReturnValue,
  324     wchar_t *wcstr,
  325     size_t sizeInWords,
  326     const char *mbstr,
  327     size_t count);
  328 
  329 static int dirent_wcstombs_s(
  330     size_t *pReturnValue,
  331     char *mbstr,
  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.
  343  */
  344 static _WDIR*
  345 _wopendir(
  346     const wchar_t *dirname)
  347 {
  348     _WDIR *dirp = NULL;
  349     int error;
  350 
  351     /* Must have directory name */
  352     if (dirname == NULL  ||  dirname[0] == '\0') {
  353         dirent_set_errno (ENOENT);
  354         return NULL;
  355     }
  356 
  357     /* Allocate new _WDIR structure */
  358     dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
  359     if (dirp != NULL) {
  360         DWORD n;
  361 
  362         /* Reset _WDIR structure */
  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);
  374 #       else
  375             n = GetFullPathNameW (dirname, 0, NULL, NULL);
  376 #       endif
  377 
  378         /* Allocate room for absolute directory name and search pattern */
  379         dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
  380         if (dirp->patt) {
  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);
  392 #           else
  393                 n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
  394 #           endif
  395             if (n > 0) {
  396                 wchar_t *p;
  397 
  398                 /* Append search pattern \* to the directory name */
  399                 p = dirp->patt + n;
  400                 if (dirp->patt < p) {
  401                     switch (p[-1]) {
  402                     case '\\':
  403                     case '/':
  404                     case ':':
  405                         /* Directory ends in path separator, e.g. c:\temp\ */
  406                         /*NOP*/;
  407                         break;
  408 
  409                     default:
  410                         /* Directory name doesn't end in path separator */
  411                         *p++ = '\\';
  412                     }
  413                 }
  414                 *p++ = '*';
  415                 *p = '\0';
  416 
  417                 /* Open directory stream and retrieve the first entry */
  418                 if (dirent_first (dirp)) {
  419                     /* Directory stream opened successfully */
  420                     error = 0;
  421                 } else {
  422                     /* Cannot retrieve first entry */
  423                     error = 1;
  424                     dirent_set_errno (ENOENT);
  425                 }
  426 
  427             } else {
  428                 /* Cannot retrieve full path name */
  429                 dirent_set_errno (ENOENT);
  430                 error = 1;
  431             }
  432 
  433         } else {
  434             /* Cannot allocate memory for search pattern */
  435             error = 1;
  436         }
  437 
  438     } else {
  439         /* Cannot allocate _WDIR structure */
  440         error = 1;
  441     }
  442 
  443     /* Clean up in case of error */
  444     if (error  &&  dirp) {
  445         _wclosedir (dirp);
  446         dirp = NULL;
  447     }
  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
  540  * _wreaddir().
  541  */
  542 static int
  543 _wclosedir(
  544     _WDIR *dirp)
  545 {
  546     int ok;
  547     if (dirp) {
  548 
  549         /* Release search handle */
  550         if (dirp->handle != INVALID_HANDLE_VALUE) {
  551             FindClose (dirp->handle);
  552             dirp->handle = INVALID_HANDLE_VALUE;
  553         }
  554 
  555         /* Release search pattern */
  556         if (dirp->patt) {
  557             free (dirp->patt);
  558             dirp->patt = NULL;
  559         }
  560 
  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 /*
  576  * Rewind directory stream such that _wreaddir() returns the very first
  577  * file name again.
  578  */
  579 static void
  580 _wrewinddir(
  581     _WDIR* dirp)
  582 {
  583     if (dirp) {
  584         /* Release existing search handle */
  585         if (dirp->handle != INVALID_HANDLE_VALUE) {
  586             FindClose (dirp->handle);
  587         }
  588 
  589         /* Open new search handle */
  590         dirent_first (dirp);
  591     }
  592 }
  593 
  594 /* Get first directory entry (internal) */
  595 static WIN32_FIND_DATAW*
  596 dirent_first(
  597     _WDIR *dirp)
  598 {
  599     WIN32_FIND_DATAW *datap;
  600 
  601     /* Open directory and retrieve the first entry */
  602     dirp->handle = FindFirstFileExW(
  603         dirp->patt, FindExInfoStandard, &dirp->data,
  604         FindExSearchNameMatch, NULL, 0);
  605     if (dirp->handle != INVALID_HANDLE_VALUE) {
  606 
  607         /* a directory entry is now waiting in memory */
  608         datap = &dirp->data;
  609         dirp->cached = 1;
  610 
  611     } else {
  612 
  613         /* Failed to re-open directory: no directory entry in memory */
  614         dirp->cached = 0;
  615         datap = NULL;
  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;
  631 
  632     /* Get next directory entry */
  633     if (dirp->cached != 0) {
  634 
  635         /* A valid directory entry already in memory */
  636         p = &dirp->data;
  637         dirp->cached = 0;
  638 
  639     } else if (dirp->handle != INVALID_HANDLE_VALUE) {
  640 
  641         /* Get the next directory entry from stream */
  642         if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
  643             /* Got a file */
  644             p = &dirp->data;
  645         } else {
  646             /* The very last entry has been processed or an error occured */
  647             FindClose (dirp->handle);
  648             dirp->handle = INVALID_HANDLE_VALUE;
  649             p = NULL;
  650         }
  651 
  652     } else {
  653 
  654         /* End of directory stream reached */
  655         p = NULL;
  656 
  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) 
  668 {
  669     struct DIR *dirp;
  670     int error;
  671 
  672     /* Must have directory name */
  673     if (dirname == NULL  ||  dirname[0] == '\0') {
  674         dirent_set_errno (ENOENT);
  675         return NULL;
  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) {
  692                 /* Directory stream opened */
  693                 error = 0;
  694             } else {
  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              */
  706             error = 1;
  707         }
  708 
  709     } else {
  710         /* Cannot allocate DIR structure */
  711         error = 1;
  712     }
  713 
  714     /* Clean up in case of error */
  715     if (error  &&  dirp) {
  716         free (dirp);
  717         dirp = NULL;
  718     }
  719 
  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          *
  772          * Be ware that the code below cannot come up with a short file
  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 */
  845         ok = _wclosedir (dirp->wdirp);
  846         dirp->wdirp = NULL;
  847 
  848         /* Release multi-byte character version */
  849         free (dirp);
  850 
  851     } else {
  852 
  853         /* Invalid directory stream */
  854         dirent_set_errno (EBADF);
  855         ok = /*failure*/-1;
  856 
  857     }
  858     return ok;
  859 }
  860 
  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 = (dirent**) 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*), 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     wchar_t *wcstr,
 1035     size_t sizeInWords,
 1036     const char *mbstr,
 1037     size_t count)
 1038 {
 1039     int error;
 1040 
 1041 #if defined(_MSC_VER)  &&  _MSC_VER >= 1400
 1042 
 1043     /* Microsoft Visual Studio 2005 or later */
 1044     error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
 1045 
 1046 #else
 1047 
 1048     /* Older Visual Studio or non-Microsoft compiler */
 1049     size_t n;
 1050 
 1051     /* Convert to wide-character string (or count characters) */
 1052     n = mbstowcs (wcstr, mbstr, sizeInWords);
 1053     if (!wcstr  ||  n < count) {
 1054 
 1055         /* Zero-terminate output buffer */
 1056         if (wcstr  &&  sizeInWords) {
 1057             if (n >= sizeInWords) {
 1058                 n = sizeInWords - 1;
 1059             }
 1060             wcstr[n] = 0;
 1061         }
 1062 
 1063         /* Length of resuting multi-byte string WITH zero terminator */
 1064         if (pReturnValue) {
 1065             *pReturnValue = n + 1;
 1066         }
 1067 
 1068         /* Success */
 1069         error = 0;
 1070 
 1071     } else {
 1072 
 1073         /* Could not convert string */
 1074         error = 1;
 1075 
 1076     }
 1077 
 1078 #endif
 1079 
 1080     return error;
 1081 }
 1082 
 1083 /* Convert wide-character string to multi-byte string */
 1084 static int
 1085 dirent_wcstombs_s(
 1086     size_t *pReturnValue,
 1087     char *mbstr,
 1088     size_t sizeInBytes, /* max size of mbstr */
 1089     const wchar_t *wcstr,
 1090     size_t count)
 1091 {
 1092     int error;
 1093 
 1094 #if defined(_MSC_VER)  &&  _MSC_VER >= 1400
 1095 
 1096     /* Microsoft Visual Studio 2005 or later */
 1097     error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
 1098 
 1099 #else
 1100 
 1101     /* Older Visual Studio or non-Microsoft compiler */
 1102     size_t n;
 1103 
 1104     /* Convert to multi-byte string (or count the number of bytes needed) */
 1105     n = wcstombs (mbstr, wcstr, sizeInBytes);
 1106     if (!mbstr  ||  n < count) {
 1107 
 1108         /* Zero-terminate output buffer */
 1109         if (mbstr  &&  sizeInBytes) {
 1110             if (n >= sizeInBytes) {
 1111                 n = sizeInBytes - 1;
 1112             }
 1113             mbstr[n] = '\0';
 1114         }
 1115 
 1116         /* Length of resulting multi-bytes string WITH zero-terminator */
 1117         if (pReturnValue) {
 1118             *pReturnValue = n + 1;
 1119         }
 1120 
 1121         /* Success */
 1122         error = 0;
 1123 
 1124     } else {
 1125 
 1126         /* Cannot convert string */
 1127         error = 1;
 1128 
 1129     }
 1130 
 1131 #endif
 1132 
 1133     return error;
 1134 }
 1135 
 1136 /* Set errno variable */
 1137 static void
 1138 dirent_set_errno(
 1139     int error)
 1140 {
 1141 #if defined(_MSC_VER)  &&  _MSC_VER >= 1400
 1142 
 1143     /* Microsoft Visual Studio 2005 and later */
 1144     _set_errno (error);
 1145 
 1146 #else
 1147 
 1148     /* Non-Microsoft compiler or older Microsoft compiler */
 1149     errno = error;
 1150 
 1151 #endif
 1152 }
 1153 
 1154 
 1155 #ifdef __cplusplus
 1156 }
 1157 #endif
 1158 #endif /*DIRENT_H*/
 1159