blob: afaee549e899dced4f831dbd6d9a49d4e93ecce0 [file] [log] [blame]
Victor Costan451bb9cf2019-03-16 04:48:071// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ken Rockot7655fcb62020-08-12 19:22:405#include "sql/sandboxed_vfs_file.h"
Victor Costan451bb9cf2019-03-16 04:48:076
7#include <atomic>
8#include <cstring>
9#include <type_traits>
10#include <utility>
11
Hans Wennborgfc109c92020-05-01 00:21:3712#include "base/check_op.h"
Victor Costan451bb9cf2019-03-16 04:48:0713#include "base/files/file.h"
Hans Wennborgfc109c92020-05-01 00:21:3714#include "base/notreached.h"
Victor Costan451bb9cf2019-03-16 04:48:0715#include "base/threading/platform_thread.h"
16#include "build/build_config.h"
17#include "sql/initialization.h"
Ken Rockot7655fcb62020-08-12 19:22:4018#include "sql/sandboxed_vfs.h"
Victor Costan451bb9cf2019-03-16 04:48:0719#include "third_party/sqlite/sqlite3.h"
20
Ken Rockot7655fcb62020-08-12 19:22:4021namespace sql {
Victor Costan451bb9cf2019-03-16 04:48:0722
23namespace {
24
25int SandboxedClose(sqlite3_file* file) {
Ken Rockot7655fcb62020-08-12 19:22:4026 return SandboxedVfsFile::FromSqliteFile(*file).Close();
Victor Costan451bb9cf2019-03-16 04:48:0727}
28int SandboxedRead(sqlite3_file* file,
29 void* buffer,
30 int size,
31 sqlite3_int64 offset) {
Ken Rockot7655fcb62020-08-12 19:22:4032 return SandboxedVfsFile::FromSqliteFile(*file).Read(buffer, size, offset);
Victor Costan451bb9cf2019-03-16 04:48:0733}
34int SandboxedWrite(sqlite3_file* file,
35 const void* buffer,
36 int size,
37 sqlite3_int64 offset) {
Ken Rockot7655fcb62020-08-12 19:22:4038 return SandboxedVfsFile::FromSqliteFile(*file).Write(buffer, size, offset);
Victor Costan451bb9cf2019-03-16 04:48:0739}
40int SandboxedTruncate(sqlite3_file* file, sqlite3_int64 size) {
Ken Rockot7655fcb62020-08-12 19:22:4041 return SandboxedVfsFile::FromSqliteFile(*file).Truncate(size);
Victor Costan451bb9cf2019-03-16 04:48:0742}
43int SandboxedSync(sqlite3_file* file, int flags) {
Ken Rockot7655fcb62020-08-12 19:22:4044 return SandboxedVfsFile::FromSqliteFile(*file).Sync(flags);
Victor Costan451bb9cf2019-03-16 04:48:0745}
46int SandboxedFileSize(sqlite3_file* file, sqlite3_int64* result_size) {
Ken Rockot7655fcb62020-08-12 19:22:4047 return SandboxedVfsFile::FromSqliteFile(*file).FileSize(result_size);
Victor Costan451bb9cf2019-03-16 04:48:0748}
49int SandboxedLock(sqlite3_file* file, int mode) {
Ken Rockot7655fcb62020-08-12 19:22:4050 return SandboxedVfsFile::FromSqliteFile(*file).Lock(mode);
Victor Costan451bb9cf2019-03-16 04:48:0751}
52int SandboxedUnlock(sqlite3_file* file, int mode) {
Ken Rockot7655fcb62020-08-12 19:22:4053 return SandboxedVfsFile::FromSqliteFile(*file).Unlock(mode);
Victor Costan451bb9cf2019-03-16 04:48:0754}
55int SandboxedCheckReservedLock(sqlite3_file* file, int* has_reserved_lock) {
Ken Rockot7655fcb62020-08-12 19:22:4056 return SandboxedVfsFile::FromSqliteFile(*file).CheckReservedLock(
Victor Costan451bb9cf2019-03-16 04:48:0757 has_reserved_lock);
58}
59int SandboxedFileControl(sqlite3_file* file, int opcode, void* data) {
Ken Rockot7655fcb62020-08-12 19:22:4060 return SandboxedVfsFile::FromSqliteFile(*file).FileControl(opcode, data);
Victor Costan451bb9cf2019-03-16 04:48:0761}
62int SandboxedSectorSize(sqlite3_file* file) {
Ken Rockot7655fcb62020-08-12 19:22:4063 return SandboxedVfsFile::FromSqliteFile(*file).SectorSize();
Victor Costan451bb9cf2019-03-16 04:48:0764}
65int SandboxedDeviceCharacteristics(sqlite3_file* file) {
Ken Rockot7655fcb62020-08-12 19:22:4066 return SandboxedVfsFile::FromSqliteFile(*file).DeviceCharacteristics();
Victor Costan451bb9cf2019-03-16 04:48:0767}
68int SandboxedShmMap(sqlite3_file* file,
69 int page_index,
70 int page_size,
71 int extend_file_if_needed,
72 void volatile** result) {
Ken Rockot7655fcb62020-08-12 19:22:4073 return SandboxedVfsFile::FromSqliteFile(*file).ShmMap(
Victor Costan451bb9cf2019-03-16 04:48:0774 page_index, page_size, extend_file_if_needed, result);
75}
76int SandboxedShmLock(sqlite3_file* file, int offset, int size, int flags) {
Ken Rockot7655fcb62020-08-12 19:22:4077 return SandboxedVfsFile::FromSqliteFile(*file).ShmLock(offset, size, flags);
Victor Costan451bb9cf2019-03-16 04:48:0778}
79void SandboxedShmBarrier(sqlite3_file* file) {
Ken Rockot7655fcb62020-08-12 19:22:4080 SandboxedVfsFile::FromSqliteFile(*file).ShmBarrier();
Victor Costan451bb9cf2019-03-16 04:48:0781}
82int SandboxedShmUnmap(sqlite3_file* file, int also_delete_file) {
Ken Rockot7655fcb62020-08-12 19:22:4083 return SandboxedVfsFile::FromSqliteFile(*file).ShmUnmap(also_delete_file);
Victor Costan451bb9cf2019-03-16 04:48:0784}
85int SandboxedFetch(sqlite3_file* file,
86 sqlite3_int64 offset,
87 int size,
88 void** result) {
Ken Rockot7655fcb62020-08-12 19:22:4089 return SandboxedVfsFile::FromSqliteFile(*file).Fetch(offset, size, result);
Victor Costan451bb9cf2019-03-16 04:48:0790}
91int SandboxedUnfetch(sqlite3_file* file,
92 sqlite3_int64 offset,
93 void* fetch_result) {
Ken Rockot7655fcb62020-08-12 19:22:4094 return SandboxedVfsFile::FromSqliteFile(*file).Unfetch(offset, fetch_result);
Victor Costan451bb9cf2019-03-16 04:48:0795}
96
97const sqlite3_io_methods* GetSqliteIoMethods() {
98 // VFS IO API entry points are listed at
99 // https://www.sqlite.org/c3ref/io_methods.html
100 static constexpr int kSqliteVfsIoApiVersion = 3;
101
102 static const sqlite3_io_methods kIoMethods = {
103 kSqliteVfsIoApiVersion,
104 SandboxedClose,
105 SandboxedRead,
106 SandboxedWrite,
107 SandboxedTruncate,
108 SandboxedSync,
109 SandboxedFileSize,
110 SandboxedLock,
111 SandboxedUnlock,
112 SandboxedCheckReservedLock,
113 SandboxedFileControl,
114 SandboxedSectorSize,
115 SandboxedDeviceCharacteristics,
116 SandboxedShmMap,
117 SandboxedShmLock,
118 SandboxedShmBarrier,
119 SandboxedShmUnmap,
120 SandboxedFetch,
121 SandboxedUnfetch,
122 };
123
124 return &kIoMethods;
125}
126
127} // namespace
128
129// static
130void SandboxedVfsFile::Create(base::File file,
Ken Rockot7655fcb62020-08-12 19:22:40131 base::FilePath file_path,
Victor Costan451bb9cf2019-03-16 04:48:07132 SandboxedVfs* vfs,
Ken Rockot7655fcb62020-08-12 19:22:40133 sqlite3_file& buffer) {
134 SandboxedVfsFileSqliteBridge& bridge =
Victor Costan451bb9cf2019-03-16 04:48:07135 SandboxedVfsFileSqliteBridge::FromSqliteFile(buffer);
Ken Rockot7655fcb62020-08-12 19:22:40136 bridge.sandboxed_vfs_file =
137 new SandboxedVfsFile(std::move(file), std::move(file_path), vfs);
138 bridge.sqlite_file.pMethods = GetSqliteIoMethods();
Victor Costan451bb9cf2019-03-16 04:48:07139}
140
141// static
Ken Rockot7655fcb62020-08-12 19:22:40142SandboxedVfsFile& SandboxedVfsFile::FromSqliteFile(sqlite3_file& sqlite_file) {
143 return *SandboxedVfsFileSqliteBridge::FromSqliteFile(sqlite_file)
144 .sandboxed_vfs_file;
Victor Costan451bb9cf2019-03-16 04:48:07145}
146
147int SandboxedVfsFile::Close() {
148 file_.Close();
Victor Costan99fe0c12019-10-07 21:06:12149 delete this;
Victor Costan451bb9cf2019-03-16 04:48:07150 return SQLITE_OK;
151}
152
153int SandboxedVfsFile::Read(void* buffer, int size, sqlite3_int64 offset) {
154 DCHECK(buffer);
155 DCHECK_GE(size, 0);
156 DCHECK_GE(offset, 0);
157 char* data = reinterpret_cast<char*>(buffer);
158
159 // If we supported mmap()ed files, we'd check for a memory mapping here,
160 // and try to fill as much of the request as possible from the mmap()ed
161 // region.
162
163 int bytes_read = file_.Read(offset, data, size);
164 DCHECK_LE(bytes_read, size);
165 if (bytes_read == size)
166 return SQLITE_OK;
167
168 // SQLite first reads the database header without locking the file. On
169 // Windows, this read will fail if there is an exclusive lock on the file,
170 // even if the current process owns that lock.
171 if (sqlite_lock_mode_ == SQLITE_LOCK_NONE) {
172 // The unlocked read is considered an optimization. SQLite can continue even
173 // if the read fails, as long as failure is communicated by zeroing out the
174 // output buffer.
175 std::memset(data, 0, size);
176 return SQLITE_OK;
177 }
178
179 if (bytes_read < 0) {
180 vfs_->SetLastError(base::File::GetLastFileError());
181 return SQLITE_IOERR_READ;
182 }
183
184 // SQLite requires that we fill the unread bytes in the buffer with zeros.
185 std::memset(data + bytes_read, 0, size - bytes_read);
186 return SQLITE_IOERR_SHORT_READ;
187}
188
189int SandboxedVfsFile::Write(const void* buffer,
190 int size,
191 sqlite3_int64 offset) {
192 DCHECK(buffer);
193 DCHECK_GE(size, 0);
194 DCHECK_GE(offset, 0);
195 const char* data = reinterpret_cast<const char*>(buffer);
196
197 // If we supported mmap()ed files, we'd check for a memory mapping here,
198 // and try to fill as much of the request as possible by copying to the
199 // mmap()ed region.
200
201 int bytes_written = file_.Write(offset, data, size);
202 DCHECK_LE(bytes_written, size);
203 if (bytes_written >= size)
204 return SQLITE_OK;
205
206 base::File::Error last_error = base::File::GetLastFileError();
207 vfs_->SetLastError(last_error);
208 if (last_error == base::File::Error::FILE_ERROR_NO_SPACE)
209 return SQLITE_FULL;
210
211 return SQLITE_IOERR_WRITE;
212}
213
214int SandboxedVfsFile::Truncate(sqlite3_int64 size) {
215 if (file_.SetLength(size))
216 return SQLITE_OK;
217
Victor Costan959eab02020-08-17 18:33:56218 // On macOS < 10.15, the default sandbox blocks ftruncate(), so we have to use
219 // a sync mojo IPC to ask the browser process to call ftruncate() for us.
Victor Costan451bb9cf2019-03-16 04:48:07220 //
Ken Rockot7655fcb62020-08-12 19:22:40221 // TODO(crbug.com/1084565): Figure out if we can allow ftruncate() in renderer
222 // and utility processes. It would be useful for low-level storage APIs, like
223 // the upcoming filesystem API.
224 if (vfs_->delegate()->SetFileLength(file_path_, file_,
225 static_cast<size_t>(size))) {
226 return SQLITE_OK;
227 }
Victor Costan451bb9cf2019-03-16 04:48:07228
Ken Rockot7655fcb62020-08-12 19:22:40229 return SQLITE_IOERR_TRUNCATE;
Victor Costan451bb9cf2019-03-16 04:48:07230}
231
232int SandboxedVfsFile::Sync(int flags) {
233 // NOTE: SQLite passes in (SQLITE_SYNC_NORMAL or SQLITE_SYNC_FULL),
234 // potentially OR-ed with SQLITE_SYNC_DATAONLY. Implementing these could
235 // lead to better performance.
236 if (!file_.Flush()) {
237 vfs_->SetLastError(base::File::GetLastFileError());
238 return SQLITE_IOERR_FSYNC;
239 }
240
241 // The unix VFS also syncs the file's directory on the first xSync() call.
242 // Chrome's LevelDB Env implementation does the same for specific files
243 // (database manifests).
244 //
245 // For WebSQL, we would want to sync the directory at file open time, when the
246 // file is opened for writing.
247
248 return SQLITE_OK;
249}
250
251int SandboxedVfsFile::FileSize(sqlite3_int64* result_size) {
252 int64_t length = file_.GetLength();
253 if (length < 0) {
254 vfs_->SetLastError(base::File::GetLastFileError());
255 return SQLITE_IOERR_FSTAT;
256 }
257
258 // SQLite's unix VFS reports 1-byte files as empty. This is documented as a
259 // workaround for a fairly obscure bug. See unixFileSize() in os_unix.c.
260 if (length == 1)
261 length = 0;
262
263 *result_size = length;
264 return SQLITE_OK;
265}
266
267namespace {
268
269// True if our simplified implementation uses an exclusive lock for a mode.
270bool IsExclusiveLockMode(int sqlite_lock_mode) {
271 switch (sqlite_lock_mode) {
272 case SQLITE_LOCK_NONE:
273 case SQLITE_LOCK_SHARED:
274 return false;
275
276 case SQLITE_LOCK_RESERVED:
277 case SQLITE_LOCK_PENDING:
278 case SQLITE_LOCK_EXCLUSIVE:
279 return true;
280 }
281
282 NOTREACHED() << "Unsupported mode: " << sqlite_lock_mode;
283 return false;
284}
285
286} // namespace
287
288int SandboxedVfsFile::Lock(int mode) {
289#if defined(OS_FUCHSIA)
290 return SQLITE_IOERR_LOCK;
291#else
292 base::File::LockMode file_lock_mode = base::File::LockMode::kExclusive;
293
294 switch (mode) {
295 case SQLITE_LOCK_NONE:
296 return SQLITE_OK;
297
298 case SQLITE_LOCK_SHARED:
299 if (sqlite_lock_mode_ != SQLITE_LOCK_NONE)
300 return SQLITE_OK;
301
302 file_lock_mode = base::File::LockMode::kShared;
303 break;
304
305 case SQLITE_LOCK_RESERVED:
306 // A SHARED lock is required before a RESERVED lock is acquired.
307 DCHECK_EQ(sqlite_lock_mode_, SQLITE_LOCK_SHARED);
308 file_lock_mode = base::File::LockMode::kExclusive;
309 break;
310
311 case SQLITE_LOCK_PENDING:
312 // A SHARED lock is required before a PENDING lock is acquired. The caller
313 // may have a RESERVED lock.
314 if (sqlite_lock_mode_ == SQLITE_LOCK_RESERVED) {
315 sqlite_lock_mode_ = mode;
316 return SQLITE_OK;
317 }
318
319 DCHECK_EQ(sqlite_lock_mode_, SQLITE_LOCK_SHARED);
320 file_lock_mode = base::File::LockMode::kExclusive;
321 break;
322
323 case SQLITE_LOCK_EXCLUSIVE:
324 if (IsExclusiveLockMode(sqlite_lock_mode_)) {
325 sqlite_lock_mode_ = mode;
326 return SQLITE_OK;
327 }
328 file_lock_mode = base::File::LockMode::kExclusive;
329 break;
330
331 default:
332 NOTREACHED() << "Unimplemented xLock() mode: " << mode;
333 }
334
335 DCHECK_EQ(IsExclusiveLockMode(mode),
336 file_lock_mode == base::File::LockMode::kExclusive)
337 << "Incorrect file_lock_mode logic for SQLite mode: " << mode;
338
339 // On POSIX, it would be possible to upgrade atomically from a shared lock to
340 // an exclusive lock. This implementation prioritizes the simplicity of no
341 // platform-specific code over being faster in high contention cases.
342 if (sqlite_lock_mode_ != SQLITE_LOCK_NONE) {
343 base::File::Error error = file_.Unlock();
344 if (error != base::File::FILE_OK) {
345 vfs_->SetLastError(base::File::GetLastFileError());
346 return SQLITE_IOERR_LOCK;
347 }
348 sqlite_lock_mode_ = SQLITE_LOCK_NONE;
349 }
350
351 base::File::Error error = file_.Lock(file_lock_mode);
352 if (error != base::File::FILE_OK) {
353 vfs_->SetLastError(base::File::GetLastFileError());
354 return SQLITE_IOERR_LOCK;
355 }
356
357 sqlite_lock_mode_ = mode;
358 return SQLITE_OK;
359#endif // defined(OS_FUCHSIA)
360}
361
362int SandboxedVfsFile::Unlock(int mode) {
363 // No-op if we're already unlocked or at the requested mode.
364 if (sqlite_lock_mode_ == mode || sqlite_lock_mode_ == SQLITE_LOCK_NONE)
365 return SQLITE_OK;
366
367#if defined(OS_FUCHSIA)
368 return SQLITE_IOERR_UNLOCK;
369#else
370 // On POSIX, it is possible to downgrade atomically from an exclusive lock to
371 // a shared lock. SQLite's unix VFS takes advantage of this. This
372 // implementation prioritizes the simplicity of no platform-specific code over
373 // being faster in high contention cases.
374 base::File::Error error = file_.Unlock();
375 if (error != base::File::FILE_OK) {
376 vfs_->SetLastError(base::File::GetLastFileError());
377 return SQLITE_IOERR_UNLOCK;
378 }
379
380 if (mode == SQLITE_LOCK_NONE) {
381 sqlite_lock_mode_ = mode;
382 return SQLITE_OK;
383 }
384
385 DCHECK_EQ(mode, SQLITE_LOCK_SHARED);
386 error = file_.Lock(base::File::LockMode::kShared);
387 if (error == base::File::FILE_OK) {
388 sqlite_lock_mode_ = mode;
389 return SQLITE_OK;
390 }
391
392 // Gave up the exclusive lock, but failed to get a shared lock.
393 vfs_->SetLastError(base::File::GetLastFileError());
394 sqlite_lock_mode_ = SQLITE_LOCK_NONE;
395 return SQLITE_IOERR_UNLOCK;
396#endif // defined(OS_FUCHSIA)
397}
398
399int SandboxedVfsFile::CheckReservedLock(int* has_reserved_lock) {
400 if (IsExclusiveLockMode(sqlite_lock_mode_)) {
401 *has_reserved_lock = 1;
402 return SQLITE_OK;
403 }
404
405 if (sqlite_lock_mode_ == SQLITE_LOCK_SHARED) {
406 // Lock modes at or above RESERVED map to exclusive locks in our simplified
407 // implementation. If this process has a shared lock, no other process can
408 // have an exclusive lock.
409 *has_reserved_lock = 0;
410 return SQLITE_OK;
411 }
412
413#if defined(OS_FUCHSIA)
414 return SQLITE_IOERR_CHECKRESERVEDLOCK;
415#else
416 // On POSIX, it's possible to query the existing lock state of a file. The
417 // SQLite unix VFS takes advantage of this. On Windows, this isn't the case.
418 // Follow the strategy of the Windows VFS, which checks by trying to get an
419 // exclusive lock on the file.
420 base::File::Error error = file_.Lock(base::File::LockMode::kShared);
421 if (error != base::File::FILE_OK) {
422 *has_reserved_lock = 1;
423 return SQLITE_OK;
424 }
425
426 *has_reserved_lock = 0;
427 if (file_.Unlock() == base::File::FILE_OK)
428 return SQLITE_OK;
429
430 // We acquired a shared lock that we can't get rid of.
431 sqlite_lock_mode_ = SQLITE_LOCK_SHARED;
432 return SQLITE_IOERR_CHECKRESERVEDLOCK;
433#endif // defined(OS_FUCHSIA)
434}
435
436int SandboxedVfsFile::FileControl(int opcode, void* data) {
437 switch (opcode) {
438 case SQLITE_FCNTL_MMAP_SIZE:
439 // Implementing memory-mapping will require handling this correctly.
440 return SQLITE_NOTFOUND;
441 default:
442 return SQLITE_NOTFOUND;
443 }
444}
445
446int SandboxedVfsFile::SectorSize() {
447 return 0;
448}
449
450int SandboxedVfsFile::DeviceCharacteristics() {
451 // TODO(pwnall): Figure out if we can get away with returning 0 on Windows.
452#if defined(OS_WIN)
453 return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN;
454#else
455 // NOTE: SQLite's unix VFS attempts to detect the underlying filesystem and
456 // sets some flags based on the result.
457 return 0;
458#endif // OS_WIN
459}
460
461int SandboxedVfsFile::ShmMap(int page_index,
462 int page_size,
463 int extend_file_if_needed,
464 void volatile** result) {
465 DCHECK_GE(page_index, 0);
466 DCHECK_GE(page_size, 0);
467 DCHECK(result);
468
Victor Costan959eab02020-08-17 18:33:56469 // https://www.sqlite.org/wal.html#use_of_wal_without_shared_memory states
470 // that SQLite only attempts to use shared memory "-shm" files for databases
471 // in WAL mode that may be accessed by multiple processes (are not EXCLUSIVE).
472 //
473 // Chrome will not only use WAL mode on EXCLUSIVE databases.
474 NOTREACHED() << "SQLite should not attempt to use shared memory";
475
Victor Costan451bb9cf2019-03-16 04:48:07476 *result = nullptr;
477 return SQLITE_IOERR;
478}
479
480int SandboxedVfsFile::ShmLock(int offset, int size, int flags) {
481 DCHECK_GE(offset, 0);
482 DCHECK_GE(size, 0);
483
Victor Costan959eab02020-08-17 18:33:56484 // https://www.sqlite.org/wal.html#use_of_wal_without_shared_memory states
485 // that SQLite only attempts to use shared memory "-shm" files for databases
486 // in WAL mode that may be accessed by multiple processes (are not EXCLUSIVE).
487 //
488 // Chrome will not only use WAL mode on EXCLUSIVE databases.
489 NOTREACHED() << "SQLite should not attempt to use shared memory";
490
Victor Costan451bb9cf2019-03-16 04:48:07491 return SQLITE_IOERR;
492}
493
494void SandboxedVfsFile::ShmBarrier() {
Victor Costan959eab02020-08-17 18:33:56495 // https://www.sqlite.org/wal.html#use_of_wal_without_shared_memory states
496 // that SQLite only attempts to use shared memory "-shm" files for databases
497 // in WAL mode that may be accessed by multiple processes (are not EXCLUSIVE).
498 //
499 // Chrome will not only use WAL mode on EXCLUSIVE databases.
500 NOTREACHED() << "SQLite should not attempt to use shared memory";
501
Victor Costan451bb9cf2019-03-16 04:48:07502 // All writes to shared memory that have already been issued before this
503 // function is called must complete before the function returns.
504 std::atomic_thread_fence(std::memory_order_acq_rel);
505}
506
507int SandboxedVfsFile::ShmUnmap(int also_delete_file) {
Victor Costan959eab02020-08-17 18:33:56508 // https://www.sqlite.org/wal.html#use_of_wal_without_shared_memory states
509 // that SQLite only attempts to use shared memory "-shm" files for databases
510 // in WAL mode that may be accessed by multiple processes (are not EXCLUSIVE).
511 //
512 // Chrome will not only use WAL mode on EXCLUSIVE databases.
513 NOTREACHED() << "SQLite should not attempt to use shared memory";
514
Victor Costan451bb9cf2019-03-16 04:48:07515 return SQLITE_IOERR;
516}
517
518int SandboxedVfsFile::Fetch(sqlite3_int64 offset, int size, void** result) {
519 DCHECK_GE(offset, 0);
520 DCHECK_GE(size, 0);
521 DCHECK(result);
522
523 // NOTE: This would be needed for mmap()ed file support.
524 *result = nullptr;
525 return SQLITE_IOERR;
526}
527
528int SandboxedVfsFile::Unfetch(sqlite3_int64 offset, void* fetch_result) {
529 DCHECK_GE(offset, 0);
530 DCHECK(fetch_result);
531
532 // NOTE: This would be needed for mmap()ed file support.
533 return SQLITE_IOERR;
534}
535
536SandboxedVfsFile::SandboxedVfsFile(base::File file,
Ken Rockot7655fcb62020-08-12 19:22:40537 base::FilePath file_path,
Victor Costan451bb9cf2019-03-16 04:48:07538 SandboxedVfs* vfs)
539 : file_(std::move(file)),
540 sqlite_lock_mode_(SQLITE_LOCK_NONE),
541 vfs_(vfs),
Ken Rockot7655fcb62020-08-12 19:22:40542 file_path_(std::move(file_path)) {}
Victor Costan451bb9cf2019-03-16 04:48:07543
544SandboxedVfsFile::~SandboxedVfsFile() = default;
545
546// static
Ken Rockot7655fcb62020-08-12 19:22:40547SandboxedVfsFileSqliteBridge& SandboxedVfsFileSqliteBridge::FromSqliteFile(
548 sqlite3_file& sqlite_file) {
Victor Costan451bb9cf2019-03-16 04:48:07549 static_assert(std::is_standard_layout<SandboxedVfsFileSqliteBridge>::value,
550 "needed for the reinterpret_cast below");
551 static_assert(offsetof(SandboxedVfsFileSqliteBridge, sqlite_file) == 0,
552 "sqlite_file must be the first member of the struct.");
553
Ken Rockot7655fcb62020-08-12 19:22:40554 SandboxedVfsFileSqliteBridge& bridge =
555 reinterpret_cast<SandboxedVfsFileSqliteBridge&>(sqlite_file);
556 DCHECK_EQ(&sqlite_file, &bridge.sqlite_file)
Victor Costan451bb9cf2019-03-16 04:48:07557 << "assumed by the reinterpret_casts in the implementation";
558 return bridge;
559}
560
Ken Rockot7655fcb62020-08-12 19:22:40561} // namespace sql