tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

BaseVFS.cpp (8550B)


      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 #include "BaseVFS.h"
      8 
      9 #include <string.h>
     10 #include "sqlite3.h"
     11 
     12 #include "mozilla/Assertions.h"
     13 
     14 namespace {
     15 
     16 // The last VFS version for which this file has been updated.
     17 constexpr int kLastKnowVfsVersion = 3;
     18 
     19 // The last io_methods version for which this file has been updated.
     20 constexpr int kLastKnownIOMethodsVersion = 3;
     21 
     22 using namespace mozilla;
     23 
     24 struct BaseFile {
     25  // Base class.  Must be first
     26  sqlite3_file base;
     27  // This points to the underlying sqlite3_file
     28  sqlite3_file pReal[1];
     29 };
     30 
     31 int BaseClose(sqlite3_file* pFile) {
     32  BaseFile* p = (BaseFile*)pFile;
     33  return p->pReal->pMethods->xClose(p->pReal);
     34 }
     35 
     36 int BaseRead(sqlite3_file* pFile, void* zBuf, int iAmt, sqlite_int64 iOfst) {
     37  BaseFile* p = (BaseFile*)pFile;
     38  return p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
     39 }
     40 
     41 int BaseWrite(sqlite3_file* pFile, const void* zBuf, int iAmt,
     42              sqlite_int64 iOfst) {
     43  BaseFile* p = (BaseFile*)pFile;
     44  return p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
     45 }
     46 
     47 int BaseTruncate(sqlite3_file* pFile, sqlite_int64 size) {
     48  BaseFile* p = (BaseFile*)pFile;
     49  return p->pReal->pMethods->xTruncate(p->pReal, size);
     50 }
     51 
     52 int BaseSync(sqlite3_file* pFile, int flags) {
     53  BaseFile* p = (BaseFile*)pFile;
     54  return p->pReal->pMethods->xSync(p->pReal, flags);
     55 }
     56 
     57 int BaseFileSize(sqlite3_file* pFile, sqlite_int64* pSize) {
     58  BaseFile* p = (BaseFile*)pFile;
     59  return p->pReal->pMethods->xFileSize(p->pReal, pSize);
     60 }
     61 
     62 int BaseLock(sqlite3_file* pFile, int eLock) {
     63  BaseFile* p = (BaseFile*)pFile;
     64  return p->pReal->pMethods->xLock(p->pReal, eLock);
     65 }
     66 
     67 int BaseUnlock(sqlite3_file* pFile, int eLock) {
     68  BaseFile* p = (BaseFile*)pFile;
     69  return p->pReal->pMethods->xUnlock(p->pReal, eLock);
     70 }
     71 
     72 int BaseCheckReservedLock(sqlite3_file* pFile, int* pResOut) {
     73  BaseFile* p = (BaseFile*)pFile;
     74  return p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
     75 }
     76 
     77 int BaseFileControl(sqlite3_file* pFile, int op, void* pArg) {
     78 #if defined(MOZ_SQLITE_PERSIST_AUXILIARY_FILES)
     79  // Persist auxiliary files (-shm and -wal) on disk, because creating and
     80  // deleting them may be expensive on slow storage.
     81  // Only do this when there is a journal size limit, so the journal is
     82  // truncated instead of deleted on shutdown, that feels safer if the user
     83  // moves a database file around without its auxiliary files.
     84  MOZ_ASSERT(
     85      ::sqlite3_compileoption_used("DEFAULT_JOURNAL_SIZE_LIMIT"),
     86      "A journal size limit ensures the journal is truncated on shutdown");
     87  if (op == SQLITE_FCNTL_PERSIST_WAL) {
     88    *static_cast<int*>(pArg) = 1;
     89    return SQLITE_OK;
     90  }
     91 #endif
     92  BaseFile* p = (BaseFile*)pFile;
     93  return p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
     94 }
     95 
     96 int BaseSectorSize(sqlite3_file* pFile) {
     97  BaseFile* p = (BaseFile*)pFile;
     98  return p->pReal->pMethods->xSectorSize(p->pReal);
     99 }
    100 
    101 int BaseDeviceCharacteristics(sqlite3_file* pFile) {
    102  BaseFile* p = (BaseFile*)pFile;
    103  return p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
    104 }
    105 
    106 int BaseShmMap(sqlite3_file* pFile, int iPg, int pgsz, int bExtend,
    107               void volatile** pp) {
    108  BaseFile* p = (BaseFile*)pFile;
    109  return p->pReal->pMethods->xShmMap(p->pReal, iPg, pgsz, bExtend, pp);
    110 }
    111 
    112 int BaseShmLock(sqlite3_file* pFile, int offset, int n, int flags) {
    113  BaseFile* p = (BaseFile*)pFile;
    114  return p->pReal->pMethods->xShmLock(p->pReal, offset, n, flags);
    115 }
    116 
    117 void BaseShmBarrier(sqlite3_file* pFile) {
    118  BaseFile* p = (BaseFile*)pFile;
    119  return p->pReal->pMethods->xShmBarrier(p->pReal);
    120 }
    121 
    122 int BaseShmUnmap(sqlite3_file* pFile, int deleteFlag) {
    123  BaseFile* p = (BaseFile*)pFile;
    124  return p->pReal->pMethods->xShmUnmap(p->pReal, deleteFlag);
    125 }
    126 
    127 int BaseFetch(sqlite3_file* pFile, sqlite3_int64 iOfst, int iAmt, void** pp) {
    128  BaseFile* p = (BaseFile*)pFile;
    129  return p->pReal->pMethods->xFetch(p->pReal, iOfst, iAmt, pp);
    130 }
    131 
    132 int BaseUnfetch(sqlite3_file* pFile, sqlite3_int64 iOfst, void* pPage) {
    133  BaseFile* p = (BaseFile*)pFile;
    134  return p->pReal->pMethods->xUnfetch(p->pReal, iOfst, pPage);
    135 }
    136 
    137 int BaseOpen(sqlite3_vfs* vfs, const char* zName, sqlite3_file* pFile,
    138             int flags, int* pOutFlags) {
    139  BaseFile* p = (BaseFile*)pFile;
    140  sqlite3_vfs* origVfs = (sqlite3_vfs*)(vfs->pAppData);
    141  int rc = origVfs->xOpen(origVfs, zName, p->pReal, flags, pOutFlags);
    142  if (rc) {
    143    return rc;
    144  }
    145  if (p->pReal->pMethods) {
    146    // If the io_methods version is higher than the last known one, you should
    147    // update this VFS adding appropriate IO methods for any methods added in
    148    // the version change.
    149    MOZ_ASSERT(p->pReal->pMethods->iVersion == kLastKnownIOMethodsVersion);
    150    static const sqlite3_io_methods IOmethods = {
    151        kLastKnownIOMethodsVersion, /* iVersion */
    152        BaseClose,                  /* xClose */
    153        BaseRead,                   /* xRead */
    154        BaseWrite,                  /* xWrite */
    155        BaseTruncate,               /* xTruncate */
    156        BaseSync,                   /* xSync */
    157        BaseFileSize,               /* xFileSize */
    158        BaseLock,                   /* xLock */
    159        BaseUnlock,                 /* xUnlock */
    160        BaseCheckReservedLock,      /* xCheckReservedLock */
    161        BaseFileControl,            /* xFileControl */
    162        BaseSectorSize,             /* xSectorSize */
    163        BaseDeviceCharacteristics,  /* xDeviceCharacteristics */
    164        BaseShmMap,                 /* xShmMap */
    165        BaseShmLock,                /* xShmLock */
    166        BaseShmBarrier,             /* xShmBarrier */
    167        BaseShmUnmap,               /* xShmUnmap */
    168        BaseFetch,                  /* xFetch */
    169        BaseUnfetch                 /* xUnfetch */
    170    };
    171    pFile->pMethods = &IOmethods;
    172  }
    173 
    174  return SQLITE_OK;
    175 }
    176 
    177 }  // namespace
    178 
    179 namespace mozilla::storage::basevfs {
    180 
    181 const char* GetVFSName(bool exclusive) {
    182  return exclusive ? "base-vfs-excl" : "base-vfs";
    183 }
    184 
    185 UniquePtr<sqlite3_vfs> ConstructVFS(bool exclusive) {
    186 #if defined(XP_WIN)
    187 #  define EXPECTED_VFS "win32"
    188 #  define EXPECTED_VFS_EXCL "win32"
    189 #else
    190 #  define EXPECTED_VFS "unix"
    191 #  define EXPECTED_VFS_EXCL "unix-excl"
    192 #endif
    193 
    194  if (sqlite3_vfs_find(GetVFSName(exclusive))) {
    195    return nullptr;
    196  }
    197 
    198  bool found;
    199  sqlite3_vfs* origVfs;
    200  if (!exclusive) {
    201    // Use the non-exclusive VFS.
    202    origVfs = sqlite3_vfs_find(nullptr);
    203    found = origVfs && origVfs->zName && !strcmp(origVfs->zName, EXPECTED_VFS);
    204  } else {
    205    origVfs = sqlite3_vfs_find(EXPECTED_VFS_EXCL);
    206    found = (origVfs != nullptr);
    207  }
    208  if (!found) {
    209    return nullptr;
    210  }
    211 
    212  // If the VFS version is higher than the last known one, you should update
    213  // this VFS adding appropriate methods for any methods added in the version
    214  // change.
    215  MOZ_ASSERT(origVfs->iVersion == kLastKnowVfsVersion);
    216 
    217  sqlite3_vfs vfs = {
    218      kLastKnowVfsVersion,                                    /* iVersion  */
    219      origVfs->szOsFile + static_cast<int>(sizeof(BaseFile)), /* szOsFile */
    220      origVfs->mxPathname,                                    /* mxPathname */
    221      nullptr,                                                /* pNext */
    222      GetVFSName(exclusive),                                  /* zName */
    223      origVfs,                                                /* pAppData */
    224      BaseOpen,                                               /* xOpen */
    225      origVfs->xDelete,                                       /* xDelete */
    226      origVfs->xAccess,                                       /* xAccess */
    227      origVfs->xFullPathname,     /* xFullPathname */
    228      origVfs->xDlOpen,           /* xDlOpen */
    229      origVfs->xDlError,          /* xDlError */
    230      origVfs->xDlSym,            /* xDlSym */
    231      origVfs->xDlClose,          /* xDlClose */
    232      origVfs->xRandomness,       /* xRandomness */
    233      origVfs->xSleep,            /* xSleep */
    234      origVfs->xCurrentTime,      /* xCurrentTime */
    235      origVfs->xGetLastError,     /* xGetLastError */
    236      origVfs->xCurrentTimeInt64, /* xCurrentTimeInt64 */
    237      origVfs->xSetSystemCall,    /* xSetSystemCall */
    238      origVfs->xGetSystemCall,    /* xGetSystemCall */
    239      origVfs->xNextSystemCall    /* xNextSystemCall */
    240  };
    241 
    242  return MakeUnique<sqlite3_vfs>(vfs);
    243 }
    244 
    245 }  // namespace mozilla::storage::basevfs