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 */
windirent_getenv(const char * name)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 */
opendir(const char * dirname)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 */
readdir(LPDIR dirp)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 */
readdir_r(LPDIR dirp,LPDIRENT entry,LPDIRENT * result)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 */
closedir(LPDIR dirp)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