forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			243 lines
		
	
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			243 lines
		
	
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- 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/. */
 | |
| 
 | |
| #include "BaseVFS.h"
 | |
| 
 | |
| #include <string.h>
 | |
| #include "sqlite3.h"
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| // The last VFS version for which this file has been updated.
 | |
| constexpr int kLastKnowVfsVersion = 3;
 | |
| 
 | |
| // The last io_methods version for which this file has been updated.
 | |
| constexpr int kLastKnownIOMethodsVersion = 3;
 | |
| 
 | |
| using namespace mozilla;
 | |
| 
 | |
| struct BaseFile {
 | |
|   // Base class.  Must be first
 | |
|   sqlite3_file base;
 | |
|   // This points to the underlying sqlite3_file
 | |
|   sqlite3_file pReal[1];
 | |
| };
 | |
| 
 | |
| int BaseClose(sqlite3_file* pFile) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xClose(p->pReal);
 | |
| }
 | |
| 
 | |
| int BaseRead(sqlite3_file* pFile, void* zBuf, int iAmt, sqlite_int64 iOfst) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
 | |
| }
 | |
| 
 | |
| int BaseWrite(sqlite3_file* pFile, const void* zBuf, int iAmt,
 | |
|               sqlite_int64 iOfst) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
 | |
| }
 | |
| 
 | |
| int BaseTruncate(sqlite3_file* pFile, sqlite_int64 size) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xTruncate(p->pReal, size);
 | |
| }
 | |
| 
 | |
| int BaseSync(sqlite3_file* pFile, int flags) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xSync(p->pReal, flags);
 | |
| }
 | |
| 
 | |
| int BaseFileSize(sqlite3_file* pFile, sqlite_int64* pSize) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xFileSize(p->pReal, pSize);
 | |
| }
 | |
| 
 | |
| int BaseLock(sqlite3_file* pFile, int eLock) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xLock(p->pReal, eLock);
 | |
| }
 | |
| 
 | |
| int BaseUnlock(sqlite3_file* pFile, int eLock) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xUnlock(p->pReal, eLock);
 | |
| }
 | |
| 
 | |
| int BaseCheckReservedLock(sqlite3_file* pFile, int* pResOut) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
 | |
| }
 | |
| 
 | |
| int BaseFileControl(sqlite3_file* pFile, int op, void* pArg) {
 | |
| #if defined(MOZ_SQLITE_PERSIST_AUXILIARY_FILES)
 | |
|   // Persist auxiliary files (-shm and -wal) on disk, because creating and
 | |
|   // deleting them may be expensive on slow storage.
 | |
|   // Only do this when there is a journal size limit, so the journal is
 | |
|   // truncated instead of deleted on shutdown, that feels safer if the user
 | |
|   // moves a database file around without its auxiliary files.
 | |
|   MOZ_ASSERT(
 | |
|       ::sqlite3_compileoption_used("DEFAULT_JOURNAL_SIZE_LIMIT"),
 | |
|       "A journal size limit ensures the journal is truncated on shutdown");
 | |
|   if (op == SQLITE_FCNTL_PERSIST_WAL) {
 | |
|     *static_cast<int*>(pArg) = 1;
 | |
|     return SQLITE_OK;
 | |
|   }
 | |
| #endif
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
 | |
| }
 | |
| 
 | |
| int BaseSectorSize(sqlite3_file* pFile) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xSectorSize(p->pReal);
 | |
| }
 | |
| 
 | |
| int BaseDeviceCharacteristics(sqlite3_file* pFile) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
 | |
| }
 | |
| 
 | |
| int BaseShmMap(sqlite3_file* pFile, int iPg, int pgsz, int bExtend,
 | |
|                void volatile** pp) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xShmMap(p->pReal, iPg, pgsz, bExtend, pp);
 | |
| }
 | |
| 
 | |
| int BaseShmLock(sqlite3_file* pFile, int offset, int n, int flags) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xShmLock(p->pReal, offset, n, flags);
 | |
| }
 | |
| 
 | |
| void BaseShmBarrier(sqlite3_file* pFile) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xShmBarrier(p->pReal);
 | |
| }
 | |
| 
 | |
| int BaseShmUnmap(sqlite3_file* pFile, int deleteFlag) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xShmUnmap(p->pReal, deleteFlag);
 | |
| }
 | |
| 
 | |
| int BaseFetch(sqlite3_file* pFile, sqlite3_int64 iOfst, int iAmt, void** pp) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xFetch(p->pReal, iOfst, iAmt, pp);
 | |
| }
 | |
| 
 | |
| int BaseUnfetch(sqlite3_file* pFile, sqlite3_int64 iOfst, void* pPage) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   return p->pReal->pMethods->xUnfetch(p->pReal, iOfst, pPage);
 | |
| }
 | |
| 
 | |
| int BaseOpen(sqlite3_vfs* vfs, const char* zName, sqlite3_file* pFile,
 | |
|              int flags, int* pOutFlags) {
 | |
|   BaseFile* p = (BaseFile*)pFile;
 | |
|   sqlite3_vfs* origVfs = (sqlite3_vfs*)(vfs->pAppData);
 | |
|   int rc = origVfs->xOpen(origVfs, zName, p->pReal, flags, pOutFlags);
 | |
|   if (rc) {
 | |
|     return rc;
 | |
|   }
 | |
|   if (p->pReal->pMethods) {
 | |
|     // If the io_methods version is higher than the last known one, you should
 | |
|     // update this VFS adding appropriate IO methods for any methods added in
 | |
|     // the version change.
 | |
|     MOZ_ASSERT(p->pReal->pMethods->iVersion == kLastKnownIOMethodsVersion);
 | |
|     static const sqlite3_io_methods IOmethods = {
 | |
|         kLastKnownIOMethodsVersion, /* iVersion */
 | |
|         BaseClose,                  /* xClose */
 | |
|         BaseRead,                   /* xRead */
 | |
|         BaseWrite,                  /* xWrite */
 | |
|         BaseTruncate,               /* xTruncate */
 | |
|         BaseSync,                   /* xSync */
 | |
|         BaseFileSize,               /* xFileSize */
 | |
|         BaseLock,                   /* xLock */
 | |
|         BaseUnlock,                 /* xUnlock */
 | |
|         BaseCheckReservedLock,      /* xCheckReservedLock */
 | |
|         BaseFileControl,            /* xFileControl */
 | |
|         BaseSectorSize,             /* xSectorSize */
 | |
|         BaseDeviceCharacteristics,  /* xDeviceCharacteristics */
 | |
|         BaseShmMap,                 /* xShmMap */
 | |
|         BaseShmLock,                /* xShmLock */
 | |
|         BaseShmBarrier,             /* xShmBarrier */
 | |
|         BaseShmUnmap,               /* xShmUnmap */
 | |
|         BaseFetch,                  /* xFetch */
 | |
|         BaseUnfetch                 /* xUnfetch */
 | |
|     };
 | |
|     pFile->pMethods = &IOmethods;
 | |
|   }
 | |
| 
 | |
|   return SQLITE_OK;
 | |
| }
 | |
| 
 | |
| }  // namespace
 | |
| 
 | |
| namespace mozilla::storage::basevfs {
 | |
| 
 | |
| const char* GetVFSName(bool exclusive) {
 | |
|   return exclusive ? "base-vfs-excl" : "base-vfs";
 | |
| }
 | |
| 
 | |
| UniquePtr<sqlite3_vfs> ConstructVFS(bool exclusive) {
 | |
| #if defined(XP_WIN)
 | |
| #  define EXPECTED_VFS "win32"
 | |
| #  define EXPECTED_VFS_EXCL "win32"
 | |
| #else
 | |
| #  define EXPECTED_VFS "unix"
 | |
| #  define EXPECTED_VFS_EXCL "unix-excl"
 | |
| #endif
 | |
| 
 | |
|   if (sqlite3_vfs_find(GetVFSName(exclusive))) {
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   bool found;
 | |
|   sqlite3_vfs* origVfs;
 | |
|   if (!exclusive) {
 | |
|     // Use the non-exclusive VFS.
 | |
|     origVfs = sqlite3_vfs_find(nullptr);
 | |
|     found = origVfs && origVfs->zName && !strcmp(origVfs->zName, EXPECTED_VFS);
 | |
|   } else {
 | |
|     origVfs = sqlite3_vfs_find(EXPECTED_VFS_EXCL);
 | |
|     found = (origVfs != nullptr);
 | |
|   }
 | |
|   if (!found) {
 | |
|     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(origVfs->iVersion == kLastKnowVfsVersion);
 | |
| 
 | |
|   sqlite3_vfs vfs = {
 | |
|       kLastKnowVfsVersion,                                    /* iVersion  */
 | |
|       origVfs->szOsFile + static_cast<int>(sizeof(BaseFile)), /* szOsFile */
 | |
|       origVfs->mxPathname,                                    /* mxPathname */
 | |
|       nullptr,                                                /* pNext */
 | |
|       GetVFSName(exclusive),                                  /* zName */
 | |
|       origVfs,                                                /* pAppData */
 | |
|       BaseOpen,                                               /* xOpen */
 | |
|       origVfs->xDelete,                                       /* xDelete */
 | |
|       origVfs->xAccess,                                       /* xAccess */
 | |
|       origVfs->xFullPathname,     /* xFullPathname */
 | |
|       origVfs->xDlOpen,           /* xDlOpen */
 | |
|       origVfs->xDlError,          /* xDlError */
 | |
|       origVfs->xDlSym,            /* xDlSym */
 | |
|       origVfs->xDlClose,          /* xDlClose */
 | |
|       origVfs->xRandomness,       /* xRandomness */
 | |
|       origVfs->xSleep,            /* xSleep */
 | |
|       origVfs->xCurrentTime,      /* xCurrentTime */
 | |
|       origVfs->xGetLastError,     /* xGetLastError */
 | |
|       origVfs->xCurrentTimeInt64, /* xCurrentTimeInt64 */
 | |
|       origVfs->xSetSystemCall,    /* xSetSystemCall */
 | |
|       origVfs->xGetSystemCall,    /* xGetSystemCall */
 | |
|       origVfs->xNextSystemCall    /* xNextSystemCall */
 | |
|   };
 | |
| 
 | |
|   return MakeUnique<sqlite3_vfs>(vfs);
 | |
| }
 | |
| 
 | |
| }  // namespace mozilla::storage::basevfs
 | 
