Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements SQLite VFS
5 : * Author: Even Rouault, <even dot rouault at spatialys.com>
6 :
7 : ******************************************************************************
8 : * Copyright (c) 2011-2012, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "cpl_port.h"
30 : #include "ogr_sqlite.h"
31 :
32 : #include <cstdio>
33 : #include <cstdlib>
34 : #include <cstring>
35 :
36 : #include "cpl_atomic_ops.h"
37 : #include "cpl_conv.h"
38 : #include "cpl_error.h"
39 : #include "cpl_string.h"
40 : #include "cpl_vsi.h"
41 : #include "ogrsqlitevfs.h"
42 :
43 : #ifdef DEBUG_IO
44 : #define DEBUG_ONLY
45 : #else
46 : #define DEBUG_ONLY CPL_UNUSED
47 : #endif
48 :
49 : // #define DEBUG_IO 1
50 :
51 : typedef struct
52 : {
53 : char szVFSName[64];
54 : sqlite3_vfs *pDefaultVFS;
55 : pfnNotifyFileOpenedType pfn;
56 : void *pfnUserData;
57 : int nCounter;
58 : } OGRSQLiteVFSAppDataStruct;
59 :
60 : #define GET_UNDERLYING_VFS(pVFS) \
61 : ((OGRSQLiteVFSAppDataStruct *)pVFS->pAppData)->pDefaultVFS
62 :
63 : typedef struct
64 : {
65 : const struct sqlite3_io_methods *pMethods;
66 : VSILFILE *fp;
67 : int bDeleteOnClose;
68 : char *pszFilename;
69 : } OGRSQLiteFileStruct;
70 :
71 19465 : static int OGRSQLiteIOClose(sqlite3_file *pFile)
72 : {
73 19465 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
74 : #ifdef DEBUG_IO
75 : CPLDebug("SQLITE", "OGRSQLiteIOClose(%p (%s))", pMyFile->fp,
76 : pMyFile->pszFilename);
77 : #endif
78 19465 : VSIFCloseL(pMyFile->fp);
79 19465 : if (pMyFile->bDeleteOnClose)
80 0 : VSIUnlink(pMyFile->pszFilename);
81 19465 : CPLFree(pMyFile->pszFilename);
82 19465 : return SQLITE_OK;
83 : }
84 :
85 219971 : static int OGRSQLiteIORead(sqlite3_file *pFile, void *pBuffer, int iAmt,
86 : sqlite3_int64 iOfst)
87 : {
88 219971 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
89 219971 : VSIFSeekL(pMyFile->fp, (vsi_l_offset)iOfst, SEEK_SET);
90 219971 : int nRead = (int)VSIFReadL(pBuffer, 1, iAmt, pMyFile->fp);
91 : #ifdef DEBUG_IO
92 : CPLDebug("SQLITE", "OGRSQLiteIORead(%p, %d, %d) = %d", pMyFile->fp, iAmt,
93 : (int)iOfst, nRead);
94 : #endif
95 219971 : if (nRead < iAmt)
96 : {
97 4289 : memset(((char *)pBuffer) + nRead, 0, iAmt - nRead);
98 4289 : return SQLITE_IOERR_SHORT_READ;
99 : }
100 215682 : return SQLITE_OK;
101 : }
102 :
103 398640 : static int OGRSQLiteIOWrite(sqlite3_file *pFile, const void *pBuffer, int iAmt,
104 : sqlite3_int64 iOfst)
105 : {
106 398640 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
107 398640 : VSIFSeekL(pMyFile->fp, (vsi_l_offset)iOfst, SEEK_SET);
108 398640 : int nWritten = (int)VSIFWriteL(pBuffer, 1, iAmt, pMyFile->fp);
109 : #ifdef DEBUG_IO
110 : CPLDebug("SQLITE", "OGRSQLiteIOWrite(%p, %d, %d) = %d", pMyFile->fp, iAmt,
111 : (int)iOfst, nWritten);
112 : #endif
113 398640 : if (nWritten < iAmt)
114 : {
115 24 : return SQLITE_IOERR_WRITE;
116 : }
117 398616 : return SQLITE_OK;
118 : }
119 :
120 23 : static int OGRSQLiteIOTruncate(sqlite3_file *pFile, sqlite3_int64 size)
121 : {
122 23 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
123 : #ifdef DEBUG_IO
124 : CPLDebug("SQLITE", "OGRSQLiteIOTruncate(%p, " CPL_FRMT_GIB ")", pMyFile->fp,
125 : size);
126 : #endif
127 23 : int nRet = VSIFTruncateL(pMyFile->fp, size);
128 23 : return (nRet == 0) ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
129 : }
130 :
131 5976 : static int OGRSQLiteIOSync(DEBUG_ONLY sqlite3_file *pFile, DEBUG_ONLY int flags)
132 : {
133 : #ifdef DEBUG_IO
134 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
135 : CPLDebug("SQLITE", "OGRSQLiteIOSync(%p, %d)", pMyFile->fp, flags);
136 : #endif
137 5976 : return SQLITE_OK;
138 : }
139 :
140 85649 : static int OGRSQLiteIOFileSize(sqlite3_file *pFile, sqlite3_int64 *pSize)
141 : {
142 85649 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
143 85649 : vsi_l_offset nCurOffset = VSIFTellL(pMyFile->fp);
144 85649 : VSIFSeekL(pMyFile->fp, 0, SEEK_END);
145 85649 : *pSize = VSIFTellL(pMyFile->fp);
146 85649 : VSIFSeekL(pMyFile->fp, nCurOffset, SEEK_SET);
147 : #ifdef DEBUG_IO
148 : CPLDebug("SQLITE", "OGRSQLiteIOFileSize(%p) = " CPL_FRMT_GIB, pMyFile->fp,
149 : *pSize);
150 : #endif
151 85649 : return SQLITE_OK;
152 : }
153 :
154 139599 : static int OGRSQLiteIOLock(DEBUG_ONLY sqlite3_file *pFile, DEBUG_ONLY int flags)
155 : {
156 : #ifdef DEBUG_IO
157 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
158 : CPLDebug("SQLITE", "OGRSQLiteIOLock(%p)", pMyFile->fp);
159 : #endif
160 139599 : return SQLITE_OK;
161 : }
162 :
163 115076 : static int OGRSQLiteIOUnlock(DEBUG_ONLY sqlite3_file *pFile,
164 : DEBUG_ONLY int flags)
165 : {
166 : #ifdef DEBUG_IO
167 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
168 : CPLDebug("SQLITE", "OGRSQLiteIOUnlock(%p)", pMyFile->fp);
169 : #endif
170 115076 : return SQLITE_OK;
171 : }
172 :
173 6 : static int OGRSQLiteIOCheckReservedLock(DEBUG_ONLY sqlite3_file *pFile,
174 : DEBUG_ONLY int *pResOut)
175 : {
176 : #ifdef DEBUG_IO
177 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
178 : CPLDebug("SQLITE", "OGRSQLiteIOCheckReservedLock(%p)", pMyFile->fp);
179 : #endif
180 6 : *pResOut = 0;
181 6 : return SQLITE_OK;
182 : }
183 :
184 96351 : static int OGRSQLiteIOFileControl(DEBUG_ONLY sqlite3_file *pFile,
185 : DEBUG_ONLY int op, DEBUG_ONLY void *pArg)
186 : {
187 : #ifdef DEBUG_IO
188 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
189 : CPLDebug("SQLITE", "OGRSQLiteIOFileControl(%p, %d)", pMyFile->fp, op);
190 : #endif
191 96351 : return SQLITE_NOTFOUND;
192 : }
193 :
194 4381 : static int OGRSQLiteIOSectorSize(DEBUG_ONLY sqlite3_file *pFile)
195 : {
196 : #ifdef DEBUG_IO
197 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
198 : CPLDebug("SQLITE", "OGRSQLiteIOSectorSize(%p)", pMyFile->fp);
199 : #endif
200 4381 : return 0;
201 : }
202 :
203 98943 : static int OGRSQLiteIODeviceCharacteristics(DEBUG_ONLY sqlite3_file *pFile)
204 : {
205 : #ifdef DEBUG_IO
206 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
207 : CPLDebug("SQLITE", "OGRSQLiteIODeviceCharacteristics(%p)", pMyFile->fp);
208 : #endif
209 98943 : return 0;
210 : }
211 :
212 : static const sqlite3_io_methods OGRSQLiteIOMethods = {
213 : 1,
214 : OGRSQLiteIOClose,
215 : OGRSQLiteIORead,
216 : OGRSQLiteIOWrite,
217 : OGRSQLiteIOTruncate,
218 : OGRSQLiteIOSync,
219 : OGRSQLiteIOFileSize,
220 : OGRSQLiteIOLock,
221 : OGRSQLiteIOUnlock,
222 : OGRSQLiteIOCheckReservedLock,
223 : OGRSQLiteIOFileControl,
224 : OGRSQLiteIOSectorSize,
225 : OGRSQLiteIODeviceCharacteristics,
226 : nullptr, // xShmMap
227 : nullptr, // xShmLock
228 : nullptr, // xShmBarrier
229 : nullptr, // xShmUnmap
230 : nullptr, // xFetch
231 : nullptr, // xUnfetch
232 : };
233 :
234 19469 : static int OGRSQLiteVFSOpen(sqlite3_vfs *pVFS, const char *zName,
235 : sqlite3_file *pFile, int flags, int *pOutFlags)
236 : {
237 : #ifdef DEBUG_IO
238 : CPLDebug("SQLITE", "OGRSQLiteVFSOpen(%s, %d)", zName ? zName : "(null)",
239 : flags);
240 : #endif
241 :
242 19469 : OGRSQLiteVFSAppDataStruct *pAppData =
243 : (OGRSQLiteVFSAppDataStruct *)pVFS->pAppData;
244 :
245 19469 : if (zName == nullptr)
246 : {
247 0 : zName = CPLSPrintf("/vsimem/sqlite/%p_%d", pVFS,
248 0 : CPLAtomicInc(&(pAppData->nCounter)));
249 : }
250 :
251 19469 : OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
252 19469 : pMyFile->pMethods = nullptr;
253 19469 : pMyFile->bDeleteOnClose = FALSE;
254 19469 : pMyFile->pszFilename = nullptr;
255 19469 : if (flags & SQLITE_OPEN_READONLY)
256 741 : pMyFile->fp = VSIFOpenL(zName, "rb");
257 18728 : else if (flags & SQLITE_OPEN_CREATE)
258 : {
259 : VSIStatBufL sStatBufL;
260 18040 : if (VSIStatExL(zName, &sStatBufL, VSI_STAT_EXISTS_FLAG) == 0)
261 55 : pMyFile->fp = VSIFOpenL(zName, "rb+");
262 : else
263 17985 : pMyFile->fp = VSIFOpenL(zName, "wb+");
264 : }
265 688 : else if (flags & SQLITE_OPEN_READWRITE)
266 688 : pMyFile->fp = VSIFOpenL(zName, "rb+");
267 : else
268 0 : pMyFile->fp = nullptr;
269 :
270 19469 : if (pMyFile->fp == nullptr)
271 4 : return SQLITE_CANTOPEN;
272 :
273 : #ifdef DEBUG_IO
274 : CPLDebug("SQLITE", "OGRSQLiteVFSOpen() = %p", pMyFile->fp);
275 : #endif
276 :
277 19465 : pfnNotifyFileOpenedType pfn = pAppData->pfn;
278 19465 : if (pfn)
279 : {
280 19043 : pfn(pAppData->pfnUserData, zName, pMyFile->fp);
281 : }
282 :
283 19465 : pMyFile->pMethods = &OGRSQLiteIOMethods;
284 19465 : pMyFile->bDeleteOnClose = (flags & SQLITE_OPEN_DELETEONCLOSE);
285 19465 : pMyFile->pszFilename = CPLStrdup(zName);
286 :
287 19465 : if (pOutFlags != nullptr)
288 2549 : *pOutFlags = flags;
289 :
290 19465 : return SQLITE_OK;
291 : }
292 :
293 16916 : static int OGRSQLiteVFSDelete(DEBUG_ONLY sqlite3_vfs *pVFS, const char *zName,
294 : int DEBUG_ONLY syncDir)
295 : {
296 : #ifdef DEBUG_IO
297 : CPLDebug("SQLITE", "OGRSQLiteVFSDelete(%s)", zName);
298 : #endif
299 16916 : VSIUnlink(zName);
300 16916 : return SQLITE_OK;
301 : }
302 :
303 170972 : static int OGRSQLiteVFSAccess(DEBUG_ONLY sqlite3_vfs *pVFS, const char *zName,
304 : int flags, int *pResOut)
305 : {
306 : #ifdef DEBUG_IO
307 : CPLDebug("SQLITE", "OGRSQLiteVFSAccess(%s, %d)", zName, flags);
308 : #endif
309 : VSIStatBufL sStatBufL;
310 : int nRet; // TODO(schwehr): Cleanup nRet and pResOut. bools?
311 170972 : if (flags == SQLITE_ACCESS_EXISTS)
312 : {
313 : /* Do not try to check the presence of a journal or a wal on /vsicurl !
314 : */
315 170972 : if ((STARTS_WITH(zName, "/vsicurl/") ||
316 170804 : STARTS_WITH(zName, "/vsitar/") ||
317 170804 : STARTS_WITH(zName, "/vsizip/")) &&
318 300 : ((strlen(zName) > strlen("-journal") &&
319 300 : strcmp(zName + strlen(zName) - strlen("-journal"), "-journal") ==
320 150 : 0) ||
321 150 : (strlen(zName) > strlen("-wal") &&
322 150 : strcmp(zName + strlen(zName) - strlen("-wal"), "-wal") == 0)))
323 : {
324 300 : nRet = -1;
325 : }
326 : else
327 : {
328 170672 : nRet = VSIStatExL(zName, &sStatBufL, VSI_STAT_EXISTS_FLAG);
329 : }
330 : }
331 0 : else if (flags == SQLITE_ACCESS_READ)
332 : {
333 0 : VSILFILE *fp = VSIFOpenL(zName, "rb");
334 0 : nRet = fp ? 0 : -1;
335 0 : if (fp)
336 0 : VSIFCloseL(fp);
337 : }
338 0 : else if (flags == SQLITE_ACCESS_READWRITE)
339 : {
340 0 : VSILFILE *fp = VSIFOpenL(zName, "rb+");
341 0 : nRet = fp ? 0 : -1;
342 0 : if (fp)
343 0 : VSIFCloseL(fp);
344 : }
345 : else
346 : {
347 0 : nRet = -1;
348 : }
349 170972 : *pResOut = (nRet == 0);
350 170972 : return SQLITE_OK;
351 : }
352 :
353 2541 : static int OGRSQLiteVFSFullPathname(sqlite3_vfs *pVFS, const char *zName,
354 : int nOut, char *zOut)
355 : {
356 2541 : sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
357 : #ifdef DEBUG_IO
358 : CPLDebug("SQLITE", "OGRSQLiteVFSFullPathname(%s)", zName);
359 : #endif
360 2541 : if (zName[0] == '/')
361 : {
362 2539 : if (static_cast<int>(strlen(zName)) >= nOut)
363 : {
364 : // The +8 comes from the fact that sqlite3 does this check as
365 : // it needs to be able to append .journal to the filename
366 0 : CPLError(CE_Failure, CPLE_AppDefined,
367 : "Maximum pathname length reserved for SQLite3 VFS "
368 : "isn't large enough. Try raising "
369 : "OGR_SQLITE_VFS_MAXPATHNAME to at least %d",
370 0 : static_cast<int>(strlen(zName)) + 8);
371 0 : return SQLITE_CANTOPEN;
372 : }
373 2539 : strncpy(zOut, zName, nOut);
374 2539 : zOut[nOut - 1] = '\0';
375 2539 : return SQLITE_OK;
376 : }
377 2 : return pUnderlyingVFS->xFullPathname(pUnderlyingVFS, zName, nOut, zOut);
378 : }
379 :
380 0 : static void *OGRSQLiteVFSDlOpen(sqlite3_vfs *pVFS, const char *zFilename)
381 : {
382 0 : sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
383 : // CPLDebug("SQLITE", "OGRSQLiteVFSDlOpen(%s)", zFilename);
384 0 : return pUnderlyingVFS->xDlOpen(pUnderlyingVFS, zFilename);
385 : }
386 :
387 0 : static void OGRSQLiteVFSDlError(sqlite3_vfs *pVFS, int nByte, char *zErrMsg)
388 : {
389 0 : sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
390 : // CPLDebug("SQLITE", "OGRSQLiteVFSDlError()");
391 0 : pUnderlyingVFS->xDlError(pUnderlyingVFS, nByte, zErrMsg);
392 0 : }
393 :
394 0 : static void (*OGRSQLiteVFSDlSym(sqlite3_vfs *pVFS, void *pHandle,
395 : const char *zSymbol))(void)
396 : {
397 0 : sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
398 : // CPLDebug("SQLITE", "OGRSQLiteVFSDlSym(%s)", zSymbol);
399 0 : return pUnderlyingVFS->xDlSym(pUnderlyingVFS, pHandle, zSymbol);
400 : }
401 :
402 0 : static void OGRSQLiteVFSDlClose(sqlite3_vfs *pVFS, void *pHandle)
403 : {
404 0 : sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
405 : // CPLDebug("SQLITE", "OGRSQLiteVFSDlClose(%p)", pHandle);
406 0 : pUnderlyingVFS->xDlClose(pUnderlyingVFS, pHandle);
407 0 : }
408 :
409 0 : static int OGRSQLiteVFSRandomness(sqlite3_vfs *pVFS, int nByte, char *zOut)
410 : {
411 0 : sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
412 : // CPLDebug("SQLITE", "OGRSQLiteVFSRandomness()");
413 0 : return pUnderlyingVFS->xRandomness(pUnderlyingVFS, nByte, zOut);
414 : }
415 :
416 0 : static int OGRSQLiteVFSSleep(sqlite3_vfs *pVFS, int microseconds)
417 : {
418 0 : sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
419 : // CPLDebug("SQLITE", "OGRSQLiteVFSSleep()");
420 0 : return pUnderlyingVFS->xSleep(pUnderlyingVFS, microseconds);
421 : }
422 :
423 : // Derived for sqlite3.c implementation of unixCurrentTime64 and
424 : // winCurrentTime64
425 : #ifdef _WIN32
426 : #include <windows.h>
427 :
428 : static int OGRSQLiteVFSCurrentTimeInt64(sqlite3_vfs * /*pVFS*/,
429 : sqlite3_int64 *piNow)
430 : {
431 : FILETIME ft;
432 : constexpr sqlite3_int64 winFiletimeEpoch =
433 : 23058135 * (sqlite3_int64)8640000;
434 : constexpr sqlite3_int64 max32BitValue = (sqlite3_int64)2000000000 +
435 : (sqlite3_int64)2000000000 +
436 : (sqlite3_int64)294967296;
437 :
438 : #if defined(_WIN32_WCE)
439 : SYSTEMTIME time;
440 : GetSystemTime(&time);
441 : /* if SystemTimeToFileTime() fails, it returns zero. */
442 : if (!SystemTimeToFileTime(&time, &ft))
443 : {
444 : return SQLITE_ERROR;
445 : }
446 : #else
447 : GetSystemTimeAsFileTime(&ft);
448 : #endif
449 : *piNow = winFiletimeEpoch +
450 : ((((sqlite3_int64)ft.dwHighDateTime) * max32BitValue) +
451 : (sqlite3_int64)ft.dwLowDateTime) /
452 : (sqlite3_int64)10000;
453 : return SQLITE_OK;
454 : }
455 : #else
456 : #include <sys/time.h>
457 :
458 4006 : static int OGRSQLiteVFSCurrentTimeInt64(sqlite3_vfs * /*pVFS*/,
459 : sqlite3_int64 *piNow)
460 : {
461 : struct timeval sNow;
462 4006 : constexpr sqlite3_int64 unixEpoch = 24405875 * (sqlite3_int64)8640000;
463 4006 : (void)gettimeofday(&sNow, nullptr); /* Cannot fail given valid arguments */
464 4006 : *piNow =
465 4006 : unixEpoch + 1000 * (sqlite3_int64)sNow.tv_sec + sNow.tv_usec / 1000;
466 :
467 4006 : return SQLITE_OK;
468 : }
469 : #endif
470 :
471 0 : static int OGRSQLiteVFSCurrentTime(sqlite3_vfs * /*pVFS*/, double *p1)
472 : {
473 0 : sqlite3_int64 i = 0;
474 0 : int rc = OGRSQLiteVFSCurrentTimeInt64(nullptr, &i);
475 0 : *p1 = i / 86400000.0;
476 0 : return rc;
477 : }
478 :
479 28 : static int OGRSQLiteVFSGetLastError(sqlite3_vfs *pVFS, int p1, char *p2)
480 : {
481 28 : sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
482 : // CPLDebug("SQLITE", "OGRSQLiteVFSGetLastError()");
483 28 : return pUnderlyingVFS->xGetLastError(pUnderlyingVFS, p1, p2);
484 : }
485 :
486 2418 : sqlite3_vfs *OGRSQLiteCreateVFS(pfnNotifyFileOpenedType pfn, void *pfnUserData)
487 : {
488 2418 : sqlite3_vfs *pDefaultVFS = sqlite3_vfs_find(nullptr);
489 2418 : sqlite3_vfs *pMyVFS = (sqlite3_vfs *)CPLCalloc(1, sizeof(sqlite3_vfs));
490 :
491 : OGRSQLiteVFSAppDataStruct *pVFSAppData =
492 2418 : (OGRSQLiteVFSAppDataStruct *)CPLCalloc(
493 : 1, sizeof(OGRSQLiteVFSAppDataStruct));
494 : char szPtr[32];
495 2418 : snprintf(szPtr, sizeof(szPtr), "%p", pVFSAppData);
496 2418 : snprintf(pVFSAppData->szVFSName, sizeof(pVFSAppData->szVFSName),
497 : "OGRSQLITEVFS_%s", szPtr);
498 2418 : pVFSAppData->pDefaultVFS = pDefaultVFS;
499 2418 : pVFSAppData->pfn = pfn;
500 2418 : pVFSAppData->pfnUserData = pfnUserData;
501 2418 : pVFSAppData->nCounter = 0;
502 :
503 2418 : pMyVFS->iVersion = 2;
504 2418 : pMyVFS->szOsFile = sizeof(OGRSQLiteFileStruct);
505 : // must be large enough to hold potentially very long names like
506 : // /vsicurl/.... with AWS S3 security tokens
507 2418 : pMyVFS->mxPathname =
508 2418 : atoi(CPLGetConfigOption("OGR_SQLITE_VFS_MAXPATHNAME", "2048"));
509 2418 : pMyVFS->zName = pVFSAppData->szVFSName;
510 2418 : pMyVFS->pAppData = pVFSAppData;
511 2418 : pMyVFS->xOpen = OGRSQLiteVFSOpen;
512 2418 : pMyVFS->xDelete = OGRSQLiteVFSDelete;
513 2418 : pMyVFS->xAccess = OGRSQLiteVFSAccess;
514 2418 : pMyVFS->xFullPathname = OGRSQLiteVFSFullPathname;
515 2418 : pMyVFS->xDlOpen = OGRSQLiteVFSDlOpen;
516 2418 : pMyVFS->xDlError = OGRSQLiteVFSDlError;
517 2418 : pMyVFS->xDlSym = OGRSQLiteVFSDlSym;
518 2418 : pMyVFS->xDlClose = OGRSQLiteVFSDlClose;
519 2418 : pMyVFS->xRandomness = OGRSQLiteVFSRandomness;
520 2418 : pMyVFS->xSleep = OGRSQLiteVFSSleep;
521 2418 : pMyVFS->xCurrentTime = OGRSQLiteVFSCurrentTime;
522 2418 : pMyVFS->xGetLastError = OGRSQLiteVFSGetLastError;
523 2418 : pMyVFS->xCurrentTimeInt64 = OGRSQLiteVFSCurrentTimeInt64;
524 :
525 2418 : return pMyVFS;
526 : }
|