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