diff options
Diffstat (limited to 'storage/ReadOnlyNoLockVFS.cpp')
-rw-r--r-- | storage/ReadOnlyNoLockVFS.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/storage/ReadOnlyNoLockVFS.cpp b/storage/ReadOnlyNoLockVFS.cpp new file mode 100644 index 0000000000..9a820085ed --- /dev/null +++ b/storage/ReadOnlyNoLockVFS.cpp @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * This VFS is built on top of the (unix|win32)-none, but it additionally + * sets any opened file as immutable, that allows to also open in read-only + * mode databases using WAL, or other journals that need auxiliary files, when + * such files cannot be created. + * This is useful when trying to read from third-party databases, avoiding any + * risk of creating auxiliary files (e.g. journals). + * It can only be used on read-only connections, because being a no-lock VFS + * it would be trivial to corrupt the data. + */ + +#include "nsDebug.h" +#include "sqlite3.h" + +#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData)) + +#if defined(XP_WIN) +# define BASE_VFS "win32-none" +#else +# define BASE_VFS "unix-none" +#endif + +#define VFS_NAME "readonly-immutable-nolock" + +namespace { + +static int vfsOpen(sqlite3_vfs* vfs, const char* zName, sqlite3_file* pFile, + int flags, int* pOutFlags) { + if ((flags & SQLITE_OPEN_READONLY) == 0) { + // This is not done to be used in readwrite connections. + return SQLITE_CANTOPEN; + } + + sqlite3_vfs* pOrigVfs = ORIGVFS(vfs); + int rc = pOrigVfs->xOpen(pOrigVfs, zName, pFile, flags, pOutFlags); + if (rc != SQLITE_OK) { + return rc; + } + + const sqlite3_io_methods* pOrigMethods = pFile->pMethods; + + // If the IO version is higher than the last known one, you should update + // this IO adding appropriate methods for any methods added in the version + // change. + MOZ_ASSERT(pOrigMethods->iVersion <= 3); + + static const sqlite3_io_methods vfs_io_methods = { + pOrigMethods->iVersion, /* iVersion */ + pOrigMethods->xClose, /* xClose */ + pOrigMethods->xRead, /* xRead */ + pOrigMethods->xWrite, /* xWrite */ + pOrigMethods->xTruncate, /* xTruncate */ + pOrigMethods->xSync, /* xSync */ + pOrigMethods->xFileSize, /* xFileSize */ + pOrigMethods->xLock, /* xLock */ + pOrigMethods->xUnlock, /* xUnlock */ + pOrigMethods->xCheckReservedLock, /* xCheckReservedLock */ + pOrigMethods->xFileControl, /* xFileControl */ + pOrigMethods->xSectorSize, /* xSectorSize */ + [](sqlite3_file*) { + return SQLITE_IOCAP_IMMUTABLE; + }, /* xDeviceCharacteristics */ + pOrigMethods->xShmMap, /* xShmMap */ + pOrigMethods->xShmLock, /* xShmLock */ + pOrigMethods->xShmBarrier, /* xShmBarrier */ + pOrigMethods->xShmUnmap, /* xShmUnmap */ + pOrigMethods->xFetch, /* xFetch */ + pOrigMethods->xUnfetch /* xUnfetch */ + }; + pFile->pMethods = &vfs_io_methods; + if (pOutFlags) { + *pOutFlags = flags; + } + + return SQLITE_OK; +} + +} // namespace + +namespace mozilla::storage { + +UniquePtr<sqlite3_vfs> ConstructReadOnlyNoLockVFS() { + if (sqlite3_vfs_find(VFS_NAME) != nullptr) { + return nullptr; + } + sqlite3_vfs* pOrigVfs = sqlite3_vfs_find(BASE_VFS); + if (!pOrigVfs) { + return nullptr; + } + + // If the VFS version is higher than the last known one, you should update + // this VFS adding appropriate methods for any methods added in the version + // change. + MOZ_ASSERT(pOrigVfs->iVersion <= 3); + + static const sqlite3_vfs vfs = { + pOrigVfs->iVersion, /* iVersion */ + pOrigVfs->szOsFile, /* szOsFile */ + pOrigVfs->mxPathname, /* mxPathname */ + nullptr, /* pNext */ + VFS_NAME, /* zName */ + pOrigVfs, /* pAppData */ + vfsOpen, /* xOpen */ + pOrigVfs->xDelete, /* xDelete */ + pOrigVfs->xAccess, /* xAccess */ + pOrigVfs->xFullPathname, /* xFullPathname */ + pOrigVfs->xDlOpen, /* xDlOpen */ + pOrigVfs->xDlError, /* xDlError */ + pOrigVfs->xDlSym, /* xDlSym */ + pOrigVfs->xDlClose, /* xDlClose */ + pOrigVfs->xRandomness, /* xRandomness */ + pOrigVfs->xSleep, /* xSleep */ + pOrigVfs->xCurrentTime, /* xCurrentTime */ + pOrigVfs->xGetLastError, /* xGetLastError */ + pOrigVfs->xCurrentTimeInt64, /* xCurrentTimeInt64 */ + pOrigVfs->xSetSystemCall, /* xSetSystemCall */ + pOrigVfs->xGetSystemCall, /* xGetSystemCall */ + pOrigVfs->xNextSystemCall /* xNextSystemCall */ + }; + + return MakeUnique<sqlite3_vfs>(vfs); +} + +} // namespace mozilla::storage |