root/win32/readdir.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. opendir
  2. readdir
  3. readdir_r
  4. closedir
  5. rewinddir

   1 #include <malloc.h>
   2 #include <string.h>
   3 #include <errno.h>
   4 
   5 #include "php.h"
   6 #include "readdir.h"
   7 #include "TSRM.h"
   8 /**********************************************************************
   9  * Implement dirent-style opendir/readdir/rewinddir/closedir on Win32
  10  *
  11  * Functions defined are opendir(), readdir(), rewinddir() and
  12  * closedir() with the same prototypes as the normal dirent.h
  13  * implementation.
  14  *
  15  * Does not implement telldir(), seekdir(), or scandir().  The dirent
  16  * struct is compatible with Unix, except that d_ino is always 1 and
  17  * d_off is made up as we go along.
  18  *
  19  * The DIR typedef is not compatible with Unix.
  20  **********************************************************************/
  21 
  22 DIR *opendir(const char *dir)
  23 {
  24         DIR *dp;
  25         char *filespec;
  26         HANDLE handle;
  27         int index;
  28         char resolved_path_buff[MAXPATHLEN];
  29 
  30         if (!VCWD_REALPATH(dir, resolved_path_buff)) {
  31                 return NULL;
  32         }
  33 
  34         filespec = (char *)malloc(strlen(resolved_path_buff) + 2 + 1);
  35         if (filespec == NULL) {
  36                 return NULL;
  37         }
  38         strcpy(filespec, resolved_path_buff);
  39         index = (int)strlen(filespec) - 1;
  40         if (index >= 0 && (filespec[index] == '/' ||
  41            (filespec[index] == '\\' && (index == 0 || !IsDBCSLeadByte(filespec[index-1])))))
  42                 filespec[index] = '\0';
  43         strcat(filespec, "\\*");
  44 
  45         dp = (DIR *) malloc(sizeof(DIR));
  46         if (dp == NULL) {
  47                 free(filespec);
  48                 return NULL;
  49         }
  50         dp->offset = 0;
  51         dp->finished = 0;
  52 
  53         if ((handle = FindFirstFile(filespec, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) {
  54                 DWORD err = GetLastError();
  55                 if (err == ERROR_NO_MORE_FILES || err == ERROR_FILE_NOT_FOUND) {
  56                         dp->finished = 1;
  57                 } else {
  58                         free(dp);
  59                         free(filespec);
  60                         return NULL;
  61                 }
  62         }
  63         dp->dir = strdup(resolved_path_buff);
  64         dp->handle = handle;
  65         free(filespec);
  66 
  67         return dp;
  68 }
  69 
  70 struct dirent *readdir(DIR *dp)
  71 {
  72         if (!dp || dp->finished)
  73                 return NULL;
  74 
  75         if (dp->offset != 0) {
  76                 if (FindNextFile(dp->handle, &(dp->fileinfo)) == 0) {
  77                         dp->finished = 1;
  78                         return NULL;
  79                 }
  80         }
  81         dp->offset++;
  82 
  83         strlcpy(dp->dent.d_name, dp->fileinfo.cFileName, _MAX_FNAME+1);
  84         dp->dent.d_ino = 1;
  85         dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name);
  86         dp->dent.d_off = dp->offset;
  87 
  88         return &(dp->dent);
  89 }
  90 
  91 int readdir_r(DIR *dp, struct dirent *entry, struct dirent **result)
  92 {
  93         if (!dp || dp->finished) {
  94                 *result = NULL;
  95                 return 0;
  96         }
  97 
  98         if (dp->offset != 0) {
  99                 if (FindNextFile(dp->handle, &(dp->fileinfo)) == 0) {
 100                         dp->finished = 1;
 101                         *result = NULL;
 102                         return 0;
 103                 }
 104         }
 105         dp->offset++;
 106 
 107         strlcpy(dp->dent.d_name, dp->fileinfo.cFileName, _MAX_FNAME+1);
 108         dp->dent.d_ino = 1;
 109         dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name);
 110         dp->dent.d_off = dp->offset;
 111 
 112         memcpy(entry, &dp->dent, sizeof(*entry));
 113 
 114         *result = &dp->dent;
 115 
 116         return 0;
 117 }
 118 
 119 int closedir(DIR *dp)
 120 {
 121         if (!dp)
 122                 return 0;
 123         /* It is valid to scan an empty directory but we have an invalid
 124            handle in this case (no first file found). */
 125         if (dp->handle != INVALID_HANDLE_VALUE) {
 126                 FindClose(dp->handle);
 127         }
 128         if (dp->dir)
 129                 free(dp->dir);
 130         if (dp)
 131                 free(dp);
 132 
 133         return 0;
 134 }
 135 
 136 int rewinddir(DIR *dp)
 137 {
 138         /* Re-set to the beginning */
 139         char *filespec;
 140         HANDLE handle;
 141         int index;
 142 
 143         FindClose(dp->handle);
 144 
 145         dp->offset = 0;
 146         dp->finished = 0;
 147 
 148         filespec = (char *)malloc(strlen(dp->dir) + 2 + 1);
 149         if (filespec == NULL) {
 150                 return -1;
 151         }
 152 
 153         strcpy(filespec, dp->dir);
 154         index = (int)strlen(filespec) - 1;
 155         if (index >= 0 && (filespec[index] == '/' ||
 156            (filespec[index] == '\\' && (index == 0 || !IsDBCSLeadByte(filespec[index-1])))))
 157                 filespec[index] = '\0';
 158         strcat(filespec, "/*");
 159 
 160         if ((handle = FindFirstFile(filespec, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) {
 161                 dp->finished = 1;
 162         }
 163 
 164         dp->handle = handle;
 165         free(filespec);
 166 
 167         return 0;
 168 }
 169 
 170 /*
 171  * Local variables:
 172  * tab-width: 4
 173  * c-basic-offset: 4
 174  * End:
 175  * vim600: sw=4 ts=4 fdm=marker
 176  * vim<600: sw=4 ts=4
 177  */

/* [<][>][^][v][top][bottom][index][help] */