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 _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 system files. */ 75 if( data.attrib&_A_HIDDEN || data.attrib&_A_SYSTEM ){ 76 if( _findnext(dirp->d_handle, &data)==-1 ){ 77 closedir(dirp); 78 return NULL; 79 } 80 } 81 82 dirp->d_first.d_attributes = data.attrib; 83 strncpy(dirp->d_first.d_name, data.name, NAME_MAX); 84 dirp->d_first.d_name[NAME_MAX] = '\0'; 85 86 return dirp; 87 } 88 89 /* 90 ** Implementation of the POSIX readdir() function using the MSVCRT. 91 */ 92 LPDIRENT readdir( 93 LPDIR dirp 94 ){ 95 struct _finddata_t data; 96 97 if( dirp==NULL ) return NULL; 98 99 if( dirp->d_first.d_ino==0 ){ 100 dirp->d_first.d_ino++; 101 dirp->d_next.d_ino++; 102 103 return &dirp->d_first; 104 } 105 106 next: 107 108 if( _findnext(dirp->d_handle, &data)==-1 ) return NULL; 109 110 /* TODO: Remove this block to allow hidden and system files. */ 111 if( data.attrib&_A_HIDDEN ) goto next; 112 if( data.attrib&_A_SYSTEM ) goto next; 113 114 dirp->d_next.d_ino++; 115 dirp->d_next.d_attributes = data.attrib; 116 strncpy(dirp->d_next.d_name, data.name, NAME_MAX); 117 dirp->d_next.d_name[NAME_MAX] = '\0'; 118 119 return &dirp->d_next; 120 } 121 122 /* 123 ** Implementation of the POSIX readdir_r() function using the MSVCRT. 124 */ 125 INT readdir_r( 126 LPDIR dirp, 127 LPDIRENT entry, 128 LPDIRENT *result 129 ){ 130 struct _finddata_t data; 131 132 if( dirp==NULL ) return EBADF; 133 134 if( dirp->d_first.d_ino==0 ){ 135 dirp->d_first.d_ino++; 136 dirp->d_next.d_ino++; 137 138 entry->d_ino = dirp->d_first.d_ino; 139 entry->d_attributes = dirp->d_first.d_attributes; 140 strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX); 141 entry->d_name[NAME_MAX] = '\0'; 142 143 *result = entry; 144 return 0; 145 } 146 147 next: 148 149 if( _findnext(dirp->d_handle, &data)==-1 ){ 150 *result = NULL; 151 return ENOENT; 152 } 153 154 /* TODO: Remove this block to allow hidden and system files. */ 155 if( data.attrib&_A_HIDDEN ) goto next; 156 if( data.attrib&_A_SYSTEM ) goto next; 157 158 entry->d_ino = (ino_t)-1; /* not available */ 159 entry->d_attributes = data.attrib; 160 strncpy(entry->d_name, data.name, NAME_MAX); 161 entry->d_name[NAME_MAX] = '\0'; 162 163 *result = entry; 164 return 0; 165 } 166 167 /* 168 ** Implementation of the POSIX closedir() function using the MSVCRT. 169 */ 170 INT closedir( 171 LPDIR dirp 172 ){ 173 INT result = 0; 174 175 if( dirp==NULL ) return EINVAL; 176 177 if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){ 178 result = _findclose(dirp->d_handle); 179 } 180 181 sqlite3_free(dirp); 182 return result; 183 } 184 185 #endif /* defined(WIN32) && defined(_MSC_VER) */ 186