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