ReadOnlyNoLockVFS.cpp (4797B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /** 8 * This VFS is built on top of the (unix|win32)-none, but it additionally 9 * sets any opened file as immutable, that allows to also open in read-only 10 * mode databases using WAL, or other journals that need auxiliary files, when 11 * such files cannot be created. 12 * This is useful when trying to read from third-party databases, avoiding any 13 * risk of creating auxiliary files (e.g. journals). 14 * It can only be used on read-only connections, because being a no-lock VFS 15 * it would be trivial to corrupt the data. 16 */ 17 18 #include "nsDebug.h" 19 #include "sqlite3.h" 20 21 #include "mozilla/UniquePtr.h" 22 23 #define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData)) 24 25 #if defined(XP_WIN) 26 # define BASE_VFS "win32-none" 27 #else 28 # define BASE_VFS "unix-none" 29 #endif 30 31 #define VFS_NAME "readonly-immutable-nolock" 32 33 namespace { 34 35 static int vfsOpen(sqlite3_vfs* vfs, const char* zName, sqlite3_file* pFile, 36 int flags, int* pOutFlags) { 37 if ((flags & SQLITE_OPEN_READONLY) == 0) { 38 // This is not done to be used in readwrite connections. 39 return SQLITE_CANTOPEN; 40 } 41 42 sqlite3_vfs* pOrigVfs = ORIGVFS(vfs); 43 int rc = pOrigVfs->xOpen(pOrigVfs, zName, pFile, flags, pOutFlags); 44 if (rc != SQLITE_OK) { 45 return rc; 46 } 47 48 const sqlite3_io_methods* pOrigMethods = pFile->pMethods; 49 50 // If the IO version is higher than the last known one, you should update 51 // this IO adding appropriate methods for any methods added in the version 52 // change. 53 MOZ_ASSERT(pOrigMethods->iVersion <= 3); 54 55 static const sqlite3_io_methods vfs_io_methods = { 56 pOrigMethods->iVersion, /* iVersion */ 57 pOrigMethods->xClose, /* xClose */ 58 pOrigMethods->xRead, /* xRead */ 59 pOrigMethods->xWrite, /* xWrite */ 60 pOrigMethods->xTruncate, /* xTruncate */ 61 pOrigMethods->xSync, /* xSync */ 62 pOrigMethods->xFileSize, /* xFileSize */ 63 pOrigMethods->xLock, /* xLock */ 64 pOrigMethods->xUnlock, /* xUnlock */ 65 pOrigMethods->xCheckReservedLock, /* xCheckReservedLock */ 66 pOrigMethods->xFileControl, /* xFileControl */ 67 pOrigMethods->xSectorSize, /* xSectorSize */ 68 [](sqlite3_file*) { 69 return SQLITE_IOCAP_IMMUTABLE; 70 }, /* xDeviceCharacteristics */ 71 pOrigMethods->xShmMap, /* xShmMap */ 72 pOrigMethods->xShmLock, /* xShmLock */ 73 pOrigMethods->xShmBarrier, /* xShmBarrier */ 74 pOrigMethods->xShmUnmap, /* xShmUnmap */ 75 pOrigMethods->xFetch, /* xFetch */ 76 pOrigMethods->xUnfetch /* xUnfetch */ 77 }; 78 pFile->pMethods = &vfs_io_methods; 79 if (pOutFlags) { 80 *pOutFlags = flags; 81 } 82 83 return SQLITE_OK; 84 } 85 86 } // namespace 87 88 namespace mozilla::storage { 89 90 UniquePtr<sqlite3_vfs> ConstructReadOnlyNoLockVFS() { 91 if (sqlite3_vfs_find(VFS_NAME) != nullptr) { 92 return nullptr; 93 } 94 sqlite3_vfs* pOrigVfs = sqlite3_vfs_find(BASE_VFS); 95 if (!pOrigVfs) { 96 return nullptr; 97 } 98 99 // If the VFS version is higher than the last known one, you should update 100 // this VFS adding appropriate methods for any methods added in the version 101 // change. 102 MOZ_ASSERT(pOrigVfs->iVersion <= 3); 103 104 static const sqlite3_vfs vfs = { 105 pOrigVfs->iVersion, /* iVersion */ 106 pOrigVfs->szOsFile, /* szOsFile */ 107 pOrigVfs->mxPathname, /* mxPathname */ 108 nullptr, /* pNext */ 109 VFS_NAME, /* zName */ 110 pOrigVfs, /* pAppData */ 111 vfsOpen, /* xOpen */ 112 pOrigVfs->xDelete, /* xDelete */ 113 pOrigVfs->xAccess, /* xAccess */ 114 pOrigVfs->xFullPathname, /* xFullPathname */ 115 pOrigVfs->xDlOpen, /* xDlOpen */ 116 pOrigVfs->xDlError, /* xDlError */ 117 pOrigVfs->xDlSym, /* xDlSym */ 118 pOrigVfs->xDlClose, /* xDlClose */ 119 pOrigVfs->xRandomness, /* xRandomness */ 120 pOrigVfs->xSleep, /* xSleep */ 121 pOrigVfs->xCurrentTime, /* xCurrentTime */ 122 pOrigVfs->xGetLastError, /* xGetLastError */ 123 pOrigVfs->xCurrentTimeInt64, /* xCurrentTimeInt64 */ 124 pOrigVfs->xSetSystemCall, /* xSetSystemCall */ 125 pOrigVfs->xGetSystemCall, /* xGetSystemCall */ 126 pOrigVfs->xNextSystemCall /* xNextSystemCall */ 127 }; 128 129 return MakeUnique<sqlite3_vfs>(vfs); 130 } 131 132 } // namespace mozilla::storage