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