xref: /sqlite-3.40.0/src/test_windirent.c (revision 03491a1a)
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