Coverage Report

Created: 2026-09-26 08:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp
Line
Count
Source
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
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "cpl_port.h"
14
#include "ogr_sqlite.h"
15
16
#include <cstdio>
17
#include <cstdlib>
18
#include <cstring>
19
20
#include "cpl_conv.h"
21
#include "cpl_error.h"
22
#include "cpl_string.h"
23
#include "cpl_vsi.h"
24
#include "ogrsqlitevfs.h"
25
26
#ifdef DEBUG_IO
27
#define DEBUG_ONLY
28
#else
29
#define DEBUG_ONLY CPL_UNUSED
30
#endif
31
32
// #define DEBUG_IO 1
33
34
typedef struct
35
{
36
    char szVFSName[64];
37
    sqlite3_vfs *pDefaultVFS;
38
    pfnNotifyFileOpenedType pfn;
39
    void *pfnUserData;
40
} OGRSQLiteVFSAppDataStruct;
41
42
#define GET_UNDERLYING_VFS(pVFS)                                               \
43
3.29k
    static_cast<OGRSQLiteVFSAppDataStruct *>(pVFS->pAppData)->pDefaultVFS
44
45
typedef struct
46
{
47
    const struct sqlite3_io_methods *pMethods;
48
    VSILFILE *fp;
49
    int bDeleteOnClose;
50
    char *pszFilename;
51
} OGRSQLiteFileStruct;
52
53
static int OGRSQLiteIOClose(sqlite3_file *pFile)
54
130k
{
55
130k
    OGRSQLiteFileStruct *pMyFile =
56
130k
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
57
#ifdef DEBUG_IO
58
    CPLDebug("SQLITE", "OGRSQLiteIOClose(%p (%s))", pMyFile->fp,
59
             pMyFile->pszFilename);
60
#endif
61
130k
    VSIFCloseL(pMyFile->fp);
62
130k
    if (pMyFile->bDeleteOnClose)
63
0
        VSIUnlink(pMyFile->pszFilename);
64
130k
    CPLFree(pMyFile->pszFilename);
65
130k
    return SQLITE_OK;
66
130k
}
67
68
static int OGRSQLiteIORead(sqlite3_file *pFile, void *pBuffer, int iAmt,
69
                           sqlite3_int64 iOfst)
70
280k
{
71
280k
    OGRSQLiteFileStruct *pMyFile =
72
280k
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
73
280k
    VSIFSeekL(pMyFile->fp, static_cast<vsi_l_offset>(iOfst), SEEK_SET);
74
280k
    int nRead = static_cast<int>(VSIFReadL(pBuffer, 1, iAmt, pMyFile->fp));
75
#ifdef DEBUG_IO
76
    CPLDebug("SQLITE", "OGRSQLiteIORead(%p, %d, %d) = %d", pMyFile->fp, iAmt,
77
             static_cast<int>(iOfst), nRead);
78
#endif
79
280k
    if (nRead < iAmt)
80
130k
    {
81
130k
        memset(static_cast<char *>(pBuffer) + nRead, 0, iAmt - nRead);
82
130k
        return SQLITE_IOERR_SHORT_READ;
83
130k
    }
84
149k
    return SQLITE_OK;
85
280k
}
86
87
static int OGRSQLiteIOWrite(sqlite3_file *pFile, const void *pBuffer, int iAmt,
88
                            sqlite3_int64 iOfst)
89
1.82M
{
90
1.82M
    OGRSQLiteFileStruct *pMyFile =
91
1.82M
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
92
1.82M
    VSIFSeekL(pMyFile->fp, static_cast<vsi_l_offset>(iOfst), SEEK_SET);
93
1.82M
    int nWritten = static_cast<int>(VSIFWriteL(pBuffer, 1, iAmt, pMyFile->fp));
94
#ifdef DEBUG_IO
95
    CPLDebug("SQLITE", "OGRSQLiteIOWrite(%p, %d, %d) = %d", pMyFile->fp, iAmt,
96
             static_cast<int>(iOfst), nWritten);
97
#endif
98
1.82M
    if (nWritten < iAmt)
99
0
    {
100
0
        return SQLITE_IOERR_WRITE;
101
0
    }
102
1.82M
    return SQLITE_OK;
103
1.82M
}
104
105
static int OGRSQLiteIOTruncate(sqlite3_file *pFile, sqlite3_int64 size)
106
0
{
107
0
    OGRSQLiteFileStruct *pMyFile =
108
0
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
109
#ifdef DEBUG_IO
110
    CPLDebug("SQLITE", "OGRSQLiteIOTruncate(%p, " CPL_FRMT_GIB ")", pMyFile->fp,
111
             size);
112
#endif
113
0
    int nRet = VSIFTruncateL(pMyFile->fp, size);
114
0
    return (nRet == 0) ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
115
0
}
116
117
static int OGRSQLiteIOSync(DEBUG_ONLY sqlite3_file *pFile, DEBUG_ONLY int flags)
118
380k
{
119
#ifdef DEBUG_IO
120
    OGRSQLiteFileStruct *pMyFile =
121
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
122
    CPLDebug("SQLITE", "OGRSQLiteIOSync(%p, %d)", pMyFile->fp, flags);
123
#endif
124
380k
    return SQLITE_OK;
125
380k
}
126
127
static int OGRSQLiteIOFileSize(sqlite3_file *pFile, sqlite3_int64 *pSize)
128
149k
{
129
149k
    OGRSQLiteFileStruct *pMyFile =
130
149k
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
131
149k
    vsi_l_offset nCurOffset = VSIFTellL(pMyFile->fp);
132
149k
    VSIFSeekL(pMyFile->fp, 0, SEEK_END);
133
149k
    *pSize = VSIFTellL(pMyFile->fp);
134
149k
    VSIFSeekL(pMyFile->fp, nCurOffset, SEEK_SET);
135
#ifdef DEBUG_IO
136
    CPLDebug("SQLITE", "OGRSQLiteIOFileSize(%p) = " CPL_FRMT_GIB, pMyFile->fp,
137
             *pSize);
138
#endif
139
149k
    return SQLITE_OK;
140
149k
}
141
142
static int OGRSQLiteIOLock(DEBUG_ONLY sqlite3_file *pFile, DEBUG_ONLY int flags)
143
419k
{
144
#ifdef DEBUG_IO
145
    OGRSQLiteFileStruct *pMyFile =
146
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
147
    CPLDebug("SQLITE", "OGRSQLiteIOLock(%p)", pMyFile->fp);
148
#endif
149
419k
    return SQLITE_OK;
150
419k
}
151
152
static int OGRSQLiteIOUnlock(DEBUG_ONLY sqlite3_file *pFile,
153
                             DEBUG_ONLY int flags)
154
286k
{
155
#ifdef DEBUG_IO
156
    OGRSQLiteFileStruct *pMyFile =
157
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
158
    CPLDebug("SQLITE", "OGRSQLiteIOUnlock(%p)", pMyFile->fp);
159
#endif
160
286k
    return SQLITE_OK;
161
286k
}
162
163
static int OGRSQLiteIOCheckReservedLock(DEBUG_ONLY sqlite3_file *pFile,
164
                                        DEBUG_ONLY int *pResOut)
165
20
{
166
#ifdef DEBUG_IO
167
    OGRSQLiteFileStruct *pMyFile =
168
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
169
    CPLDebug("SQLITE", "OGRSQLiteIOCheckReservedLock(%p)", pMyFile->fp);
170
#endif
171
20
    *pResOut = 0;
172
20
    return SQLITE_OK;
173
20
}
174
175
static int OGRSQLiteIOFileControl(DEBUG_ONLY sqlite3_file *pFile,
176
                                  DEBUG_ONLY int op, DEBUG_ONLY void *pArg)
177
419k
{
178
#ifdef DEBUG_IO
179
    OGRSQLiteFileStruct *pMyFile =
180
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
181
    CPLDebug("SQLITE", "OGRSQLiteIOFileControl(%p, %d)", pMyFile->fp, op);
182
#endif
183
419k
    return SQLITE_NOTFOUND;
184
419k
}
185
186
static int OGRSQLiteIOSectorSize(DEBUG_ONLY sqlite3_file *pFile)
187
4.29k
{
188
#ifdef DEBUG_IO
189
    OGRSQLiteFileStruct *pMyFile =
190
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
191
    CPLDebug("SQLITE", "OGRSQLiteIOSectorSize(%p)", pMyFile->fp);
192
#endif
193
4.29k
    return 0;
194
4.29k
}
195
196
static int OGRSQLiteIODeviceCharacteristics(DEBUG_ONLY sqlite3_file *pFile)
197
411k
{
198
#ifdef DEBUG_IO
199
    OGRSQLiteFileStruct *pMyFile =
200
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
201
    CPLDebug("SQLITE", "OGRSQLiteIODeviceCharacteristics(%p)", pMyFile->fp);
202
#endif
203
411k
    return 0;
204
411k
}
205
206
static const sqlite3_io_methods OGRSQLiteIOMethods = {
207
    1,
208
    OGRSQLiteIOClose,
209
    OGRSQLiteIORead,
210
    OGRSQLiteIOWrite,
211
    OGRSQLiteIOTruncate,
212
    OGRSQLiteIOSync,
213
    OGRSQLiteIOFileSize,
214
    OGRSQLiteIOLock,
215
    OGRSQLiteIOUnlock,
216
    OGRSQLiteIOCheckReservedLock,
217
    OGRSQLiteIOFileControl,
218
    OGRSQLiteIOSectorSize,
219
    OGRSQLiteIODeviceCharacteristics,
220
    nullptr,  // xShmMap
221
    nullptr,  // xShmLock
222
    nullptr,  // xShmBarrier
223
    nullptr,  // xShmUnmap
224
    nullptr,  // xFetch
225
    nullptr,  // xUnfetch
226
};
227
228
static int OGRSQLiteVFSOpen(sqlite3_vfs *pVFS, const char *zNameIn,
229
                            sqlite3_file *pFile, int flags, int *pOutFlags)
230
131k
{
231
#ifdef DEBUG_IO
232
    CPLDebug("SQLITE", "OGRSQLiteVFSOpen(%s, %d)", zNameIn ? zNameIn : "(null)",
233
             flags);
234
#endif
235
236
131k
    OGRSQLiteVFSAppDataStruct *pAppData =
237
131k
        static_cast<OGRSQLiteVFSAppDataStruct *>(pVFS->pAppData);
238
239
131k
    const std::string osName(
240
131k
        zNameIn ? zNameIn : VSIMemGenerateHiddenFilename("sqlitevfs"));
241
242
131k
    OGRSQLiteFileStruct *pMyFile =
243
131k
        reinterpret_cast<OGRSQLiteFileStruct *>(pFile);
244
131k
    pMyFile->pMethods = nullptr;
245
131k
    pMyFile->bDeleteOnClose = FALSE;
246
131k
    pMyFile->pszFilename = nullptr;
247
131k
    if (flags & SQLITE_OPEN_READONLY)
248
1.14k
        pMyFile->fp = VSIFOpenL(osName.c_str(), "rb");
249
129k
    else if (flags & SQLITE_OPEN_CREATE)
250
129k
    {
251
129k
        VSIStatBufL sStatBufL;
252
129k
        if (VSIStatExL(osName.c_str(), &sStatBufL, VSI_STAT_EXISTS_FLAG) == 0)
253
979
            pMyFile->fp = VSIFOpenL(osName.c_str(), "rb+");
254
128k
        else
255
128k
            pMyFile->fp = VSIFOpenL(osName.c_str(), "wb+");
256
129k
    }
257
0
    else if (flags & SQLITE_OPEN_READWRITE)
258
0
        pMyFile->fp = VSIFOpenL(osName.c_str(), "rb+");
259
0
    else
260
0
        pMyFile->fp = nullptr;
261
262
131k
    if (pMyFile->fp == nullptr)
263
257
        return SQLITE_CANTOPEN;
264
265
#ifdef DEBUG_IO
266
    CPLDebug("SQLITE", "OGRSQLiteVFSOpen() = %p", pMyFile->fp);
267
#endif
268
269
130k
    pfnNotifyFileOpenedType pfn = pAppData->pfn;
270
130k
    if (pfn)
271
129k
    {
272
129k
        pfn(pAppData->pfnUserData, osName.c_str(), pMyFile->fp);
273
129k
    }
274
275
130k
    pMyFile->pMethods = &OGRSQLiteIOMethods;
276
130k
    pMyFile->bDeleteOnClose = (flags & SQLITE_OPEN_DELETEONCLOSE);
277
130k
    pMyFile->pszFilename = CPLStrdup(osName.c_str());
278
279
130k
    if (pOutFlags != nullptr)
280
2.56k
        *pOutFlags = flags;
281
282
130k
    return SQLITE_OK;
283
131k
}
284
285
static int OGRSQLiteVFSDelete(DEBUG_ONLY sqlite3_vfs *pVFS, const char *zName,
286
                              int DEBUG_ONLY syncDir)
287
128k
{
288
#ifdef DEBUG_IO
289
    CPLDebug("SQLITE", "OGRSQLiteVFSDelete(%s)", zName);
290
#endif
291
128k
    VSIUnlink(zName);
292
128k
    return SQLITE_OK;
293
128k
}
294
295
static int OGRSQLiteVFSAccess(DEBUG_ONLY sqlite3_vfs *pVFS, const char *zName,
296
                              int flags, int *pResOut)
297
298k
{
298
#ifdef DEBUG_IO
299
    CPLDebug("SQLITE", "OGRSQLiteVFSAccess(%s, %d)", zName, flags);
300
#endif
301
298k
    VSIStatBufL sStatBufL;
302
298k
    int nRet;  // TODO(schwehr): Cleanup nRet and pResOut.  bools?
303
298k
    if (flags == SQLITE_ACCESS_EXISTS)
304
298k
    {
305
        /* Do not try to check the presence of a journal or a wal on /vsicurl !
306
         */
307
298k
        if ((STARTS_WITH(zName, "/vsicurl/") ||
308
296k
             STARTS_WITH(zName, "/vsitar/") ||
309
296k
             STARTS_WITH(zName, "/vsizip/")) &&
310
6.65k
            ((strlen(zName) > strlen("-journal") &&
311
6.65k
              strcmp(zName + strlen(zName) - strlen("-journal"), "-journal") ==
312
6.65k
                  0) ||
313
3.32k
             (strlen(zName) > strlen("-wal") &&
314
3.32k
              strcmp(zName + strlen(zName) - strlen("-wal"), "-wal") == 0)))
315
6.65k
        {
316
6.65k
            nRet = -1;
317
6.65k
        }
318
291k
        else
319
291k
        {
320
291k
            nRet = VSIStatExL(zName, &sStatBufL, VSI_STAT_EXISTS_FLAG);
321
291k
        }
322
298k
    }
323
0
    else if (flags == SQLITE_ACCESS_READ)
324
0
    {
325
0
        VSILFILE *fp = VSIFOpenL(zName, "rb");
326
0
        nRet = fp ? 0 : -1;
327
0
        if (fp)
328
0
            VSIFCloseL(fp);
329
0
    }
330
0
    else if (flags == SQLITE_ACCESS_READWRITE)
331
0
    {
332
0
        VSILFILE *fp = VSIFOpenL(zName, "rb+");
333
0
        nRet = fp ? 0 : -1;
334
0
        if (fp)
335
0
            VSIFCloseL(fp);
336
0
    }
337
0
    else
338
0
    {
339
0
        nRet = -1;
340
0
    }
341
298k
    *pResOut = (nRet == 0);
342
298k
    return SQLITE_OK;
343
298k
}
344
345
static int OGRSQLiteVFSFullPathname(sqlite3_vfs *pVFS, const char *zName,
346
                                    int nOut, char *zOut)
347
2.92k
{
348
2.92k
    sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
349
#ifdef DEBUG_IO
350
    CPLDebug("SQLITE", "OGRSQLiteVFSFullPathname(%s)", zName);
351
#endif
352
2.92k
    if (zName[0] == '/')
353
2.84k
    {
354
2.84k
        if (static_cast<int>(strlen(zName)) >= nOut)
355
100
        {
356
            // The +8 comes from the fact that sqlite3 does this check as
357
            // it needs to be able to append .journal to the filename
358
100
            CPLError(CE_Failure, CPLE_AppDefined,
359
100
                     "Maximum pathname length reserved for SQLite3 VFS "
360
100
                     "isn't large enough. Try raising "
361
100
                     "OGR_SQLITE_VFS_MAXPATHNAME to at least %d",
362
100
                     static_cast<int>(strlen(zName)) + 8);
363
100
            return SQLITE_CANTOPEN;
364
100
        }
365
2.74k
        strncpy(zOut, zName, nOut);
366
2.74k
        zOut[nOut - 1] = '\0';
367
2.74k
        return SQLITE_OK;
368
2.84k
    }
369
82
    return pUnderlyingVFS->xFullPathname(pUnderlyingVFS, zName, nOut, zOut);
370
2.92k
}
371
372
static void *OGRSQLiteVFSDlOpen(sqlite3_vfs *pVFS, const char *zFilename)
373
0
{
374
0
    sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
375
    // CPLDebug("SQLITE", "OGRSQLiteVFSDlOpen(%s)", zFilename);
376
0
    return pUnderlyingVFS->xDlOpen(pUnderlyingVFS, zFilename);
377
0
}
378
379
static void OGRSQLiteVFSDlError(sqlite3_vfs *pVFS, int nByte, char *zErrMsg)
380
0
{
381
0
    sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
382
    // CPLDebug("SQLITE", "OGRSQLiteVFSDlError()");
383
0
    pUnderlyingVFS->xDlError(pUnderlyingVFS, nByte, zErrMsg);
384
0
}
385
386
static void (*OGRSQLiteVFSDlSym(sqlite3_vfs *pVFS, void *pHandle,
387
                                const char *zSymbol))(void)
388
0
{
389
0
    sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
390
    // CPLDebug("SQLITE", "OGRSQLiteVFSDlSym(%s)", zSymbol);
391
0
    return pUnderlyingVFS->xDlSym(pUnderlyingVFS, pHandle, zSymbol);
392
0
}
393
394
static void OGRSQLiteVFSDlClose(sqlite3_vfs *pVFS, void *pHandle)
395
0
{
396
0
    sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
397
    // CPLDebug("SQLITE", "OGRSQLiteVFSDlClose(%p)", pHandle);
398
0
    pUnderlyingVFS->xDlClose(pUnderlyingVFS, pHandle);
399
0
}
400
401
static int OGRSQLiteVFSRandomness(sqlite3_vfs *pVFS, int nByte, char *zOut)
402
0
{
403
0
    sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
404
    // CPLDebug("SQLITE", "OGRSQLiteVFSRandomness()");
405
0
    return pUnderlyingVFS->xRandomness(pUnderlyingVFS, nByte, zOut);
406
0
}
407
408
static int OGRSQLiteVFSSleep(sqlite3_vfs *pVFS, int microseconds)
409
0
{
410
0
    sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
411
    // CPLDebug("SQLITE", "OGRSQLiteVFSSleep()");
412
0
    return pUnderlyingVFS->xSleep(pUnderlyingVFS, microseconds);
413
0
}
414
415
// Derived for sqlite3.c implementation of unixCurrentTime64 and
416
// winCurrentTime64
417
#ifdef _WIN32
418
#include <windows.h>
419
420
static int OGRSQLiteVFSCurrentTimeInt64(sqlite3_vfs * /*pVFS*/,
421
                                        sqlite3_int64 *piNow)
422
{
423
    FILETIME ft;
424
    constexpr sqlite3_int64 winFiletimeEpoch =
425
        23058135 * static_cast<sqlite3_int64>(8640000);
426
    constexpr sqlite3_int64 max32BitValue =
427
        static_cast<sqlite3_int64>(2000000000) +
428
        static_cast<sqlite3_int64>(2000000000) +
429
        static_cast<sqlite3_int64>(294967296);
430
431
#if defined(_WIN32_WCE)
432
    SYSTEMTIME time;
433
    GetSystemTime(&time);
434
    /* if SystemTimeToFileTime() fails, it returns zero. */
435
    if (!SystemTimeToFileTime(&time, &ft))
436
    {
437
        return SQLITE_ERROR;
438
    }
439
#else
440
    GetSystemTimeAsFileTime(&ft);
441
#endif
442
    *piNow = winFiletimeEpoch +
443
             ((static_cast<sqlite3_int64>(ft.dwHighDateTime) * max32BitValue) +
444
              static_cast<sqlite3_int64>(ft.dwLowDateTime)) /
445
                 static_cast<sqlite3_int64>(10000);
446
    return SQLITE_OK;
447
}
448
#else
449
#include <sys/time.h>
450
451
static int OGRSQLiteVFSCurrentTimeInt64(sqlite3_vfs * /*pVFS*/,
452
                                        sqlite3_int64 *piNow)
453
1.89k
{
454
1.89k
    struct timeval sNow;
455
1.89k
    constexpr sqlite3_int64 unixEpoch =
456
1.89k
        24405875 * static_cast<sqlite3_int64>(8640000);
457
1.89k
    (void)gettimeofday(&sNow, nullptr); /* Cannot fail given valid arguments */
458
1.89k
    *piNow = unixEpoch + 1000 * static_cast<sqlite3_int64>(sNow.tv_sec) +
459
1.89k
             sNow.tv_usec / 1000;
460
461
1.89k
    return SQLITE_OK;
462
1.89k
}
463
#endif
464
465
static int OGRSQLiteVFSCurrentTime(sqlite3_vfs * /*pVFS*/, double *p1)
466
0
{
467
0
    sqlite3_int64 i = 0;
468
0
    int rc = OGRSQLiteVFSCurrentTimeInt64(nullptr, &i);
469
0
    *p1 = i / 86400000.0;
470
0
    return rc;
471
0
}
472
473
static int OGRSQLiteVFSGetLastError(sqlite3_vfs *pVFS, int p1, char *p2)
474
368
{
475
368
    sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
476
    // CPLDebug("SQLITE", "OGRSQLiteVFSGetLastError()");
477
368
    return pUnderlyingVFS->xGetLastError(pUnderlyingVFS, p1, p2);
478
368
}
479
480
sqlite3_vfs *OGRSQLiteCreateVFS(pfnNotifyFileOpenedType pfn, void *pfnUserData)
481
2.92k
{
482
2.92k
    sqlite3_vfs *pDefaultVFS = sqlite3_vfs_find(nullptr);
483
2.92k
    sqlite3_vfs *pMyVFS =
484
2.92k
        static_cast<sqlite3_vfs *>(CPLCalloc(1, sizeof(sqlite3_vfs)));
485
486
2.92k
    OGRSQLiteVFSAppDataStruct *pVFSAppData =
487
2.92k
        static_cast<OGRSQLiteVFSAppDataStruct *>(
488
2.92k
            CPLCalloc(1, sizeof(OGRSQLiteVFSAppDataStruct)));
489
2.92k
    char szPtr[32];
490
2.92k
    snprintf(szPtr, sizeof(szPtr), "%p", pVFSAppData);
491
2.92k
    snprintf(pVFSAppData->szVFSName, sizeof(pVFSAppData->szVFSName),
492
2.92k
             "OGRSQLITEVFS_%s", szPtr);
493
2.92k
    pVFSAppData->pDefaultVFS = pDefaultVFS;
494
2.92k
    pVFSAppData->pfn = pfn;
495
2.92k
    pVFSAppData->pfnUserData = pfnUserData;
496
497
2.92k
    pMyVFS->iVersion = 2;
498
2.92k
    pMyVFS->szOsFile = sizeof(OGRSQLiteFileStruct);
499
    // must be large enough to hold potentially very long names like
500
    // /vsicurl/.... with AWS S3 security tokens
501
2.92k
    pMyVFS->mxPathname =
502
2.92k
        atoi(CPLGetConfigOption("OGR_SQLITE_VFS_MAXPATHNAME", "2048"));
503
2.92k
    pMyVFS->zName = pVFSAppData->szVFSName;
504
2.92k
    pMyVFS->pAppData = pVFSAppData;
505
2.92k
    pMyVFS->xOpen = OGRSQLiteVFSOpen;
506
2.92k
    pMyVFS->xDelete = OGRSQLiteVFSDelete;
507
2.92k
    pMyVFS->xAccess = OGRSQLiteVFSAccess;
508
2.92k
    pMyVFS->xFullPathname = OGRSQLiteVFSFullPathname;
509
2.92k
    pMyVFS->xDlOpen = OGRSQLiteVFSDlOpen;
510
2.92k
    pMyVFS->xDlError = OGRSQLiteVFSDlError;
511
2.92k
    pMyVFS->xDlSym = OGRSQLiteVFSDlSym;
512
2.92k
    pMyVFS->xDlClose = OGRSQLiteVFSDlClose;
513
2.92k
    pMyVFS->xRandomness = OGRSQLiteVFSRandomness;
514
2.92k
    pMyVFS->xSleep = OGRSQLiteVFSSleep;
515
2.92k
    pMyVFS->xCurrentTime = OGRSQLiteVFSCurrentTime;
516
2.92k
    pMyVFS->xGetLastError = OGRSQLiteVFSGetLastError;
517
2.92k
    pMyVFS->xCurrentTimeInt64 = OGRSQLiteVFSCurrentTimeInt64;
518
519
2.92k
    return pMyVFS;
520
2.92k
}