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_H_
6 #define SQL_SANDBOXED_VFS_H_
12 #include "base/component_export.h"
13 #include "base/files/file.h"
14 #include "base/files/file_path.h"
15 #include "base/time/time.h"
16 #include "third_party/abseil-cpp/absl/types/optional.h"
17 #include "third_party/sqlite/sqlite3.h"
21 // SQLite VFS file implementation that works in a sandboxed process.
23 // Instances are thread-friendly.
24 class COMPONENT_EXPORT(SQL) SandboxedVfs {
26 // Describes access rights for a path, used by Delegate::GetPathAccess below.
27 struct PathAccessInfo {
28 bool can_read = false;
29 bool can_write = false;
32 // Environment-specific SandboxedVfs implementation details.
34 // This abstracts a handful of operations that don't typically work in a
35 // sandbox environment given a typical naive implementation. Instances must be
39 virtual ~Delegate() = default;
43 // `file_path` is the parsed version of a path passed by SQLite to Open().
44 // `sqlite_requested_flags` is a bitwise combination SQLite flags used when
45 // opening files. Returns the opened File on success, or an invalid File on
47 virtual base::File OpenFile(const base::FilePath& file_path,
48 int sqlite_requested_flags) = 0;
52 // `file_path` is the parsed version of a path passed by SQLite to Delete().
53 // If `sync_dir` is true, the implementation should attempt to flush to disk
54 // the changes to the file's directory, to ensure that the deletion is
55 // reflected after a power failure. Returns an SQLite error code indicating
56 // the status of the operation.
57 virtual int DeleteFile(const base::FilePath& file_path, bool sync_dir) = 0;
59 // Queries path access information for `file_path`. Returns null if the
60 // given path does not exist.
61 virtual absl::optional<PathAccessInfo> GetPathAccess(
62 const base::FilePath& file_path) = 0;
66 // `file` is the result of a previous call to Delegate::OpenFile() with
67 // `file_path`. `size` is the new desired size in bytes, and may be smaller
68 // or larger than the current file size. Returns true if successful and
71 // Implementations can modify `file` directly, or operate on the filesystem
74 // This is only called after the direct approach of base::File::SetLength()
75 // fails. So, the implementation should not bother trying to call
76 // SetLength() on `file`. This currently only happens on macOS < 10.15.
77 virtual bool SetFileLength(const base::FilePath& file_path,
82 // We don't allow SandboxedVfs instances to be destroyed. Once created, they
83 // are permanently registered in the calling process.
84 ~SandboxedVfs() = delete;
86 // Constructs a new instance of ths object using `delegate` to support various
87 // operations from within the sandbox. The VFS is registered with SQLite under
88 // `name` and if `make_default` is true then the VFS is also set as the global
89 // default for new database instances within the calling process.
91 // Note that `name` must be globally unique to the calling process.
92 static void Register(const char* name,
93 std::unique_ptr<Delegate> delegate,
96 Delegate* delegate() const { return delegate_.get(); }
98 // sqlite3_vfs implementation.
99 int Open(const char* full_path,
100 sqlite3_file& result_file,
103 int Delete(const char* full_path, int sync_dir);
104 int Access(const char* full_path, int flags, int& result);
105 int FullPathname(const char* file_path, int result_size, char* result);
106 int Randomness(int result_size, char* result);
107 int Sleep(int microseconds);
108 int GetLastError(int message_size, char* message) const;
109 int CurrentTimeInt64(sqlite3_int64* result_ms);
111 // Used by SandboxedVfsFile.
112 void SetLastError(base::File::Error error) { this->last_error_ = error; }
115 SandboxedVfs(const char* name,
116 std::unique_ptr<Delegate> delegate,
119 sqlite3_vfs sandboxed_vfs_;
120 const base::Time sqlite_epoch_;
121 const std::unique_ptr<Delegate> delegate_;
122 base::File::Error last_error_;
127 #endif // SQL_SANDBOXED_VFS_H_