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