1 /* 2 ** 2015 November 30 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ************************************************************************* 12 ** This file contains code to implement most of the opendir() family of 13 ** POSIX functions on Win32 using the MSVCRT. 14 */ 15 16 #if defined(_WIN32) && defined(_MSC_VER) 17 18 #include "test_windirent.h" 19 20 /* 21 ** Implementation of the POSIX getenv() function using the Win32 API. 22 ** This function is not thread-safe. 23 */ 24 const char *windirent_getenv( 25 const char *name 26 ){ 27 static char value[32768]; /* Maximum length, per MSDN */ 28 DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */ 29 DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */ 30 31 memset(value, 0, sizeof(value)); 32 dwRet = GetEnvironmentVariableA(name, value, dwSize); 33 if( dwRet==0 || dwRet>dwSize ){ 34 /* 35 ** The function call to GetEnvironmentVariableA() failed -OR- 36 ** the buffer is not large enough. Either way, return NULL. 37 */ 38 return 0; 39 }else{ 40 /* 41 ** The function call to GetEnvironmentVariableA() succeeded 42 ** -AND- the buffer contains the entire value. 43 */ 44 return value; 45 } 46 } 47 48 /* 49 ** Implementation of the POSIX opendir() function using the MSVCRT. 50 */ 51 LPDIR opendir( 52 const char *dirname 53 ){ 54 struct _finddata_t data; 55 LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR)); 56 SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]); 57 58 if( dirp==NULL ) return NULL; 59 memset(dirp, 0, sizeof(DIR)); 60 61 /* TODO: Remove this if Unix-style root paths are not used. */ 62 if( sqlite3_stricmp(dirname, "/")==0 ){ 63 dirname = windirent_getenv("SystemDrive"); 64 } 65 66 memset(&data, 0, sizeof(struct _finddata_t)); 67 _snprintf(data.name, namesize, "%s\\*", dirname); 68 dirp->d_handle = _findfirst(data.name, &data); 69 70 if( dirp->d_handle==BAD_INTPTR_T ){ 71 closedir(dirp); 72 return NULL; 73 } 74 75 /* TODO: Remove this block to allow hidden and/or system files. */ 76 if( is_filtered(data) ){ 77 next: 78 79 memset(&data, 0, sizeof(struct _finddata_t)); 80 if( _findnext(dirp->d_handle, &data)==-1 ){ 81 closedir(dirp); 82 return NULL; 83 } 84 85 /* TODO: Remove this block to allow hidden and/or system files. */ 86 if( is_filtered(data) ) goto next; 87 } 88 89 dirp->d_first.d_attributes = data.attrib; 90 strncpy(dirp->d_first.d_name, data.name, NAME_MAX); 91 dirp->d_first.d_name[NAME_MAX] = '\0'; 92 93 return dirp; 94 } 95 96 /* 97 ** Implementation of the POSIX readdir() function using the MSVCRT. 98 */ 99 LPDIRENT readdir( 100 LPDIR dirp 101 ){ 102 struct _finddata_t data; 103 104 if( dirp==NULL ) return NULL; 105 106 if( dirp->d_first.d_ino==0 ){ 107 dirp->d_first.d_ino++; 108 dirp->d_next.d_ino++; 109 110 return &dirp->d_first; 111 } 112 113 next: 114 115 memset(&data, 0, sizeof(struct _finddata_t)); 116 if( _findnext(dirp->d_handle, &data)==-1 ) return NULL; 117 118 /* TODO: Remove this block to allow hidden and/or system files. */ 119 if( is_filtered(data) ) goto next; 120 121 dirp->d_next.d_ino++; 122 dirp->d_next.d_attributes = data.attrib; 123 strncpy(dirp->d_next.d_name, data.name, NAME_MAX); 124 dirp->d_next.d_name[NAME_MAX] = '\0'; 125 126 return &dirp->d_next; 127 } 128 129 /* 130 ** Implementation of the POSIX readdir_r() function using the MSVCRT. 131 */ 132 INT readdir_r( 133 LPDIR dirp, 134 LPDIRENT entry, 135 LPDIRENT *result 136 ){ 137 struct _finddata_t data; 138 139 if( dirp==NULL ) return EBADF; 140 141 if( dirp->d_first.d_ino==0 ){ 142 dirp->d_first.d_ino++; 143 dirp->d_next.d_ino++; 144 145 entry->d_ino = dirp->d_first.d_ino; 146 entry->d_attributes = dirp->d_first.d_attributes; 147 strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX); 148 entry->d_name[NAME_MAX] = '\0'; 149 150 *result = entry; 151 return 0; 152 } 153 154 next: 155 156 memset(&data, 0, sizeof(struct _finddata_t)); 157 if( _findnext(dirp->d_handle, &data)==-1 ){ 158 *result = NULL; 159 return ENOENT; 160 } 161 162 /* TODO: Remove this block to allow hidden and/or system files. */ 163 if( is_filtered(data) ) goto next; 164 165 entry->d_ino = (ino_t)-1; /* not available */ 166 entry->d_attributes = data.attrib; 167 strncpy(entry->d_name, data.name, NAME_MAX); 168 entry->d_name[NAME_MAX] = '\0'; 169 170 *result = entry; 171 return 0; 172 } 173 174 /* 175 ** Implementation of the POSIX closedir() function using the MSVCRT. 176 */ 177 INT closedir( 178 LPDIR dirp 179 ){ 180 INT result = 0; 181 182 if( dirp==NULL ) return EINVAL; 183 184 if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){ 185 result = _findclose(dirp->d_handle); 186 } 187 188 sqlite3_free(dirp); 189 return result; 190 } 191 192 #endif /* defined(WIN32) && defined(_MSC_VER) */ 193