1 /* |
|
2 ** 2005 November 29 |
|
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 ** |
|
13 ** This file contains OS interface code that is common to all |
|
14 ** architectures. |
|
15 */ |
|
16 #define _SQLITE_OS_C_ 1 |
|
17 #include "sqliteInt.h" |
|
18 #undef _SQLITE_OS_C_ |
|
19 |
|
20 /* |
|
21 ** The default SQLite sqlite3_vfs implementations do not allocate |
|
22 ** memory (actually, os_unix.c allocates a small amount of memory |
|
23 ** from within OsOpen()), but some third-party implementations may. |
|
24 ** So we test the effects of a malloc() failing and the sqlite3OsXXX() |
|
25 ** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro. |
|
26 ** |
|
27 ** The following functions are instrumented for malloc() failure |
|
28 ** testing: |
|
29 ** |
|
30 ** sqlite3OsOpen() |
|
31 ** sqlite3OsRead() |
|
32 ** sqlite3OsWrite() |
|
33 ** sqlite3OsSync() |
|
34 ** sqlite3OsLock() |
|
35 ** |
|
36 */ |
|
37 #ifdef SQLITE_TEST |
|
38 #define DO_OS_MALLOC_TEST if (1) { \ |
|
39 void *pTstAlloc = sqlite3_malloc(10); \ |
|
40 if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ |
|
41 sqlite3_free(pTstAlloc); \ |
|
42 } |
|
43 #else |
|
44 #define DO_OS_MALLOC_TEST |
|
45 #endif |
|
46 |
|
47 /* |
|
48 ** The following routines are convenience wrappers around methods |
|
49 ** of the sqlite3_file object. This is mostly just syntactic sugar. All |
|
50 ** of this would be completely automatic if SQLite were coded using |
|
51 ** C++ instead of plain old C. |
|
52 */ |
|
53 int sqlite3OsClose(sqlite3_file *pId){ |
|
54 int rc = SQLITE_OK; |
|
55 /* if( pId->pMethods ){ |
|
56 rc = pId->pMethods->xClose(pId); |
|
57 pId->pMethods = 0; |
|
58 }*/ |
|
59 rc = winClose(pId); |
|
60 return rc; |
|
61 } |
|
62 int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){ |
|
63 DO_OS_MALLOC_TEST; |
|
64 //return id->pMethods->xRead(id, pBuf, amt, offset); |
|
65 return winRead(id, pBuf, amt, offset); |
|
66 } |
|
67 int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){ |
|
68 DO_OS_MALLOC_TEST; |
|
69 //return id->pMethods->xWrite(id, pBuf, amt, offset); |
|
70 return winWrite(id, pBuf, amt, offset); |
|
71 } |
|
72 int sqlite3OsTruncate(sqlite3_file *id, i64 size){ |
|
73 //return id->pMethods->xTruncate(id, size); |
|
74 return winTruncate(id, size); |
|
75 } |
|
76 int sqlite3OsSync(sqlite3_file *id, int flags){ |
|
77 DO_OS_MALLOC_TEST; |
|
78 // return id->pMethods->xSync(id, flags); |
|
79 return winSync(id, flags); |
|
80 } |
|
81 int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){ |
|
82 // return id->pMethods->xFileSize(id, pSize); |
|
83 return winFileSize(id, pSize); |
|
84 } |
|
85 int sqlite3OsLock(sqlite3_file *id, int lockType){ |
|
86 DO_OS_MALLOC_TEST; |
|
87 //return id->pMethods->xLock(id, lockType); |
|
88 return winLock(id, lockType); |
|
89 } |
|
90 int sqlite3OsUnlock(sqlite3_file *id, int lockType){ |
|
91 //return id->pMethods->xUnlock(id, lockType); |
|
92 return winUnlock(id, lockType); |
|
93 } |
|
94 int sqlite3OsCheckReservedLock(sqlite3_file *id){ |
|
95 //return id->pMethods->xCheckReservedLock(id); |
|
96 return winCheckReservedLock(id); |
|
97 } |
|
98 int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ |
|
99 //return id->pMethods->xFileControl(id,op,pArg); |
|
100 return winFileControl(id, op, pArg); |
|
101 } |
|
102 |
|
103 #ifdef SQLITE_TEST |
|
104 /* The following two variables are used to override the values returned |
|
105 ** by the xSectorSize() and xDeviceCharacteristics() vfs methods for |
|
106 ** testing purposes. They are usually set by a test command implemented |
|
107 ** in test6.c. |
|
108 */ |
|
109 int sqlite3_test_sector_size = 0; |
|
110 int sqlite3_test_device_characteristics = 0; |
|
111 int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ |
|
112 int dc = id->pMethods->xDeviceCharacteristics(id); |
|
113 return dc | sqlite3_test_device_characteristics; |
|
114 } |
|
115 int sqlite3OsSectorSize(sqlite3_file *id){ |
|
116 if( sqlite3_test_sector_size==0 ){ |
|
117 int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize; |
|
118 return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE); |
|
119 } |
|
120 return sqlite3_test_sector_size; |
|
121 } |
|
122 #else |
|
123 int sqlite3OsSectorSize(sqlite3_file *id){ |
|
124 //int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize; |
|
125 //return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE); |
|
126 return winSectorSize(id); |
|
127 } |
|
128 int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ |
|
129 // return id->pMethods->xDeviceCharacteristics(id); |
|
130 return winDeviceCharacteristics(id); |
|
131 } |
|
132 #endif |
|
133 |
|
134 /* |
|
135 ** The next group of routines are convenience wrappers around the |
|
136 ** VFS methods. |
|
137 */ |
|
138 int sqlite3OsOpen( |
|
139 sqlite3_vfs *pVfs, |
|
140 const char *zPath, |
|
141 sqlite3_file *pFile, |
|
142 int flags, |
|
143 int *pFlagsOut |
|
144 ){ |
|
145 //return pVfs->xOpen(pVfs, zPath, pFile, flags, pFlagsOut); |
|
146 return winOpen(pVfs, zPath, pFile, flags, pFlagsOut); |
|
147 } |
|
148 int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
|
149 //return pVfs->xDelete(pVfs, zPath, dirSync); |
|
150 return winDelete(pVfs, zPath, dirSync); |
|
151 } |
|
152 int sqlite3OsAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){ |
|
153 // return pVfs->xAccess(pVfs, zPath, flags); |
|
154 return winAccess(pVfs, zPath, flags); |
|
155 } |
|
156 int sqlite3OsGetTempname(sqlite3_vfs *pVfs, int nBufOut, char *zBufOut){ |
|
157 // return pVfs->xGetTempname(pVfs, nBufOut, zBufOut); |
|
158 return winGetTempname(pVfs, nBufOut, zBufOut); |
|
159 } |
|
160 int sqlite3OsFullPathname( |
|
161 sqlite3_vfs *pVfs, |
|
162 const char *zPath, |
|
163 int nPathOut, |
|
164 char *zPathOut |
|
165 ){ |
|
166 // return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); |
|
167 return winFullPathname(pVfs, zPath, nPathOut, zPathOut); |
|
168 } |
|
169 void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ |
|
170 // return pVfs->xDlOpen(pVfs, zPath); |
|
171 return NULL; |
|
172 } |
|
173 void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ |
|
174 // pVfs->xDlError(pVfs, nByte, zBufOut); |
|
175 |
|
176 } |
|
177 void *sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ |
|
178 // return pVfs->xDlSym(pVfs, pHandle, zSymbol); |
|
179 return NULL; |
|
180 } |
|
181 void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ |
|
182 // pVfs->xDlClose(pVfs, pHandle); |
|
183 } |
|
184 int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ |
|
185 // return pVfs->xRandomness(pVfs, nByte, zBufOut); |
|
186 return winRandomness(pVfs, nByte, zBufOut); |
|
187 } |
|
188 int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ |
|
189 // return pVfs->xSleep(pVfs, nMicro); |
|
190 return winSleep(pVfs, nMicro); |
|
191 } |
|
192 int sqlite3OsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ |
|
193 // return pVfs->xCurrentTime(pVfs, pTimeOut); |
|
194 return winCurrentTime(pVfs, pTimeOut); |
|
195 } |
|
196 |
|
197 int sqlite3OsOpenMalloc( |
|
198 sqlite3_vfs *pVfs, |
|
199 const char *zFile, |
|
200 sqlite3_file **ppFile, |
|
201 int flags, |
|
202 int *pOutFlags |
|
203 ){ |
|
204 int rc = SQLITE_NOMEM; |
|
205 sqlite3_file *pFile; |
|
206 pFile = (sqlite3_file *)sqlite3_malloc(pVfs->szOsFile); |
|
207 if( pFile ){ |
|
208 rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags); |
|
209 if( rc!=SQLITE_OK ){ |
|
210 sqlite3_free(pFile); |
|
211 }else{ |
|
212 *ppFile = pFile; |
|
213 } |
|
214 } |
|
215 return rc; |
|
216 } |
|
217 int sqlite3OsCloseFree(sqlite3_file *pFile){ |
|
218 int rc = SQLITE_OK; |
|
219 if( pFile ){ |
|
220 rc = sqlite3OsClose(pFile); |
|
221 sqlite3_free(pFile); |
|
222 } |
|
223 return rc; |
|
224 } |
|
225 |
|
226 /* |
|
227 ** The list of all registered VFS implementations. This list is |
|
228 ** initialized to the single VFS returned by sqlite3OsDefaultVfs() |
|
229 ** upon the first call to sqlite3_vfs_find(). |
|
230 */ |
|
231 static sqlite3_vfs *vfsList = 0; |
|
232 |
|
233 /* |
|
234 ** Locate a VFS by name. If no name is given, simply return the |
|
235 ** first VFS on the list. |
|
236 */ |
|
237 EXPORT_C sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){ |
|
238 sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); |
|
239 sqlite3_vfs *pVfs = 0; |
|
240 static int isInit = 0; |
|
241 sqlite3_mutex_enter(mutex); |
|
242 if( !isInit ){ |
|
243 vfsList = sqlite3OsDefaultVfs(); |
|
244 isInit = 1; |
|
245 } |
|
246 for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){ |
|
247 if( zVfs==0 ) break; |
|
248 if( strcmp(zVfs, pVfs->zName)==0 ) break; |
|
249 } |
|
250 sqlite3_mutex_leave(mutex); |
|
251 return pVfs; |
|
252 } |
|
253 |
|
254 /* |
|
255 ** Unlink a VFS from the linked list |
|
256 */ |
|
257 static void vfsUnlink(sqlite3_vfs *pVfs){ |
|
258 assert( sqlite3_mutex_held(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)) ); |
|
259 if( pVfs==0 ){ |
|
260 /* No-op */ |
|
261 }else if( vfsList==pVfs ){ |
|
262 vfsList = pVfs->pNext; |
|
263 }else if( vfsList ){ |
|
264 sqlite3_vfs *p = vfsList; |
|
265 while( p->pNext && p->pNext!=pVfs ){ |
|
266 p = p->pNext; |
|
267 } |
|
268 if( p->pNext==pVfs ){ |
|
269 p->pNext = pVfs->pNext; |
|
270 } |
|
271 } |
|
272 } |
|
273 |
|
274 /* |
|
275 ** Register a VFS with the system. It is harmless to register the same |
|
276 ** VFS multiple times. The new VFS becomes the default if makeDflt is |
|
277 ** true. |
|
278 */ |
|
279 EXPORT_C int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ |
|
280 sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); |
|
281 sqlite3_vfs_find(0); /* Make sure we are initialized */ |
|
282 sqlite3_mutex_enter(mutex); |
|
283 vfsUnlink(pVfs); |
|
284 if( makeDflt || vfsList==0 ){ |
|
285 pVfs->pNext = vfsList; |
|
286 vfsList = pVfs; |
|
287 }else{ |
|
288 pVfs->pNext = vfsList->pNext; |
|
289 vfsList->pNext = pVfs; |
|
290 } |
|
291 assert(vfsList); |
|
292 sqlite3_mutex_leave(mutex); |
|
293 return SQLITE_OK; |
|
294 } |
|
295 |
|
296 /* |
|
297 ** Unregister a VFS so that it is no longer accessible. |
|
298 */ |
|
299 EXPORT_C int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ |
|
300 sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); |
|
301 sqlite3_mutex_enter(mutex); |
|
302 vfsUnlink(pVfs); |
|
303 sqlite3_mutex_leave(mutex); |
|
304 return SQLITE_OK; |
|
305 } |
|