/* -*- 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 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(vfs); } } // namespace mozilla::storage