summaryrefslogtreecommitdiffstats
path: root/storage/ReadOnlyNoLockVFS.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/ReadOnlyNoLockVFS.cpp')
-rw-r--r--storage/ReadOnlyNoLockVFS.cpp130
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