1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef SQL_SANDBOXED_VFS_FILE_H_
6 #define SQL_SANDBOXED_VFS_FILE_H_
8 #include "base/files/file.h"
9 #include "base/files/file_path.h"
10 #include "base/memory/raw_ptr.h"
11 #include "base/memory/raw_ptr_exclusion.h"
12 #include "third_party/sqlite/sqlite3.h"
16 // The file types associated with a SQLite database.
17 enum class SandboxedVfsFileType {
18 // The main file, which stores the database pages.
20 // The transaction rollback journal file. Used when WAL is off.
21 // This file has the same path as the database, plus the "-journal" suffix.
23 // The Write-Ahead Log (WAL) file.
24 // This file has the same path as the database, plus the "-wal" suffix.
30 // SQLite VFS file implementation that works in a sandboxed process.
32 // An instance is created when SQLite calls into SandboxedVfs::Open(). The
33 // instance is deleted by a call to SandboxedVfsFile::Close().
35 // The SQLite VFS API includes a complex locking strategy documented in
36 // https://www.sqlite.org/lockingv3.html
38 // This implementation uses a simplified locking strategy, where we grab an
39 // exclusive lock when entering any of the modes that prepare for a transition
40 // to EXCLUSIVE. (These modes are RESERVED and PENDING). This approach is easy
41 // to implement on top of base::File's locking primitives, at the cost of some
42 // false contention, which makes us slower under high concurrency.
44 // SQLite's built-in VFSes use the OS support for locking a range of bytes in
45 // the file, rather locking than the whole file.
46 class SandboxedVfsFile {
48 // Creates an instance in the given buffer. Note that `vfs` MUST outlive the
49 // returned sqlite3_file object.
50 static void Create(base::File file,
51 base::FilePath file_path,
53 SandboxedVfsFileType file_type,
54 #endif // DCHECK_IS_ON()
56 sqlite3_file& buffer);
58 // Extracts the instance bridged to the given SQLite VFS file.
59 static SandboxedVfsFile& FromSqliteFile(sqlite3_file& sqlite_file);
61 // sqlite3_file implementation.
63 int Read(void* buffer, int size, sqlite3_int64 offset);
64 int Write(const void* buffer, int size, sqlite3_int64 offset);
65 int Truncate(sqlite3_int64 size);
67 int FileSize(sqlite3_int64* result_size);
70 int CheckReservedLock(int* has_reserved_lock);
71 int FileControl(int opcode, void* data);
73 int DeviceCharacteristics();
74 int ShmMap(int page_index,
76 int extend_file_if_needed,
77 void volatile** result);
78 int ShmLock(int offset, int size, int flags);
80 int ShmUnmap(int also_delete_file);
81 int Fetch(sqlite3_int64 offset, int size, void** result);
82 int Unfetch(sqlite3_int64 offset, void* fetch_result);
85 SandboxedVfsFile(base::File file,
86 base::FilePath file_path,
88 SandboxedVfsFileType file_type,
89 #endif // DCHECK_IS_ON()
93 // Constructed from a file handle passed from the browser process.
95 // One of the SQLite locking mode constants.
96 int sqlite_lock_mode_;
97 // The SandboxedVfs that created this instance.
98 const raw_ptr<SandboxedVfs> vfs_;
100 // Tracked to check assumptions about SQLite's locking protocol.
101 const SandboxedVfsFileType file_type_;
102 #endif // DCHECK_IS_ON()
103 // Used to identify the file in IPCs to the browser process.
104 const base::FilePath file_path_;
107 // sqlite3_file "subclass" that bridges to a SandboxedVfsFile instance.
108 struct SandboxedVfsFileSqliteBridge {
109 sqlite3_file sqlite_file;
110 // `sandboxed_vfs_file` is not a raw_ptr<SandboxedVfsFile>, because
111 // reinterpret_cast of uninitialized memory to raw_ptr can cause ref-counting
113 RAW_PTR_EXCLUSION SandboxedVfsFile* sandboxed_vfs_file;
115 static SandboxedVfsFileSqliteBridge& FromSqliteFile(
116 sqlite3_file& sqlite_file);
121 #endif // SQL_SANDBOXED_VFS_FILE_H_