tor-browser

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

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