1 : /******************************************************************************
2 : * $Id: ogrsqlitevfs.cpp 23346 2011-11-06 15:27:58Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements SQLite VFS
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 :
8 : ******************************************************************************
9 : * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_sqlite.h"
31 :
32 : CPL_CVSID("$Id: ogrsqlitevfs.cpp 23346 2011-11-06 15:27:58Z rouault $");
33 :
34 : //#define DEBUG_IO 1
35 :
36 : #ifdef HAVE_SQLITE_VFS
37 :
38 : typedef struct
39 : {
40 : const struct sqlite3_io_methods *pMethods;
41 : VSILFILE *fp;
42 : int bDeleteOnClose;
43 : char *pszFilename;
44 : } OGRSQLiteFileStruct;
45 :
46 68 : static int OGRSQLiteIOClose(sqlite3_file* pFile)
47 : {
48 68 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
49 : #ifdef DEBUG_IO
50 : CPLDebug("SQLITE", "OGRSQLiteIOClose(%p (%s))", pMyFile->fp, pMyFile->pszFilename);
51 : #endif
52 68 : VSIFCloseL(pMyFile->fp);
53 68 : if (pMyFile->bDeleteOnClose)
54 23 : VSIUnlink(pMyFile->pszFilename);
55 68 : CPLFree(pMyFile->pszFilename);
56 68 : return SQLITE_OK;
57 : }
58 :
59 82 : static int OGRSQLiteIORead(sqlite3_file* pFile, void* pBuffer, int iAmt, sqlite3_int64 iOfst)
60 : {
61 82 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
62 : #ifdef DEBUG_IO
63 : CPLDebug("SQLITE", "OGRSQLiteIORead(%p, %d, %d)", pMyFile->fp, iAmt, (int)iOfst);
64 : #endif
65 82 : VSIFSeekL(pMyFile->fp, (vsi_l_offset) iOfst, SEEK_SET);
66 82 : int nRead = (int)VSIFReadL(pBuffer, 1, iAmt, pMyFile->fp);
67 82 : if (nRead < iAmt)
68 : {
69 2 : memset(((char*)pBuffer) + nRead, 0, iAmt - nRead);
70 2 : return SQLITE_IOERR_SHORT_READ;
71 : }
72 80 : return SQLITE_OK;
73 : }
74 :
75 508 : static int OGRSQLiteIOWrite(sqlite3_file* pFile, const void* pBuffer, int iAmt, sqlite3_int64 iOfst)
76 : {
77 508 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
78 : #ifdef DEBUG_IO
79 : CPLDebug("SQLITE", "OGRSQLiteIOWrite(%p, %d, %d)", pMyFile->fp, iAmt, (int)iOfst);
80 : #endif
81 508 : VSIFSeekL(pMyFile->fp, (vsi_l_offset) iOfst, SEEK_SET);
82 508 : int nWritten = (int)VSIFWriteL(pBuffer, 1, iAmt, pMyFile->fp);
83 508 : if (nWritten < iAmt)
84 : {
85 0 : return SQLITE_IOERR_WRITE;
86 : }
87 508 : return SQLITE_OK;
88 : }
89 :
90 46 : static int OGRSQLiteIOTruncate(sqlite3_file* pFile, sqlite3_int64 size)
91 : {
92 46 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
93 : #ifdef DEBUG_IO
94 : CPLDebug("SQLITE", "OGRSQLiteIOTruncate(%p)", pMyFile->fp);
95 : #endif
96 46 : int nRet = VSIFTruncateL(pMyFile->fp, size);
97 46 : return (nRet == 0) ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
98 : }
99 :
100 0 : static int OGRSQLiteIOSync(sqlite3_file* pFile, int flags)
101 : {
102 : #ifdef DEBUG_IO
103 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
104 : CPLDebug("SQLITE", "OGRSQLiteIOSync(%p, %d)", pMyFile->fp, flags);
105 : #endif
106 0 : return SQLITE_OK;
107 : }
108 :
109 77 : static int OGRSQLiteIOFileSize(sqlite3_file* pFile, sqlite3_int64 *pSize)
110 : {
111 77 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
112 : #ifdef DEBUG_IO
113 : CPLDebug("SQLITE", "OGRSQLiteIOFileSize(%p)", pMyFile->fp);
114 : #endif
115 77 : vsi_l_offset nCurOffset = VSIFTellL(pMyFile->fp);
116 77 : VSIFSeekL(pMyFile->fp, 0, SEEK_END);
117 77 : *pSize = VSIFTellL(pMyFile->fp);
118 77 : VSIFSeekL(pMyFile->fp, nCurOffset, SEEK_SET);
119 77 : return SQLITE_OK;
120 : }
121 :
122 160 : static int OGRSQLiteIOLock(sqlite3_file* pFile, int flags)
123 : {
124 : #ifdef DEBUG_IO
125 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
126 : CPLDebug("SQLITE", "OGRSQLiteIOLock(%p)", pMyFile->fp);
127 : #endif
128 160 : return SQLITE_OK;
129 : }
130 :
131 122 : static int OGRSQLiteIOUnlock(sqlite3_file* pFile, int flags)
132 : {
133 : #ifdef DEBUG_IO
134 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
135 : CPLDebug("SQLITE", "OGRSQLiteIOUnlock(%p)", pMyFile->fp);
136 : #endif
137 122 : return SQLITE_OK;
138 : }
139 :
140 0 : static int OGRSQLiteIOCheckReservedLock(sqlite3_file* pFile, int *pResOut)
141 : {
142 : #ifdef DEBUG_IO
143 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
144 : CPLDebug("SQLITE", "OGRSQLiteIOCheckReservedLock(%p)", pMyFile->fp);
145 : #endif
146 0 : *pResOut = 0;
147 0 : return SQLITE_OK;
148 : }
149 :
150 0 : static int OGRSQLiteIOFileControl(sqlite3_file* pFile, int op, void *pArg)
151 : {
152 : #ifdef DEBUG_IO
153 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
154 : CPLDebug("SQLITE", "OGRSQLiteIOFileControl(%p)", pMyFile->fp);
155 : #endif
156 0 : return SQLITE_OK;
157 : }
158 :
159 5 : static int OGRSQLiteIOSectorSize(sqlite3_file* pFile)
160 : {
161 : #ifdef DEBUG_IO
162 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
163 : CPLDebug("SQLITE", "OGRSQLiteIOSectorSize(%p)", pMyFile->fp);
164 : #endif
165 5 : return 0;
166 : }
167 :
168 0 : static int OGRSQLiteIODeviceCharacteristics(sqlite3_file* pFile)
169 : {
170 : #ifdef DEBUG_IO
171 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
172 : CPLDebug("SQLITE", "OGRSQLiteIODeviceCharacteristics(%p)", pMyFile->fp);
173 : #endif
174 0 : return 0;
175 : }
176 :
177 : static const sqlite3_io_methods OGRSQLiteIOMethods =
178 : {
179 : 1,
180 : OGRSQLiteIOClose,
181 : OGRSQLiteIORead,
182 : OGRSQLiteIOWrite,
183 : OGRSQLiteIOTruncate,
184 : OGRSQLiteIOSync,
185 : OGRSQLiteIOFileSize,
186 : OGRSQLiteIOLock,
187 : OGRSQLiteIOUnlock,
188 : OGRSQLiteIOCheckReservedLock,
189 : OGRSQLiteIOFileControl,
190 : OGRSQLiteIOSectorSize,
191 : OGRSQLiteIODeviceCharacteristics
192 : };
193 :
194 68 : static int OGRSQLiteVFSOpen(sqlite3_vfs* pVFS,
195 : const char *zName,
196 : sqlite3_file* pFile,
197 : int flags,
198 : int *pOutFlags)
199 : {
200 : #ifdef DEBUG_IO
201 : CPLDebug("SQLITE", "OGRSQLiteVFSOpen(%s, %d)", zName ? zName : "(null)", flags);
202 : #endif
203 :
204 68 : if (zName == NULL)
205 : //return SQLITE_IOERR;
206 23 : zName = CPLSPrintf("/vsimem/sqlite/%p", pVFS);
207 :
208 68 : OGRSQLiteFileStruct* pMyFile = (OGRSQLiteFileStruct*) pFile;
209 68 : pMyFile->pMethods = NULL;
210 68 : pMyFile->bDeleteOnClose = FALSE;
211 68 : pMyFile->pszFilename = NULL;
212 68 : if ( flags & SQLITE_OPEN_READONLY )
213 1 : pMyFile->fp = VSIFOpenL(zName, "rb");
214 67 : else if ( flags & SQLITE_OPEN_CREATE )
215 67 : pMyFile->fp = VSIFOpenL(zName, "wb+");
216 0 : else if ( flags & SQLITE_OPEN_READWRITE )
217 0 : pMyFile->fp = VSIFOpenL(zName, "rb+");
218 : else
219 0 : pMyFile->fp = NULL;
220 :
221 68 : if (pMyFile->fp == NULL)
222 0 : return SQLITE_CANTOPEN;
223 :
224 : #ifdef DEBUG_IO
225 : CPLDebug("SQLITE", "OGRSQLiteVFSOpen() = %p", pMyFile->fp);
226 : #endif
227 :
228 68 : pMyFile->pMethods = &OGRSQLiteIOMethods;
229 68 : pMyFile->bDeleteOnClose = ( flags & SQLITE_OPEN_DELETEONCLOSE );
230 68 : pMyFile->pszFilename = CPLStrdup(zName);
231 :
232 68 : if (pOutFlags != NULL)
233 3 : *pOutFlags = flags;
234 :
235 68 : return SQLITE_OK;
236 : }
237 :
238 42 : static int OGRSQLiteVFSDelete(sqlite3_vfs* pVFS, const char *zName, int syncDir)
239 : {
240 : #ifdef DEBUG_IO
241 : CPLDebug("SQLITE", "OGRSQLiteVFSDelete(%s)", zName);
242 : #endif
243 42 : VSIUnlink(zName);
244 42 : return SQLITE_OK;
245 : }
246 :
247 77 : static int OGRSQLiteVFSAccess (sqlite3_vfs* pVFS, const char *zName, int flags, int *pResOut)
248 : {
249 : #ifdef DEBUG_IO
250 : CPLDebug("SQLITE", "OGRSQLiteVFSAccess(%s, %d)", zName, flags);
251 : #endif
252 : VSIStatBufL sStatBufL;
253 : int nRet;
254 77 : if (flags == SQLITE_ACCESS_EXISTS)
255 77 : nRet = VSIStatExL(zName, &sStatBufL, VSI_STAT_EXISTS_FLAG);
256 0 : else if (flags == SQLITE_ACCESS_READ)
257 : {
258 0 : VSILFILE* fp = VSIFOpenL(zName, "rb");
259 0 : nRet = fp ? 0 : -1;
260 0 : if (fp)
261 0 : VSIFCloseL(fp);
262 : }
263 0 : else if (flags == SQLITE_ACCESS_READWRITE)
264 : {
265 0 : VSILFILE* fp = VSIFOpenL(zName, "rb+");
266 0 : nRet = fp ? 0 : -1;
267 0 : if (fp)
268 0 : VSIFCloseL(fp);
269 : }
270 : else
271 0 : nRet = -1;
272 77 : *pResOut = (nRet == 0);
273 77 : return SQLITE_OK;
274 : }
275 :
276 3 : static int OGRSQLiteVFSFullPathname (sqlite3_vfs* pVFS, const char *zName, int nOut, char *zOut)
277 : {
278 3 : sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
279 : #ifdef DEBUG_IO
280 : CPLDebug("SQLITE", "OGRSQLiteVFSFullPathname(%s)", zName);
281 : #endif
282 3 : if (zName[0] == '/')
283 : {
284 3 : strncpy(zOut, zName, nOut);
285 3 : zOut[nOut-1] = '\0';
286 3 : return SQLITE_OK;
287 : }
288 0 : return pUnderlyingVFS->xFullPathname(pUnderlyingVFS, zName, nOut, zOut);
289 : }
290 :
291 0 : static void* OGRSQLiteVFSDlOpen (sqlite3_vfs* pVFS, const char *zFilename)
292 : {
293 0 : sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
294 : //CPLDebug("SQLITE", "OGRSQLiteVFSDlOpen(%s)", zFilename);
295 0 : return pUnderlyingVFS->xDlOpen(pUnderlyingVFS, zFilename);
296 : }
297 :
298 0 : static void OGRSQLiteVFSDlError (sqlite3_vfs* pVFS, int nByte, char *zErrMsg)
299 : {
300 0 : sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
301 : //CPLDebug("SQLITE", "OGRSQLiteVFSDlError()");
302 0 : pUnderlyingVFS->xDlError(pUnderlyingVFS, nByte, zErrMsg);
303 0 : }
304 :
305 0 : static void (*OGRSQLiteVFSDlSym (sqlite3_vfs* pVFS,void* pHandle, const char *zSymbol))(void)
306 : {
307 0 : sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
308 : //CPLDebug("SQLITE", "OGRSQLiteVFSDlSym(%s)", zSymbol);
309 0 : return pUnderlyingVFS->xDlSym(pUnderlyingVFS, pHandle, zSymbol);
310 : }
311 :
312 0 : static void OGRSQLiteVFSDlClose (sqlite3_vfs* pVFS, void* pHandle)
313 : {
314 0 : sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
315 : //CPLDebug("SQLITE", "OGRSQLiteVFSDlClose(%p)", pHandle);
316 0 : pUnderlyingVFS->xDlClose(pUnderlyingVFS, pHandle);
317 0 : }
318 :
319 0 : static int OGRSQLiteVFSRandomness (sqlite3_vfs* pVFS, int nByte, char *zOut)
320 : {
321 0 : sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
322 : //CPLDebug("SQLITE", "OGRSQLiteVFSRandomness()");
323 0 : return pUnderlyingVFS->xRandomness(pUnderlyingVFS, nByte, zOut);
324 : }
325 :
326 0 : static int OGRSQLiteVFSSleep (sqlite3_vfs* pVFS, int microseconds)
327 : {
328 0 : sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
329 : //CPLDebug("SQLITE", "OGRSQLiteVFSSleep()");
330 0 : return pUnderlyingVFS->xSleep(pUnderlyingVFS, microseconds);
331 : }
332 :
333 0 : static int OGRSQLiteVFSCurrentTime (sqlite3_vfs* pVFS, double* p1)
334 : {
335 0 : sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
336 : //CPLDebug("SQLITE", "OGRSQLiteVFSCurrentTime()");
337 0 : return pUnderlyingVFS->xCurrentTime(pUnderlyingVFS, p1);
338 : }
339 :
340 0 : static int OGRSQLiteVFSGetLastError (sqlite3_vfs* pVFS, int p1, char *p2)
341 : {
342 0 : sqlite3_vfs* pUnderlyingVFS = (sqlite3_vfs* )pVFS->pAppData;
343 : //CPLDebug("SQLITE", "OGRSQLiteVFSGetLastError()");
344 0 : return pUnderlyingVFS->xGetLastError(pUnderlyingVFS, p1, p2);
345 : }
346 :
347 3 : sqlite3_vfs* OGRSQLiteCreateVFS()
348 : {
349 3 : sqlite3_vfs* pDefaultVFS = sqlite3_vfs_find(NULL);
350 3 : sqlite3_vfs* pMyVFS = (sqlite3_vfs*) CPLCalloc(1, sizeof(sqlite3_vfs));
351 3 : pMyVFS->iVersion = 1;
352 3 : pMyVFS->szOsFile = sizeof(OGRSQLiteFileStruct);
353 3 : pMyVFS->mxPathname = pDefaultVFS->mxPathname;
354 3 : pMyVFS->zName = "myvfs";
355 3 : pMyVFS->pAppData = pDefaultVFS;
356 3 : pMyVFS->xOpen = OGRSQLiteVFSOpen;
357 3 : pMyVFS->xDelete = OGRSQLiteVFSDelete;
358 3 : pMyVFS->xAccess = OGRSQLiteVFSAccess;
359 3 : pMyVFS->xFullPathname = OGRSQLiteVFSFullPathname;
360 3 : pMyVFS->xDlOpen = OGRSQLiteVFSDlOpen;
361 3 : pMyVFS->xDlError = OGRSQLiteVFSDlError;
362 3 : pMyVFS->xDlSym = OGRSQLiteVFSDlSym;
363 3 : pMyVFS->xDlClose = OGRSQLiteVFSDlClose;
364 3 : pMyVFS->xRandomness = OGRSQLiteVFSRandomness;
365 3 : pMyVFS->xSleep = OGRSQLiteVFSSleep;
366 3 : pMyVFS->xCurrentTime = OGRSQLiteVFSCurrentTime;
367 3 : pMyVFS->xGetLastError = OGRSQLiteVFSGetLastError;
368 3 : return pMyVFS;
369 : }
370 :
371 : #endif // HAVE_SQLITE_VFS
|