zoukankan      html  css  js  c++  java
  • dirent.h文件

     dirent.h头文件

       1 /*
       2  * Dirent interface for Microsoft Visual Studio
       3  *
       4  * Copyright (C) 1998-2019 Toni Ronkko
       5  * This file is part of dirent.  Dirent may be freely distributed
       6  * under the MIT license.  For all details and documentation, see
       7  * https://github.com/tronkko/dirent
       8  */
       9 #ifndef DIRENT_H
      10 #define DIRENT_H
      11 
      12 /* Hide warnings about unreferenced local functions */
      13 #if defined(__clang__)
      14 #   pragma clang diagnostic ignored "-Wunused-function"
      15 #elif defined(_MSC_VER)
      16 #   pragma warning(disable:4505)
      17 #elif defined(__GNUC__)
      18 #   pragma GCC diagnostic ignored "-Wunused-function"
      19 #endif
      20 
      21 /*
      22  * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
      23  * Windows Sockets 2.0.
      24  */
      25 #ifndef WIN32_LEAN_AND_MEAN
      26 #   define WIN32_LEAN_AND_MEAN
      27 #endif
      28 #include <windows.h>
      29 
      30 #include <stdio.h>
      31 #include <stdarg.h>
      32 #include <wchar.h>
      33 #include <string.h>
      34 #include <stdlib.h>
      35 #include <malloc.h>
      36 #include <sys/types.h>
      37 #include <sys/stat.h>
      38 #include <errno.h>
      39 
      40 /* Indicates that d_type field is available in dirent structure */
      41 #define _DIRENT_HAVE_D_TYPE
      42 
      43 /* Indicates that d_namlen field is available in dirent structure */
      44 #define _DIRENT_HAVE_D_NAMLEN
      45 
      46 /* Entries missing from MSVC 6.0 */
      47 #if !defined(FILE_ATTRIBUTE_DEVICE)
      48 #   define FILE_ATTRIBUTE_DEVICE 0x40
      49 #endif
      50 
      51 /* File type and permission flags for stat(), general mask */
      52 #if !defined(S_IFMT)
      53 #   define S_IFMT _S_IFMT
      54 #endif
      55 
      56 /* Directory bit */
      57 #if !defined(S_IFDIR)
      58 #   define S_IFDIR _S_IFDIR
      59 #endif
      60 
      61 /* Character device bit */
      62 #if !defined(S_IFCHR)
      63 #   define S_IFCHR _S_IFCHR
      64 #endif
      65 
      66 /* Pipe bit */
      67 #if !defined(S_IFFIFO)
      68 #   define S_IFFIFO _S_IFFIFO
      69 #endif
      70 
      71 /* Regular file bit */
      72 #if !defined(S_IFREG)
      73 #   define S_IFREG _S_IFREG
      74 #endif
      75 
      76 /* Read permission */
      77 #if !defined(S_IREAD)
      78 #   define S_IREAD _S_IREAD
      79 #endif
      80 
      81 /* Write permission */
      82 #if !defined(S_IWRITE)
      83 #   define S_IWRITE _S_IWRITE
      84 #endif
      85 
      86 /* Execute permission */
      87 #if !defined(S_IEXEC)
      88 #   define S_IEXEC _S_IEXEC
      89 #endif
      90 
      91 /* Pipe */
      92 #if !defined(S_IFIFO)
      93 #   define S_IFIFO _S_IFIFO
      94 #endif
      95 
      96 /* Block device */
      97 #if !defined(S_IFBLK)
      98 #   define S_IFBLK 0
      99 #endif
     100 
     101 /* Link */
     102 #if !defined(S_IFLNK)
     103 #   define S_IFLNK 0
     104 #endif
     105 
     106 /* Socket */
     107 #if !defined(S_IFSOCK)
     108 #   define S_IFSOCK 0
     109 #endif
     110 
     111 /* Read user permission */
     112 #if !defined(S_IRUSR)
     113 #   define S_IRUSR S_IREAD
     114 #endif
     115 
     116 /* Write user permission */
     117 #if !defined(S_IWUSR)
     118 #   define S_IWUSR S_IWRITE
     119 #endif
     120 
     121 /* Execute user permission */
     122 #if !defined(S_IXUSR)
     123 #   define S_IXUSR 0
     124 #endif
     125 
     126 /* Read group permission */
     127 #if !defined(S_IRGRP)
     128 #   define S_IRGRP 0
     129 #endif
     130 
     131 /* Write group permission */
     132 #if !defined(S_IWGRP)
     133 #   define S_IWGRP 0
     134 #endif
     135 
     136 /* Execute group permission */
     137 #if !defined(S_IXGRP)
     138 #   define S_IXGRP 0
     139 #endif
     140 
     141 /* Read others permission */
     142 #if !defined(S_IROTH)
     143 #   define S_IROTH 0
     144 #endif
     145 
     146 /* Write others permission */
     147 #if !defined(S_IWOTH)
     148 #   define S_IWOTH 0
     149 #endif
     150 
     151 /* Execute others permission */
     152 #if !defined(S_IXOTH)
     153 #   define S_IXOTH 0
     154 #endif
     155 
     156 /* Maximum length of file name */
     157 #if !defined(PATH_MAX)
     158 #   define PATH_MAX MAX_PATH
     159 #endif
     160 #if !defined(FILENAME_MAX)
     161 #   define FILENAME_MAX MAX_PATH
     162 #endif
     163 #if !defined(NAME_MAX)
     164 #   define NAME_MAX FILENAME_MAX
     165 #endif
     166 
     167 /* File type flags for d_type */
     168 #define DT_UNKNOWN 0
     169 #define DT_REG S_IFREG
     170 #define DT_DIR S_IFDIR
     171 #define DT_FIFO S_IFIFO
     172 #define DT_SOCK S_IFSOCK
     173 #define DT_CHR S_IFCHR
     174 #define DT_BLK S_IFBLK
     175 #define DT_LNK S_IFLNK
     176 
     177 /* Macros for converting between st_mode and d_type */
     178 #define IFTODT(mode) ((mode) & S_IFMT)
     179 #define DTTOIF(type) (type)
     180 
     181 /*
     182  * File type macros.  Note that block devices, sockets and links cannot be
     183  * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
     184  * only defined for compatibility.  These macros should always return false
     185  * on Windows.
     186  */
     187 #if !defined(S_ISFIFO)
     188 #   define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
     189 #endif
     190 #if !defined(S_ISDIR)
     191 #   define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
     192 #endif
     193 #if !defined(S_ISREG)
     194 #   define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
     195 #endif
     196 #if !defined(S_ISLNK)
     197 #   define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
     198 #endif
     199 #if !defined(S_ISSOCK)
     200 #   define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
     201 #endif
     202 #if !defined(S_ISCHR)
     203 #   define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
     204 #endif
     205 #if !defined(S_ISBLK)
     206 #   define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
     207 #endif
     208 
     209 /* Return the exact length of the file name without zero terminator */
     210 #define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
     211 
     212 /* Return the maximum size of a file name */
     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     /* Always zero */
     224     long d_ino;
     225 
     226     /* File position within stream */
     227     long d_off;
     228 
     229     /* Structure size */
     230     unsigned short d_reclen;
     231 
     232     /* Length of name without  */
     233     size_t d_namlen;
     234 
     235     /* File type */
     236     int d_type;
     237 
     238     /* File name */
     239     wchar_t d_name[PATH_MAX+1];
     240 };
     241 typedef struct _wdirent _wdirent;
     242 
     243 struct _WDIR {
     244     /* Current directory entry */
     245     struct _wdirent ent;
     246 
     247     /* Private file data */
     248     WIN32_FIND_DATAW data;
     249 
     250     /* True if data is valid */
     251     int cached;
     252 
     253     /* Win32 search handle */
     254     HANDLE handle;
     255 
     256     /* Initial directory name */
     257     wchar_t *patt;
     258 };
     259 typedef struct _WDIR _WDIR;
     260 
     261 /* Multi-byte character version */
     262 struct dirent {
     263     /* Always zero */
     264     long d_ino;
     265 
     266     /* File position within stream */
     267     long d_off;
     268 
     269     /* Structure size */
     270     unsigned short d_reclen;
     271 
     272     /* Length of name without  */
     273     size_t d_namlen;
     274 
     275     /* File type */
     276     int d_type;
     277 
     278     /* File name */
     279     char d_name[PATH_MAX+1];
     280 };
     281 typedef struct dirent dirent;
     282 
     283 struct DIR {
     284     struct dirent ent;
     285     struct _WDIR *wdirp;
     286 };
     287 typedef struct DIR DIR;
     288 
     289 
     290 /* Dirent functions */
     291 static DIR *opendir (const char *dirname);
     292 static _WDIR *_wopendir (const wchar_t *dirname);
     293 
     294 static struct dirent *readdir (DIR *dirp);
     295 static struct _wdirent *_wreaddir (_WDIR *dirp);
     296 
     297 static int readdir_r(
     298     DIR *dirp, struct dirent *entry, struct dirent **result);
     299 static int _wreaddir_r(
     300     _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result);
     301 
     302 static int closedir (DIR *dirp);
     303 static int _wclosedir (_WDIR *dirp);
     304 
     305 static void rewinddir (DIR* dirp);
     306 static void _wrewinddir (_WDIR* dirp);
     307 
     308 static int scandir (const char *dirname, struct dirent ***namelist,
     309     int (*filter)(const struct dirent*),
     310     int (*compare)(const struct dirent**, const struct dirent**));
     311 
     312 static int alphasort (const struct dirent **a, const struct dirent **b);
     313 
     314 static int versionsort (const struct dirent **a, const struct dirent **b);
     315 
     316 
     317 /* For compatibility with Symbian */
     318 #define wdirent _wdirent
     319 #define WDIR _WDIR
     320 #define wopendir _wopendir
     321 #define wreaddir _wreaddir
     322 #define wclosedir _wclosedir
     323 #define wrewinddir _wrewinddir
     324 
     325 
     326 /* Internal utility functions */
     327 static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
     328 static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
     329 
     330 static int dirent_mbstowcs_s(
     331     size_t *pReturnValue,
     332     wchar_t *wcstr,
     333     size_t sizeInWords,
     334     const char *mbstr,
     335     size_t count);
     336 
     337 static int dirent_wcstombs_s(
     338     size_t *pReturnValue,
     339     char *mbstr,
     340     size_t sizeInBytes,
     341     const wchar_t *wcstr,
     342     size_t count);
     343 
     344 static void dirent_set_errno (int error);
     345 
     346 
     347 /*
     348  * Open directory stream DIRNAME for read and return a pointer to the
     349  * internal working area that is used to retrieve individual directory
     350  * entries.
     351  */
     352 static _WDIR*
     353 _wopendir(
     354     const wchar_t *dirname)
     355 {
     356     _WDIR *dirp;
     357     DWORD n;
     358     wchar_t *p;
     359 
     360     /* Must have directory name */
     361     if (dirname == NULL  ||  dirname[0] == '') {
     362         dirent_set_errno (ENOENT);
     363         return NULL;
     364     }
     365 
     366     /* Allocate new _WDIR structure */
     367     dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
     368     if (!dirp) {
     369         return NULL;
     370     }
     371 
     372     /* Reset _WDIR structure */
     373     dirp->handle = INVALID_HANDLE_VALUE;
     374     dirp->patt = NULL;
     375     dirp->cached = 0;
     376 
     377     /*
     378      * Compute the length of full path plus zero terminator
     379      *
     380      * Note that on WinRT there's no way to convert relative paths
     381      * into absolute paths, so just assume it is an absolute path.
     382      */
     383 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
     384     /* Desktop */
     385     n = GetFullPathNameW (dirname, 0, NULL, NULL);
     386 #else
     387     /* WinRT */
     388     n = wcslen (dirname);
     389 #endif
     390 
     391     /* Allocate room for absolute directory name and search pattern */
     392     dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
     393     if (dirp->patt == NULL) {
     394         goto exit_closedir;
     395     }
     396 
     397     /*
     398      * Convert relative directory name to an absolute one.  This
     399      * allows rewinddir() to function correctly even when current
     400      * working directory is changed between opendir() and rewinddir().
     401      *
     402      * Note that on WinRT there's no way to convert relative paths
     403      * into absolute paths, so just assume it is an absolute path.
     404      */
     405 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
     406     /* Desktop */
     407     n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
     408     if (n <= 0) {
     409         goto exit_closedir;
     410     }
     411 #else
     412     /* WinRT */
     413     wcsncpy_s (dirp->patt, n+1, dirname, n);
     414 #endif
     415 
     416     /* Append search pattern * to the directory name */
     417     p = dirp->patt + n;
     418     switch (p[-1]) {
     419     case '\':
     420     case '/':
     421     case ':':
     422         /* Directory ends in path separator, e.g. c:	emp */
     423         /*NOP*/;
     424         break;
     425 
     426     default:
     427         /* Directory name doesn't end in path separator */
     428         *p++ = '\';
     429     }
     430     *p++ = '*';
     431     *p = '';
     432 
     433     /* Open directory stream and retrieve the first entry */
     434     if (!dirent_first (dirp)) {
     435         goto exit_closedir;
     436     }
     437 
     438     /* Success */
     439     return dirp;
     440 
     441     /* Failure */
     442 exit_closedir:
     443     _wclosedir (dirp);
     444     return NULL;
     445 }
     446 
     447 /*
     448  * Read next directory entry.
     449  *
     450  * Returns pointer to static directory entry which may be overwritten by
     451  * subsequent calls to _wreaddir().
     452  */
     453 static struct _wdirent*
     454 _wreaddir(
     455     _WDIR *dirp)
     456 {
     457     struct _wdirent *entry;
     458 
     459     /*
     460      * Read directory entry to buffer.  We can safely ignore the return value
     461      * as entry will be set to NULL in case of error.
     462      */
     463     (void) _wreaddir_r (dirp, &dirp->ent, &entry);
     464 
     465     /* Return pointer to statically allocated directory entry */
     466     return entry;
     467 }
     468 
     469 /*
     470  * Read next directory entry.
     471  *
     472  * Returns zero on success.  If end of directory stream is reached, then sets
     473  * result to NULL and returns zero.
     474  */
     475 static int
     476 _wreaddir_r(
     477     _WDIR *dirp,
     478     struct _wdirent *entry,
     479     struct _wdirent **result)
     480 {
     481     WIN32_FIND_DATAW *datap;
     482 
     483     /* Read next directory entry */
     484     datap = dirent_next (dirp);
     485     if (datap) {
     486         size_t n;
     487         DWORD attr;
     488 
     489         /*
     490          * Copy file name as wide-character string.  If the file name is too
     491          * long to fit in to the destination buffer, then truncate file name
     492          * to PATH_MAX characters and zero-terminate the buffer.
     493          */
     494         n = 0;
     495         while (n < PATH_MAX  &&  datap->cFileName[n] != 0) {
     496             entry->d_name[n] = datap->cFileName[n];
     497             n++;
     498         }
     499         entry->d_name[n] = 0;
     500 
     501         /* Length of file name excluding zero terminator */
     502         entry->d_namlen = n;
     503 
     504         /* File type */
     505         attr = datap->dwFileAttributes;
     506         if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
     507             entry->d_type = DT_CHR;
     508         } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
     509             entry->d_type = DT_DIR;
     510         } else {
     511             entry->d_type = DT_REG;
     512         }
     513 
     514         /* Reset dummy fields */
     515         entry->d_ino = 0;
     516         entry->d_off = 0;
     517         entry->d_reclen = sizeof (struct _wdirent);
     518 
     519         /* Set result address */
     520         *result = entry;
     521 
     522     } else {
     523 
     524         /* Return NULL to indicate end of directory */
     525         *result = NULL;
     526 
     527     }
     528 
     529     return /*OK*/0;
     530 }
     531 
     532 /*
     533  * Close directory stream opened by opendir() function.  This invalidates the
     534  * DIR structure as well as any directory entry read previously by
     535  * _wreaddir().
     536  */
     537 static int
     538 _wclosedir(
     539     _WDIR *dirp)
     540 {
     541     int ok;
     542     if (dirp) {
     543 
     544         /* Release search handle */
     545         if (dirp->handle != INVALID_HANDLE_VALUE) {
     546             FindClose (dirp->handle);
     547         }
     548 
     549         /* Release search pattern */
     550         free (dirp->patt);
     551 
     552         /* Release directory structure */
     553         free (dirp);
     554         ok = /*success*/0;
     555 
     556     } else {
     557 
     558         /* Invalid directory stream */
     559         dirent_set_errno (EBADF);
     560         ok = /*failure*/-1;
     561 
     562     }
     563     return ok;
     564 }
     565 
     566 /*
     567  * Rewind directory stream such that _wreaddir() returns the very first
     568  * file name again.
     569  */
     570 static void
     571 _wrewinddir(
     572     _WDIR* dirp)
     573 {
     574     if (dirp) {
     575         /* Release existing search handle */
     576         if (dirp->handle != INVALID_HANDLE_VALUE) {
     577             FindClose (dirp->handle);
     578         }
     579 
     580         /* Open new search handle */
     581         dirent_first (dirp);
     582     }
     583 }
     584 
     585 /* Get first directory entry (internal) */
     586 static WIN32_FIND_DATAW*
     587 dirent_first(
     588     _WDIR *dirp)
     589 {
     590     WIN32_FIND_DATAW *datap;
     591     DWORD error;
     592 
     593     /* Open directory and retrieve the first entry */
     594     dirp->handle = FindFirstFileExW(
     595         dirp->patt, FindExInfoStandard, &dirp->data,
     596         FindExSearchNameMatch, NULL, 0);
     597     if (dirp->handle != INVALID_HANDLE_VALUE) {
     598 
     599         /* a directory entry is now waiting in memory */
     600         datap = &dirp->data;
     601         dirp->cached = 1;
     602 
     603     } else {
     604 
     605         /* Failed to open directory: no directory entry in memory */
     606         dirp->cached = 0;
     607         datap = NULL;
     608 
     609         /* Set error code */
     610         error = GetLastError ();
     611         switch (error) {
     612         case ERROR_ACCESS_DENIED:
     613             /* No read access to directory */
     614             dirent_set_errno (EACCES);
     615             break;
     616 
     617         case ERROR_DIRECTORY:
     618             /* Directory name is invalid */
     619             dirent_set_errno (ENOTDIR);
     620             break;
     621 
     622         case ERROR_PATH_NOT_FOUND:
     623         default:
     624             /* Cannot find the file */
     625             dirent_set_errno (ENOENT);
     626         }
     627 
     628     }
     629     return datap;
     630 }
     631 
     632 /*
     633  * Get next directory entry (internal).
     634  *
     635  * Returns
     636  */
     637 static WIN32_FIND_DATAW*
     638 dirent_next(
     639     _WDIR *dirp)
     640 {
     641     WIN32_FIND_DATAW *p;
     642 
     643     /* Get next directory entry */
     644     if (dirp->cached != 0) {
     645 
     646         /* A valid directory entry already in memory */
     647         p = &dirp->data;
     648         dirp->cached = 0;
     649 
     650     } else if (dirp->handle != INVALID_HANDLE_VALUE) {
     651 
     652         /* Get the next directory entry from stream */
     653         if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
     654             /* Got a file */
     655             p = &dirp->data;
     656         } else {
     657             /* The very last entry has been processed or an error occurred */
     658             FindClose (dirp->handle);
     659             dirp->handle = INVALID_HANDLE_VALUE;
     660             p = NULL;
     661         }
     662 
     663     } else {
     664 
     665         /* End of directory stream reached */
     666         p = NULL;
     667 
     668     }
     669 
     670     return p;
     671 }
     672 
     673 /*
     674  * Open directory stream using plain old C-string.
     675  */
     676 static DIR*
     677 opendir(
     678     const char *dirname)
     679 {
     680     struct DIR *dirp;
     681 
     682     /* Must have directory name */
     683     if (dirname == NULL  ||  dirname[0] == '') {
     684         dirent_set_errno (ENOENT);
     685         return NULL;
     686     }
     687 
     688     /* Allocate memory for DIR structure */
     689     dirp = (DIR*) malloc (sizeof (struct DIR));
     690     if (!dirp) {
     691         return NULL;
     692     }
     693     {
     694         int error;
     695         wchar_t wname[PATH_MAX + 1];
     696         size_t n;
     697 
     698         /* Convert directory name to wide-character string */
     699         error = dirent_mbstowcs_s(
     700             &n, wname, PATH_MAX + 1, dirname, PATH_MAX + 1);
     701         if (error) {
     702             /*
     703              * Cannot convert file name to wide-character string.  This
     704              * occurs if the string contains invalid multi-byte sequences or
     705              * the output buffer is too small to contain the resulting
     706              * string.
     707              */
     708             goto exit_free;
     709         }
     710 
     711 
     712         /* Open directory stream using wide-character name */
     713         dirp->wdirp = _wopendir (wname);
     714         if (!dirp->wdirp) {
     715             goto exit_free;
     716         }
     717 
     718     }
     719 
     720     /* Success */
     721     return dirp;
     722 
     723     /* Failure */
     724 exit_free:
     725     free (dirp);
     726     return NULL;
     727 }
     728 
     729 /*
     730  * Read next directory entry.
     731  */
     732 static struct dirent*
     733 readdir(
     734     DIR *dirp)
     735 {
     736     struct dirent *entry;
     737 
     738     /*
     739      * Read directory entry to buffer.  We can safely ignore the return value
     740      * as entry will be set to NULL in case of error.
     741      */
     742     (void) readdir_r (dirp, &dirp->ent, &entry);
     743 
     744     /* Return pointer to statically allocated directory entry */
     745     return entry;
     746 }
     747 
     748 /*
     749  * Read next directory entry into called-allocated buffer.
     750  *
     751  * Returns zero on success.  If the end of directory stream is reached, then
     752  * sets result to NULL and returns zero.
     753  */
     754 static int
     755 readdir_r(
     756     DIR *dirp,
     757     struct dirent *entry,
     758     struct dirent **result)
     759 {
     760     WIN32_FIND_DATAW *datap;
     761 
     762     /* Read next directory entry */
     763     datap = dirent_next (dirp->wdirp);
     764     if (datap) {
     765         size_t n;
     766         int error;
     767 
     768         /* Attempt to convert file name to multi-byte string */
     769         error = dirent_wcstombs_s(
     770             &n, entry->d_name, PATH_MAX + 1, datap->cFileName, PATH_MAX + 1);
     771 
     772         /*
     773          * If the file name cannot be represented by a multi-byte string,
     774          * then attempt to use old 8+3 file name.  This allows traditional
     775          * Unix-code to access some file names despite of unicode
     776          * characters, although file names may seem unfamiliar to the user.
     777          *
     778          * Be ware that the code below cannot come up with a short file
     779          * name unless the file system provides one.  At least
     780          * VirtualBox shared folders fail to do this.
     781          */
     782         if (error  &&  datap->cAlternateFileName[0] != '') {
     783             error = dirent_wcstombs_s(
     784                 &n, entry->d_name, PATH_MAX + 1,
     785                 datap->cAlternateFileName, PATH_MAX + 1);
     786         }
     787 
     788         if (!error) {
     789             DWORD attr;
     790 
     791             /* Length of file name excluding zero terminator */
     792             entry->d_namlen = n - 1;
     793 
     794             /* File attributes */
     795             attr = datap->dwFileAttributes;
     796             if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
     797                 entry->d_type = DT_CHR;
     798             } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
     799                 entry->d_type = DT_DIR;
     800             } else {
     801                 entry->d_type = DT_REG;
     802             }
     803 
     804             /* Reset dummy fields */
     805             entry->d_ino = 0;
     806             entry->d_off = 0;
     807             entry->d_reclen = sizeof (struct dirent);
     808 
     809         } else {
     810 
     811             /*
     812              * Cannot convert file name to multi-byte string so construct
     813              * an erroneous directory entry and return that.  Note that
     814              * we cannot return NULL as that would stop the processing
     815              * of directory entries completely.
     816              */
     817             entry->d_name[0] = '?';
     818             entry->d_name[1] = '';
     819             entry->d_namlen = 1;
     820             entry->d_type = DT_UNKNOWN;
     821             entry->d_ino = 0;
     822             entry->d_off = -1;
     823             entry->d_reclen = 0;
     824 
     825         }
     826 
     827         /* Return pointer to directory entry */
     828         *result = entry;
     829 
     830     } else {
     831 
     832         /* No more directory entries */
     833         *result = NULL;
     834 
     835     }
     836 
     837     return /*OK*/0;
     838 }
     839 
     840 /*
     841  * Close directory stream.
     842  */
     843 static int
     844 closedir(
     845     DIR *dirp)
     846 {
     847     int ok;
     848     if (dirp) {
     849 
     850         /* Close wide-character directory stream */
     851         ok = _wclosedir (dirp->wdirp);
     852         dirp->wdirp = NULL;
     853 
     854         /* Release multi-byte character version */
     855         free (dirp);
     856 
     857     } else {
     858 
     859         /* Invalid directory stream */
     860         dirent_set_errno (EBADF);
     861         ok = /*failure*/-1;
     862 
     863     }
     864     return ok;
     865 }
     866 
     867 /*
     868  * Rewind directory stream to beginning.
     869  */
     870 static void
     871 rewinddir(
     872     DIR* dirp)
     873 {
     874     /* Rewind wide-character string directory stream */
     875     _wrewinddir (dirp->wdirp);
     876 }
     877 
     878 /*
     879  * Scan directory for entries.
     880  */
     881 static int
     882 scandir(
     883     const char *dirname,
     884     struct dirent ***namelist,
     885     int (*filter)(const struct dirent*),
     886     int (*compare)(const struct dirent**, const struct dirent**))
     887 {
     888     struct dirent **files = NULL;
     889     size_t size = 0;
     890     size_t allocated = 0;
     891     const size_t init_size = 1;
     892     DIR *dir = NULL;
     893     struct dirent *entry;
     894     struct dirent *tmp = NULL;
     895     size_t i;
     896     int result = 0;
     897 
     898     /* Open directory stream */
     899     dir = opendir (dirname);
     900     if (dir) {
     901 
     902         /* Read directory entries to memory */
     903         while (1) {
     904 
     905             /* Enlarge pointer table to make room for another pointer */
     906             if (size >= allocated) {
     907                 void *p;
     908                 size_t num_entries;
     909 
     910                 /* Compute number of entries in the enlarged pointer table */
     911                 if (size < init_size) {
     912                     /* Allocate initial pointer table */
     913                     num_entries = init_size;
     914                 } else {
     915                     /* Double the size */
     916                     num_entries = size * 2;
     917                 }
     918 
     919                 /* Allocate first pointer table or enlarge existing table */
     920                 p = realloc (files, sizeof (void*) * num_entries);
     921                 if (p != NULL) {
     922                     /* Got the memory */
     923                     files = (dirent**) p;
     924                     allocated = num_entries;
     925                 } else {
     926                     /* Out of memory */
     927                     result = -1;
     928                     break;
     929                 }
     930 
     931             }
     932 
     933             /* Allocate room for temporary directory entry */
     934             if (tmp == NULL) {
     935                 tmp = (struct dirent*) malloc (sizeof (struct dirent));
     936                 if (tmp == NULL) {
     937                     /* Cannot allocate temporary directory entry */
     938                     result = -1;
     939                     break;
     940                 }
     941             }
     942 
     943             /* Read directory entry to temporary area */
     944             if (readdir_r (dir, tmp, &entry) == /*OK*/0) {
     945 
     946                 /* Did we get an entry? */
     947                 if (entry != NULL) {
     948                     int pass;
     949 
     950                     /* Determine whether to include the entry in result */
     951                     if (filter) {
     952                         /* Let the filter function decide */
     953                         pass = filter (tmp);
     954                     } else {
     955                         /* No filter function, include everything */
     956                         pass = 1;
     957                     }
     958 
     959                     if (pass) {
     960                         /* Store the temporary entry to pointer table */
     961                         files[size++] = tmp;
     962                         tmp = NULL;
     963 
     964                         /* Keep up with the number of files */
     965                         result++;
     966                     }
     967 
     968                 } else {
     969 
     970                     /*
     971                      * End of directory stream reached => sort entries and
     972                      * exit.
     973                      */
     974                     qsort (files, size, sizeof (void*),
     975                         (int (*) (const void*, const void*)) compare);
     976                     break;
     977 
     978                 }
     979 
     980             } else {
     981                 /* Error reading directory entry */
     982                 result = /*Error*/ -1;
     983                 break;
     984             }
     985 
     986         }
     987 
     988     } else {
     989         /* Cannot open directory */
     990         result = /*Error*/ -1;
     991     }
     992 
     993     /* Release temporary directory entry */
     994     free (tmp);
     995 
     996     /* Release allocated memory on error */
     997     if (result < 0) {
     998         for (i = 0; i < size; i++) {
     999             free (files[i]);
    1000         }
    1001         free (files);
    1002         files = NULL;
    1003     }
    1004 
    1005     /* Close directory stream */
    1006     if (dir) {
    1007         closedir (dir);
    1008     }
    1009 
    1010     /* Pass pointer table to caller */
    1011     if (namelist) {
    1012         *namelist = files;
    1013     }
    1014     return result;
    1015 }
    1016 
    1017 /* Alphabetical sorting */
    1018 static int
    1019 alphasort(
    1020     const struct dirent **a, const struct dirent **b)
    1021 {
    1022     return strcoll ((*a)->d_name, (*b)->d_name);
    1023 }
    1024 
    1025 /* Sort versions */
    1026 static int
    1027 versionsort(
    1028     const struct dirent **a, const struct dirent **b)
    1029 {
    1030     /* FIXME: implement strverscmp and use that */
    1031     return alphasort (a, b);
    1032 }
    1033 
    1034 /* Convert multi-byte string to wide character string */
    1035 static int
    1036 dirent_mbstowcs_s(
    1037     size_t *pReturnValue,
    1038     wchar_t *wcstr,
    1039     size_t sizeInWords,
    1040     const char *mbstr,
    1041     size_t count)
    1042 {
    1043     int error;
    1044 
    1045 #if defined(_MSC_VER)  &&  _MSC_VER >= 1400
    1046 
    1047     /* Microsoft Visual Studio 2005 or later */
    1048     error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
    1049 
    1050 #else
    1051 
    1052     /* Older Visual Studio or non-Microsoft compiler */
    1053     size_t n;
    1054 
    1055     /* Convert to wide-character string (or count characters) */
    1056     n = mbstowcs (wcstr, mbstr, sizeInWords);
    1057     if (!wcstr  ||  n < count) {
    1058 
    1059         /* Zero-terminate output buffer */
    1060         if (wcstr  &&  sizeInWords) {
    1061             if (n >= sizeInWords) {
    1062                 n = sizeInWords - 1;
    1063             }
    1064             wcstr[n] = 0;
    1065         }
    1066 
    1067         /* Length of resulting multi-byte string WITH zero terminator */
    1068         if (pReturnValue) {
    1069             *pReturnValue = n + 1;
    1070         }
    1071 
    1072         /* Success */
    1073         error = 0;
    1074 
    1075     } else {
    1076 
    1077         /* Could not convert string */
    1078         error = 1;
    1079 
    1080     }
    1081 
    1082 #endif
    1083     return error;
    1084 }
    1085 
    1086 /* Convert wide-character string to multi-byte string */
    1087 static int
    1088 dirent_wcstombs_s(
    1089     size_t *pReturnValue,
    1090     char *mbstr,
    1091     size_t sizeInBytes, /* max size of mbstr */
    1092     const wchar_t *wcstr,
    1093     size_t count)
    1094 {
    1095     int error;
    1096 
    1097 #if defined(_MSC_VER)  &&  _MSC_VER >= 1400
    1098 
    1099     /* Microsoft Visual Studio 2005 or later */
    1100     error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
    1101 
    1102 #else
    1103 
    1104     /* Older Visual Studio or non-Microsoft compiler */
    1105     size_t n;
    1106 
    1107     /* Convert to multi-byte string (or count the number of bytes needed) */
    1108     n = wcstombs (mbstr, wcstr, sizeInBytes);
    1109     if (!mbstr  ||  n < count) {
    1110 
    1111         /* Zero-terminate output buffer */
    1112         if (mbstr  &&  sizeInBytes) {
    1113             if (n >= sizeInBytes) {
    1114                 n = sizeInBytes - 1;
    1115             }
    1116             mbstr[n] = '';
    1117         }
    1118 
    1119         /* Length of resulting multi-bytes string WITH zero-terminator */
    1120         if (pReturnValue) {
    1121             *pReturnValue = n + 1;
    1122         }
    1123 
    1124         /* Success */
    1125         error = 0;
    1126 
    1127     } else {
    1128 
    1129         /* Cannot convert string */
    1130         error = 1;
    1131 
    1132     }
    1133 
    1134 #endif
    1135     return error;
    1136 }
    1137 
    1138 /* Set errno variable */
    1139 static void
    1140 dirent_set_errno(
    1141     int error)
    1142 {
    1143 #if defined(_MSC_VER)  &&  _MSC_VER >= 1400
    1144 
    1145     /* Microsoft Visual Studio 2005 and later */
    1146     _set_errno (error);
    1147 
    1148 #else
    1149 
    1150     /* Non-Microsoft compiler or older Microsoft compiler */
    1151     errno = error;
    1152 
    1153 #endif
    1154 }
    1155 
    1156 
    1157 #ifdef __cplusplus
    1158 }
    1159 #endif
    1160 #endif /*DIRENT_H*/
  • 相关阅读:
    9、Spring Boot 2.x 集成 Thymeleaf
    【专题】Spring Boot 2.x 面试题
    8、Spring Boot 2.x 服务器部署
    7、Spring Boot 2.x 集成 Redis
    6、Spring Boot 2.x 集成 MyBatis
    5、Spring Boot 2.x 启动原理解析
    4、Spring Boot 2.x 自动配置原理
    3、Spring Boot 2.x 核心技术
    2、Spring Boot 2.x 快速入门
    centOS下安装JDK1.8.60,glassfish4.1.1以及MySQL
  • 原文地址:https://www.cnblogs.com/hsy1941/p/11711452.html
Copyright © 2011-2022 走看看