Coverage Report

Created: 2025-08-28 06:57

/src/proj/src/memvfs.c
Line
Count
Source (jump to first uncovered line)
1
/* Derived from https://www.sqlite.org/src/doc/tip/ext/misc/memvfs.c */
2
/*
3
** 2016-09-07
4
**
5
** The author disclaims copyright to this source code.  In place of
6
** a legal notice, here is a blessing:
7
**
8
**    May you do good and not evil.
9
**    May you find forgiveness for yourself and forgive others.
10
**    May you share freely, never taking more than you give.
11
**
12
******************************************************************************
13
**
14
** This is an in-memory VFS implementation.  The application supplies
15
** a chunk of memory to hold the database file.
16
**
17
** Because there is place to store a rollback or wal journal, the database
18
** must use one of journal_mode=MEMORY or journal_mode=NONE.
19
**
20
** USAGE:
21
**
22
**    sqlite3_open_v2("file:/whatever?ptr=0xf05538&sz=14336&max=65536", &db,
23
**                    SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI,
24
**                    "memvfs");
25
**
26
** These are the query parameters:
27
**
28
**    ptr=          The address of the memory buffer that holds the database.
29
**
30
**    sz=           The current size the database file
31
**
32
**    maxsz=        The maximum size of the database.  In other words, the
33
**                  amount of space allocated for the ptr= buffer.
34
**
35
** The ptr= and sz= query parameters are required.  If maxsz= is omitted,
36
** then it defaults to the sz= value.  Parameter values can be in either
37
** decimal or hexadecimal.  The filename in the URI is ignored.
38
*/
39
#include <sqlite3.h>
40
41
#include <assert.h>
42
#include <stdint.h>
43
#include <string.h>
44
45
#include "memvfs.h"
46
47
#ifdef __GNUC__
48
#pragma GCC diagnostic push
49
#pragma GCC diagnostic ignored "-Wunused-parameter"
50
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
51
#endif
52
53
#ifdef _MSC_VER
54
#pragma warning(push)
55
// Ignore unreferenced formal parameter
56
#pragma warning(disable : 4100)
57
#endif
58
59
/*
60
** Forward declaration of objects used by this utility
61
*/
62
typedef struct sqlite3_vfs MemVfs;
63
typedef struct MemFile MemFile;
64
65
typedef struct MemVfsAppData {
66
    const unsigned char *buffer;
67
    size_t bufferSize;
68
    sqlite3_vfs *pBaseVFS;
69
} MemVfsAppData;
70
71
/* Access to a lower-level VFS that (might) implement dynamic loading,
72
** access to randomness, etc.
73
*/
74
9.60k
#define ORIGVFS(p) (((MemVfsAppData *)((p)->pAppData))->pBaseVFS)
75
76
/* An open file */
77
struct MemFile {
78
    sqlite3_file base;          /* IO methods */
79
    sqlite3_int64 sz;           /* Size of the file */
80
    sqlite3_int64 szMax;        /* Space allocated to aData */
81
    const unsigned char *aData; /* content of the file */
82
};
83
84
/*
85
** Methods for MemFile
86
*/
87
static int memClose(sqlite3_file *);
88
static int memRead(sqlite3_file *, void *, int iAmt, sqlite3_int64 iOfst);
89
static int memWrite(sqlite3_file *, const void *, int iAmt,
90
                    sqlite3_int64 iOfst);
91
static int memTruncate(sqlite3_file *, sqlite3_int64 size);
92
static int memSync(sqlite3_file *, int flags);
93
static int memFileSize(sqlite3_file *, sqlite3_int64 *pSize);
94
static int memLock(sqlite3_file *, int);
95
static int memUnlock(sqlite3_file *, int);
96
static int memCheckReservedLock(sqlite3_file *, int *pResOut);
97
static int memFileControl(sqlite3_file *, int op, void *pArg);
98
static int memSectorSize(sqlite3_file *);
99
static int memDeviceCharacteristics(sqlite3_file *);
100
static int memShmMap(sqlite3_file *, int iPg, int pgsz, int, void volatile **);
101
static int memShmLock(sqlite3_file *, int offset, int n, int flags);
102
static void memShmBarrier(sqlite3_file *);
103
static int memShmUnmap(sqlite3_file *, int deleteFlag);
104
static int memFetch(sqlite3_file *, sqlite3_int64 iOfst, int iAmt, void **pp);
105
static int memUnfetch(sqlite3_file *, sqlite3_int64 iOfst, void *p);
106
107
/*
108
** Methods for MemVfs
109
*/
110
static int memOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int *);
111
static int memDelete(sqlite3_vfs *, const char *zName, int syncDir);
112
static int memAccess(sqlite3_vfs *, const char *zName, int flags, int *);
113
static int memFullPathname(sqlite3_vfs *, const char *zName, int, char *zOut);
114
static void *memDlOpen(sqlite3_vfs *, const char *zFilename);
115
static void memDlError(sqlite3_vfs *, int nByte, char *zErrMsg);
116
static void (*memDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void);
117
static void memDlClose(sqlite3_vfs *, void *);
118
static int memRandomness(sqlite3_vfs *, int nByte, char *zOut);
119
static int memSleep(sqlite3_vfs *, int microseconds);
120
static int memCurrentTime(sqlite3_vfs *, double *);
121
static int memGetLastError(sqlite3_vfs *, int, char *);
122
static int memCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64 *);
123
124
static sqlite3_vfs mem_vfs = {
125
    2,                  /* iVersion */
126
    0,                  /* szOsFile (set when registered) */
127
    1024,               /* mxPathname */
128
    0,                  /* pNext */
129
    "memvfs",           /* zName */
130
    0,                  /* pAppData (set when registered) */
131
    memOpen,            /* xOpen */
132
    memDelete,          /* xDelete */
133
    memAccess,          /* xAccess */
134
    memFullPathname,    /* xFullPathname */
135
    memDlOpen,          /* xDlOpen */
136
    memDlError,         /* xDlError */
137
    memDlSym,           /* xDlSym */
138
    memDlClose,         /* xDlClose */
139
    memRandomness,      /* xRandomness */
140
    memSleep,           /* xSleep */
141
    memCurrentTime,     /* xCurrentTime */
142
    memGetLastError,    /* xGetLastError */
143
    memCurrentTimeInt64 /* xCurrentTimeInt64 */
144
};
145
146
static const sqlite3_io_methods mem_io_methods = {
147
    3,                        /* iVersion */
148
    memClose,                 /* xClose */
149
    memRead,                  /* xRead */
150
    memWrite,                 /* xWrite */
151
    memTruncate,              /* xTruncate */
152
    memSync,                  /* xSync */
153
    memFileSize,              /* xFileSize */
154
    memLock,                  /* xLock */
155
    memUnlock,                /* xUnlock */
156
    memCheckReservedLock,     /* xCheckReservedLock */
157
    memFileControl,           /* xFileControl */
158
    memSectorSize,            /* xSectorSize */
159
    memDeviceCharacteristics, /* xDeviceCharacteristics */
160
    memShmMap,                /* xShmMap */
161
    memShmLock,               /* xShmLock */
162
    memShmBarrier,            /* xShmBarrier */
163
    memShmUnmap,              /* xShmUnmap */
164
    memFetch,                 /* xFetch */
165
    memUnfetch                /* xUnfetch */
166
};
167
168
/*
169
** Close an mem-file.
170
**
171
** The pData pointer is owned by the application, so there is nothing
172
** to free.
173
*/
174
0
static int memClose(sqlite3_file *pFile) { return SQLITE_OK; }
175
176
/*
177
** Read data from an mem-file.
178
*/
179
static int memRead(sqlite3_file *pFile, void *zBuf, int iAmt,
180
6.39M
                   sqlite_int64 iOfst) {
181
6.39M
    MemFile *p = (MemFile *)pFile;
182
6.39M
    memcpy(zBuf, p->aData + iOfst, iAmt);
183
6.39M
    return SQLITE_OK;
184
6.39M
}
185
186
/*
187
** Write data to an mem-file.
188
*/
189
static int memWrite(sqlite3_file *pFile, const void *z, int iAmt,
190
0
                    sqlite_int64 iOfst) {
191
0
    return SQLITE_READONLY;
192
0
}
193
194
/*
195
** Truncate an mem-file.
196
*/
197
0
static int memTruncate(sqlite3_file *pFile, sqlite_int64 size) {
198
0
    return SQLITE_READONLY;
199
0
}
200
201
/*
202
** Sync an mem-file.
203
*/
204
0
static int memSync(sqlite3_file *pFile, int flags) { return SQLITE_OK; }
205
206
/*
207
** Return the current file-size of an mem-file.
208
*/
209
1
static int memFileSize(sqlite3_file *pFile, sqlite_int64 *pSize) {
210
1
    MemFile *p = (MemFile *)pFile;
211
1
    *pSize = p->sz;
212
1
    return SQLITE_OK;
213
1
}
214
215
/*
216
** Lock an mem-file.
217
*/
218
0
static int memLock(sqlite3_file *pFile, int eLock) { return SQLITE_OK; }
219
220
/*
221
** Unlock an mem-file.
222
*/
223
0
static int memUnlock(sqlite3_file *pFile, int eLock) { return SQLITE_OK; }
224
225
/*
226
** Check if another file-handle holds a RESERVED lock on an mem-file.
227
*/
228
0
static int memCheckReservedLock(sqlite3_file *pFile, int *pResOut) {
229
0
    *pResOut = 0;
230
0
    return SQLITE_OK;
231
0
}
232
233
/*
234
** File control method. For custom operations on an mem-file.
235
*/
236
5
static int memFileControl(sqlite3_file *pFile, int op, void *pArg) {
237
5
    MemFile *p = (MemFile *)pFile;
238
5
    int rc = SQLITE_NOTFOUND;
239
5
    if (op == SQLITE_FCNTL_VFSNAME) {
240
0
        *(char **)pArg = sqlite3_mprintf("mem(%p,%lld)", p->aData, p->sz);
241
0
        rc = SQLITE_OK;
242
0
    }
243
5
    return rc;
244
5
}
245
246
/*
247
** Return the sector-size in bytes for an mem-file.
248
*/
249
0
static int memSectorSize(sqlite3_file *pFile) { return 1024; }
250
251
/*
252
** Return the device characteristic flags supported by an mem-file.
253
*/
254
2
static int memDeviceCharacteristics(sqlite3_file *pFile) {
255
2
    return SQLITE_IOCAP_ATOMIC | SQLITE_IOCAP_POWERSAFE_OVERWRITE |
256
2
           SQLITE_IOCAP_SAFE_APPEND | SQLITE_IOCAP_SEQUENTIAL;
257
2
}
258
259
/* Create a shared memory file mapping */
260
static int memShmMap(sqlite3_file *pFile, int iPg, int pgsz, int bExtend,
261
0
                     void volatile **pp) {
262
0
    return SQLITE_IOERR_SHMMAP;
263
0
}
264
265
/* Perform locking on a shared-memory segment */
266
0
static int memShmLock(sqlite3_file *pFile, int offset, int n, int flags) {
267
0
    return SQLITE_IOERR_SHMLOCK;
268
0
}
269
270
/* Memory barrier operation on shared memory */
271
0
static void memShmBarrier(sqlite3_file *pFile) { return; }
272
273
/* Unmap a shared memory segment */
274
0
static int memShmUnmap(sqlite3_file *pFile, int deleteFlag) {
275
0
    return SQLITE_OK;
276
0
}
277
278
/* Fetch a page of a memory-mapped file */
279
static int memFetch(sqlite3_file *pFile, sqlite3_int64 iOfst, int iAmt,
280
0
                    void **pp) {
281
0
    MemFile *p = (MemFile *)pFile;
282
0
    *pp = (void *)(p->aData + iOfst);
283
0
    return SQLITE_OK;
284
0
}
285
286
/* Release a memory-mapped page */
287
0
static int memUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage) {
288
0
    return SQLITE_OK;
289
0
}
290
291
/*
292
** Open an mem file handle.
293
*/
294
static int memOpen(sqlite3_vfs *pVfs, const char *zName, sqlite3_file *pFile,
295
4.80k
                   int flags, int *pOutFlags) {
296
4.80k
    MemFile *p = (MemFile *)pFile;
297
4.80k
    MemVfsAppData *appData = (MemVfsAppData *)(pVfs->pAppData);
298
4.80k
    memset(p, 0, sizeof(*p));
299
4.80k
    if ((flags & SQLITE_OPEN_MAIN_DB) == 0) {
300
        /* Modification w.r.t upstream: instead of returning SQLITE_CANTOPEN,
301
         * delegate to origin VFS. Typically for temporary file creation.
302
         */
303
4.80k
        return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags,
304
4.80k
                                    pOutFlags);
305
4.80k
    }
306
1
    if ((uintptr_t)(appData->buffer) !=
307
1
        (uintptr_t)sqlite3_uri_int64(zName, "ptr", 0)) {
308
0
        return SQLITE_CANTOPEN;
309
0
    }
310
1
    p->aData = appData->buffer;
311
1
    p->sz = sqlite3_uri_int64(zName, "sz", 0);
312
1
    if (p->sz < 0 || (size_t)p->sz != appData->bufferSize)
313
0
        return SQLITE_CANTOPEN;
314
1
    p->szMax = sqlite3_uri_int64(zName, "max", p->sz);
315
1
    if (p->szMax < p->sz)
316
0
        return SQLITE_CANTOPEN;
317
1
    pFile->pMethods = &mem_io_methods;
318
1
    return SQLITE_OK;
319
1
}
320
321
/*
322
** Delete the file located at zPath. If the dirSync argument is true,
323
** ensure the file-system modifications are synced to disk before
324
** returning.
325
*/
326
0
static int memDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync) {
327
0
    return SQLITE_IOERR_DELETE;
328
0
}
329
330
/*
331
** Test for access permissions. Return true if the requested permission
332
** is available, or false otherwise.
333
*/
334
static int memAccess(sqlite3_vfs *pVfs, const char *zPath, int flags,
335
0
                     int *pResOut) {
336
0
    *pResOut = 0;
337
0
    return SQLITE_OK;
338
0
}
339
340
/*
341
** Populate buffer zOut with the full canonical pathname corresponding
342
** to the pathname in zPath. zOut is guaranteed to point to a buffer
343
** of at least (INST_MAX_PATHNAME+1) bytes.
344
*/
345
static int memFullPathname(sqlite3_vfs *pVfs, const char *zPath, int nOut,
346
1
                           char *zOut) {
347
1
    sqlite3_snprintf(nOut, zOut, "%s", zPath);
348
1
    return SQLITE_OK;
349
1
}
350
351
/*
352
** Open the dynamic library located at zPath and return a handle.
353
*/
354
0
static void *memDlOpen(sqlite3_vfs *pVfs, const char *zPath) {
355
0
    return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
356
0
}
357
358
/*
359
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
360
** utf-8 string describing the most recent error encountered associated
361
** with dynamic libraries.
362
*/
363
0
static void memDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg) {
364
0
    ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
365
0
}
366
367
/*
368
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
369
*/
370
0
static void (*memDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void) {
371
0
    return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
372
0
}
373
374
/*
375
** Close the dynamic library handle pHandle.
376
*/
377
0
static void memDlClose(sqlite3_vfs *pVfs, void *pHandle) {
378
0
    ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
379
0
}
380
381
/*
382
** Populate the buffer pointed to by zBufOut with nByte bytes of
383
** random data.
384
*/
385
0
static int memRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut) {
386
0
    return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
387
0
}
388
389
/*
390
** Sleep for nMicro microseconds. Return the number of microseconds
391
** actually slept.
392
*/
393
0
static int memSleep(sqlite3_vfs *pVfs, int nMicro) {
394
0
    return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
395
0
}
396
397
/*
398
** Return the current time as a Julian Day number in *pTimeOut.
399
*/
400
0
static int memCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut) {
401
0
    return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
402
0
}
403
404
0
static int memGetLastError(sqlite3_vfs *pVfs, int a, char *b) {
405
0
    return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
406
0
}
407
0
static int memCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p) {
408
0
    return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
409
0
}
410
411
/*
412
 * Register the new VFS.
413
 */
414
int pj_sqlite3_memvfs_init(sqlite3_vfs *vfs, const char *vfs_name,
415
1
                           const void *buffer, size_t bufferSize) {
416
1
    memcpy(vfs, &mem_vfs, sizeof(mem_vfs));
417
1
    vfs->zName = vfs_name;
418
1
    sqlite3_vfs *defaultVFS = sqlite3_vfs_find(NULL);
419
1
    if (!defaultVFS)
420
0
        return SQLITE_ERROR;
421
1
    MemVfsAppData *appData =
422
1
        (MemVfsAppData *)sqlite3_malloc(sizeof(MemVfsAppData));
423
1
    appData->buffer = buffer;
424
1
    appData->bufferSize = bufferSize;
425
1
    appData->pBaseVFS = defaultVFS;
426
1
    vfs->pAppData = appData;
427
1
    vfs->szOsFile = sizeof(MemFile);
428
    /* Modification w.r.t upstream: as we might delegate file opening
429
     * to default VFS for temporary files, we need to make sure szOsFile is
430
     * the maximum of our own need and of the default VFS.
431
     */
432
1
    if (vfs->szOsFile < defaultVFS->szOsFile)
433
1
        vfs->szOsFile = defaultVFS->szOsFile;
434
1
    return sqlite3_vfs_register(vfs, 0);
435
1
}
436
437
0
void pj_sqlite3_memvfs_deallocate_user_data(sqlite3_vfs *vfs) {
438
0
    sqlite3_free(vfs->pAppData);
439
0
    vfs->pAppData = NULL;
440
0
}
441
442
#ifdef _MSC_VER
443
#pragma warning(pop)
444
#endif
445
446
#ifdef __GNUC__
447
#pragma GCC diagnostic pop
448
#endif